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// Disable this attribute when documenting, as a workaround for
9// https://github.com/rust-lang/rust/issues/62184.
10#![cfg_attr(not(doc), no_main)]
11#![deny(missing_docs)]
12
13use core::ptr::{addr_of, addr_of_mut};
14
15use kernel::component::Component;
16use kernel::deferred_call::DeferredCallClient;
17use kernel::hil::led::LedLow;
18use kernel::hil::time::Counter;
19use kernel::platform::{KernelResources, SyscallDriverLookup};
20use kernel::scheduler::round_robin::RoundRobinSched;
21use kernel::{capabilities, create_capability, static_init};
22use nrf52840::gpio::Pin;
23use nrf52840::interrupt_service::Nrf52840DefaultPeripherals;
24use nrf52_components::{UartChannel, UartPins};
25
26// The nRF52840DK LEDs (see back of board)
27const LED1_PIN: Pin = Pin::P0_13;
28const LED2_PIN: Pin = Pin::P0_14;
29const LED3_PIN: Pin = Pin::P0_15;
30const LED4_PIN: Pin = Pin::P0_16;
31
32const BUTTON_RST_PIN: Pin = Pin::P0_18;
33
34const UART_RTS: Option<Pin> = Some(Pin::P0_05);
35const UART_TXD: Pin = Pin::P0_06;
36const UART_CTS: Option<Pin> = Some(Pin::P0_07);
37const UART_RXD: Pin = Pin::P0_08;
38
39/// Debug Writer
40pub mod io;
41
42// State for loading and holding applications.
43// How should the kernel respond when a process faults.
44const FAULT_RESPONSE: capsules_system::process_policies::PanicFaultPolicy =
45    capsules_system::process_policies::PanicFaultPolicy {};
46
47// Number of concurrent processes this platform supports.
48const NUM_PROCS: usize = 8;
49
50static mut PROCESSES: [Option<&'static dyn kernel::process::Process>; NUM_PROCS] =
51    [None; NUM_PROCS];
52
53static mut CHIP: Option<&'static nrf52840::chip::NRF52<Nrf52840DefaultPeripherals>> = None;
54
55/// Dummy buffer that causes the linker to reserve enough space for the stack.
56#[no_mangle]
57#[link_section = ".stack_buffer"]
58pub static mut STACK_MEMORY: [u8; 0x2000] = [0; 0x2000];
59
60//------------------------------------------------------------------------------
61// SYSCALL DRIVER TYPE DEFINITIONS
62//------------------------------------------------------------------------------
63
64type AlarmDriver = components::alarm::AlarmDriverComponentType<nrf52840::rtc::Rtc<'static>>;
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    // Set up peripheral drivers. Called in separate function to reduce stack
156    // usage.
157    let nrf52840_peripherals = create_peripherals();
158
159    // Set up circular peripheral dependencies.
160    nrf52840_peripherals.init();
161    let base_peripherals = &nrf52840_peripherals.nrf52;
162
163    // Choose the channel for serial output. This board can be configured to use
164    // either the Segger RTT channel or via UART with traditional TX/RX GPIO
165    // pins.
166    let uart_channel = UartChannel::Pins(UartPins::new(UART_RTS, UART_TXD, UART_CTS, UART_RXD));
167
168    // Setup space to store the core kernel data structure.
169    let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(&*addr_of!(PROCESSES)));
170
171    // Create (and save for panic debugging) a chip object to setup low-level
172    // resources (e.g. MPU, systick).
173    let chip = static_init!(
174        nrf52840::chip::NRF52<Nrf52840DefaultPeripherals>,
175        nrf52840::chip::NRF52::new(nrf52840_peripherals)
176    );
177    CHIP = Some(chip);
178
179    // Do nRF configuration and setup. This is shared code with other nRF-based
180    // platforms.
181    nrf52_components::startup::NrfStartupComponent::new(
182        false,
183        BUTTON_RST_PIN,
184        nrf52840::uicr::Regulator0Output::DEFAULT,
185        &base_peripherals.nvmc,
186    )
187    .finalize(());
188
189    //--------------------------------------------------------------------------
190    // CAPABILITIES
191    //--------------------------------------------------------------------------
192
193    // Create capabilities that the board needs to call certain protected kernel
194    // functions.
195    let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
196
197    //--------------------------------------------------------------------------
198    // LEDs
199    //--------------------------------------------------------------------------
200
201    let led = components::led::LedsComponent::new().finalize(components::led_component_static!(
202        LedLow<'static, nrf52840::gpio::GPIOPin>,
203        LedLow::new(&nrf52840_peripherals.gpio_port[LED1_PIN]),
204        LedLow::new(&nrf52840_peripherals.gpio_port[LED2_PIN]),
205        LedLow::new(&nrf52840_peripherals.gpio_port[LED3_PIN]),
206        LedLow::new(&nrf52840_peripherals.gpio_port[LED4_PIN]),
207    ));
208
209    //--------------------------------------------------------------------------
210    // TIMER
211    //--------------------------------------------------------------------------
212
213    let rtc = &base_peripherals.rtc;
214    let _ = rtc.start();
215    let mux_alarm = components::alarm::AlarmMuxComponent::new(rtc)
216        .finalize(components::alarm_mux_component_static!(nrf52840::rtc::Rtc));
217    let alarm = components::alarm::AlarmDriverComponent::new(
218        board_kernel,
219        capsules_core::alarm::DRIVER_NUM,
220        mux_alarm,
221    )
222    .finalize(components::alarm_component_static!(nrf52840::rtc::Rtc));
223
224    //--------------------------------------------------------------------------
225    // UART & CONSOLE & DEBUG
226    //--------------------------------------------------------------------------
227
228    let uart_channel = nrf52_components::UartChannelComponent::new(
229        uart_channel,
230        mux_alarm,
231        &base_peripherals.uarte0,
232    )
233    .finalize(nrf52_components::uart_channel_component_static!(
234        nrf52840::rtc::Rtc
235    ));
236
237    // Virtualize the UART channel for the console and for kernel debug.
238    let uart_mux = components::console::UartMuxComponent::new(uart_channel, 115200)
239        .finalize(components::uart_mux_component_static!());
240
241    // Setup the serial console for userspace.
242    let console = components::console::ConsoleComponent::new(
243        board_kernel,
244        capsules_core::console::DRIVER_NUM,
245        uart_mux,
246    )
247    .finalize(components::console_component_static!());
248
249    //--------------------------------------------------------------------------
250    // NRF CLOCK SETUP
251    //--------------------------------------------------------------------------
252
253    nrf52_components::NrfClockComponent::new(&base_peripherals.clock).finalize(());
254
255    //--------------------------------------------------------------------------
256    // Credential Checking
257    //--------------------------------------------------------------------------
258
259    // Create the software-based SHA engine.
260    let sha = components::sha::ShaSoftware256Component::new()
261        .finalize(components::sha_software_256_component_static!());
262
263    // Create the credential checker.
264    //
265    // Setup an example key.
266    //
267    // - `ec-secp256r1-priv-key.pem`:
268    //   ```
269    //   -----BEGIN EC PRIVATE KEY-----
270    //   MHcCAQEEIGU0zCXHLqxDmrHHAWEQP5zNfWRQrAiIpH9YwxHlqysmoAoGCCqGSM49
271    //   AwEHoUQDQgAE4BM6kKdKNWFRjuFECfFpwc9q239+Uvi3QXniTVdBI1IuthIDs4UQ
272    //   5fMlB2KPVJWCV0VQvaPiF+g0MIkmTCNisQ==
273    //   -----END EC PRIVATE KEY-----
274    //   ```
275    //
276    // - `ec-secp256r1-pub-key.pem`:
277    //   ```
278    //   -----BEGIN PUBLIC KEY-----
279    //   MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE4BM6kKdKNWFRjuFECfFpwc9q239+
280    //   Uvi3QXniTVdBI1IuthIDs4UQ5fMlB2KPVJWCV0VQvaPiF+g0MIkmTCNisQ==
281    //   -----END PUBLIC KEY-----
282    //   ```
283    //
284    // You can add the correct signature to a TBF by saving the private key to
285    // a file and then running:
286    //
287    //     tockloader tbf credential add ecdsap256 --private-key ec-secp256r1-priv-key.pem
288    //
289    let verifying_key = kernel::static_init!(
290        [u8; 64],
291        [
292            0xe0, 0x13, 0x3a, 0x90, 0xa7, 0x4a, 0x35, 0x61, 0x51, 0x8e, 0xe1, 0x44, 0x09, 0xf1,
293            0x69, 0xc1, 0xcf, 0x6a, 0xdb, 0x7f, 0x7e, 0x52, 0xf8, 0xb7, 0x41, 0x79, 0xe2, 0x4d,
294            0x57, 0x41, 0x23, 0x52, 0x2e, 0xb6, 0x12, 0x03, 0xb3, 0x85, 0x10, 0xe5, 0xf3, 0x25,
295            0x07, 0x62, 0x8f, 0x54, 0x95, 0x82, 0x57, 0x45, 0x50, 0xbd, 0xa3, 0xe2, 0x17, 0xe8,
296            0x34, 0x30, 0x89, 0x26, 0x4c, 0x23, 0x62, 0xb1
297        ]
298    );
299
300    // Setup the ECDSA-P256 verifier.
301    let ecdsa_p256_verifier = kernel::static_init!(
302        ecdsa_sw::p256_verifier::EcdsaP256SignatureVerifier<'static>,
303        ecdsa_sw::p256_verifier::EcdsaP256SignatureVerifier::new(verifying_key)
304    );
305    ecdsa_p256_verifier.register();
306
307    // Policy checks for a valid EcdsaNistP256 signature.
308    let checking_policy = components::appid::checker_signature::AppCheckerSignatureComponent::new(
309        sha,
310        ecdsa_p256_verifier,
311        tock_tbf::types::TbfFooterV2CredentialsType::EcdsaNistP256,
312    )
313    .finalize(components::app_checker_signature_component_static!(
314        ecdsa_sw::p256_verifier::EcdsaP256SignatureVerifier<'static>,
315        capsules_extra::sha256::Sha256Software<'static>,
316        32,
317        64,
318    ));
319
320    // Create the AppID assigner.
321    let assigner = components::appid::assigner_name::AppIdAssignerNamesComponent::new()
322        .finalize(components::appid_assigner_names_component_static!());
323
324    // Create the process checking machine.
325    let checker = components::appid::checker::ProcessCheckerMachineComponent::new(checking_policy)
326        .finalize(components::process_checker_machine_component_static!());
327
328    //--------------------------------------------------------------------------
329    // STORAGE PERMISSIONS
330    //--------------------------------------------------------------------------
331
332    let storage_permissions_policy =
333        components::storage_permissions::null::StoragePermissionsNullComponent::new().finalize(
334            components::storage_permissions_null_component_static!(
335                nrf52840::chip::NRF52<Nrf52840DefaultPeripherals>,
336                kernel::process::ProcessStandardDebugFull,
337            ),
338        );
339
340    //--------------------------------------------------------------------------
341    // PROCESS LOADING
342    //--------------------------------------------------------------------------
343
344    // Create and start the asynchronous process loader.
345    let _loader = components::loader::sequential::ProcessLoaderSequentialComponent::new(
346        checker,
347        &mut *addr_of_mut!(PROCESSES),
348        board_kernel,
349        chip,
350        &FAULT_RESPONSE,
351        assigner,
352        storage_permissions_policy,
353    )
354    .finalize(components::process_loader_sequential_component_static!(
355        nrf52840::chip::NRF52<Nrf52840DefaultPeripherals>,
356        kernel::process::ProcessStandardDebugFull,
357        NUM_PROCS
358    ));
359
360    //--------------------------------------------------------------------------
361    // PLATFORM SETUP, SCHEDULER, AND START KERNEL LOOP
362    //--------------------------------------------------------------------------
363
364    let scheduler = components::sched::round_robin::RoundRobinComponent::new(&*addr_of!(PROCESSES))
365        .finalize(components::round_robin_component_static!(NUM_PROCS));
366
367    let platform = Platform {
368        console,
369        led,
370        alarm,
371        scheduler,
372        systick: cortexm4::systick::SysTick::new_with_calibration(64000000),
373    };
374
375    board_kernel.kernel_loop(
376        &platform,
377        chip,
378        None::<&kernel::ipc::IPC<0>>,
379        &main_loop_capability,
380    );
381}