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(
303 rsa: &'a mut Rsa<'d, Dm>,
304 operand_a: &T::InputType,
305 modulus: &T::InputType,
306 r: &T::InputType,
307 m_prime: u32,
308 ) -> Self {
309 Self::write_mode(rsa);
310 rsa.write_mprime(m_prime);
311 rsa.write_modulus(modulus);
312 rsa.write_operand_a(operand_a);
313 rsa.write_r(r);
314
315 Self {
316 rsa,
317 phantom: PhantomData,
318 }
319 }
320
321 pub fn start_modular_multiplication(&mut self, operand_b: &T::InputType) {
325 self.set_up_modular_multiplication(operand_b);
326 self.rsa.write_modmulti_start();
327 }
328
329 pub fn read_results(&mut self, outbuf: &mut T::InputType) {
333 self.rsa.read_results(outbuf);
334 }
335}
336
337pub struct RsaMultiplication<'a, 'd, T: RsaMode + Multi, Dm: crate::DriverMode> {
342 rsa: &'a mut Rsa<'d, Dm>,
343 phantom: PhantomData<T>,
344}
345
346impl<'a, 'd, T: RsaMode + Multi, Dm: crate::DriverMode, const N: usize>
347 RsaMultiplication<'a, 'd, T, Dm>
348where
349 T: RsaMode<InputType = [u32; N]>,
350{
351 pub fn new(rsa: &'a mut Rsa<'d, Dm>, operand_a: &T::InputType) -> Self {
353 Self::write_mode(rsa);
354 rsa.write_operand_a(operand_a);
355
356 Self {
357 rsa,
358 phantom: PhantomData,
359 }
360 }
361
362 pub fn start_multiplication(&mut self, operand_b: &T::InputType) {
364 self.set_up_multiplication(operand_b);
365 self.rsa.write_multi_start();
366 }
367
368 pub fn read_results<const O: usize>(&mut self, outbuf: &mut T::OutputType)
373 where
374 T: Multi<OutputType = [u32; O]>,
375 {
376 self.rsa.read_results(outbuf);
377 }
378}
379
380pub(crate) mod asynch {
382 use core::task::Poll;
383
384 use portable_atomic::{AtomicBool, Ordering};
385 use procmacros::handler;
386
387 use crate::{
388 Async,
389 asynch::AtomicWaker,
390 peripherals::RSA,
391 rsa::{
392 Multi,
393 Rsa,
394 RsaMode,
395 RsaModularExponentiation,
396 RsaModularMultiplication,
397 RsaMultiplication,
398 },
399 };
400
401 static WAKER: AtomicWaker = AtomicWaker::new();
402
403 static SIGNALED: AtomicBool = AtomicBool::new(false);
404
405 #[must_use = "futures do nothing unless you `.await` or poll them"]
407 struct RsaFuture<'a, 'd> {
408 #[cfg_attr(esp32, allow(dead_code))]
409 driver: &'a Rsa<'d, Async>,
410 }
411
412 impl<'a, 'd> RsaFuture<'a, 'd> {
413 fn new(driver: &'a Rsa<'d, Async>) -> Self {
414 SIGNALED.store(false, Ordering::Relaxed);
415
416 #[cfg(not(esp32))]
417 driver.regs().int_ena().write(|w| w.int_ena().set_bit());
418
419 Self { driver }
420 }
421
422 fn is_done(&self) -> bool {
423 SIGNALED.load(Ordering::Acquire)
424 }
425 }
426
427 impl Drop for RsaFuture<'_, '_> {
428 fn drop(&mut self) {
429 #[cfg(not(esp32))]
430 self.driver
431 .regs()
432 .int_ena()
433 .write(|w| w.int_ena().clear_bit());
434 }
435 }
436
437 impl core::future::Future for RsaFuture<'_, '_> {
438 type Output = ();
439
440 fn poll(
441 self: core::pin::Pin<&mut Self>,
442 cx: &mut core::task::Context<'_>,
443 ) -> core::task::Poll<Self::Output> {
444 WAKER.register(cx.waker());
445 if self.is_done() {
446 Poll::Ready(())
447 } else {
448 Poll::Pending
449 }
450 }
451 }
452
453 impl<T: RsaMode, const N: usize> RsaModularExponentiation<'_, '_, T, Async>
454 where
455 T: RsaMode<InputType = [u32; N]>,
456 {
457 pub async fn exponentiation(
459 &mut self,
460 base: &T::InputType,
461 r: &T::InputType,
462 outbuf: &mut T::InputType,
463 ) {
464 self.set_up_exponentiation(base, r);
465 let fut = RsaFuture::new(self.rsa);
466 self.rsa.write_modexp_start();
467 fut.await;
468 self.rsa.read_out(outbuf);
469 }
470 }
471
472 impl<T: RsaMode, const N: usize> RsaModularMultiplication<'_, '_, T, Async>
473 where
474 T: RsaMode<InputType = [u32; N]>,
475 {
476 pub async fn modular_multiplication(
478 &mut self,
479 operand_b: &T::InputType,
480 outbuf: &mut T::InputType,
481 ) {
482 cfg_if::cfg_if! {
483 if #[cfg(esp32)] {
484 let fut = RsaFuture::new(self.rsa);
485 self.rsa.write_multi_start();
486 fut.await;
487
488 self.rsa.write_operand_a(operand_b);
489 } else {
490 self.set_up_modular_multiplication(operand_b);
491 }
492 }
493
494 let fut = RsaFuture::new(self.rsa);
495 self.rsa.write_modmulti_start();
496 fut.await;
497 self.rsa.read_out(outbuf);
498 }
499 }
500
501 impl<T: RsaMode + Multi, const N: usize> RsaMultiplication<'_, '_, T, Async>
502 where
503 T: RsaMode<InputType = [u32; N]>,
504 {
505 pub async fn multiplication<const O: usize>(
507 &mut self,
508 operand_b: &T::InputType,
509 outbuf: &mut T::OutputType,
510 ) where
511 T: Multi<OutputType = [u32; O]>,
512 {
513 self.set_up_multiplication(operand_b);
514 let fut = RsaFuture::new(self.rsa);
515 self.rsa.write_multi_start();
516 fut.await;
517 self.rsa.read_out(outbuf);
518 }
519 }
520
521 #[handler]
522 pub(super) fn rsa_interrupt_handler() {
524 let rsa = RSA::regs();
525 SIGNALED.store(true, Ordering::Release);
526 cfg_if::cfg_if! {
527 if #[cfg(esp32)] {
528 rsa.interrupt().write(|w| w.interrupt().set_bit());
529 } else {
530 rsa.int_clr().write(|w| w.int_clr().set_bit());
531 }
532 }
533
534 WAKER.wake();
535 }
536}