aboutsummaryrefslogtreecommitdiff
path: root/embassy-nrf/src/cracen.rs
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-nrf/src/cracen.rs')
-rw-r--r--embassy-nrf/src/cracen.rs149
1 files changed, 149 insertions, 0 deletions
diff --git a/embassy-nrf/src/cracen.rs b/embassy-nrf/src/cracen.rs
new file mode 100644
index 000000000..6381701c0
--- /dev/null
+++ b/embassy-nrf/src/cracen.rs
@@ -0,0 +1,149 @@
1//! CRACEN - Cryptographic Accelerator Engine driver.
2
3#![macro_use]
4
5use core::marker::PhantomData;
6
7use crate::mode::{Blocking, Mode};
8use crate::{Peri, interrupt, pac, peripherals};
9
10/// A wrapper around an nRF54 CRACEN peripheral.
11///
12/// It has a blocking api through `rand`.
13pub struct Cracen<'d, M: Mode> {
14 _peri: Peri<'d, peripherals::CRACEN>,
15 _p: PhantomData<M>,
16}
17
18impl<'d> Cracen<'d, Blocking> {
19 /// Create a new CRACEN driver.
20 pub fn new_blocking(_peri: Peri<'d, peripherals::CRACEN>) -> Self {
21 Self { _peri, _p: PhantomData }
22 }
23}
24
25impl<'d, M: Mode> Cracen<'d, M> {
26 fn regs() -> pac::cracen::Cracen {
27 pac::CRACEN
28 }
29
30 fn core() -> pac::cracencore::Cracencore {
31 pac::CRACENCORE
32 }
33
34 fn start_rng(&self) {
35 let r = Self::regs();
36 r.enable().write(|w| {
37 w.set_rng(true);
38 });
39
40 let r = Self::core();
41 r.rngcontrol().control().write(|w| {
42 w.set_enable(true);
43 });
44
45 while r.rngcontrol().status().read().state() == pac::cracencore::vals::State::STARTUP {}
46 }
47
48 fn stop_rng(&self) {
49 let r = Self::core();
50 r.rngcontrol().control().write(|w| {
51 w.set_enable(false);
52 });
53
54 while r.rngcontrol().status().read().state() != pac::cracencore::vals::State::RESET {}
55
56 let r = Self::regs();
57 r.enable().write(|w| {
58 w.set_cryptomaster(false);
59 w.set_rng(false);
60 w.set_pkeikg(false);
61 });
62 }
63
64 /// Fill the buffer with random bytes, blocking version.
65 pub fn blocking_fill_bytes(&mut self, dest: &mut [u8]) {
66 self.start_rng();
67
68 let r = Self::core();
69 for chunk in dest.chunks_mut(4) {
70 while r.rngcontrol().fifolevel().read() == 0 {}
71 let word = r.rngcontrol().fifo(0).read().to_ne_bytes();
72 let to_copy = word.len().min(chunk.len());
73 chunk[..to_copy].copy_from_slice(&word[..to_copy]);
74 }
75
76 self.stop_rng();
77 }
78
79 /// Generate a random u32
80 pub fn blocking_next_u32(&mut self) -> u32 {
81 let mut bytes = [0; 4];
82 self.blocking_fill_bytes(&mut bytes);
83 // We don't care about the endianness, so just use the native one.
84 u32::from_ne_bytes(bytes)
85 }
86
87 /// Generate a random u64
88 pub fn blocking_next_u64(&mut self) -> u64 {
89 let mut bytes = [0; 8];
90 self.blocking_fill_bytes(&mut bytes);
91 u64::from_ne_bytes(bytes)
92 }
93}
94
95impl<'d, M: Mode> Drop for Cracen<'d, M> {
96 fn drop(&mut self) {
97 // nothing to do here, since we stop+disable rng for each operation.
98 }
99}
100
101impl<'d, M: Mode> rand_core_06::RngCore for Cracen<'d, M> {
102 fn fill_bytes(&mut self, dest: &mut [u8]) {
103 self.blocking_fill_bytes(dest);
104 }
105 fn next_u32(&mut self) -> u32 {
106 self.blocking_next_u32()
107 }
108 fn next_u64(&mut self) -> u64 {
109 self.blocking_next_u64()
110 }
111 fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core_06::Error> {
112 self.blocking_fill_bytes(dest);
113 Ok(())
114 }
115}
116
117impl<'d, M: Mode> rand_core_06::CryptoRng for Cracen<'d, M> {}
118
119impl<'d, M: Mode> rand_core_09::RngCore for Cracen<'d, M> {
120 fn fill_bytes(&mut self, dest: &mut [u8]) {
121 self.blocking_fill_bytes(dest);
122 }
123 fn next_u32(&mut self) -> u32 {
124 self.blocking_next_u32()
125 }
126 fn next_u64(&mut self) -> u64 {
127 self.blocking_next_u64()
128 }
129}
130
131impl<'d, M: Mode> rand_core_09::CryptoRng for Cracen<'d, M> {}
132
133pub(crate) trait SealedInstance {}
134
135/// CRACEN peripheral instance.
136#[allow(private_bounds)]
137pub trait Instance: SealedInstance + 'static + Send {
138 /// Interrupt for this peripheral.
139 type Interrupt: interrupt::typelevel::Interrupt;
140}
141
142macro_rules! impl_cracen {
143 ($type:ident, $pac_type:ident, $irq:ident) => {
144 impl crate::cracen::SealedInstance for peripherals::$type {}
145 impl crate::cracen::Instance for peripherals::$type {
146 type Interrupt = crate::interrupt::typelevel::$irq;
147 }
148 };
149}