diff options
| author | Ulf Lilleengen <[email protected]> | 2025-11-04 13:10:45 +0100 |
|---|---|---|
| committer | Ulf Lilleengen <[email protected]> | 2025-11-04 13:13:22 +0100 |
| commit | 729a7c2cc5e5fe1d9badb0a0f1c758ba2c57b6aa (patch) | |
| tree | 967f9fcb91f33b80fa7decc25a0c948927d607c0 /embassy-nrf/src | |
| parent | 18a5872a2586335496aec056e24edacef6fd76cb (diff) | |
feat: initial support for nrf54 CRACEN peripheral
The CRACEN peripheral supports random number generation,
digest and key generation, and key exchange.
The initial support implements random number generation.
Diffstat (limited to 'embassy-nrf/src')
| -rw-r--r-- | embassy-nrf/src/chips/nrf54l15_app.rs | 2 | ||||
| -rw-r--r-- | embassy-nrf/src/cracen.rs | 161 | ||||
| -rw-r--r-- | embassy-nrf/src/lib.rs | 4 |
3 files changed, 166 insertions, 1 deletions
diff --git a/embassy-nrf/src/chips/nrf54l15_app.rs b/embassy-nrf/src/chips/nrf54l15_app.rs index d0068eb20..285cdec07 100644 --- a/embassy-nrf/src/chips/nrf54l15_app.rs +++ b/embassy-nrf/src/chips/nrf54l15_app.rs | |||
| @@ -682,6 +682,8 @@ impl_saadc_input!(P1_12, 1, 12); | |||
| 682 | impl_saadc_input!(P1_13, 1, 13); | 682 | impl_saadc_input!(P1_13, 1, 13); |
| 683 | impl_saadc_input!(P1_14, 1, 14); | 683 | impl_saadc_input!(P1_14, 1, 14); |
| 684 | 684 | ||
| 685 | impl_cracen!(CRACEN, CRACEN, CRACEN); | ||
| 686 | |||
| 685 | embassy_hal_internal::interrupt_mod!( | 687 | embassy_hal_internal::interrupt_mod!( |
| 686 | SWI00, | 688 | SWI00, |
| 687 | SWI01, | 689 | SWI01, |
diff --git a/embassy-nrf/src/cracen.rs b/embassy-nrf/src/cracen.rs new file mode 100644 index 000000000..ddc592689 --- /dev/null +++ b/embassy-nrf/src/cracen.rs | |||
| @@ -0,0 +1,161 @@ | |||
| 1 | //! CRACEN - Cryptographic Accelerator Engine driver. | ||
| 2 | |||
| 3 | #![macro_use] | ||
| 4 | |||
| 5 | use crate::mode::{Async, Blocking, Mode}; | ||
| 6 | use crate::{Peri, interrupt, pac, peripherals}; | ||
| 7 | use core::marker::PhantomData; | ||
| 8 | |||
| 9 | pub struct Cracen<'d, M: Mode> { | ||
| 10 | _peri: Peri<'d, peripherals::CRACEN>, | ||
| 11 | _p: PhantomData<M>, | ||
| 12 | } | ||
| 13 | |||
| 14 | impl<'d> Cracen<'d, Blocking> { | ||
| 15 | /// Create a new CRACEN driver. | ||
| 16 | pub fn new_blocking(_peri: Peri<'d, peripherals::CRACEN>) -> Self { | ||
| 17 | let r = pac::CRACEN; | ||
| 18 | |||
| 19 | let me = Self { _peri, _p: PhantomData }; | ||
| 20 | |||
| 21 | me.stop(); | ||
| 22 | me | ||
| 23 | } | ||
| 24 | } | ||
| 25 | |||
| 26 | impl<'d, M: Mode> Cracen<'d, M> { | ||
| 27 | fn regs() -> pac::cracen::Cracen { | ||
| 28 | pac::CRACEN | ||
| 29 | } | ||
| 30 | |||
| 31 | fn core() -> pac::cracencore::Cracencore { | ||
| 32 | pac::CRACENCORE | ||
| 33 | } | ||
| 34 | |||
| 35 | fn start_rng(&self) { | ||
| 36 | let r = Self::regs(); | ||
| 37 | r.enable().write(|w| { | ||
| 38 | w.set_rng(true); | ||
| 39 | }); | ||
| 40 | |||
| 41 | let r = Self::core(); | ||
| 42 | r.rngcontrol().control().write(|w| { | ||
| 43 | w.set_enable(true); | ||
| 44 | }); | ||
| 45 | |||
| 46 | while r.rngcontrol().status().read().state() == pac::cracencore::vals::State::STARTUP {} | ||
| 47 | } | ||
| 48 | |||
| 49 | fn stop(&self) { | ||
| 50 | let r = Self::regs(); | ||
| 51 | r.enable().write(|w| { | ||
| 52 | w.set_cryptomaster(false); | ||
| 53 | w.set_rng(false); | ||
| 54 | w.set_pkeikg(false); | ||
| 55 | }); | ||
| 56 | } | ||
| 57 | |||
| 58 | /// Fill the buffer with random bytes, blocking version. | ||
| 59 | pub fn blocking_fill_bytes(&mut self, dest: &mut [u8]) { | ||
| 60 | self.start_rng(); | ||
| 61 | |||
| 62 | let r = Self::core(); | ||
| 63 | for chunk in dest.chunks_mut(4) { | ||
| 64 | while r.rngcontrol().fifolevel().read() == 0 {} | ||
| 65 | let word = r.rngcontrol().fifo(0).read().to_ne_bytes(); | ||
| 66 | let to_copy = word.len().min(chunk.len()); | ||
| 67 | chunk[..to_copy].copy_from_slice(&word[..to_copy]); | ||
| 68 | } | ||
| 69 | |||
| 70 | self.stop(); | ||
| 71 | } | ||
| 72 | |||
| 73 | /// Generate a random u32 | ||
| 74 | pub fn blocking_next_u32(&mut self) -> u32 { | ||
| 75 | let mut bytes = [0; 4]; | ||
| 76 | self.blocking_fill_bytes(&mut bytes); | ||
| 77 | // We don't care about the endianness, so just use the native one. | ||
| 78 | u32::from_ne_bytes(bytes) | ||
| 79 | } | ||
| 80 | |||
| 81 | /// Generate a random u64 | ||
| 82 | pub fn blocking_next_u64(&mut self) -> u64 { | ||
| 83 | let mut bytes = [0; 8]; | ||
| 84 | self.blocking_fill_bytes(&mut bytes); | ||
| 85 | u64::from_ne_bytes(bytes) | ||
| 86 | } | ||
| 87 | } | ||
| 88 | |||
| 89 | impl<'d, M: Mode> Drop for Cracen<'d, M> { | ||
| 90 | fn drop(&mut self) { | ||
| 91 | let r = Self::core(); | ||
| 92 | r.rngcontrol().control().write(|w| { | ||
| 93 | w.set_enable(false); | ||
| 94 | }); | ||
| 95 | |||
| 96 | while r.rngcontrol().status().read().state() != pac::cracencore::vals::State::RESET {} | ||
| 97 | |||
| 98 | let r = Self::regs(); | ||
| 99 | r.enable().write(|w| { | ||
| 100 | w.set_cryptomaster(false); | ||
| 101 | w.set_rng(false); | ||
| 102 | w.set_pkeikg(false); | ||
| 103 | }); | ||
| 104 | } | ||
| 105 | } | ||
| 106 | |||
| 107 | impl<'d, M: Mode> rand_core_06::RngCore for Cracen<'d, M> { | ||
| 108 | fn fill_bytes(&mut self, dest: &mut [u8]) { | ||
| 109 | self.blocking_fill_bytes(dest); | ||
| 110 | } | ||
| 111 | fn next_u32(&mut self) -> u32 { | ||
| 112 | self.blocking_next_u32() | ||
| 113 | } | ||
| 114 | fn next_u64(&mut self) -> u64 { | ||
| 115 | self.blocking_next_u64() | ||
| 116 | } | ||
| 117 | fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core_06::Error> { | ||
| 118 | self.blocking_fill_bytes(dest); | ||
| 119 | Ok(()) | ||
| 120 | } | ||
| 121 | } | ||
| 122 | |||
| 123 | impl<'d, M: Mode> rand_core_06::CryptoRng for Cracen<'d, M> {} | ||
| 124 | |||
| 125 | impl<'d, M: Mode> rand_core_09::RngCore for Cracen<'d, M> { | ||
| 126 | fn fill_bytes(&mut self, dest: &mut [u8]) { | ||
| 127 | self.blocking_fill_bytes(dest); | ||
| 128 | } | ||
| 129 | fn next_u32(&mut self) -> u32 { | ||
| 130 | self.blocking_next_u32() | ||
| 131 | } | ||
| 132 | fn next_u64(&mut self) -> u64 { | ||
| 133 | self.blocking_next_u64() | ||
| 134 | } | ||
| 135 | } | ||
| 136 | |||
| 137 | impl<'d, M: Mode> rand_core_09::CryptoRng for Cracen<'d, M> {} | ||
| 138 | |||
| 139 | pub(crate) trait SealedInstance { | ||
| 140 | fn regs() -> pac::cracen::Cracen; | ||
| 141 | } | ||
| 142 | |||
| 143 | /// CRACEN peripheral instance. | ||
| 144 | #[allow(private_bounds)] | ||
| 145 | pub trait Instance: SealedInstance + 'static + Send { | ||
| 146 | /// Interrupt for this peripheral. | ||
| 147 | type Interrupt: interrupt::typelevel::Interrupt; | ||
| 148 | } | ||
| 149 | |||
| 150 | macro_rules! impl_cracen { | ||
| 151 | ($type:ident, $pac_type:ident, $irq:ident) => { | ||
| 152 | impl crate::cracen::SealedInstance for peripherals::$type { | ||
| 153 | fn regs() -> crate::pac::cracen::Cracen { | ||
| 154 | pac::$pac_type | ||
| 155 | } | ||
| 156 | } | ||
| 157 | impl crate::cracen::Instance for peripherals::$type { | ||
| 158 | type Interrupt = crate::interrupt::typelevel::$irq; | ||
| 159 | } | ||
| 160 | }; | ||
| 161 | } | ||
diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs index 4c3b92a83..530964107 100644 --- a/embassy-nrf/src/lib.rs +++ b/embassy-nrf/src/lib.rs | |||
| @@ -145,10 +145,12 @@ pub mod radio; | |||
| 145 | #[cfg(feature = "_net-driver")] | 145 | #[cfg(feature = "_net-driver")] |
| 146 | pub mod embassy_net_802154_driver; | 146 | pub mod embassy_net_802154_driver; |
| 147 | 147 | ||
| 148 | #[cfg(feature = "_nrf54l")] | ||
| 149 | pub mod cracen; | ||
| 148 | #[cfg(not(feature = "_nrf54l"))] // TODO | 150 | #[cfg(not(feature = "_nrf54l"))] // TODO |
| 149 | #[cfg(feature = "_nrf5340")] | 151 | #[cfg(feature = "_nrf5340")] |
| 150 | pub mod reset; | 152 | pub mod reset; |
| 151 | #[cfg(not(feature = "_nrf54l"))] // TODO | 153 | #[cfg(not(feature = "_nrf54l"))] |
| 152 | #[cfg(not(any(feature = "_nrf5340-app", feature = "_nrf91")))] | 154 | #[cfg(not(any(feature = "_nrf5340-app", feature = "_nrf91")))] |
| 153 | pub mod rng; | 155 | pub mod rng; |
| 154 | pub mod rtc; | 156 | pub mod rtc; |
