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