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]
149 pub fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
150 self.rsa.disable_peri_interrupt_on_all_cores();
151 self.rsa.bind_peri_interrupt(handler);
152 }
153}
154
155impl crate::private::Sealed for Rsa<'_, Blocking> {}
156
157#[instability::unstable]
158impl crate::interrupt::InterruptConfigurable for Rsa<'_, Blocking> {
159 fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
160 self.set_interrupt_handler(handler);
161 }
162}
163
164impl<'d> Rsa<'d, Async> {
165 pub fn into_blocking(self) -> Rsa<'d, Blocking> {
167 self.internal_enable_disable_interrupt(false);
168 self.rsa.disable_peri_interrupt_on_all_cores();
169
170 Rsa {
171 rsa: self.rsa,
172 phantom: PhantomData,
173 _guard: self._guard,
174 }
175 }
176}
177
178impl<'d, Dm: DriverMode> Rsa<'d, Dm> {
179 fn internal_enable_disable_interrupt(&self, enable: bool) {
180 low_level::enable_disable_interrupt(self.regs(), enable);
181 }
182
183 fn regs(&self) -> &pac::rsa::RegisterBlock {
184 self.rsa.register_block()
185 }
186
187 fn ready(&self) -> bool {
189 low_level::ready(self.regs())
190 }
191
192 fn start_modexp(&self) {
194 low_level::start_modexp(self.regs());
195 }
196
197 fn start_multi(&self) {
199 low_level::start_multi(self.regs());
200 }
201
202 fn start_modmulti(&self) {
204 low_level::start_modmulti(self.regs());
205 }
206
207 fn clear_interrupt(&mut self) {
209 low_level::clear_interrupt(self.regs());
210 }
211
212 fn is_idle(&self) -> bool {
214 low_level::is_idle(self.regs())
215 }
216
217 fn wait_for_idle(&mut self) {
218 while !self.is_idle() {}
219 self.clear_interrupt();
220 }
221
222 fn write_multi_mode(&mut self, mode: u32, modular: bool) {
224 low_level::write_multi_mode(self.regs(), mode, modular);
225 }
226
227 fn write_modexp_mode(&mut self, mode: u32) {
229 low_level::write_modexp_mode(self.regs(), mode);
230 }
231
232 fn write_operand_b(&mut self, operand: &[u32]) {
233 for (reg, op) in self.regs().y_mem_iter().zip(operand.iter().copied()) {
234 reg.write(|w| unsafe { w.bits(op) });
235 }
236 }
237
238 fn write_modulus(&mut self, modulus: &[u32]) {
239 for (reg, op) in self.regs().m_mem_iter().zip(modulus.iter().copied()) {
240 reg.write(|w| unsafe { w.bits(op) });
241 }
242 }
243
244 fn write_mprime(&mut self, m_prime: u32) {
245 self.regs().m_prime().write(|w| unsafe { w.bits(m_prime) });
246 }
247
248 fn write_operand_a(&mut self, operand: &[u32]) {
249 for (reg, op) in self.regs().x_mem_iter().zip(operand.iter().copied()) {
250 reg.write(|w| unsafe { w.bits(op) });
251 }
252 }
253
254 fn write_multi_operand_b(&mut self, operand: &[u32]) {
255 for (reg, op) in self
256 .regs()
257 .z_mem_iter()
258 .skip(operand.len())
259 .zip(operand.iter().copied())
260 {
261 reg.write(|w| unsafe { w.bits(op) });
262 }
263 }
264
265 fn write_r(&mut self, r: &[u32]) {
266 for (reg, op) in self.regs().z_mem_iter().zip(r.iter().copied()) {
267 reg.write(|w| unsafe { w.bits(op) });
268 }
269 }
270
271 fn read_out(&self, outbuf: &mut [u32]) {
272 for (reg, op) in self.regs().z_mem_iter().zip(outbuf.iter_mut()) {
273 *op = reg.read().bits();
274 }
275
276 #[cfg(clear_crypto_secrets)]
277 self.clear_secrets();
278 }
279
280 #[cfg(clear_crypto_secrets)]
282 fn clear_secrets(&self) {
283 for reg in self.regs().x_mem_iter() {
284 reg.write(|w| unsafe { w.bits(0) });
285 }
286 for reg in self.regs().y_mem_iter() {
287 reg.write(|w| unsafe { w.bits(0) });
288 }
289 for reg in self.regs().z_mem_iter() {
290 reg.write(|w| unsafe { w.bits(0) });
291 }
292 for reg in self.regs().m_mem_iter() {
293 reg.write(|w| unsafe { w.bits(0) });
294 }
295 }
296
297 fn read_results(&mut self, outbuf: &mut [u32]) {
298 self.wait_for_idle();
299 self.read_out(outbuf);
300 }
301
302 #[doc = trm_markdown_link!("rsa")]
313 #[cfg(not(rsa_version = "1"))]
314 pub fn disable_constant_time(&mut self, disable: bool) {
315 self.regs()
316 .constant_time()
317 .write(|w| w.constant_time().bit(disable));
318 }
319
320 #[doc = trm_markdown_link!("rsa")]
330 #[cfg(not(rsa_version = "1"))]
331 pub fn search_acceleration(&mut self, enable: bool) {
332 self.regs()
333 .search_enable()
334 .write(|w| w.search_enable().bit(enable));
335 }
336
337 #[cfg(not(rsa_version = "1"))]
339 fn is_search_enabled(&mut self) -> bool {
340 self.regs()
341 .search_enable()
342 .read()
343 .search_enable()
344 .bit_is_set()
345 }
346
347 #[cfg(not(rsa_version = "1"))]
349 fn write_search_position(&mut self, search_position: u32) {
350 self.regs()
351 .search_pos()
352 .write(|w| unsafe { w.bits(search_position) });
353 }
354}
355
356pub trait RsaMode: crate::private::Sealed {
358 type InputType: AsRef<[u32]> + AsMut<[u32]>;
360}
361
362pub trait Multi: RsaMode {
364 type OutputType: AsRef<[u32]> + AsMut<[u32]>;
366}
367
368pub mod operand_sizes {
370 for_each_rsa_exponentiation!(
371 ($x:literal) => {
372 paste::paste! {
373 #[doc = concat!(stringify!($x), "-bit RSA operation.")]
374 pub struct [<Op $x>];
375
376 impl crate::private::Sealed for [<Op $x>] {}
377 impl crate::rsa::RsaMode for [<Op $x>] {
378 type InputType = [u32; $x / 32];
379 }
380 }
381 };
382 );
383
384 for_each_rsa_multiplication!(
385 ($x:literal) => {
386 impl crate::rsa::Multi for paste::paste!( [<Op $x>] ) {
387 type OutputType = [u32; $x * 2 / 32];
388 }
389 };
390 );
391}
392
393pub struct RsaModularExponentiation<'a, 'd, T: RsaMode, Dm: DriverMode> {
398 rsa: &'a mut Rsa<'d, Dm>,
399 phantom: PhantomData<T>,
400}
401
402impl<'a, 'd, T: RsaMode, Dm: DriverMode, const N: usize> RsaModularExponentiation<'a, 'd, T, Dm>
403where
404 T: RsaMode<InputType = [u32; N]>,
405{
406 #[doc = trm_markdown_link!("rsa")]
413 pub fn new(
414 rsa: &'a mut Rsa<'d, Dm>,
415 exponent: &T::InputType,
416 modulus: &T::InputType,
417 m_prime: u32,
418 ) -> Self {
419 Self::write_mode(rsa);
420 rsa.write_operand_b(exponent);
421 rsa.write_modulus(modulus);
422 rsa.write_mprime(m_prime);
423
424 #[cfg(not(rsa_version = "1"))]
425 if rsa.is_search_enabled() {
426 rsa.write_search_position(Self::find_search_pos(exponent));
427 }
428
429 Self {
430 rsa,
431 phantom: PhantomData,
432 }
433 }
434
435 fn set_up_exponentiation(&mut self, base: &T::InputType, r: &T::InputType) {
436 self.rsa.write_operand_a(base);
437 self.rsa.write_r(r);
438 }
439
440 #[doc = trm_markdown_link!("rsa")]
446 pub fn start_exponentiation(&mut self, base: &T::InputType, r: &T::InputType) {
447 self.set_up_exponentiation(base, r);
448 self.rsa.start_modexp();
449 }
450
451 pub fn read_results(&mut self, outbuf: &mut T::InputType) {
457 self.rsa.read_results(outbuf);
458 }
459
460 #[cfg(not(rsa_version = "1"))]
461 fn find_search_pos(exponent: &T::InputType) -> u32 {
462 for (i, byte) in exponent.iter().rev().enumerate() {
463 if *byte == 0 {
464 continue;
465 }
466 return (exponent.len() * 32) as u32 - (byte.leading_zeros() + i as u32 * 32) - 1;
467 }
468 0
469 }
470
471 fn write_mode(rsa: &mut Rsa<'d, Dm>) {
473 rsa.write_modexp_mode(N as u32 / WORDS_PER_INCREMENT - 1);
474 }
475}
476
477pub struct RsaModularMultiplication<'a, 'd, T, Dm>
482where
483 T: RsaMode,
484 Dm: DriverMode,
485{
486 rsa: &'a mut Rsa<'d, Dm>,
487 phantom: PhantomData<T>,
488}
489
490impl<'a, 'd, T, Dm, const N: usize> RsaModularMultiplication<'a, 'd, T, Dm>
491where
492 T: RsaMode<InputType = [u32; N]>,
493 Dm: DriverMode,
494{
495 #[doc = trm_markdown_link!("rsa")]
502 pub fn new(
503 rsa: &'a mut Rsa<'d, Dm>,
504 operand_a: &T::InputType,
505 modulus: &T::InputType,
506 r: &T::InputType,
507 m_prime: u32,
508 ) -> Self {
509 rsa.write_multi_mode(N as u32 / WORDS_PER_INCREMENT - 1, true);
510
511 rsa.write_mprime(m_prime);
512 rsa.write_modulus(modulus);
513 rsa.write_operand_a(operand_a);
514 rsa.write_r(r);
515
516 Self {
517 rsa,
518 phantom: PhantomData,
519 }
520 }
521
522 #[doc = trm_markdown_link!("rsa")]
526 pub fn start_modular_multiplication(&mut self, operand_b: &T::InputType) {
527 self.set_up_modular_multiplication(operand_b);
528 self.rsa.start_modmulti();
529 }
530
531 pub fn read_results(&mut self, outbuf: &mut T::InputType) {
537 self.rsa.read_results(outbuf);
538 }
539
540 fn set_up_modular_multiplication(&mut self, operand_b: &T::InputType) {
541 if cfg!(rsa_version = "1") {
542 self.rsa.start_multi();
543 self.rsa.wait_for_idle();
544
545 self.rsa.write_operand_a(operand_b);
546 } else {
547 self.rsa.write_operand_b(operand_b);
548 }
549 }
550}
551
552pub struct RsaMultiplication<'a, 'd, T, Dm>
557where
558 T: RsaMode + Multi,
559 Dm: DriverMode,
560{
561 rsa: &'a mut Rsa<'d, Dm>,
562 phantom: PhantomData<T>,
563}
564
565impl<'a, 'd, T, Dm, const N: usize> RsaMultiplication<'a, 'd, T, Dm>
566where
567 T: RsaMode<InputType = [u32; N]>,
568 T: Multi,
569 Dm: DriverMode,
570{
571 pub fn new(rsa: &'a mut Rsa<'d, Dm>, operand_a: &T::InputType) -> Self {
573 rsa.write_multi_mode(2 * N as u32 / WORDS_PER_INCREMENT - 1, false);
575 rsa.write_operand_a(operand_a);
576
577 Self {
578 rsa,
579 phantom: PhantomData,
580 }
581 }
582
583 pub fn start_multiplication(&mut self, operand_b: &T::InputType) {
585 self.set_up_multiplication(operand_b);
586 self.rsa.start_multi();
587 }
588
589 pub fn read_results<const O: usize>(&mut self, outbuf: &mut T::OutputType)
595 where
596 T: Multi<OutputType = [u32; O]>,
597 {
598 self.rsa.read_results(outbuf);
599 }
600
601 fn set_up_multiplication(&mut self, operand_b: &T::InputType) {
602 self.rsa.write_multi_operand_b(operand_b);
603 }
604}
605
606static WAKER: AtomicWaker = AtomicWaker::new();
607#[cfg(rsa_version = "1")]
608static SIGNALED: AtomicBool = AtomicBool::new(false);
609
610#[must_use = "futures do nothing unless you `.await` or poll them"]
612struct RsaFuture<'a, 'd> {
613 driver: &'a Rsa<'d, Async>,
614 _wake_lock: WakeLock,
615}
616
617impl<'a, 'd> RsaFuture<'a, 'd> {
618 fn new(driver: &'a Rsa<'d, Async>) -> Self {
619 #[cfg(rsa_version = "1")]
620 SIGNALED.store(false, Ordering::Relaxed);
621
622 driver.internal_enable_disable_interrupt(true);
623
624 Self {
625 driver,
626 _wake_lock: WakeLock::new(),
627 }
628 }
629
630 fn is_done(&self) -> bool {
631 cfg_select! {
632 rsa_version = "1" => SIGNALED.load(Ordering::Acquire),
633 _ => self.driver.is_idle(),
634 }
635 }
636}
637
638impl Drop for RsaFuture<'_, '_> {
639 fn drop(&mut self) {
640 self.driver.internal_enable_disable_interrupt(false);
641 }
642}
643
644impl core::future::Future for RsaFuture<'_, '_> {
645 type Output = ();
646
647 fn poll(
648 self: core::pin::Pin<&mut Self>,
649 cx: &mut core::task::Context<'_>,
650 ) -> core::task::Poll<Self::Output> {
651 WAKER.register(cx.waker());
652 if self.is_done() {
653 Poll::Ready(())
654 } else {
655 Poll::Pending
656 }
657 }
658}
659
660impl<T: RsaMode, const N: usize> RsaModularExponentiation<'_, '_, T, Async>
661where
662 T: RsaMode<InputType = [u32; N]>,
663{
664 pub async fn exponentiation(
666 &mut self,
667 base: &T::InputType,
668 r: &T::InputType,
669 outbuf: &mut T::InputType,
670 ) {
671 self.set_up_exponentiation(base, r);
672 let fut = RsaFuture::new(self.rsa);
673 self.rsa.start_modexp();
674 fut.await;
675 self.rsa.read_out(outbuf);
676 }
677}
678
679impl<T: RsaMode, const N: usize> RsaModularMultiplication<'_, '_, T, Async>
680where
681 T: RsaMode<InputType = [u32; N]>,
682{
683 pub async fn modular_multiplication(
685 &mut self,
686 operand_b: &T::InputType,
687 outbuf: &mut T::InputType,
688 ) {
689 if cfg!(rsa_version = "1") {
690 let fut = RsaFuture::new(self.rsa);
691 self.rsa.start_multi();
692 fut.await;
693
694 self.rsa.write_operand_a(operand_b);
695 } else {
696 self.set_up_modular_multiplication(operand_b);
697 }
698
699 let fut = RsaFuture::new(self.rsa);
700 self.rsa.start_modmulti();
701 fut.await;
702 self.rsa.read_out(outbuf);
703 }
704}
705
706impl<T: RsaMode + Multi, const N: usize> RsaMultiplication<'_, '_, T, Async>
707where
708 T: RsaMode<InputType = [u32; N]>,
709{
710 pub async fn multiplication<const O: usize>(
712 &mut self,
713 operand_b: &T::InputType,
714 outbuf: &mut T::OutputType,
715 ) where
716 T: Multi<OutputType = [u32; O]>,
717 {
718 self.set_up_multiplication(operand_b);
719 let fut = RsaFuture::new(self.rsa);
720 self.rsa.start_multi();
721 fut.await;
722 self.rsa.read_out(outbuf);
723 }
724}
725
726#[handler]
727pub(super) fn rsa_interrupt_handler() {
729 let rsa = RSA::regs();
730
731 #[cfg(rsa_version = "1")]
732 SIGNALED.store(true, Ordering::Release);
733
734 low_level::clear_interrupt(rsa);
735
736 WAKER.wake();
737}
738
739static RSA_WORK_QUEUE: WorkQueue<RsaWorkItem> = WorkQueue::new();
740const RSA_VTABLE: VTable<RsaWorkItem> = VTable {
741 post: |driver, item| {
742 let driver = unsafe { RsaBackend::from_raw(driver) };
744 Some(driver.process_item(item))
745 },
746 poll: |driver, item| {
747 let driver = unsafe { RsaBackend::from_raw(driver) };
748 driver.process_item(item)
749 },
750 cancel: |driver, item| {
751 let driver = unsafe { RsaBackend::from_raw(driver) };
752 driver.cancel(item)
753 },
754 stop: |driver| {
755 let driver = unsafe { RsaBackend::from_raw(driver) };
756 driver.deinitialize()
757 },
758};
759
760#[derive(Default)]
761enum RsaBackendState<'d> {
762 #[default]
763 Idle,
764 Initializing(Rsa<'d, Blocking>),
765 Ready(Rsa<'d, Blocking>),
766 #[cfg(rsa_version = "1")]
767 ModularMultiplicationRoundOne(Rsa<'d, Blocking>),
768 Processing(Rsa<'d, Blocking>),
769}
770
771#[procmacros::doc_replace]
772pub struct RsaBackend<'d> {
802 peri: RSA<'d>,
803 state: RsaBackendState<'d>,
804}
805
806impl<'d> RsaBackend<'d> {
807 #[procmacros::doc_replace]
808 pub fn new(rsa: RSA<'d>) -> Self {
820 Self {
821 peri: rsa,
822 state: RsaBackendState::Idle,
823 }
824 }
825
826 #[procmacros::doc_replace]
827 pub fn start(&mut self) -> RsaWorkQueueDriver<'_, 'd> {
843 RsaWorkQueueDriver {
844 inner: WorkQueueDriver::new(self, RSA_VTABLE, &RSA_WORK_QUEUE),
845 }
846 }
847
848 unsafe fn from_raw<'any>(ptr: NonNull<()>) -> &'any mut Self {
851 unsafe { ptr.cast::<RsaBackend<'_>>().as_mut() }
852 }
853
854 fn process_item(&mut self, item: &mut RsaWorkItem) -> work_queue::Poll {
855 match core::mem::take(&mut self.state) {
856 RsaBackendState::Idle => {
857 let driver = Rsa {
858 rsa: unsafe { self.peri.clone_unchecked() },
859 phantom: PhantomData,
860 _guard: RsaGuard::new(),
861 };
862 self.state = RsaBackendState::Initializing(driver);
863 work_queue::Poll::Pending(true)
864 }
865 RsaBackendState::Initializing(mut rsa) => {
866 self.state = if rsa.ready() {
869 rsa.set_interrupt_handler(rsa_work_queue_handler);
870 rsa.enable_disable_interrupt(true);
871 RsaBackendState::Ready(rsa)
872 } else {
873 RsaBackendState::Initializing(rsa)
874 };
875 work_queue::Poll::Pending(true)
876 }
877 RsaBackendState::Ready(mut rsa) => {
878 #[cfg(not(rsa_version = "1"))]
879 {
880 rsa.disable_constant_time(!item.constant_time);
881 rsa.search_acceleration(item.search_acceleration);
882 }
883
884 match item.operation {
885 RsaOperation::Multiplication { x, y } => {
886 let n = x.len() as u32;
887 rsa.write_operand_a(unsafe { x.as_ref() });
888
889 rsa.write_multi_mode(2 * n / WORDS_PER_INCREMENT - 1, false);
891 rsa.write_multi_operand_b(unsafe { y.as_ref() });
892 rsa.start_multi();
893 }
894
895 RsaOperation::ModularMultiplication {
896 x,
897 #[cfg(not(rsa_version = "1"))]
898 y,
899 m,
900 m_prime,
901 r: r_inv,
902 ..
903 } => {
904 let n = x.len() as u32;
905 rsa.write_operand_a(unsafe { x.as_ref() });
906
907 rsa.write_multi_mode(n / WORDS_PER_INCREMENT - 1, true);
908
909 #[cfg(not(rsa_version = "1"))]
910 rsa.write_operand_b(unsafe { y.as_ref() });
911
912 rsa.write_modulus(unsafe { m.as_ref() });
913 rsa.write_mprime(m_prime);
914 rsa.write_r(unsafe { r_inv.as_ref() });
915
916 rsa.start_modmulti();
917
918 #[cfg(rsa_version = "1")]
919 {
920 self.state = RsaBackendState::ModularMultiplicationRoundOne(rsa);
923
924 return work_queue::Poll::Pending(false);
925 }
926 }
927 RsaOperation::ModularExponentiation {
928 x,
929 y,
930 m,
931 m_prime,
932 r_inv,
933 } => {
934 let n = x.len() as u32;
935 rsa.write_operand_a(unsafe { x.as_ref() });
936
937 rsa.write_modexp_mode(n / WORDS_PER_INCREMENT - 1);
938 rsa.write_operand_b(unsafe { y.as_ref() });
939 rsa.write_modulus(unsafe { m.as_ref() });
940 rsa.write_mprime(m_prime);
941 rsa.write_r(unsafe { r_inv.as_ref() });
942
943 #[cfg(not(rsa_version = "1"))]
944 if item.search_acceleration {
945 fn find_search_pos(exponent: &[u32]) -> u32 {
946 for (i, byte) in exponent.iter().rev().enumerate() {
947 if *byte == 0 {
948 continue;
949 }
950 return (exponent.len() * 32) as u32
951 - (byte.leading_zeros() + i as u32 * 32)
952 - 1;
953 }
954 0
955 }
956 rsa.write_search_position(find_search_pos(unsafe { y.as_ref() }));
957 }
958
959 rsa.start_modexp();
960 }
961 }
962
963 self.state = RsaBackendState::Processing(rsa);
964
965 work_queue::Poll::Pending(false)
966 }
967
968 #[cfg(rsa_version = "1")]
969 RsaBackendState::ModularMultiplicationRoundOne(mut rsa) => {
970 if rsa.is_idle() {
971 let RsaOperation::ModularMultiplication { y, .. } = item.operation else {
972 unreachable!();
973 };
974
975 rsa.write_operand_a(unsafe { y.as_ref() });
977 rsa.start_modmulti();
978
979 self.state = RsaBackendState::Processing(rsa);
980 } else {
981 self.state = RsaBackendState::ModularMultiplicationRoundOne(rsa);
983 }
984 work_queue::Poll::Pending(false)
985 }
986
987 RsaBackendState::Processing(rsa) => {
988 if rsa.is_idle() {
989 rsa.read_out(unsafe { item.result.as_mut() });
990
991 self.state = RsaBackendState::Ready(rsa);
992 work_queue::Poll::Ready(Status::Completed)
993 } else {
994 self.state = RsaBackendState::Processing(rsa);
995 work_queue::Poll::Pending(false)
996 }
997 }
998 }
999 }
1000
1001 fn cancel(&mut self, _item: &mut RsaWorkItem) {
1002 self.state = RsaBackendState::Idle;
1005 }
1006
1007 fn deinitialize(&mut self) {
1008 self.state = RsaBackendState::Idle;
1009 }
1010}
1011
1012pub struct RsaWorkQueueDriver<'t, 'd> {
1018 inner: WorkQueueDriver<'t, RsaBackend<'d>, RsaWorkItem>,
1019}
1020
1021impl<'t, 'd> RsaWorkQueueDriver<'t, 'd> {
1022 pub fn stop(self) -> impl Future<Output = ()> {
1024 self.inner.stop()
1025 }
1026}
1027
1028#[derive(Clone)]
1029struct RsaWorkItem {
1030 #[cfg(not(rsa_version = "1"))]
1032 search_acceleration: bool,
1033 #[cfg(not(rsa_version = "1"))]
1034 constant_time: bool,
1035
1036 operation: RsaOperation,
1038 result: NonNull<[u32]>,
1039}
1040
1041unsafe impl Sync for RsaWorkItem {}
1042unsafe impl Send for RsaWorkItem {}
1043
1044#[derive(Clone)]
1045enum RsaOperation {
1046 Multiplication {
1049 x: NonNull<[u32]>,
1050 y: NonNull<[u32]>,
1051 },
1052 ModularMultiplication {
1054 x: NonNull<[u32]>,
1055 y: NonNull<[u32]>,
1056 m: NonNull<[u32]>,
1057 r: NonNull<[u32]>,
1058 m_prime: u32,
1059 },
1060 ModularExponentiation {
1062 x: NonNull<[u32]>,
1063 y: NonNull<[u32]>,
1064 m: NonNull<[u32]>,
1065 r_inv: NonNull<[u32]>,
1066 m_prime: u32,
1067 },
1068}
1069
1070#[handler]
1071#[ram]
1072fn rsa_work_queue_handler() {
1073 if !RSA_WORK_QUEUE.process() {
1074 low_level::clear_interrupt(RSA::regs());
1077 }
1078}
1079
1080#[cfg_attr(
1087 not(rsa_version = "1"),
1088 doc = " \nThe context is created with a secure configuration by default. You can enable hardware acceleration
1089 options using [enable_search_acceleration][Self::enable_search_acceleration] and
1090 [enable_acceleration][Self::enable_acceleration] when appropriate."
1091)]
1092#[derive(Clone)]
1093pub struct RsaContext {
1094 frontend: WorkQueueFrontend<RsaWorkItem>,
1095}
1096
1097impl Default for RsaContext {
1098 fn default() -> Self {
1099 Self::new()
1100 }
1101}
1102
1103impl RsaContext {
1104 pub fn new() -> Self {
1106 Self {
1107 frontend: WorkQueueFrontend::new(RsaWorkItem {
1108 #[cfg(not(rsa_version = "1"))]
1109 search_acceleration: false,
1110 #[cfg(not(rsa_version = "1"))]
1111 constant_time: true,
1112 operation: RsaOperation::Multiplication {
1113 x: NonNull::from(&[]),
1114 y: NonNull::from(&[]),
1115 },
1116 result: NonNull::from(&mut []),
1117 }),
1118 }
1119 }
1120
1121 #[cfg(not(rsa_version = "1"))]
1122 #[doc = trm_markdown_link!("rsa")]
1132 pub fn enable_search_acceleration(&mut self) {
1133 self.frontend.data_mut().search_acceleration = true;
1134 }
1135
1136 #[cfg(not(rsa_version = "1"))]
1137 #[doc = trm_markdown_link!("rsa")]
1148 pub fn enable_acceleration(&mut self) {
1149 self.frontend.data_mut().constant_time = false;
1150 }
1151
1152 fn post(&mut self) -> RsaHandle<'_> {
1153 RsaHandle(self.frontend.post(&RSA_WORK_QUEUE))
1154 }
1155
1156 #[procmacros::doc_replace]
1157 pub fn modular_exponentiate<'t, OP>(
1225 &'t mut self,
1226 x: &'t OP::InputType,
1227 y: &'t OP::InputType,
1228 m: &'t OP::InputType,
1229 r: &'t OP::InputType,
1230 m_prime: u32,
1231 result: &'t mut OP::InputType,
1232 ) -> RsaHandle<'t>
1233 where
1234 OP: RsaMode,
1235 {
1236 self.frontend.data_mut().operation = RsaOperation::ModularExponentiation {
1237 x: NonNull::from(x.as_ref()),
1238 y: NonNull::from(y.as_ref()),
1239 m: NonNull::from(m.as_ref()),
1240 r_inv: NonNull::from(r.as_ref()),
1241 m_prime,
1242 };
1243 self.frontend.data_mut().result = NonNull::from(result.as_mut());
1244 self.post()
1245 }
1246
1247 pub fn modular_multiply<'t, OP>(
1263 &'t mut self,
1264 x: &'t OP::InputType,
1265 y: &'t OP::InputType,
1266 m: &'t OP::InputType,
1267 r: &'t OP::InputType,
1268 m_prime: u32,
1269 result: &'t mut OP::InputType,
1270 ) -> RsaHandle<'t>
1271 where
1272 OP: RsaMode,
1273 {
1274 self.frontend.data_mut().operation = RsaOperation::ModularMultiplication {
1275 x: NonNull::from(x.as_ref()),
1276 y: NonNull::from(y.as_ref()),
1277 m: NonNull::from(m.as_ref()),
1278 r: NonNull::from(r.as_ref()),
1279 m_prime,
1280 };
1281 self.frontend.data_mut().result = NonNull::from(result.as_mut());
1282 self.post()
1283 }
1284
1285 #[procmacros::doc_replace]
1286 pub fn multiply<'t, OP>(
1316 &'t mut self,
1317 x: &'t OP::InputType,
1318 y: &'t OP::InputType,
1319 result: &'t mut OP::OutputType,
1320 ) -> RsaHandle<'t>
1321 where
1322 OP: Multi,
1323 {
1324 self.frontend.data_mut().operation = RsaOperation::Multiplication {
1325 x: NonNull::from(x.as_ref()),
1326 y: NonNull::from(y.as_ref()),
1327 };
1328 self.frontend.data_mut().result = NonNull::from(result.as_mut());
1329 self.post()
1330 }
1331}
1332
1333pub struct RsaHandle<'t>(work_queue::Handle<'t, RsaWorkItem>);
1335
1336impl RsaHandle<'_> {
1337 #[inline]
1339 pub fn poll(&mut self) -> bool {
1340 self.0.poll()
1341 }
1342
1343 #[inline]
1345 pub fn wait_blocking(self) {
1346 self.0.wait_blocking();
1347 }
1348
1349 #[inline]
1351 pub fn wait(&mut self) -> impl Future<Output = Status> {
1352 self.0.wait()
1353 }
1354}