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::scheduler::round_robin::RoundRobinSched;
17use kernel::{capabilities, create_capability, static_init};
18use nrf52840::gpio::Pin;
19use nrf52840::interrupt_service::Nrf52840DefaultPeripherals;
20use nrf52_components::{UartChannel, UartPins};
21
22// The nRF52840DK LEDs (see back of board)
23const LED1_PIN: Pin = Pin::P0_13;
24const LED2_PIN: Pin = Pin::P0_14;
25const LED3_PIN: Pin = Pin::P0_15;
26const LED4_PIN: Pin = Pin::P0_16;
27
28const BUTTON_RST_PIN: Pin = Pin::P0_18;
29
30const UART_RTS: Option<Pin> = Some(Pin::P0_05);
31const UART_TXD: Pin = Pin::P0_06;
32const UART_CTS: Option<Pin> = Some(Pin::P0_07);
33const UART_RXD: Pin = Pin::P0_08;
34
35/// Debug Writer
36pub mod io;
37
38// State for loading and holding applications.
39// How should the kernel respond when a process faults.
40const FAULT_RESPONSE: capsules_system::process_policies::PanicFaultPolicy =
41    capsules_system::process_policies::PanicFaultPolicy {};
42
43// Number of concurrent processes this platform supports.
44const NUM_PROCS: usize = 8;
45
46type ChipHw = nrf52840::chip::NRF52<'static, Nrf52840DefaultPeripherals<'static>>;
47
48kernel::stack_size! {0x2000}
49
50//------------------------------------------------------------------------------
51// SYSCALL DRIVER TYPE DEFINITIONS
52//------------------------------------------------------------------------------
53
54type AlarmDriver = components::alarm::AlarmDriverComponentType<nrf52840::rtc::Rtc<'static>>;
55
56type Verifier = ecdsa_sw::p256_verifier::EcdsaP256SignatureVerifier<'static>;
57type SignatureVerifyInMemoryKeys =
58    components::signature_verify_in_memory_keys::SignatureVerifyInMemoryKeysComponentType<
59        Verifier,
60        2,
61        64,
62        32,
63        64,
64    >;
65
66/// Supported drivers by the platform
67pub struct Platform {
68    console: &'static capsules_core::console::Console<'static>,
69    led: &'static capsules_core::led::LedDriver<
70        'static,
71        kernel::hil::led::LedLow<'static, nrf52840::gpio::GPIOPin<'static>>,
72        4,
73    >,
74    alarm: &'static AlarmDriver,
75    scheduler: &'static RoundRobinSched<'static>,
76    systick: cortexm4::systick::SysTick,
77}
78
79impl SyscallDriverLookup for Platform {
80    fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
81    where
82        F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R,
83    {
84        match driver_num {
85            capsules_core::console::DRIVER_NUM => f(Some(self.console)),
86            capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)),
87            capsules_core::led::DRIVER_NUM => f(Some(self.led)),
88            _ => f(None),
89        }
90    }
91}
92
93/// This is in a separate, inline(never) function so that its stack frame is
94/// removed when this function returns. Otherwise, the stack space used for
95/// these static_inits is wasted.
96#[inline(never)]
97unsafe fn create_peripherals() -> &'static mut Nrf52840DefaultPeripherals<'static> {
98    let ieee802154_ack_buf = static_init!(
99        [u8; nrf52840::ieee802154_radio::ACK_BUF_SIZE],
100        [0; nrf52840::ieee802154_radio::ACK_BUF_SIZE]
101    );
102    // Initialize chip peripheral drivers
103    let nrf52840_peripherals = static_init!(
104        Nrf52840DefaultPeripherals,
105        Nrf52840DefaultPeripherals::new(ieee802154_ack_buf)
106    );
107
108    nrf52840_peripherals
109}
110
111impl KernelResources<nrf52840::chip::NRF52<'static, Nrf52840DefaultPeripherals<'static>>>
112    for Platform
113{
114    type SyscallDriverLookup = Self;
115    type SyscallFilter = ();
116    type ProcessFault = ();
117    type Scheduler = RoundRobinSched<'static>;
118    type SchedulerTimer = cortexm4::systick::SysTick;
119    type WatchDog = ();
120    type ContextSwitchCallback = ();
121
122    fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
123        self
124    }
125    fn syscall_filter(&self) -> &Self::SyscallFilter {
126        &()
127    }
128    fn process_fault(&self) -> &Self::ProcessFault {
129        &()
130    }
131    fn scheduler(&self) -> &Self::Scheduler {
132        self.scheduler
133    }
134    fn scheduler_timer(&self) -> &Self::SchedulerTimer {
135        &self.systick
136    }
137    fn watchdog(&self) -> &Self::WatchDog {
138        &()
139    }
140    fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
141        &()
142    }
143}
144
145/// Main function called after RAM initialized.
146#[no_mangle]
147pub unsafe fn main() {
148    //--------------------------------------------------------------------------
149    // INITIAL SETUP
150    //--------------------------------------------------------------------------
151
152    // Apply errata fixes and enable interrupts.
153    nrf52840::init();
154
155    // Initialize deferred calls very early.
156    kernel::deferred_call::initialize_deferred_call_state::<
157        <ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider,
158    >();
159
160    // Set up peripheral drivers. Called in separate function to reduce stack
161    // usage.
162    let nrf52840_peripherals = create_peripherals();
163
164    // Set up circular peripheral dependencies.
165    nrf52840_peripherals.init();
166    let base_peripherals = &nrf52840_peripherals.nrf52;
167
168    // Choose the channel for serial output. This board can be configured to use
169    // either the Segger RTT channel or via UART with traditional TX/RX GPIO
170    // pins.
171    let uart_channel = UartChannel::Pins(UartPins::new(UART_RTS, UART_TXD, UART_CTS, UART_RXD));
172
173    // Create an array to hold process references.
174    let processes = components::process_array::ProcessArrayComponent::new()
175        .finalize(components::process_array_component_static!(NUM_PROCS));
176
177    // Setup space to store the core kernel data structure.
178    let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(processes.as_slice()));
179
180    // Create (and save for panic debugging) a chip object to setup low-level
181    // resources (e.g. MPU, systick).
182    let chip = static_init!(
183        nrf52840::chip::NRF52<Nrf52840DefaultPeripherals>,
184        nrf52840::chip::NRF52::new(nrf52840_peripherals)
185    );
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}