1#[cfg_attr(rsa_version = "1", path = "low_level/v1.rs")]
17#[cfg_attr(rsa_version = "2", path = "low_level/v2.rs")]
18#[cfg_attr(rsa_version = "3", path = "low_level/v3.rs")]
19mod low_level;
20
21use core::{marker::PhantomData, ptr::NonNull, task::Poll};
22
23#[cfg(rsa_version = "1")]
24use portable_atomic::{AtomicBool, Ordering};
25use procmacros::{handler, ram};
26
27use crate::{
28 Async,
29 Blocking,
30 DriverMode,
31 asynch::AtomicWaker,
32 interrupt::InterruptHandler,
33 pac,
34 peripherals::RSA,
35 rtc_cntl::WakeLock,
36 system::{GenericPeripheralGuard, Peripheral as PeripheralEnable},
37 trm_markdown_link,
38 work_queue::{self, Status, VTable, WorkQueue, WorkQueueDriver, WorkQueueFrontend},
39};
40
41pub struct Rsa<'d, Dm: DriverMode> {
43 rsa: RSA<'d>,
44 phantom: PhantomData<Dm>,
45 _guard: RsaGuard,
46}
47
48const WORDS_PER_INCREMENT: u32 = property!("rsa.size_increment") / 32;
57
58struct RsaGuard {
59 _guard: GenericPeripheralGuard<{ PeripheralEnable::Rsa as u8 }>,
60}
61
62impl RsaGuard {
63 fn new() -> Self {
64 let _guard = GenericPeripheralGuard::new();
65 cfg_select! {
66 rsa_version = "1" => {}
67 esp32s31 => {}
68 _ => {
69 crate::peripherals::SYSTEM::regs()
70 .rsa_pd_ctrl()
71 .modify(|_, w| {
72 w.rsa_mem_force_pd().clear_bit();
73 w.rsa_mem_force_pu().set_bit();
74 w.rsa_mem_pd().clear_bit()
75 });
76 }
77 }
78
79 Self { _guard }
80 }
81}
82
83impl Drop for RsaGuard {
84 fn drop(&mut self) {
85 unsafe {
86 crate::peripherals::RSA::steal().disable_peri_interrupt_on_all_cores();
91 }
92
93 cfg_select! {
94 rsa_version = "1" => {}
95 esp32s31 => {}
96 _ => {
97 crate::peripherals::SYSTEM::regs()
98 .rsa_pd_ctrl()
99 .modify(|_, w| {
100 w.rsa_mem_force_pd().clear_bit();
101 w.rsa_mem_force_pu().clear_bit();
102 w.rsa_mem_pd().set_bit()
103 });
104 }
105 }
106 }
107}
108
109impl<'d> Rsa<'d, Blocking> {
110 pub fn new(rsa: RSA<'d>) -> Self {
114 let this = Self {
115 rsa,
116 phantom: PhantomData,
117 _guard: RsaGuard::new(),
118 };
119
120 while !this.ready() {}
121
122 this
123 }
124
125 pub fn into_async(mut self) -> Rsa<'d, Async> {
127 self.set_interrupt_handler(rsa_interrupt_handler);
128 self.enable_disable_interrupt(true);
129
130 Rsa {
131 rsa: self.rsa,
132 phantom: PhantomData,
133 _guard: self._guard,
134 }
135 }
136
137 pub fn enable_disable_interrupt(&mut self, enable: bool) {
142 self.internal_enable_disable_interrupt(enable);
143 }
144
145 #[instability::unstable]
150 pub fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
151 self.rsa.disable_peri_interrupt_on_all_cores();
152 self.rsa.bind_peri_interrupt(handler);
153 }
154}
155
156impl crate::private::Sealed for Rsa<'_, Blocking> {}
157
158#[instability::unstable]
159impl crate::interrupt::InterruptConfigurable for Rsa<'_, Blocking> {
160 fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
161 self.set_interrupt_handler(handler);
162 }
163}
164
165impl<'d> Rsa<'d, Async> {
166 pub fn into_blocking(self) -> Rsa<'d, Blocking> {
168 self.internal_enable_disable_interrupt(false);
169 self.rsa.disable_peri_interrupt_on_all_cores();
170
171 Rsa {
172 rsa: self.rsa,
173 phantom: PhantomData,
174 _guard: self._guard,
175 }
176 }
177}
178
179impl<'d, Dm: DriverMode> Rsa<'d, Dm> {
180 fn internal_enable_disable_interrupt(&self, enable: bool) {
181 low_level::enable_disable_interrupt(self.regs(), enable);
182 }
183
184 fn regs(&self) -> &pac::rsa::RegisterBlock {
185 self.rsa.register_block()
186 }
187
188 fn ready(&self) -> bool {
193 low_level::ready(self.regs())
194 }
195
196 fn start_modexp(&self) {
198 low_level::start_modexp(self.regs());
199 }
200
201 fn start_multi(&self) {
203 low_level::start_multi(self.regs());
204 }
205
206 fn start_modmulti(&self) {
208 low_level::start_modmulti(self.regs());
209 }
210
211 fn clear_interrupt(&mut self) {
213 low_level::clear_interrupt(self.regs());
214 }
215
216 fn is_idle(&self) -> bool {
218 low_level::is_idle(self.regs())
219 }
220
221 fn wait_for_idle(&mut self) {
222 while !self.is_idle() {}
223 self.clear_interrupt();
224 }
225
226 fn write_multi_mode(&mut self, mode: u32, modular: bool) {
228 low_level::write_multi_mode(self.regs(), mode, modular);
229 }
230
231 fn write_modexp_mode(&mut self, mode: u32) {
233 low_level::write_modexp_mode(self.regs(), mode);
234 }
235
236 fn write_operand_b(&mut self, operand: &[u32]) {
237 for (reg, op) in self.regs().y_mem_iter().zip(operand.iter().copied()) {
238 reg.write(|w| unsafe { w.bits(op) });
239 }
240 }
241
242 fn write_modulus(&mut self, modulus: &[u32]) {
243 for (reg, op) in self.regs().m_mem_iter().zip(modulus.iter().copied()) {
244 reg.write(|w| unsafe { w.bits(op) });
245 }
246 }
247
248 fn write_mprime(&mut self, m_prime: u32) {
249 self.regs().m_prime().write(|w| unsafe { w.bits(m_prime) });
250 }
251
252 fn write_operand_a(&mut self, operand: &[u32]) {
253 for (reg, op) in self.regs().x_mem_iter().zip(operand.iter().copied()) {
254 reg.write(|w| unsafe { w.bits(op) });
255 }
256 }
257
258 fn write_multi_operand_b(&mut self, operand: &[u32]) {
259 for (reg, op) in self
260 .regs()
261 .z_mem_iter()
262 .skip(operand.len())
263 .zip(operand.iter().copied())
264 {
265 reg.write(|w| unsafe { w.bits(op) });
266 }
267 }
268
269 fn write_r(&mut self, r: &[u32]) {
270 for (reg, op) in self.regs().z_mem_iter().zip(r.iter().copied()) {
271 reg.write(|w| unsafe { w.bits(op) });
272 }
273 }
274
275 fn read_out(&self, outbuf: &mut [u32]) {
276 for (reg, op) in self.regs().z_mem_iter().zip(outbuf.iter_mut()) {
277 *op = reg.read().bits();
278 }
279
280 #[cfg(clear_crypto_secrets)]
281 self.clear_secrets();
282 }
283
284 #[cfg(clear_crypto_secrets)]
286 fn clear_secrets(&self) {
287 for reg in self.regs().x_mem_iter() {
288 reg.write(|w| unsafe { w.bits(0) });
289 }
290 for reg in self.regs().y_mem_iter() {
291 reg.write(|w| unsafe { w.bits(0) });
292 }
293 for reg in self.regs().z_mem_iter() {
294 reg.write(|w| unsafe { w.bits(0) });
295 }
296 for reg in self.regs().m_mem_iter() {
297 reg.write(|w| unsafe { w.bits(0) });
298 }
299 }
300
301 fn read_results(&mut self, outbuf: &mut [u32]) {
302 self.wait_for_idle();
303 self.read_out(outbuf);
304 }
305
306 #[doc = trm_markdown_link!("rsa")]
317 #[cfg(not(rsa_version = "1"))]
318 pub fn disable_constant_time(&mut self, disable: bool) {
319 self.regs()
320 .constant_time()
321 .write(|w| w.constant_time().bit(disable));
322 }
323
324 #[doc = trm_markdown_link!("rsa")]
334 #[cfg(not(rsa_version = "1"))]
335 pub fn search_acceleration(&mut self, enable: bool) {
336 self.regs()
337 .search_enable()
338 .write(|w| w.search_enable().bit(enable));
339 }
340
341 #[cfg(not(rsa_version = "1"))]
343 fn is_search_enabled(&mut self) -> bool {
344 self.regs()
345 .search_enable()
346 .read()
347 .search_enable()
348 .bit_is_set()
349 }
350
351 #[cfg(not(rsa_version = "1"))]
353 fn write_search_position(&mut self, search_position: u32) {
354 self.regs()
355 .search_pos()
356 .write(|w| unsafe { w.bits(search_position) });
357 }
358}
359
360pub trait RsaMode: crate::private::Sealed {
362 type InputType: AsRef<[u32]> + AsMut<[u32]>;
364}
365
366pub trait Multi: RsaMode {
368 type OutputType: AsRef<[u32]> + AsMut<[u32]>;
370}
371
372pub mod operand_sizes {
374 for_each_rsa_exponentiation!(
375 ($x:literal) => {
376 paste::paste! {
377 #[doc = concat!(stringify!($x), "-bit RSA operation.")]
378 pub struct [<Op $x>];
379
380 impl crate::private::Sealed for [<Op $x>] {}
381 impl crate::rsa::RsaMode for [<Op $x>] {
382 type InputType = [u32; $x / 32];
383 }
384 }
385 };
386 );
387
388 for_each_rsa_multiplication!(
389 ($x:literal) => {
390 impl crate::rsa::Multi for paste::paste!( [<Op $x>] ) {
391 type OutputType = [u32; $x * 2 / 32];
392 }
393 };
394 );
395}
396
397pub struct RsaModularExponentiation<'a, 'd, T: RsaMode, Dm: DriverMode> {
402 rsa: &'a mut Rsa<'d, Dm>,
403 phantom: PhantomData<T>,
404}
405
406impl<'a, 'd, T: RsaMode, Dm: DriverMode, const N: usize> RsaModularExponentiation<'a, 'd, T, Dm>
407where
408 T: RsaMode<InputType = [u32; N]>,
409{
410 #[doc = trm_markdown_link!("rsa")]
417 pub fn new(
418 rsa: &'a mut Rsa<'d, Dm>,
419 exponent: &T::InputType,
420 modulus: &T::InputType,
421 m_prime: u32,
422 ) -> Self {
423 Self::write_mode(rsa);
424 rsa.write_operand_b(exponent);
425 rsa.write_modulus(modulus);
426 rsa.write_mprime(m_prime);
427
428 #[cfg(not(rsa_version = "1"))]
429 if rsa.is_search_enabled() {
430 rsa.write_search_position(Self::find_search_pos(exponent));
431 }
432
433 Self {
434 rsa,
435 phantom: PhantomData,
436 }
437 }
438
439 fn set_up_exponentiation(&mut self, base: &T::InputType, r: &T::InputType) {
440 self.rsa.write_operand_a(base);
441 self.rsa.write_r(r);
442 }
443
444 #[doc = trm_markdown_link!("rsa")]
450 pub fn start_exponentiation(&mut self, base: &T::InputType, r: &T::InputType) {
451 self.set_up_exponentiation(base, r);
452 self.rsa.start_modexp();
453 }
454
455 pub fn read_results(&mut self, outbuf: &mut T::InputType) {
461 self.rsa.read_results(outbuf);
462 }
463
464 #[cfg(not(rsa_version = "1"))]
465 fn find_search_pos(exponent: &T::InputType) -> u32 {
466 for (i, byte) in exponent.iter().rev().enumerate() {
467 if *byte == 0 {
468 continue;
469 }
470 return (exponent.len() * 32) as u32 - (byte.leading_zeros() + i as u32 * 32) - 1;
471 }
472 0
473 }
474
475 fn write_mode(rsa: &mut Rsa<'d, Dm>) {
477 rsa.write_modexp_mode(N as u32 / WORDS_PER_INCREMENT - 1);
478 }
479}
480
481pub struct RsaModularMultiplication<'a, 'd, T, Dm>
486where
487 T: RsaMode,
488 Dm: DriverMode,
489{
490 rsa: &'a mut Rsa<'d, Dm>,
491 phantom: PhantomData<T>,
492}
493
494impl<'a, 'd, T, Dm, const N: usize> RsaModularMultiplication<'a, 'd, T, Dm>
495where
496 T: RsaMode<InputType = [u32; N]>,
497 Dm: DriverMode,
498{
499 #[doc = trm_markdown_link!("rsa")]
506 pub fn new(
507 rsa: &'a mut Rsa<'d, Dm>,
508 operand_a: &T::InputType,
509 modulus: &T::InputType,
510 r: &T::InputType,
511 m_prime: u32,
512 ) -> Self {
513 rsa.write_multi_mode(N as u32 / WORDS_PER_INCREMENT - 1, true);
514
515 rsa.write_mprime(m_prime);
516 rsa.write_modulus(modulus);
517 rsa.write_operand_a(operand_a);
518 rsa.write_r(r);
519
520 Self {
521 rsa,
522 phantom: PhantomData,
523 }
524 }
525
526 #[doc = trm_markdown_link!("rsa")]
530 pub fn start_modular_multiplication(&mut self, operand_b: &T::InputType) {
531 self.set_up_modular_multiplication(operand_b);
532 self.rsa.start_modmulti();
533 }
534
535 pub fn read_results(&mut self, outbuf: &mut T::InputType) {
541 self.rsa.read_results(outbuf);
542 }
543
544 fn set_up_modular_multiplication(&mut self, operand_b: &T::InputType) {
545 if cfg!(rsa_version = "1") {
546 self.rsa.start_multi();
547 self.rsa.wait_for_idle();
548
549 self.rsa.write_operand_a(operand_b);
550 } else {
551 self.rsa.write_operand_b(operand_b);
552 }
553 }
554}
555
556pub struct RsaMultiplication<'a, 'd, T, Dm>
561where
562 T: RsaMode + Multi,
563 Dm: DriverMode,
564{
565 rsa: &'a mut Rsa<'d, Dm>,
566 phantom: PhantomData<T>,
567}
568
569impl<'a, 'd, T, Dm, const N: usize> RsaMultiplication<'a, 'd, T, Dm>
570where
571 T: RsaMode<InputType = [u32; N]>,
572 T: Multi,
573 Dm: DriverMode,
574{
575 pub fn new(rsa: &'a mut Rsa<'d, Dm>, operand_a: &T::InputType) -> Self {
577 rsa.write_multi_mode(2 * N as u32 / WORDS_PER_INCREMENT - 1, false);
579 rsa.write_operand_a(operand_a);
580
581 Self {
582 rsa,
583 phantom: PhantomData,
584 }
585 }
586
587 pub fn start_multiplication(&mut self, operand_b: &T::InputType) {
589 self.set_up_multiplication(operand_b);
590 self.rsa.start_multi();
591 }
592
593 pub fn read_results<const O: usize>(&mut self, outbuf: &mut T::OutputType)
599 where
600 T: Multi<OutputType = [u32; O]>,
601 {
602 self.rsa.read_results(outbuf);
603 }
604
605 fn set_up_multiplication(&mut self, operand_b: &T::InputType) {
606 self.rsa.write_multi_operand_b(operand_b);
607 }
608}
609
610static WAKER: AtomicWaker = AtomicWaker::new();
611#[cfg(rsa_version = "1")]
612static SIGNALED: AtomicBool = AtomicBool::new(false);
613
614#[must_use = "futures do nothing unless you `.await` or poll them"]
616struct RsaFuture<'a, 'd> {
617 driver: &'a Rsa<'d, Async>,
618 _wake_lock: WakeLock,
619}
620
621impl<'a, 'd> RsaFuture<'a, 'd> {
622 fn new(driver: &'a Rsa<'d, Async>) -> Self {
623 #[cfg(rsa_version = "1")]
624 SIGNALED.store(false, Ordering::Relaxed);
625
626 driver.internal_enable_disable_interrupt(true);
627
628 Self {
629 driver,
630 _wake_lock: WakeLock::new(),
631 }
632 }
633
634 fn is_done(&self) -> bool {
635 cfg_select! {
636 rsa_version = "1" => SIGNALED.load(Ordering::Acquire),
637 _ => self.driver.is_idle(),
638 }
639 }
640}
641
642impl Drop for RsaFuture<'_, '_> {
643 fn drop(&mut self) {
644 self.driver.internal_enable_disable_interrupt(false);
645 }
646}
647
648impl core::future::Future for RsaFuture<'_, '_> {
649 type Output = ();
650
651 fn poll(
652 self: core::pin::Pin<&mut Self>,
653 cx: &mut core::task::Context<'_>,
654 ) -> core::task::Poll<Self::Output> {
655 WAKER.register(cx.waker());
656 if self.is_done() {
657 Poll::Ready(())
658 } else {
659 Poll::Pending
660 }
661 }
662}
663
664impl<T: RsaMode, const N: usize> RsaModularExponentiation<'_, '_, T, Async>
665where
666 T: RsaMode<InputType = [u32; N]>,
667{
668 pub async fn exponentiation(
670 &mut self,
671 base: &T::InputType,
672 r: &T::InputType,
673 outbuf: &mut T::InputType,
674 ) {
675 self.set_up_exponentiation(base, r);
676 let fut = RsaFuture::new(self.rsa);
677 self.rsa.start_modexp();
678 fut.await;
679 self.rsa.read_out(outbuf);
680 }
681}
682
683impl<T: RsaMode, const N: usize> RsaModularMultiplication<'_, '_, T, Async>
684where
685 T: RsaMode<InputType = [u32; N]>,
686{
687 pub async fn modular_multiplication(
689 &mut self,
690 operand_b: &T::InputType,
691 outbuf: &mut T::InputType,
692 ) {
693 if cfg!(rsa_version = "1") {
694 let fut = RsaFuture::new(self.rsa);
695 self.rsa.start_multi();
696 fut.await;
697
698 self.rsa.write_operand_a(operand_b);
699 } else {
700 self.set_up_modular_multiplication(operand_b);
701 }
702
703 let fut = RsaFuture::new(self.rsa);
704 self.rsa.start_modmulti();
705 fut.await;
706 self.rsa.read_out(outbuf);
707 }
708}
709
710impl<T: RsaMode + Multi, const N: usize> RsaMultiplication<'_, '_, T, Async>
711where
712 T: RsaMode<InputType = [u32; N]>,
713{
714 pub async fn multiplication<const O: usize>(
716 &mut self,
717 operand_b: &T::InputType,
718 outbuf: &mut T::OutputType,
719 ) where
720 T: Multi<OutputType = [u32; O]>,
721 {
722 self.set_up_multiplication(operand_b);
723 let fut = RsaFuture::new(self.rsa);
724 self.rsa.start_multi();
725 fut.await;
726 self.rsa.read_out(outbuf);
727 }
728}
729
730#[handler]
731pub(super) fn rsa_interrupt_handler() {
733 let rsa = RSA::regs();
734
735 #[cfg(rsa_version = "1")]
736 SIGNALED.store(true, Ordering::Release);
737
738 low_level::clear_interrupt(rsa);
739
740 WAKER.wake();
741}
742
743static RSA_WORK_QUEUE: WorkQueue<RsaWorkItem> = WorkQueue::new();
744const RSA_VTABLE: VTable<RsaWorkItem> = VTable {
745 post: |driver, item| {
746 let driver = unsafe { RsaBackend::from_raw(driver) };
748 Some(driver.process_item(item))
749 },
750 poll: |driver, item| {
751 let driver = unsafe { RsaBackend::from_raw(driver) };
752 driver.process_item(item)
753 },
754 cancel: |driver, item| {
755 let driver = unsafe { RsaBackend::from_raw(driver) };
756 driver.cancel(item)
757 },
758 stop: |driver| {
759 let driver = unsafe { RsaBackend::from_raw(driver) };
760 driver.deinitialize()
761 },
762};
763
764#[derive(Default)]
765enum RsaBackendState<'d> {
766 #[default]
767 Idle,
768 Initializing(Rsa<'d, Blocking>),
769 Ready(Rsa<'d, Blocking>),
770 #[cfg(rsa_version = "1")]
771 ModularMultiplicationRoundOne(Rsa<'d, Blocking>),
772 Processing(Rsa<'d, Blocking>),
773}
774
775#[procmacros::doc_replace]
776pub struct RsaBackend<'d> {
806 peri: RSA<'d>,
807 state: RsaBackendState<'d>,
808}
809
810impl<'d> RsaBackend<'d> {
811 #[procmacros::doc_replace]
812 pub fn new(rsa: RSA<'d>) -> Self {
824 Self {
825 peri: rsa,
826 state: RsaBackendState::Idle,
827 }
828 }
829
830 #[procmacros::doc_replace]
831 pub fn start(&mut self) -> RsaWorkQueueDriver<'_, 'd> {
847 RsaWorkQueueDriver {
848 inner: WorkQueueDriver::new(self, RSA_VTABLE, &RSA_WORK_QUEUE),
849 }
850 }
851
852 unsafe fn from_raw<'any>(ptr: NonNull<()>) -> &'any mut Self {
855 unsafe { ptr.cast::<RsaBackend<'_>>().as_mut() }
856 }
857
858 fn process_item(&mut self, item: &mut RsaWorkItem) -> work_queue::Poll {
859 match core::mem::take(&mut self.state) {
860 RsaBackendState::Idle => {
861 let driver = Rsa {
862 rsa: unsafe { self.peri.clone_unchecked() },
863 phantom: PhantomData,
864 _guard: RsaGuard::new(),
865 };
866 self.state = RsaBackendState::Initializing(driver);
867 work_queue::Poll::Pending(true)
868 }
869 RsaBackendState::Initializing(mut rsa) => {
870 self.state = if rsa.ready() {
873 rsa.set_interrupt_handler(rsa_work_queue_handler);
874 rsa.enable_disable_interrupt(true);
875 RsaBackendState::Ready(rsa)
876 } else {
877 RsaBackendState::Initializing(rsa)
878 };
879 work_queue::Poll::Pending(true)
880 }
881 RsaBackendState::Ready(mut rsa) => {
882 #[cfg(not(rsa_version = "1"))]
883 {
884 rsa.disable_constant_time(!item.constant_time);
885 rsa.search_acceleration(item.search_acceleration);
886 }
887
888 match item.operation {
889 RsaOperation::Multiplication { x, y } => {
890 let n = x.len() as u32;
891 rsa.write_operand_a(unsafe { x.as_ref() });
892
893 rsa.write_multi_mode(2 * n / WORDS_PER_INCREMENT - 1, false);
895 rsa.write_multi_operand_b(unsafe { y.as_ref() });
896 rsa.start_multi();
897 }
898
899 RsaOperation::ModularMultiplication {
900 x,
901 #[cfg(not(rsa_version = "1"))]
902 y,
903 m,
904 m_prime,
905 r: r_inv,
906 ..
907 } => {
908 let n = x.len() as u32;
909 rsa.write_operand_a(unsafe { x.as_ref() });
910
911 rsa.write_multi_mode(n / WORDS_PER_INCREMENT - 1, true);
912
913 #[cfg(not(rsa_version = "1"))]
914 rsa.write_operand_b(unsafe { y.as_ref() });
915
916 rsa.write_modulus(unsafe { m.as_ref() });
917 rsa.write_mprime(m_prime);
918 rsa.write_r(unsafe { r_inv.as_ref() });
919
920 rsa.start_modmulti();
921
922 #[cfg(rsa_version = "1")]
923 {
924 self.state = RsaBackendState::ModularMultiplicationRoundOne(rsa);
927
928 return work_queue::Poll::Pending(false);
929 }
930 }
931 RsaOperation::ModularExponentiation {
932 x,
933 y,
934 m,
935 m_prime,
936 r_inv,
937 } => {
938 let n = x.len() as u32;
939 rsa.write_operand_a(unsafe { x.as_ref() });
940
941 rsa.write_modexp_mode(n / WORDS_PER_INCREMENT - 1);
942 rsa.write_operand_b(unsafe { y.as_ref() });
943 rsa.write_modulus(unsafe { m.as_ref() });
944 rsa.write_mprime(m_prime);
945 rsa.write_r(unsafe { r_inv.as_ref() });
946
947 #[cfg(not(rsa_version = "1"))]
948 if item.search_acceleration {
949 fn find_search_pos(exponent: &[u32]) -> u32 {
950 for (i, byte) in exponent.iter().rev().enumerate() {
951 if *byte == 0 {
952 continue;
953 }
954 return (exponent.len() * 32) as u32
955 - (byte.leading_zeros() + i as u32 * 32)
956 - 1;
957 }
958 0
959 }
960 rsa.write_search_position(find_search_pos(unsafe { y.as_ref() }));
961 }
962
963 rsa.start_modexp();
964 }
965 }
966
967 self.state = RsaBackendState::Processing(rsa);
968
969 work_queue::Poll::Pending(false)
970 }
971
972 #[cfg(rsa_version = "1")]
973 RsaBackendState::ModularMultiplicationRoundOne(mut rsa) => {
974 if rsa.is_idle() {
975 let RsaOperation::ModularMultiplication { y, .. } = item.operation else {
976 unreachable!();
977 };
978
979 rsa.write_operand_a(unsafe { y.as_ref() });
981 rsa.start_modmulti();
982
983 self.state = RsaBackendState::Processing(rsa);
984 } else {
985 self.state = RsaBackendState::ModularMultiplicationRoundOne(rsa);
987 }
988 work_queue::Poll::Pending(false)
989 }
990
991 RsaBackendState::Processing(rsa) => {
992 if rsa.is_idle() {
993 rsa.read_out(unsafe { item.result.as_mut() });
994
995 self.state = RsaBackendState::Ready(rsa);
996 work_queue::Poll::Ready(Status::Completed)
997 } else {
998 self.state = RsaBackendState::Processing(rsa);
999 work_queue::Poll::Pending(false)
1000 }
1001 }
1002 }
1003 }
1004
1005 fn cancel(&mut self, _item: &mut RsaWorkItem) {
1006 self.state = RsaBackendState::Idle;
1009 }
1010
1011 fn deinitialize(&mut self) {
1012 self.state = RsaBackendState::Idle;
1013 }
1014}
1015
1016pub struct RsaWorkQueueDriver<'t, 'd> {
1022 inner: WorkQueueDriver<'t, RsaBackend<'d>, RsaWorkItem>,
1023}
1024
1025impl<'t, 'd> RsaWorkQueueDriver<'t, 'd> {
1026 pub fn stop(self) -> impl Future<Output = ()> {
1028 self.inner.stop()
1029 }
1030}
1031
1032#[derive(Clone)]
1033struct RsaWorkItem {
1034 #[cfg(not(rsa_version = "1"))]
1036 search_acceleration: bool,
1037 #[cfg(not(rsa_version = "1"))]
1038 constant_time: bool,
1039
1040 operation: RsaOperation,
1042 result: NonNull<[u32]>,
1043}
1044
1045unsafe impl Sync for RsaWorkItem {}
1046unsafe impl Send for RsaWorkItem {}
1047
1048#[derive(Clone)]
1049enum RsaOperation {
1050 Multiplication {
1053 x: NonNull<[u32]>,
1054 y: NonNull<[u32]>,
1055 },
1056 ModularMultiplication {
1058 x: NonNull<[u32]>,
1059 y: NonNull<[u32]>,
1060 m: NonNull<[u32]>,
1061 r: NonNull<[u32]>,
1062 m_prime: u32,
1063 },
1064 ModularExponentiation {
1066 x: NonNull<[u32]>,
1067 y: NonNull<[u32]>,
1068 m: NonNull<[u32]>,
1069 r_inv: NonNull<[u32]>,
1070 m_prime: u32,
1071 },
1072}
1073
1074#[handler]
1075#[ram]
1076fn rsa_work_queue_handler() {
1077 if !RSA_WORK_QUEUE.process() {
1078 low_level::clear_interrupt(RSA::regs());
1081 }
1082}
1083
1084#[cfg_attr(
1091 not(rsa_version = "1"),
1092 doc = " \nThe context is created with a secure configuration by default. You can enable hardware acceleration
1093 options using [enable_search_acceleration][Self::enable_search_acceleration] and
1094 [enable_acceleration][Self::enable_acceleration] when appropriate."
1095)]
1096#[derive(Clone)]
1097pub struct RsaContext {
1098 frontend: WorkQueueFrontend<RsaWorkItem>,
1099}
1100
1101impl Default for RsaContext {
1102 fn default() -> Self {
1103 Self::new()
1104 }
1105}
1106
1107impl RsaContext {
1108 pub fn new() -> Self {
1110 Self {
1111 frontend: WorkQueueFrontend::new(RsaWorkItem {
1112 #[cfg(not(rsa_version = "1"))]
1113 search_acceleration: false,
1114 #[cfg(not(rsa_version = "1"))]
1115 constant_time: true,
1116 operation: RsaOperation::Multiplication {
1117 x: NonNull::from(&[]),
1118 y: NonNull::from(&[]),
1119 },
1120 result: NonNull::from(&mut []),
1121 }),
1122 }
1123 }
1124
1125 #[cfg(not(rsa_version = "1"))]
1126 #[doc = trm_markdown_link!("rsa")]
1136 pub fn enable_search_acceleration(&mut self) {
1137 self.frontend.data_mut().search_acceleration = true;
1138 }
1139
1140 #[cfg(not(rsa_version = "1"))]
1141 #[doc = trm_markdown_link!("rsa")]
1152 pub fn enable_acceleration(&mut self) {
1153 self.frontend.data_mut().constant_time = false;
1154 }
1155
1156 fn post(&mut self) -> RsaHandle<'_> {
1157 RsaHandle(self.frontend.post(&RSA_WORK_QUEUE))
1158 }
1159
1160 #[procmacros::doc_replace]
1161 pub fn modular_exponentiate<'t, OP>(
1229 &'t mut self,
1230 x: &'t OP::InputType,
1231 y: &'t OP::InputType,
1232 m: &'t OP::InputType,
1233 r: &'t OP::InputType,
1234 m_prime: u32,
1235 result: &'t mut OP::InputType,
1236 ) -> RsaHandle<'t>
1237 where
1238 OP: RsaMode,
1239 {
1240 self.frontend.data_mut().operation = RsaOperation::ModularExponentiation {
1241 x: NonNull::from(x.as_ref()),
1242 y: NonNull::from(y.as_ref()),
1243 m: NonNull::from(m.as_ref()),
1244 r_inv: NonNull::from(r.as_ref()),
1245 m_prime,
1246 };
1247 self.frontend.data_mut().result = NonNull::from(result.as_mut());
1248 self.post()
1249 }
1250
1251 pub fn modular_multiply<'t, OP>(
1267 &'t mut self,
1268 x: &'t OP::InputType,
1269 y: &'t OP::InputType,
1270 m: &'t OP::InputType,
1271 r: &'t OP::InputType,
1272 m_prime: u32,
1273 result: &'t mut OP::InputType,
1274 ) -> RsaHandle<'t>
1275 where
1276 OP: RsaMode,
1277 {
1278 self.frontend.data_mut().operation = RsaOperation::ModularMultiplication {
1279 x: NonNull::from(x.as_ref()),
1280 y: NonNull::from(y.as_ref()),
1281 m: NonNull::from(m.as_ref()),
1282 r: NonNull::from(r.as_ref()),
1283 m_prime,
1284 };
1285 self.frontend.data_mut().result = NonNull::from(result.as_mut());
1286 self.post()
1287 }
1288
1289 #[procmacros::doc_replace]
1290 pub fn multiply<'t, OP>(
1320 &'t mut self,
1321 x: &'t OP::InputType,
1322 y: &'t OP::InputType,
1323 result: &'t mut OP::OutputType,
1324 ) -> RsaHandle<'t>
1325 where
1326 OP: Multi,
1327 {
1328 self.frontend.data_mut().operation = RsaOperation::Multiplication {
1329 x: NonNull::from(x.as_ref()),
1330 y: NonNull::from(y.as_ref()),
1331 };
1332 self.frontend.data_mut().result = NonNull::from(result.as_mut());
1333 self.post()
1334 }
1335}
1336
1337pub struct RsaHandle<'t>(work_queue::Handle<'t, RsaWorkItem>);
1339
1340impl RsaHandle<'_> {
1341 #[inline]
1343 pub fn poll(&mut self) -> bool {
1344 self.0.poll()
1345 }
1346
1347 #[inline]
1349 pub fn wait_blocking(self) {
1350 self.0.wait_blocking();
1351 }
1352
1353 #[inline]
1355 pub fn wait(&mut self) -> impl Future<Output = Status> {
1356 self.0.wait()
1357 }
1358}