1use core::{marker::PhantomData, ptr::copy_nonoverlapping};
25
26use crate::{
27 interrupt::InterruptHandler,
28 pac,
29 peripheral::{Peripheral, PeripheralRef},
30 peripherals::{Interrupt, RSA},
31 system::{Cpu, GenericPeripheralGuard, Peripheral as PeripheralEnable},
32 Async,
33 Blocking,
34};
35
36#[cfg_attr(esp32s2, path = "esp32sX.rs")]
37#[cfg_attr(esp32s3, path = "esp32sX.rs")]
38#[cfg_attr(esp32c3, path = "esp32cX.rs")]
39#[cfg_attr(esp32c6, path = "esp32cX.rs")]
40#[cfg_attr(esp32h2, path = "esp32cX.rs")]
41#[cfg_attr(esp32, path = "esp32.rs")]
42mod rsa_spec_impl;
43
44pub use rsa_spec_impl::operand_sizes;
45
46pub struct Rsa<'d, Dm: crate::DriverMode> {
48 rsa: PeripheralRef<'d, RSA>,
49 phantom: PhantomData<Dm>,
50 _guard: GenericPeripheralGuard<{ PeripheralEnable::Rsa as u8 }>,
51}
52
53impl<'d> Rsa<'d, Blocking> {
54 pub fn new(rsa: impl Peripheral<P = RSA> + 'd) -> Self {
58 Self::new_internal(rsa)
59 }
60
61 pub fn into_async(mut self) -> Rsa<'d, Async> {
63 self.set_interrupt_handler(asynch::rsa_interrupt_handler);
64 Rsa {
65 rsa: self.rsa,
66 phantom: PhantomData,
67 _guard: self._guard,
68 }
69 }
70
71 #[instability::unstable]
76 pub fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
77 for core in crate::system::Cpu::other() {
78 crate::interrupt::disable(core, Interrupt::RSA);
79 }
80 unsafe { crate::interrupt::bind_interrupt(Interrupt::RSA, handler.handler()) };
81 unwrap!(crate::interrupt::enable(Interrupt::RSA, handler.priority()));
82 }
83}
84
85impl crate::private::Sealed for Rsa<'_, Blocking> {}
86
87#[instability::unstable]
88impl crate::interrupt::InterruptConfigurable for Rsa<'_, Blocking> {
89 fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
90 self.set_interrupt_handler(handler);
91 }
92}
93
94impl<'d> Rsa<'d, Async> {
95 pub fn into_blocking(self) -> Rsa<'d, Blocking> {
97 crate::interrupt::disable(Cpu::current(), Interrupt::RSA);
98 Rsa {
99 rsa: self.rsa,
100 phantom: PhantomData,
101 _guard: self._guard,
102 }
103 }
104}
105
106impl<'d, Dm: crate::DriverMode> Rsa<'d, Dm> {
107 fn new_internal(rsa: impl Peripheral<P = RSA> + 'd) -> Self {
108 crate::into_ref!(rsa);
109
110 let guard = GenericPeripheralGuard::new();
111
112 Self {
113 rsa,
114 phantom: PhantomData,
115 _guard: guard,
116 }
117 }
118
119 fn regs(&self) -> &pac::rsa::RegisterBlock {
120 self.rsa.register_block()
121 }
122
123 fn write_operand_b<const N: usize>(&mut self, operand_b: &[u32; N]) {
124 unsafe { copy_nonoverlapping(operand_b.as_ptr(), self.regs().y_mem(0).as_ptr(), N) };
125 }
126
127 fn write_modulus<const N: usize>(&mut self, modulus: &[u32; N]) {
128 unsafe { copy_nonoverlapping(modulus.as_ptr(), self.regs().m_mem(0).as_ptr(), N) };
129 }
130
131 fn write_mprime(&mut self, m_prime: u32) {
132 self.regs().m_prime().write(|w| unsafe { w.bits(m_prime) });
133 }
134
135 fn write_operand_a<const N: usize>(&mut self, operand_a: &[u32; N]) {
136 unsafe { copy_nonoverlapping(operand_a.as_ptr(), self.regs().x_mem(0).as_ptr(), N) };
137 }
138
139 fn write_multi_operand_b<const N: usize>(&mut self, operand_b: &[u32; N]) {
140 unsafe { copy_nonoverlapping(operand_b.as_ptr(), self.regs().z_mem(0).as_ptr().add(N), N) };
141 }
142
143 fn write_r<const N: usize>(&mut self, r: &[u32; N]) {
144 unsafe { copy_nonoverlapping(r.as_ptr(), self.regs().z_mem(0).as_ptr(), N) };
145 }
146
147 fn read_out<const N: usize>(&self, outbuf: &mut [u32; N]) {
148 unsafe {
149 copy_nonoverlapping(
150 self.regs().z_mem(0).as_ptr() as *const u32,
151 outbuf.as_ptr() as *mut u32,
152 N,
153 );
154 }
155 }
156 fn wait_for_idle(&mut self) {
157 while !self.is_idle() {}
158 self.clear_interrupt();
159 }
160
161 fn read_results<const N: usize>(&mut self, outbuf: &mut [u32; N]) {
162 self.wait_for_idle();
163 self.read_out(outbuf);
164 }
165}
166
167pub trait RsaMode: crate::private::Sealed {
169 type InputType;
171}
172
173pub trait Multi: RsaMode {
175 type OutputType;
177}
178
179macro_rules! implement_op {
180 (($x:literal, multi)) => {
181 paste! {
182 #[doc = concat!($x, "-bit RSA operation.")]
183 pub struct [<Op $x>];
184
185 impl Multi for [<Op $x>] {
186 type OutputType = [u32; $x * 2 / 32];
187 }
188
189 impl crate::private::Sealed for [<Op $x>] {}
190
191 impl RsaMode for [<Op $x>] {
192 type InputType = [u32; $x / 32];
193 }
194 }
195 };
196
197 (($x:literal)) => {
198 paste! {
199 pub struct [<Op $x>];
201
202 impl crate::private::Sealed for [<Op $x>] {}
203
204 impl RsaMode for [<Op $x>] {
205 type InputType = [u32; $x / 32];
206 }
207 }
208 };
209
210 ($x:tt, $($y:tt),+) => {
211 implement_op!($x);
212 implement_op!($($y),+);
213 };
214}
215
216use implement_op;
217
218pub struct RsaModularExponentiation<'a, 'd, T: RsaMode, Dm: crate::DriverMode> {
223 rsa: &'a mut Rsa<'d, Dm>,
224 phantom: PhantomData<T>,
225}
226
227impl<'a, 'd, T: RsaMode, Dm: crate::DriverMode, const N: usize>
228 RsaModularExponentiation<'a, 'd, T, Dm>
229where
230 T: RsaMode<InputType = [u32; N]>,
231{
232 pub fn new(
239 rsa: &'a mut Rsa<'d, Dm>,
240 exponent: &T::InputType,
241 modulus: &T::InputType,
242 m_prime: u32,
243 ) -> Self {
244 Self::write_mode(rsa);
245 rsa.write_operand_b(exponent);
246 rsa.write_modulus(modulus);
247 rsa.write_mprime(m_prime);
248
249 #[cfg(not(esp32))]
250 if rsa.is_search_enabled() {
251 rsa.write_search_position(Self::find_search_pos(exponent));
252 }
253
254 Self {
255 rsa,
256 phantom: PhantomData,
257 }
258 }
259
260 fn set_up_exponentiation(&mut self, base: &T::InputType, r: &T::InputType) {
261 self.rsa.write_operand_a(base);
262 self.rsa.write_r(r);
263 }
264
265 pub fn start_exponentiation(&mut self, base: &T::InputType, r: &T::InputType) {
271 self.set_up_exponentiation(base, r);
272 self.rsa.write_modexp_start();
273 }
274
275 pub fn read_results(&mut self, outbuf: &mut T::InputType) {
281 self.rsa.read_results(outbuf);
282 }
283}
284
285pub struct RsaModularMultiplication<'a, 'd, T: RsaMode, Dm: crate::DriverMode> {
290 rsa: &'a mut Rsa<'d, Dm>,
291 phantom: PhantomData<T>,
292}
293
294impl<'a, 'd, T: RsaMode, Dm: crate::DriverMode, const N: usize>
295 RsaModularMultiplication<'a, 'd, T, Dm>
296where
297 T: RsaMode<InputType = [u32; N]>,
298{
299 pub fn new(
307 rsa: &'a mut Rsa<'d, Dm>,
308 operand_a: &T::InputType,
309 modulus: &T::InputType,
310 r: &T::InputType,
311 m_prime: u32,
312 ) -> Self {
313 Self::write_mode(rsa);
314 rsa.write_mprime(m_prime);
315 rsa.write_modulus(modulus);
316 rsa.write_operand_a(operand_a);
317 rsa.write_r(r);
318
319 Self {
320 rsa,
321 phantom: PhantomData,
322 }
323 }
324
325 pub fn start_modular_multiplication(&mut self, operand_b: &T::InputType) {
329 self.set_up_modular_multiplication(operand_b);
330 self.rsa.write_modmulti_start();
331 }
332
333 pub fn read_results(&mut self, outbuf: &mut T::InputType) {
337 self.rsa.read_results(outbuf);
338 }
339}
340
341pub struct RsaMultiplication<'a, 'd, T: RsaMode + Multi, Dm: crate::DriverMode> {
346 rsa: &'a mut Rsa<'d, Dm>,
347 phantom: PhantomData<T>,
348}
349
350impl<'a, 'd, T: RsaMode + Multi, Dm: crate::DriverMode, const N: usize>
351 RsaMultiplication<'a, 'd, T, Dm>
352where
353 T: RsaMode<InputType = [u32; N]>,
354{
355 pub fn new(rsa: &'a mut Rsa<'d, Dm>, operand_a: &T::InputType) -> Self {
357 Self::write_mode(rsa);
358 rsa.write_operand_a(operand_a);
359
360 Self {
361 rsa,
362 phantom: PhantomData,
363 }
364 }
365
366 pub fn start_multiplication(&mut self, operand_b: &T::InputType) {
368 self.set_up_multiplication(operand_b);
369 self.rsa.write_multi_start();
370 }
371
372 pub fn read_results<const O: usize>(&mut self, outbuf: &mut T::OutputType)
377 where
378 T: Multi<OutputType = [u32; O]>,
379 {
380 self.rsa.read_results(outbuf);
381 }
382}
383
384pub(crate) mod asynch {
386 use core::task::Poll;
387
388 use portable_atomic::{AtomicBool, Ordering};
389 use procmacros::handler;
390
391 use crate::{
392 asynch::AtomicWaker,
393 peripherals::RSA,
394 rsa::{
395 Multi,
396 Rsa,
397 RsaMode,
398 RsaModularExponentiation,
399 RsaModularMultiplication,
400 RsaMultiplication,
401 },
402 Async,
403 };
404
405 static WAKER: AtomicWaker = AtomicWaker::new();
406
407 static SIGNALED: AtomicBool = AtomicBool::new(false);
408
409 #[must_use = "futures do nothing unless you `.await` or poll them"]
411 struct RsaFuture<'a, 'd> {
412 #[cfg_attr(esp32, allow(dead_code))]
413 driver: &'a Rsa<'d, Async>,
414 }
415
416 impl<'a, 'd> RsaFuture<'a, 'd> {
417 fn new(driver: &'a Rsa<'d, Async>) -> Self {
418 SIGNALED.store(false, Ordering::Relaxed);
419
420 #[cfg(not(esp32))]
421 driver.regs().int_ena().write(|w| w.int_ena().set_bit());
422
423 Self { driver }
424 }
425
426 fn is_done(&self) -> bool {
427 SIGNALED.load(Ordering::Acquire)
428 }
429 }
430
431 impl Drop for RsaFuture<'_, '_> {
432 fn drop(&mut self) {
433 #[cfg(not(esp32))]
434 self.driver
435 .regs()
436 .int_ena()
437 .write(|w| w.int_ena().clear_bit());
438 }
439 }
440
441 impl core::future::Future for RsaFuture<'_, '_> {
442 type Output = ();
443
444 fn poll(
445 self: core::pin::Pin<&mut Self>,
446 cx: &mut core::task::Context<'_>,
447 ) -> core::task::Poll<Self::Output> {
448 WAKER.register(cx.waker());
449 if self.is_done() {
450 Poll::Ready(())
451 } else {
452 Poll::Pending
453 }
454 }
455 }
456
457 impl<T: RsaMode, const N: usize> RsaModularExponentiation<'_, '_, T, Async>
458 where
459 T: RsaMode<InputType = [u32; N]>,
460 {
461 pub async fn exponentiation(
463 &mut self,
464 base: &T::InputType,
465 r: &T::InputType,
466 outbuf: &mut T::InputType,
467 ) {
468 self.set_up_exponentiation(base, r);
469 let fut = RsaFuture::new(self.rsa);
470 self.rsa.write_modexp_start();
471 fut.await;
472 self.rsa.read_out(outbuf);
473 }
474 }
475
476 impl<T: RsaMode, const N: usize> RsaModularMultiplication<'_, '_, T, Async>
477 where
478 T: RsaMode<InputType = [u32; N]>,
479 {
480 pub async fn modular_multiplication(
482 &mut self,
483 operand_b: &T::InputType,
484 outbuf: &mut T::InputType,
485 ) {
486 cfg_if::cfg_if! {
487 if #[cfg(esp32)] {
488 let fut = RsaFuture::new(self.rsa);
489 self.rsa.write_multi_start();
490 fut.await;
491
492 self.rsa.write_operand_a(operand_b);
493 } else {
494 self.set_up_modular_multiplication(operand_b);
495 }
496 }
497
498 let fut = RsaFuture::new(self.rsa);
499 self.rsa.write_modmulti_start();
500 fut.await;
501 self.rsa.read_out(outbuf);
502 }
503 }
504
505 impl<T: RsaMode + Multi, const N: usize> RsaMultiplication<'_, '_, T, Async>
506 where
507 T: RsaMode<InputType = [u32; N]>,
508 {
509 pub async fn multiplication<const O: usize>(
511 &mut self,
512 operand_b: &T::InputType,
513 outbuf: &mut T::OutputType,
514 ) where
515 T: Multi<OutputType = [u32; O]>,
516 {
517 self.set_up_multiplication(operand_b);
518 let fut = RsaFuture::new(self.rsa);
519 self.rsa.write_multi_start();
520 fut.await;
521 self.rsa.read_out(outbuf);
522 }
523 }
524
525 #[handler]
526 pub(super) fn rsa_interrupt_handler() {
528 let rsa = RSA::regs();
529 SIGNALED.store(true, Ordering::Release);
530 cfg_if::cfg_if! {
531 if #[cfg(esp32)] {
532 rsa.interrupt().write(|w| w.interrupt().set_bit());
533 } else {
534 rsa.int_clr().write(|w| w.int_clr().set_bit());
535 }
536 }
537
538 WAKER.wake();
539 }
540}