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