aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src/cryp
diff options
context:
space:
mode:
authorCaleb Garrett <[email protected]>2024-02-13 10:11:54 -0500
committerCaleb Garrett <[email protected]>2024-02-25 20:59:07 -0500
commit79e5e8b052b56f8c6fc07d8407fcfc3aaf39bab3 (patch)
tree98f03f8a822eae52fb16ffba7eb5beb8af9a66b3 /embassy-stm32/src/cryp
parentfd5058875ad5bda90de9603abe28a1b6134b5a51 (diff)
Add cryp configuration.
Diffstat (limited to 'embassy-stm32/src/cryp')
-rw-r--r--embassy-stm32/src/cryp/mod.rs227
1 files changed, 227 insertions, 0 deletions
diff --git a/embassy-stm32/src/cryp/mod.rs b/embassy-stm32/src/cryp/mod.rs
new file mode 100644
index 000000000..dedc6ddc5
--- /dev/null
+++ b/embassy-stm32/src/cryp/mod.rs
@@ -0,0 +1,227 @@
1use embassy_hal_internal::{into_ref, PeripheralRef};
2use pac::cryp::Init;
3
4use crate::pac;
5use crate::peripherals::CRYP;
6use crate::rcc::sealed::RccPeripheral;
7use crate::{interrupt, peripherals, Peripheral};
8
9pub struct Context<'c> {
10 key: &'c [u8],
11}
12
13#[derive(PartialEq)]
14pub enum Algorithm {
15 AES,
16 DES,
17 TDES,
18}
19
20#[derive(PartialEq)]
21pub enum Mode {
22 ECB,
23 CBC,
24 CTR,
25 GCM,
26 GMAC,
27 CCM,
28}
29
30#[derive(PartialEq)]
31pub enum Direction {
32 Encrypt,
33 Decrypt,
34}
35
36/// Crypto Accelerator Driver
37pub struct Cryp<'d, T: Instance, In, Out> {
38 _peripheral: PeripheralRef<'d, T>,
39 indma: PeripheralRef<'d, In>,
40 outdma: PeripheralRef<'d, Out>,
41}
42
43type InitVector<'v> = Option<&'v [u8]>;
44
45impl<'d, T: Instance, In, Out> Cryp<'d, T, In, Out> {
46 /// Create a new CRYP driver.
47 pub fn new(
48 peri: impl Peripheral<P = T> + 'd,
49 indma: impl Peripheral<P = In> + 'd,
50 outdma: impl Peripheral<P = Out> + 'd,
51 ) -> Self {
52 CRYP::enable_and_reset();
53 into_ref!(peri, indma, outdma);
54 let instance = Self {
55 _peripheral: peri,
56 indma: indma,
57 outdma: outdma,
58 };
59 instance
60 }
61
62 /// Start a new cipher operation.
63 /// Key size must be 128, 192, or 256 bits.
64 pub fn start(key: &[u8], iv: InitVector, algo: Algorithm, mode: Mode, dir: Direction) -> Context {
65 T::regs().cr().modify(|w| w.set_crypen(false));
66
67 let keylen = key.len() * 8;
68 let ivlen;
69 if let Some(iv) = iv {
70 ivlen = iv.len() * 8;
71 } else {
72 ivlen = 0;
73 }
74
75 // Checks for correctness
76 if algo == Algorithm::AES {
77 match keylen {
78 128 => T::regs().cr().write(|w| w.set_keysize(0)),
79 192 => T::regs().cr().write(|w| w.set_keysize(1)),
80 256 => T::regs().cr().write(|w| w.set_keysize(2)),
81 _ => panic!("Key length must be 128, 192, or 256 bits."),
82 }
83
84 if (mode == Mode::GCM) && (ivlen != 96) {
85 panic!("IV length must be 96 bits for GCM.");
86 } else if (mode == Mode::CBC) && (ivlen != 128) {
87 panic!("IV length must be 128 bits for CBC.");
88 } else if (mode == Mode::CCM) && (ivlen != 128) {
89 panic!("IV length must be 128 bits for CCM.");
90 } else if (mode == Mode::CTR) && (ivlen != 64) {
91 panic!("IV length must be 64 bits for CTR.");
92 } else if (mode == Mode::GCM) && (ivlen != 96) {
93 panic!("IV length must be 96 bits for GCM.");
94 } else if (mode == Mode::GMAC) && (ivlen != 96) {
95 panic!("IV length must be 96 bits for GMAC.");
96 }
97 }
98
99 // Load the key into the registers.
100 let mut keyidx = 0;
101 let mut keyword: [u8; 4] = [0; 4];
102 if keylen > 192 {
103 keyword.copy_from_slice(&key[keyidx..keyidx + 4]);
104 keyidx += 4;
105 T::regs().key(0).klr().write_value(u32::from_be_bytes(keyword));
106 keyword.copy_from_slice(&key[keyidx..keyidx + 4]);
107 keyidx += 4;
108 T::regs().key(0).krr().write_value(u32::from_be_bytes(keyword));
109 }
110 if keylen > 128 {
111 keyword.copy_from_slice(&key[keyidx..keyidx + 4]);
112 keyidx += 4;
113 T::regs().key(1).klr().write_value(u32::from_be_bytes(keyword));
114 keyword.copy_from_slice(&key[keyidx..keyidx + 4]);
115 keyidx += 4;
116 T::regs().key(1).krr().write_value(u32::from_be_bytes(keyword));
117 }
118 if keylen > 64 {
119 keyword.copy_from_slice(&key[keyidx..keyidx + 4]);
120 keyidx += 4;
121 T::regs().key(2).klr().write_value(u32::from_be_bytes(keyword));
122 keyword.copy_from_slice(&key[keyidx..keyidx + 4]);
123 keyidx += 4;
124 T::regs().key(2).krr().write_value(u32::from_be_bytes(keyword));
125 }
126 keyword.copy_from_slice(&key[keyidx..keyidx + 4]);
127 keyidx += 4;
128 T::regs().key(3).klr().write_value(u32::from_be_bytes(keyword));
129 keyword.copy_from_slice(&key[keyidx..keyidx + 4]);
130 T::regs().key(3).krr().write_value(u32::from_be_bytes(keyword));
131
132 // Set data type to 8-bit. This will match software implementations.
133 T::regs().cr().modify(|w| w.set_datatype(2));
134
135 if algo == Algorithm::AES {
136 if (mode == Mode::ECB) || (mode == Mode::CBC) {
137 T::regs().cr().modify(|w| w.set_algomode0(7));
138 T::regs().cr().modify(|w| w.set_crypen(true));
139 while T::regs().sr().read().busy() {}
140 }
141
142 match mode {
143 Mode::ECB => T::regs().cr().modify(|w| w.set_algomode0(4)),
144 Mode::CBC => T::regs().cr().modify(|w| w.set_algomode0(5)),
145 Mode::CTR => T::regs().cr().modify(|w| w.set_algomode0(6)),
146 Mode::GCM => T::regs().cr().modify(|w| w.set_algomode0(8)),
147 Mode::GMAC => T::regs().cr().modify(|w| w.set_algomode0(8)),
148 Mode::CCM => T::regs().cr().modify(|w| w.set_algomode0(9)),
149 }
150 } else if algo == Algorithm::DES {
151 match mode {
152 Mode::ECB => T::regs().cr().modify(|w| w.set_algomode0(2)),
153 Mode::CBC => T::regs().cr().modify(|w| w.set_algomode0(3)),
154 _ => panic!("Only ECB and CBC modes are valid for DES."),
155 }
156 } else if algo == Algorithm::TDES {
157 match mode {
158 Mode::ECB => T::regs().cr().modify(|w| w.set_algomode0(0)),
159 Mode::CBC => T::regs().cr().modify(|w| w.set_algomode0(1)),
160 _ => panic!("Only ECB and CBC modes are valid for TDES."),
161 }
162 }
163
164 // Set encrypt/decrypt
165 if dir == Direction::Encrypt {
166 T::regs().cr().modify(|w| w.set_algodir(false));
167 } else {
168 T::regs().cr().modify(|w| w.set_algodir(true));
169 }
170
171 // Load the IV into the registers.
172 if let Some(iv) = iv {
173 let mut iv_idx = 0;
174 let mut iv_word: [u8; 4] = [0; 4];
175 iv_word.copy_from_slice(&iv[iv_idx..iv_idx + 4]);
176 iv_idx += 4;
177 T::regs().init(0).ivlr().write_value(u32::from_be_bytes(iv_word));
178 iv_word.copy_from_slice(&iv[iv_idx..iv_idx + 4]);
179 iv_idx += 4;
180 if iv.len() >= 12 {
181 T::regs().init(0).ivrr().write_value(u32::from_be_bytes(iv_word));
182 iv_word.copy_from_slice(&iv[iv_idx..iv_idx + 4]);
183 iv_idx += 4;
184 }
185 if iv.len() >= 16 {
186 T::regs().init(1).ivlr().write_value(u32::from_be_bytes(iv_word));
187 iv_word.copy_from_slice(&iv[iv_idx..iv_idx + 4]);
188 T::regs().init(1).ivrr().write_value(u32::from_be_bytes(iv_word));
189 }
190 }
191
192 // Flush in/out FIFOs
193 T::regs().cr().modify(|w| w.fflush());
194
195 let ctx = Context { key: key };
196
197 ctx
198 }
199}
200
201pub(crate) mod sealed {
202 use super::*;
203
204 pub trait Instance {
205 fn regs() -> pac::cryp::Cryp;
206 }
207}
208
209/// RNG instance trait.
210pub trait Instance: sealed::Instance + Peripheral<P = Self> + crate::rcc::RccPeripheral + 'static + Send {
211 /// Interrupt for this RNG instance.
212 type Interrupt: interrupt::typelevel::Interrupt;
213}
214
215foreach_interrupt!(
216 ($inst:ident, rng, CRYP, GLOBAL, $irq:ident) => {
217 impl Instance for peripherals::$inst {
218 type Interrupt = crate::interrupt::typelevel::$irq;
219 }
220
221 impl sealed::Instance for peripherals::$inst {
222 fn regs() -> crate::pac::cryp::Cryp {
223 crate::pac::$inst
224 }
225 }
226 };
227);