nrf52840dk_test_appid_ecdsap256/
main.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! Tock kernel for the Nordic Semiconductor nRF52840 development kit (DK).
6
7#![no_std]
8#![no_main]
9#![deny(missing_docs)]
10
11use kernel::component::Component;
12use kernel::deferred_call::DeferredCallClient;
13use kernel::hil::led::LedLow;
14use kernel::hil::time::Counter;
15use kernel::platform::{KernelResources, SyscallDriverLookup};
16use kernel::process::ProcessArray;
17use kernel::scheduler::round_robin::RoundRobinSched;
18use kernel::{capabilities, create_capability, static_init};
19use nrf52840::gpio::Pin;
20use nrf52840::interrupt_service::Nrf52840DefaultPeripherals;
21use nrf52_components::{UartChannel, UartPins};
22
23// The nRF52840DK LEDs (see back of board)
24const LED1_PIN: Pin = Pin::P0_13;
25const LED2_PIN: Pin = Pin::P0_14;
26const LED3_PIN: Pin = Pin::P0_15;
27const LED4_PIN: Pin = Pin::P0_16;
28
29const BUTTON_RST_PIN: Pin = Pin::P0_18;
30
31const UART_RTS: Option<Pin> = Some(Pin::P0_05);
32const UART_TXD: Pin = Pin::P0_06;
33const UART_CTS: Option<Pin> = Some(Pin::P0_07);
34const UART_RXD: Pin = Pin::P0_08;
35
36/// Debug Writer
37pub mod io;
38
39// State for loading and holding applications.
40// How should the kernel respond when a process faults.
41const FAULT_RESPONSE: capsules_system::process_policies::PanicFaultPolicy =
42    capsules_system::process_policies::PanicFaultPolicy {};
43
44// Number of concurrent processes this platform supports.
45const NUM_PROCS: usize = 8;
46
47/// Static variables used by io.rs.
48static mut PROCESSES: Option<&'static ProcessArray<NUM_PROCS>> = None;
49static mut CHIP: Option<&'static nrf52840::chip::NRF52<Nrf52840DefaultPeripherals>> = None;
50
51/// Dummy buffer that causes the linker to reserve enough space for the stack.
52#[no_mangle]
53#[link_section = ".stack_buffer"]
54static mut STACK_MEMORY: [u8; 0x2000] = [0; 0x2000];
55
56//------------------------------------------------------------------------------
57// SYSCALL DRIVER TYPE DEFINITIONS
58//------------------------------------------------------------------------------
59
60type AlarmDriver = components::alarm::AlarmDriverComponentType<nrf52840::rtc::Rtc<'static>>;
61
62type Verifier = ecdsa_sw::p256_verifier::EcdsaP256SignatureVerifier<'static>;
63type SignatureVerifyInMemoryKeys =
64    components::signature_verify_in_memory_keys::SignatureVerifyInMemoryKeysComponentType<
65        Verifier,
66        2,
67        64,
68        32,
69        64,
70    >;
71
72/// Supported drivers by the platform
73pub struct Platform {
74    console: &'static capsules_core::console::Console<'static>,
75    led: &'static capsules_core::led::LedDriver<
76        'static,
77        kernel::hil::led::LedLow<'static, nrf52840::gpio::GPIOPin<'static>>,
78        4,
79    >,
80    alarm: &'static AlarmDriver,
81    scheduler: &'static RoundRobinSched<'static>,
82    systick: cortexm4::systick::SysTick,
83}
84
85impl SyscallDriverLookup for Platform {
86    fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
87    where
88        F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R,
89    {
90        match driver_num {
91            capsules_core::console::DRIVER_NUM => f(Some(self.console)),
92            capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)),
93            capsules_core::led::DRIVER_NUM => f(Some(self.led)),
94            _ => f(None),
95        }
96    }
97}
98
99/// This is in a separate, inline(never) function so that its stack frame is
100/// removed when this function returns. Otherwise, the stack space used for
101/// these static_inits is wasted.
102#[inline(never)]
103unsafe fn create_peripherals() -> &'static mut Nrf52840DefaultPeripherals<'static> {
104    let ieee802154_ack_buf = static_init!(
105        [u8; nrf52840::ieee802154_radio::ACK_BUF_SIZE],
106        [0; nrf52840::ieee802154_radio::ACK_BUF_SIZE]
107    );
108    // Initialize chip peripheral drivers
109    let nrf52840_peripherals = static_init!(
110        Nrf52840DefaultPeripherals,
111        Nrf52840DefaultPeripherals::new(ieee802154_ack_buf)
112    );
113
114    nrf52840_peripherals
115}
116
117impl KernelResources<nrf52840::chip::NRF52<'static, Nrf52840DefaultPeripherals<'static>>>
118    for Platform
119{
120    type SyscallDriverLookup = Self;
121    type SyscallFilter = ();
122    type ProcessFault = ();
123    type Scheduler = RoundRobinSched<'static>;
124    type SchedulerTimer = cortexm4::systick::SysTick;
125    type WatchDog = ();
126    type ContextSwitchCallback = ();
127
128    fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
129        self
130    }
131    fn syscall_filter(&self) -> &Self::SyscallFilter {
132        &()
133    }
134    fn process_fault(&self) -> &Self::ProcessFault {
135        &()
136    }
137    fn scheduler(&self) -> &Self::Scheduler {
138        self.scheduler
139    }
140    fn scheduler_timer(&self) -> &Self::SchedulerTimer {
141        &self.systick
142    }
143    fn watchdog(&self) -> &Self::WatchDog {
144        &()
145    }
146    fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
147        &()
148    }
149}
150
151/// Main function called after RAM initialized.
152#[no_mangle]
153pub unsafe fn main() {
154    //--------------------------------------------------------------------------
155    // INITIAL SETUP
156    //--------------------------------------------------------------------------
157
158    // Apply errata fixes and enable interrupts.
159    nrf52840::init();
160
161    // Set up peripheral drivers. Called in separate function to reduce stack
162    // usage.
163    let nrf52840_peripherals = create_peripherals();
164
165    // Set up circular peripheral dependencies.
166    nrf52840_peripherals.init();
167    let base_peripherals = &nrf52840_peripherals.nrf52;
168
169    // Choose the channel for serial output. This board can be configured to use
170    // either the Segger RTT channel or via UART with traditional TX/RX GPIO
171    // pins.
172    let uart_channel = UartChannel::Pins(UartPins::new(UART_RTS, UART_TXD, UART_CTS, UART_RXD));
173
174    // Create an array to hold process references.
175    let processes = components::process_array::ProcessArrayComponent::new()
176        .finalize(components::process_array_component_static!(NUM_PROCS));
177    PROCESSES = Some(processes);
178
179    // Setup space to store the core kernel data structure.
180    let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(processes.as_slice()));
181
182    // Create (and save for panic debugging) a chip object to setup low-level
183    // resources (e.g. MPU, systick).
184    let chip = static_init!(
185        nrf52840::chip::NRF52<Nrf52840DefaultPeripherals>,
186        nrf52840::chip::NRF52::new(nrf52840_peripherals)
187    );
188    CHIP = Some(chip);
189
190    // Do nRF configuration and setup. This is shared code with other nRF-based
191    // platforms.
192    nrf52_components::startup::NrfStartupComponent::new(
193        false,
194        BUTTON_RST_PIN,
195        nrf52840::uicr::Regulator0Output::DEFAULT,
196        &base_peripherals.nvmc,
197    )
198    .finalize(());
199
200    //--------------------------------------------------------------------------
201    // CAPABILITIES
202    //--------------------------------------------------------------------------
203
204    // Create capabilities that the board needs to call certain protected kernel
205    // functions.
206    let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
207
208    //--------------------------------------------------------------------------
209    // LEDs
210    //--------------------------------------------------------------------------
211
212    let led = components::led::LedsComponent::new().finalize(components::led_component_static!(
213        LedLow<'static, nrf52840::gpio::GPIOPin>,
214        LedLow::new(&nrf52840_peripherals.gpio_port[LED1_PIN]),
215        LedLow::new(&nrf52840_peripherals.gpio_port[LED2_PIN]),
216        LedLow::new(&nrf52840_peripherals.gpio_port[LED3_PIN]),
217        LedLow::new(&nrf52840_peripherals.gpio_port[LED4_PIN]),
218    ));
219
220    //--------------------------------------------------------------------------
221    // TIMER
222    //--------------------------------------------------------------------------
223
224    let rtc = &base_peripherals.rtc;
225    let _ = rtc.start();
226    let mux_alarm = components::alarm::AlarmMuxComponent::new(rtc)
227        .finalize(components::alarm_mux_component_static!(nrf52840::rtc::Rtc));
228    let alarm = components::alarm::AlarmDriverComponent::new(
229        board_kernel,
230        capsules_core::alarm::DRIVER_NUM,
231        mux_alarm,
232    )
233    .finalize(components::alarm_component_static!(nrf52840::rtc::Rtc));
234
235    //--------------------------------------------------------------------------
236    // UART & CONSOLE & DEBUG
237    //--------------------------------------------------------------------------
238
239    let uart_channel = nrf52_components::UartChannelComponent::new(
240        uart_channel,
241        mux_alarm,
242        &base_peripherals.uarte0,
243    )
244    .finalize(nrf52_components::uart_channel_component_static!(
245        nrf52840::rtc::Rtc
246    ));
247
248    // Virtualize the UART channel for the console and for kernel debug.
249    let uart_mux = components::console::UartMuxComponent::new(uart_channel, 115200)
250        .finalize(components::uart_mux_component_static!());
251
252    // Setup the serial console for userspace.
253    let console = components::console::ConsoleComponent::new(
254        board_kernel,
255        capsules_core::console::DRIVER_NUM,
256        uart_mux,
257    )
258    .finalize(components::console_component_static!());
259
260    //--------------------------------------------------------------------------
261    // NRF CLOCK SETUP
262    //--------------------------------------------------------------------------
263
264    nrf52_components::NrfClockComponent::new(&base_peripherals.clock).finalize(());
265
266    //--------------------------------------------------------------------------
267    // Credential Checking
268    //--------------------------------------------------------------------------
269
270    // Create the software-based SHA engine.
271    let sha = components::sha::ShaSoftware256Component::new()
272        .finalize(components::sha_software_256_component_static!());
273
274    // Create the credential checker.
275    //
276    // Setup an example key.
277    //
278    // - `ec-secp256r1-priv-key.pem`:
279    //   ```
280    //   -----BEGIN EC PRIVATE KEY-----
281    //   MHcCAQEEIGU0zCXHLqxDmrHHAWEQP5zNfWRQrAiIpH9YwxHlqysmoAoGCCqGSM49
282    //   AwEHoUQDQgAE4BM6kKdKNWFRjuFECfFpwc9q239+Uvi3QXniTVdBI1IuthIDs4UQ
283    //   5fMlB2KPVJWCV0VQvaPiF+g0MIkmTCNisQ==
284    //   -----END EC PRIVATE KEY-----
285    //   ```
286    //
287    // - `ec-secp256r1-pub-key.pem`:
288    //   ```
289    //   -----BEGIN PUBLIC KEY-----
290    //   MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE4BM6kKdKNWFRjuFECfFpwc9q239+
291    //   Uvi3QXniTVdBI1IuthIDs4UQ5fMlB2KPVJWCV0VQvaPiF+g0MIkmTCNisQ==
292    //   -----END PUBLIC KEY-----
293    //   ```
294    //
295    // You can add the correct signature to a TBF by saving the private key to
296    // a file and then running:
297    //
298    //     tockloader tbf credential add ecdsap256 --private-key ec-secp256r1-priv-key.pem
299    //
300    let verifying_key0 = kernel::static_init!(
301        [u8; 64],
302        [
303            0xe0, 0x13, 0x3a, 0x90, 0xa7, 0x4a, 0x35, 0x61, 0x51, 0x8e, 0xe1, 0x44, 0x09, 0xf1,
304            0x69, 0xc1, 0xcf, 0x6a, 0xdb, 0x7f, 0x7e, 0x52, 0xf8, 0xb7, 0x41, 0x79, 0xe2, 0x4d,
305            0x57, 0x41, 0x23, 0x52, 0x2e, 0xb6, 0x12, 0x03, 0xb3, 0x85, 0x10, 0xe5, 0xf3, 0x25,
306            0x07, 0x62, 0x8f, 0x54, 0x95, 0x82, 0x57, 0x45, 0x50, 0xbd, 0xa3, 0xe2, 0x17, 0xe8,
307            0x34, 0x30, 0x89, 0x26, 0x4c, 0x23, 0x62, 0xb1
308        ]
309    );
310    // - `ec-secp256r1-priv-key2.pem`:
311    //   ```
312    //   -----BEGIN EC PRIVATE KEY-----
313    //   MHcCAQEEIMlpHXMiwjFiTRH015zyxsur59JVKzBUzM9jQTUSjcC9oAoGCCqGSM49
314    //   AwEHoUQDQgAEyT04ecALSi9cv8r8AyQUe++on+X1K3ec2fNR/bw35wwp5u7DxO1X
315    //   bZWNw8Bzh031jaY+je/40/CnCCKt9/ejqg==
316    //   -----END EC PRIVATE KEY-----
317    //   ```
318    //
319    // - `ec-secp256r1-pub-key2.pem`:
320    //   ```
321    //   -----BEGIN PUBLIC KEY-----
322    //   MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEyT04ecALSi9cv8r8AyQUe++on+X1
323    //   K3ec2fNR/bw35wwp5u7DxO1XbZWNw8Bzh031jaY+je/40/CnCCKt9/ejqg==
324    //   -----END PUBLIC KEY-----
325    //   ```
326    let verifying_key1 = kernel::static_init!(
327        [u8; 64],
328        [
329            0xc9, 0x3d, 0x38, 0x79, 0xc0, 0x0b, 0x4a, 0x2f, 0x5c, 0xbf, 0xca, 0xfc, 0x03, 0x24,
330            0x14, 0x7b, 0xef, 0xa8, 0x9f, 0xe5, 0xf5, 0x2b, 0x77, 0x9c, 0xd9, 0xf3, 0x51, 0xfd,
331            0xbc, 0x37, 0xe7, 0x0c, 0x29, 0xe6, 0xee, 0xc3, 0xc4, 0xed, 0x57, 0x6d, 0x95, 0x8d,
332            0xc3, 0xc0, 0x73, 0x87, 0x4d, 0xf5, 0x8d, 0xa6, 0x3e, 0x8d, 0xef, 0xf8, 0xd3, 0xf0,
333            0xa7, 0x08, 0x22, 0xad, 0xf7, 0xf7, 0xa3, 0xaa,
334        ]
335    );
336    let verifying_keys =
337        kernel::static_init!([&'static mut [u8; 64]; 2], [verifying_key0, verifying_key1]);
338    // kernel::static_init!([&'static mut [u8; 64]; 1], [verifying_key0]);
339    // Setup the ECDSA-P256 verifier.
340    let ecdsa_p256_verifying_key = kernel::static_init!([u8; 64], [0; 64]);
341    let ecdsa_p256_verifier = kernel::static_init!(
342        ecdsa_sw::p256_verifier::EcdsaP256SignatureVerifier<'static>,
343        ecdsa_sw::p256_verifier::EcdsaP256SignatureVerifier::new(ecdsa_p256_verifying_key)
344    );
345    ecdsa_p256_verifier.register();
346
347    // Setup the in-memory key selector.
348    let verifier_multiple_keys =
349        components::signature_verify_in_memory_keys::SignatureVerifyInMemoryKeysComponent::new(
350            ecdsa_p256_verifier,
351            verifying_keys,
352        )
353        .finalize(
354            components::signature_verify_in_memory_keys_component_static!(Verifier, 2, 64, 32, 64,),
355        );
356
357    // Policy checks for a valid EcdsaNistP256 signature.
358    let checking_policy = components::appid::checker_signature::AppCheckerSignatureComponent::new(
359        sha,
360        verifier_multiple_keys,
361        tock_tbf::types::TbfFooterV2CredentialsType::EcdsaNistP256,
362    )
363    .finalize(components::app_checker_signature_component_static!(
364        SignatureVerifyInMemoryKeys,
365        capsules_extra::sha256::Sha256Software<'static>,
366        32,
367        64,
368    ));
369
370    // Create the AppID assigner.
371    let assigner = components::appid::assigner_name::AppIdAssignerNamesComponent::new()
372        .finalize(components::appid_assigner_names_component_static!());
373
374    // Create the process checking machine.
375    let checker = components::appid::checker::ProcessCheckerMachineComponent::new(checking_policy)
376        .finalize(components::process_checker_machine_component_static!());
377
378    //--------------------------------------------------------------------------
379    // STORAGE PERMISSIONS
380    //--------------------------------------------------------------------------
381
382    let storage_permissions_policy =
383        components::storage_permissions::null::StoragePermissionsNullComponent::new().finalize(
384            components::storage_permissions_null_component_static!(
385                nrf52840::chip::NRF52<Nrf52840DefaultPeripherals>,
386                kernel::process::ProcessStandardDebugFull,
387            ),
388        );
389
390    //--------------------------------------------------------------------------
391    // PROCESS LOADING
392    //--------------------------------------------------------------------------
393
394    // These symbols are defined in the standard Tock linker script.
395    extern "C" {
396        /// Beginning of the ROM region containing app images.
397        static _sapps: u8;
398        /// End of the ROM region containing app images.
399        static _eapps: u8;
400        /// Beginning of the RAM region for app memory.
401        static mut _sappmem: u8;
402        /// End of the RAM region for app memory.
403        static _eappmem: u8;
404    }
405
406    let app_flash = core::slice::from_raw_parts(
407        core::ptr::addr_of!(_sapps),
408        core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
409    );
410    let app_memory = core::slice::from_raw_parts_mut(
411        core::ptr::addr_of_mut!(_sappmem),
412        core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
413    );
414
415    // Create and start the asynchronous process loader.
416    let _loader = components::loader::sequential::ProcessLoaderSequentialComponent::new(
417        checker,
418        board_kernel,
419        chip,
420        &FAULT_RESPONSE,
421        assigner,
422        storage_permissions_policy,
423        app_flash,
424        app_memory,
425    )
426    .finalize(components::process_loader_sequential_component_static!(
427        nrf52840::chip::NRF52<Nrf52840DefaultPeripherals>,
428        kernel::process::ProcessStandardDebugFull,
429        NUM_PROCS
430    ));
431
432    //--------------------------------------------------------------------------
433    // PLATFORM SETUP, SCHEDULER, AND START KERNEL LOOP
434    //--------------------------------------------------------------------------
435
436    let scheduler = components::sched::round_robin::RoundRobinComponent::new(processes)
437        .finalize(components::round_robin_component_static!(NUM_PROCS));
438
439    let platform = Platform {
440        console,
441        led,
442        alarm,
443        scheduler,
444        systick: cortexm4::systick::SysTick::new_with_calibration(64000000),
445    };
446
447    board_kernel.kernel_loop(
448        &platform,
449        chip,
450        None::<&kernel::ipc::IPC<0>>,
451        &main_loop_capability,
452    );
453}