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