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::{CryptoClockGuard, 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
48#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, procmacros::BuilderLite)]
53#[cfg_attr(feature = "defmt", derive(defmt::Format))]
54#[non_exhaustive]
55pub struct Config {
56 #[cfg(not(rsa_version = "1"))]
64 constant_time: bool,
65
66 #[cfg(not(rsa_version = "1"))]
74 search_acceleration: bool,
75}
76
77#[cfg_attr(rsa_version = "1", expect(clippy::derivable_impls))]
78impl Default for Config {
79 fn default() -> Self {
80 Self {
81 #[cfg(not(rsa_version = "1"))]
82 constant_time: true,
83 #[cfg(not(rsa_version = "1"))]
84 search_acceleration: false,
85 }
86 }
87}
88
89#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
91#[cfg_attr(feature = "defmt", derive(defmt::Format))]
92#[non_exhaustive]
93pub enum ConfigError {}
94
95const WORDS_PER_INCREMENT: u32 = property!("rsa.size_increment") / 32;
104
105struct RsaGuard {
106 _guard: GenericPeripheralGuard<{ PeripheralEnable::Rsa as u8 }>,
107 _clock_guard: CryptoClockGuard,
108}
109
110impl RsaGuard {
111 fn new() -> Self {
112 let _clock_guard = CryptoClockGuard::new();
113 let _guard = GenericPeripheralGuard::new();
114 cfg_select! {
115 rsa_version = "1" => {}
116 esp32s31 => {}
117 _ => {
118 crate::peripherals::SYSTEM::regs()
119 .rsa_pd_ctrl()
120 .modify(|_, w| {
121 w.rsa_mem_force_pd().clear_bit();
122 w.rsa_mem_force_pu().set_bit();
123 w.rsa_mem_pd().clear_bit()
124 });
125 }
126 }
127
128 Self {
129 _guard,
130 _clock_guard,
131 }
132 }
133}
134
135impl Drop for RsaGuard {
136 fn drop(&mut self) {
137 unsafe {
138 crate::peripherals::RSA::steal().disable_peri_interrupt_on_all_cores();
143 }
144
145 cfg_select! {
146 rsa_version = "1" => {}
147 esp32s31 => {}
148 _ => {
149 crate::peripherals::SYSTEM::regs()
150 .rsa_pd_ctrl()
151 .modify(|_, w| {
152 w.rsa_mem_force_pd().clear_bit();
153 w.rsa_mem_force_pu().clear_bit();
154 w.rsa_mem_pd().set_bit()
155 });
156 }
157 }
158 }
159}
160
161impl<'d> Rsa<'d, Blocking> {
162 pub fn new(rsa: RSA<'d>, config: Config) -> Result<Self, ConfigError> {
166 let mut this = Self {
167 rsa,
168 phantom: PhantomData,
169 _guard: RsaGuard::new(),
170 };
171
172 while !this.ready() {}
173
174 this.apply_config(&config)?;
175 Ok(this)
176 }
177
178 pub fn into_async(mut self) -> Rsa<'d, Async> {
180 self.set_interrupt_handler(rsa_interrupt_handler);
181 self.enable_disable_interrupt(true);
182
183 Rsa {
184 rsa: self.rsa,
185 phantom: PhantomData,
186 _guard: self._guard,
187 }
188 }
189
190 pub fn enable_disable_interrupt(&mut self, enable: bool) {
195 self.internal_enable_disable_interrupt(enable);
196 }
197
198 #[instability::unstable]
202 pub fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
203 self.rsa.disable_peri_interrupt_on_all_cores();
204 self.rsa.bind_peri_interrupt(handler);
205 }
206}
207
208impl crate::private::Sealed for Rsa<'_, Blocking> {}
209
210#[instability::unstable]
211impl crate::interrupt::InterruptConfigurable for Rsa<'_, Blocking> {
212 fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
213 self.set_interrupt_handler(handler);
214 }
215}
216
217impl<'d> Rsa<'d, Async> {
218 pub fn into_blocking(self) -> Rsa<'d, Blocking> {
220 self.internal_enable_disable_interrupt(false);
221 self.rsa.disable_peri_interrupt_on_all_cores();
222
223 Rsa {
224 rsa: self.rsa,
225 phantom: PhantomData,
226 _guard: self._guard,
227 }
228 }
229}
230
231impl<'d, Dm: DriverMode> Rsa<'d, Dm> {
232 fn internal_enable_disable_interrupt(&self, enable: bool) {
233 low_level::enable_disable_interrupt(self.regs(), enable);
234 }
235
236 fn regs(&self) -> &pac::rsa::RegisterBlock {
237 self.rsa.register_block()
238 }
239
240 fn ready(&self) -> bool {
242 low_level::ready(self.regs())
243 }
244
245 fn start_modexp(&self) {
247 low_level::start_modexp(self.regs());
248 }
249
250 fn start_multi(&self) {
252 low_level::start_multi(self.regs());
253 }
254
255 fn start_modmulti(&self) {
257 low_level::start_modmulti(self.regs());
258 }
259
260 fn clear_interrupt(&mut self) {
262 low_level::clear_interrupt(self.regs());
263 }
264
265 fn is_idle(&self) -> bool {
267 low_level::is_idle(self.regs())
268 }
269
270 fn wait_for_idle(&mut self) {
271 while !self.is_idle() {}
272 self.clear_interrupt();
273 }
274
275 fn write_multi_mode(&mut self, mode: u32, modular: bool) {
277 low_level::write_multi_mode(self.regs(), mode, modular);
278 }
279
280 fn write_modexp_mode(&mut self, mode: u32) {
282 low_level::write_modexp_mode(self.regs(), mode);
283 }
284
285 fn write_operand_b(&mut self, operand: &[u32]) {
286 for (reg, op) in self.regs().y_mem_iter().zip(operand.iter().copied()) {
287 reg.write(|w| unsafe { w.bits(op) });
288 }
289 }
290
291 fn write_modulus(&mut self, modulus: &[u32]) {
292 for (reg, op) in self.regs().m_mem_iter().zip(modulus.iter().copied()) {
293 reg.write(|w| unsafe { w.bits(op) });
294 }
295 }
296
297 fn write_mprime(&mut self, m_prime: u32) {
298 self.regs().m_prime().write(|w| unsafe { w.bits(m_prime) });
299 }
300
301 fn write_operand_a(&mut self, operand: &[u32]) {
302 for (reg, op) in self.regs().x_mem_iter().zip(operand.iter().copied()) {
303 reg.write(|w| unsafe { w.bits(op) });
304 }
305 }
306
307 fn write_multi_operand_b(&mut self, operand: &[u32]) {
308 for (reg, op) in self
309 .regs()
310 .z_mem_iter()
311 .skip(operand.len())
312 .zip(operand.iter().copied())
313 {
314 reg.write(|w| unsafe { w.bits(op) });
315 }
316 }
317
318 fn write_r(&mut self, r: &[u32]) {
319 for (reg, op) in self.regs().z_mem_iter().zip(r.iter().copied()) {
320 reg.write(|w| unsafe { w.bits(op) });
321 }
322 }
323
324 fn read_out(&self, outbuf: &mut [u32]) {
325 for (reg, op) in self.regs().z_mem_iter().zip(outbuf.iter_mut()) {
326 *op = reg.read().bits();
327 }
328
329 #[cfg(clear_crypto_secrets)]
330 self.clear_secrets();
331 }
332
333 #[cfg(clear_crypto_secrets)]
335 fn clear_secrets(&self) {
336 for reg in self.regs().x_mem_iter() {
337 reg.write(|w| unsafe { w.bits(0) });
338 }
339 for reg in self.regs().y_mem_iter() {
340 reg.write(|w| unsafe { w.bits(0) });
341 }
342 for reg in self.regs().z_mem_iter() {
343 reg.write(|w| unsafe { w.bits(0) });
344 }
345 for reg in self.regs().m_mem_iter() {
346 reg.write(|w| unsafe { w.bits(0) });
347 }
348 }
349
350 fn read_results(&mut self, outbuf: &mut [u32]) {
351 self.wait_for_idle();
352 self.read_out(outbuf);
353 }
354
355 #[doc = trm_markdown_link!("rsa")]
359 pub fn apply_config(&mut self, config: &Config) -> Result<(), ConfigError> {
360 self.write_config(config);
361 Ok(())
362 }
363
364 fn write_config(&mut self, _config: &Config) {
365 #[cfg(not(rsa_version = "1"))]
366 {
367 self.regs()
368 .constant_time()
369 .write(|w| w.constant_time().bit(_config.constant_time));
370 self.regs()
371 .search_enable()
372 .write(|w| w.search_enable().bit(_config.search_acceleration));
373 }
374 }
375
376 #[cfg(not(rsa_version = "1"))]
378 fn is_search_enabled(&mut self) -> bool {
379 self.regs()
380 .search_enable()
381 .read()
382 .search_enable()
383 .bit_is_set()
384 }
385
386 #[cfg(not(rsa_version = "1"))]
388 fn write_search_position(&mut self, search_position: u32) {
389 self.regs()
390 .search_pos()
391 .write(|w| unsafe { w.bits(search_position) });
392 }
393}
394
395pub trait RsaMode: crate::private::Sealed {
397 type InputType: AsRef<[u32]> + AsMut<[u32]>;
399}
400
401pub trait Multi: RsaMode {
403 type OutputType: AsRef<[u32]> + AsMut<[u32]>;
405}
406
407pub mod operand_sizes {
409 for_each_rsa_exponentiation!(
410 ($x:literal) => {
411 paste::paste! {
412 #[doc = concat!(stringify!($x), "-bit RSA operation.")]
413 pub struct [<Op $x>];
414
415 impl crate::private::Sealed for [<Op $x>] {}
416 impl crate::rsa::RsaMode for [<Op $x>] {
417 type InputType = [u32; $x / 32];
418 }
419 }
420 };
421 );
422
423 for_each_rsa_multiplication!(
424 ($x:literal) => {
425 impl crate::rsa::Multi for paste::paste!( [<Op $x>] ) {
426 type OutputType = [u32; $x * 2 / 32];
427 }
428 };
429 );
430}
431
432pub struct RsaModularExponentiation<'a, 'd, T: RsaMode, Dm: DriverMode> {
437 rsa: &'a mut Rsa<'d, Dm>,
438 phantom: PhantomData<T>,
439}
440
441impl<'a, 'd, T: RsaMode, Dm: DriverMode, const N: usize> RsaModularExponentiation<'a, 'd, T, Dm>
442where
443 T: RsaMode<InputType = [u32; N]>,
444{
445 #[doc = trm_markdown_link!("rsa")]
452 pub fn new(
453 rsa: &'a mut Rsa<'d, Dm>,
454 exponent: &T::InputType,
455 modulus: &T::InputType,
456 m_prime: u32,
457 ) -> Self {
458 Self::write_mode(rsa);
459 rsa.write_operand_b(exponent);
460 rsa.write_modulus(modulus);
461 rsa.write_mprime(m_prime);
462
463 #[cfg(not(rsa_version = "1"))]
464 if rsa.is_search_enabled() {
465 rsa.write_search_position(Self::find_search_pos(exponent));
466 }
467
468 Self {
469 rsa,
470 phantom: PhantomData,
471 }
472 }
473
474 fn set_up_exponentiation(&mut self, base: &T::InputType, r: &T::InputType) {
475 self.rsa.write_operand_a(base);
476 self.rsa.write_r(r);
477 }
478
479 #[doc = trm_markdown_link!("rsa")]
485 pub fn start_exponentiation(&mut self, base: &T::InputType, r: &T::InputType) {
486 self.set_up_exponentiation(base, r);
487 self.rsa.start_modexp();
488 }
489
490 pub fn read_results(&mut self, outbuf: &mut T::InputType) {
496 self.rsa.read_results(outbuf);
497 }
498
499 #[cfg(not(rsa_version = "1"))]
500 fn find_search_pos(exponent: &T::InputType) -> u32 {
501 for (i, byte) in exponent.iter().rev().enumerate() {
502 if *byte == 0 {
503 continue;
504 }
505 return (exponent.len() * 32) as u32 - (byte.leading_zeros() + i as u32 * 32) - 1;
506 }
507 0
508 }
509
510 fn write_mode(rsa: &mut Rsa<'d, Dm>) {
512 rsa.write_modexp_mode(N as u32 / WORDS_PER_INCREMENT - 1);
513 }
514}
515
516pub struct RsaModularMultiplication<'a, 'd, T, Dm>
521where
522 T: RsaMode,
523 Dm: DriverMode,
524{
525 rsa: &'a mut Rsa<'d, Dm>,
526 phantom: PhantomData<T>,
527}
528
529impl<'a, 'd, T, Dm, const N: usize> RsaModularMultiplication<'a, 'd, T, Dm>
530where
531 T: RsaMode<InputType = [u32; N]>,
532 Dm: DriverMode,
533{
534 #[doc = trm_markdown_link!("rsa")]
541 pub fn new(
542 rsa: &'a mut Rsa<'d, Dm>,
543 operand_a: &T::InputType,
544 modulus: &T::InputType,
545 r: &T::InputType,
546 m_prime: u32,
547 ) -> Self {
548 rsa.write_multi_mode(N as u32 / WORDS_PER_INCREMENT - 1, true);
549
550 rsa.write_mprime(m_prime);
551 rsa.write_modulus(modulus);
552 rsa.write_operand_a(operand_a);
553 rsa.write_r(r);
554
555 Self {
556 rsa,
557 phantom: PhantomData,
558 }
559 }
560
561 #[doc = trm_markdown_link!("rsa")]
565 pub fn start_modular_multiplication(&mut self, operand_b: &T::InputType) {
566 self.set_up_modular_multiplication(operand_b);
567 self.rsa.start_modmulti();
568 }
569
570 pub fn read_results(&mut self, outbuf: &mut T::InputType) {
576 self.rsa.read_results(outbuf);
577 }
578
579 fn set_up_modular_multiplication(&mut self, operand_b: &T::InputType) {
580 if cfg!(rsa_version = "1") {
581 self.rsa.start_multi();
582 self.rsa.wait_for_idle();
583
584 self.rsa.write_operand_a(operand_b);
585 } else {
586 self.rsa.write_operand_b(operand_b);
587 }
588 }
589}
590
591pub struct RsaMultiplication<'a, 'd, T, Dm>
596where
597 T: RsaMode + Multi,
598 Dm: DriverMode,
599{
600 rsa: &'a mut Rsa<'d, Dm>,
601 phantom: PhantomData<T>,
602}
603
604impl<'a, 'd, T, Dm, const N: usize> RsaMultiplication<'a, 'd, T, Dm>
605where
606 T: RsaMode<InputType = [u32; N]>,
607 T: Multi,
608 Dm: DriverMode,
609{
610 pub fn new(rsa: &'a mut Rsa<'d, Dm>, operand_a: &T::InputType) -> Self {
612 rsa.write_multi_mode(2 * N as u32 / WORDS_PER_INCREMENT - 1, false);
614 rsa.write_operand_a(operand_a);
615
616 Self {
617 rsa,
618 phantom: PhantomData,
619 }
620 }
621
622 pub fn start_multiplication(&mut self, operand_b: &T::InputType) {
624 self.set_up_multiplication(operand_b);
625 self.rsa.start_multi();
626 }
627
628 pub fn read_results<const O: usize>(&mut self, outbuf: &mut T::OutputType)
634 where
635 T: Multi<OutputType = [u32; O]>,
636 {
637 self.rsa.read_results(outbuf);
638 }
639
640 fn set_up_multiplication(&mut self, operand_b: &T::InputType) {
641 self.rsa.write_multi_operand_b(operand_b);
642 }
643}
644
645static WAKER: AtomicWaker = AtomicWaker::new();
646#[cfg(rsa_version = "1")]
647static SIGNALED: AtomicBool = AtomicBool::new(false);
648
649#[must_use = "futures do nothing unless you `.await` or poll them"]
651struct RsaFuture<'a, 'd> {
652 driver: &'a Rsa<'d, Async>,
653 _wake_lock: WakeLock,
654}
655
656impl<'a, 'd> RsaFuture<'a, 'd> {
657 fn new(driver: &'a Rsa<'d, Async>) -> Self {
658 #[cfg(rsa_version = "1")]
659 SIGNALED.store(false, Ordering::Relaxed);
660
661 driver.internal_enable_disable_interrupt(true);
662
663 Self {
664 driver,
665 _wake_lock: WakeLock::new(),
666 }
667 }
668
669 fn is_done(&self) -> bool {
670 cfg_select! {
671 rsa_version = "1" => SIGNALED.load(Ordering::Acquire),
672 _ => self.driver.is_idle(),
673 }
674 }
675}
676
677impl Drop for RsaFuture<'_, '_> {
678 fn drop(&mut self) {
679 self.driver.internal_enable_disable_interrupt(false);
680 }
681}
682
683impl core::future::Future for RsaFuture<'_, '_> {
684 type Output = ();
685
686 fn poll(
687 self: core::pin::Pin<&mut Self>,
688 cx: &mut core::task::Context<'_>,
689 ) -> core::task::Poll<Self::Output> {
690 WAKER.register(cx.waker());
691 if self.is_done() {
692 Poll::Ready(())
693 } else {
694 Poll::Pending
695 }
696 }
697}
698
699impl<T: RsaMode, const N: usize> RsaModularExponentiation<'_, '_, T, Async>
700where
701 T: RsaMode<InputType = [u32; N]>,
702{
703 pub async fn exponentiation(
705 &mut self,
706 base: &T::InputType,
707 r: &T::InputType,
708 outbuf: &mut T::InputType,
709 ) {
710 self.set_up_exponentiation(base, r);
711 let fut = RsaFuture::new(self.rsa);
712 self.rsa.start_modexp();
713 fut.await;
714 self.rsa.read_out(outbuf);
715 }
716}
717
718impl<T: RsaMode, const N: usize> RsaModularMultiplication<'_, '_, T, Async>
719where
720 T: RsaMode<InputType = [u32; N]>,
721{
722 pub async fn modular_multiplication(
724 &mut self,
725 operand_b: &T::InputType,
726 outbuf: &mut T::InputType,
727 ) {
728 if cfg!(rsa_version = "1") {
729 let fut = RsaFuture::new(self.rsa);
730 self.rsa.start_multi();
731 fut.await;
732
733 self.rsa.write_operand_a(operand_b);
734 } else {
735 self.set_up_modular_multiplication(operand_b);
736 }
737
738 let fut = RsaFuture::new(self.rsa);
739 self.rsa.start_modmulti();
740 fut.await;
741 self.rsa.read_out(outbuf);
742 }
743}
744
745impl<T: RsaMode + Multi, const N: usize> RsaMultiplication<'_, '_, T, Async>
746where
747 T: RsaMode<InputType = [u32; N]>,
748{
749 pub async fn multiplication<const O: usize>(
751 &mut self,
752 operand_b: &T::InputType,
753 outbuf: &mut T::OutputType,
754 ) where
755 T: Multi<OutputType = [u32; O]>,
756 {
757 self.set_up_multiplication(operand_b);
758 let fut = RsaFuture::new(self.rsa);
759 self.rsa.start_multi();
760 fut.await;
761 self.rsa.read_out(outbuf);
762 }
763}
764
765#[handler]
766pub(super) fn rsa_interrupt_handler() {
768 let rsa = RSA::regs();
769
770 #[cfg(rsa_version = "1")]
771 SIGNALED.store(true, Ordering::Release);
772
773 low_level::clear_interrupt(rsa);
774
775 WAKER.wake();
776}
777
778static RSA_WORK_QUEUE: WorkQueue<RsaWorkItem> = WorkQueue::new();
779const RSA_VTABLE: VTable<RsaWorkItem> = VTable {
780 post: |driver, item| {
781 let driver = unsafe { RsaBackend::from_raw(driver) };
783 Some(driver.process_item(item))
784 },
785 poll: |driver, item| {
786 let driver = unsafe { RsaBackend::from_raw(driver) };
787 driver.process_item(item)
788 },
789 cancel: |driver, item| {
790 let driver = unsafe { RsaBackend::from_raw(driver) };
791 driver.cancel(item)
792 },
793 stop: |driver| {
794 let driver = unsafe { RsaBackend::from_raw(driver) };
795 driver.deinitialize()
796 },
797};
798
799#[derive(Default)]
800enum RsaBackendState<'d> {
801 #[default]
802 Idle,
803 Initializing(Rsa<'d, Blocking>),
804 Ready(Rsa<'d, Blocking>),
805 #[cfg(rsa_version = "1")]
806 ModularMultiplicationRoundOne(Rsa<'d, Blocking>),
807 Processing(Rsa<'d, Blocking>),
808}
809
810#[procmacros::doc_replace]
811pub struct RsaBackend<'d> {
841 peri: RSA<'d>,
842 state: RsaBackendState<'d>,
843}
844
845impl<'d> RsaBackend<'d> {
846 #[procmacros::doc_replace]
847 pub fn new(rsa: RSA<'d>) -> Self {
859 Self {
860 peri: rsa,
861 state: RsaBackendState::Idle,
862 }
863 }
864
865 #[procmacros::doc_replace]
866 pub fn start(&mut self) -> RsaWorkQueueDriver<'_, 'd> {
882 RsaWorkQueueDriver {
883 inner: WorkQueueDriver::new(self, RSA_VTABLE, &RSA_WORK_QUEUE),
884 }
885 }
886
887 unsafe fn from_raw<'any>(ptr: NonNull<()>) -> &'any mut Self {
890 unsafe { ptr.cast::<RsaBackend<'_>>().as_mut() }
891 }
892
893 fn process_item(&mut self, item: &mut RsaWorkItem) -> work_queue::Poll {
894 match core::mem::take(&mut self.state) {
895 RsaBackendState::Idle => {
896 let driver = Rsa {
897 rsa: unsafe { self.peri.clone_unchecked() },
898 phantom: PhantomData,
899 _guard: RsaGuard::new(),
900 };
901 self.state = RsaBackendState::Initializing(driver);
902 work_queue::Poll::Pending(true)
903 }
904 RsaBackendState::Initializing(mut rsa) => {
905 self.state = if rsa.ready() {
908 rsa.set_interrupt_handler(rsa_work_queue_handler);
909 rsa.enable_disable_interrupt(true);
910 RsaBackendState::Ready(rsa)
911 } else {
912 RsaBackendState::Initializing(rsa)
913 };
914 work_queue::Poll::Pending(true)
915 }
916 RsaBackendState::Ready(mut rsa) => {
917 rsa.write_config(&item.config);
918
919 match item.operation {
920 RsaOperation::Multiplication { x, y } => {
921 let n = x.len() as u32;
922 rsa.write_operand_a(unsafe { x.as_ref() });
923
924 rsa.write_multi_mode(2 * n / WORDS_PER_INCREMENT - 1, false);
926 rsa.write_multi_operand_b(unsafe { y.as_ref() });
927 rsa.start_multi();
928 }
929
930 RsaOperation::ModularMultiplication {
931 x,
932 #[cfg(not(rsa_version = "1"))]
933 y,
934 m,
935 m_prime,
936 r: r_inv,
937 ..
938 } => {
939 let n = x.len() as u32;
940 rsa.write_operand_a(unsafe { x.as_ref() });
941
942 rsa.write_multi_mode(n / WORDS_PER_INCREMENT - 1, true);
943
944 #[cfg(not(rsa_version = "1"))]
945 rsa.write_operand_b(unsafe { y.as_ref() });
946
947 rsa.write_modulus(unsafe { m.as_ref() });
948 rsa.write_mprime(m_prime);
949 rsa.write_r(unsafe { r_inv.as_ref() });
950
951 rsa.start_modmulti();
952
953 #[cfg(rsa_version = "1")]
954 {
955 self.state = RsaBackendState::ModularMultiplicationRoundOne(rsa);
958
959 return work_queue::Poll::Pending(false);
960 }
961 }
962 RsaOperation::ModularExponentiation {
963 x,
964 y,
965 m,
966 m_prime,
967 r_inv,
968 } => {
969 let n = x.len() as u32;
970 rsa.write_operand_a(unsafe { x.as_ref() });
971
972 rsa.write_modexp_mode(n / WORDS_PER_INCREMENT - 1);
973 rsa.write_operand_b(unsafe { y.as_ref() });
974 rsa.write_modulus(unsafe { m.as_ref() });
975 rsa.write_mprime(m_prime);
976 rsa.write_r(unsafe { r_inv.as_ref() });
977
978 #[cfg(not(rsa_version = "1"))]
979 if item.config.search_acceleration {
980 fn find_search_pos(exponent: &[u32]) -> u32 {
981 for (i, byte) in exponent.iter().rev().enumerate() {
982 if *byte == 0 {
983 continue;
984 }
985 return (exponent.len() * 32) as u32
986 - (byte.leading_zeros() + i as u32 * 32)
987 - 1;
988 }
989 0
990 }
991 rsa.write_search_position(find_search_pos(unsafe { y.as_ref() }));
992 }
993
994 rsa.start_modexp();
995 }
996 }
997
998 self.state = RsaBackendState::Processing(rsa);
999
1000 work_queue::Poll::Pending(false)
1001 }
1002
1003 #[cfg(rsa_version = "1")]
1004 RsaBackendState::ModularMultiplicationRoundOne(mut rsa) => {
1005 if rsa.is_idle() {
1006 let RsaOperation::ModularMultiplication { y, .. } = item.operation else {
1007 unreachable!();
1008 };
1009
1010 rsa.write_operand_a(unsafe { y.as_ref() });
1012 rsa.start_modmulti();
1013
1014 self.state = RsaBackendState::Processing(rsa);
1015 } else {
1016 self.state = RsaBackendState::ModularMultiplicationRoundOne(rsa);
1018 }
1019 work_queue::Poll::Pending(false)
1020 }
1021
1022 RsaBackendState::Processing(rsa) => {
1023 if rsa.is_idle() {
1024 rsa.read_out(unsafe { item.result.as_mut() });
1025
1026 self.state = RsaBackendState::Ready(rsa);
1027 work_queue::Poll::Ready(Status::Completed)
1028 } else {
1029 self.state = RsaBackendState::Processing(rsa);
1030 work_queue::Poll::Pending(false)
1031 }
1032 }
1033 }
1034 }
1035
1036 fn cancel(&mut self, _item: &mut RsaWorkItem) {
1037 self.state = RsaBackendState::Idle;
1040 }
1041
1042 fn deinitialize(&mut self) {
1043 self.state = RsaBackendState::Idle;
1044 }
1045}
1046
1047pub struct RsaWorkQueueDriver<'t, 'd> {
1053 inner: WorkQueueDriver<'t, RsaBackend<'d>, RsaWorkItem>,
1054}
1055
1056impl<'t, 'd> RsaWorkQueueDriver<'t, 'd> {
1057 pub fn stop(self) -> impl Future<Output = ()> {
1059 self.inner.stop()
1060 }
1061}
1062
1063#[derive(Clone)]
1064struct RsaWorkItem {
1065 config: Config,
1066
1067 operation: RsaOperation,
1069 result: NonNull<[u32]>,
1070}
1071
1072unsafe impl Sync for RsaWorkItem {}
1073unsafe impl Send for RsaWorkItem {}
1074
1075#[derive(Clone)]
1076enum RsaOperation {
1077 Multiplication {
1080 x: NonNull<[u32]>,
1081 y: NonNull<[u32]>,
1082 },
1083 ModularMultiplication {
1085 x: NonNull<[u32]>,
1086 y: NonNull<[u32]>,
1087 m: NonNull<[u32]>,
1088 r: NonNull<[u32]>,
1089 m_prime: u32,
1090 },
1091 ModularExponentiation {
1093 x: NonNull<[u32]>,
1094 y: NonNull<[u32]>,
1095 m: NonNull<[u32]>,
1096 r_inv: NonNull<[u32]>,
1097 m_prime: u32,
1098 },
1099}
1100
1101#[handler]
1102#[ram]
1103fn rsa_work_queue_handler() {
1104 if !RSA_WORK_QUEUE.process() {
1105 low_level::clear_interrupt(RSA::regs());
1108 }
1109}
1110
1111#[cfg_attr(
1118 not(rsa_version = "1"),
1119 doc = " \nThe context is created with a secure configuration by default. You can enable hardware acceleration
1120 options using [enable_search_acceleration][Self::enable_search_acceleration] and
1121 [enable_acceleration][Self::enable_acceleration] when appropriate."
1122)]
1123#[derive(Clone)]
1124pub struct RsaContext {
1125 frontend: WorkQueueFrontend<RsaWorkItem>,
1126}
1127
1128impl Default for RsaContext {
1129 fn default() -> Self {
1130 Self::new()
1131 }
1132}
1133
1134impl RsaContext {
1135 pub fn new() -> Self {
1137 Self {
1138 frontend: WorkQueueFrontend::new(RsaWorkItem {
1139 config: Config::default(),
1140 operation: RsaOperation::Multiplication {
1141 x: NonNull::from(&[]),
1142 y: NonNull::from(&[]),
1143 },
1144 result: NonNull::from(&mut []),
1145 }),
1146 }
1147 }
1148
1149 #[cfg(not(rsa_version = "1"))]
1150 #[doc = trm_markdown_link!("rsa")]
1160 pub fn enable_search_acceleration(&mut self) {
1161 self.frontend.data_mut().config.search_acceleration = true;
1162 }
1163
1164 #[cfg(not(rsa_version = "1"))]
1165 #[doc = trm_markdown_link!("rsa")]
1176 pub fn enable_acceleration(&mut self) {
1177 self.frontend.data_mut().config.constant_time = false;
1178 }
1179
1180 fn post(&mut self) -> RsaHandle<'_> {
1181 RsaHandle(self.frontend.post(&RSA_WORK_QUEUE))
1182 }
1183
1184 #[procmacros::doc_replace]
1185 pub fn modular_exponentiate<'t, OP>(
1253 &'t mut self,
1254 x: &'t OP::InputType,
1255 y: &'t OP::InputType,
1256 m: &'t OP::InputType,
1257 r: &'t OP::InputType,
1258 m_prime: u32,
1259 result: &'t mut OP::InputType,
1260 ) -> RsaHandle<'t>
1261 where
1262 OP: RsaMode,
1263 {
1264 self.frontend.data_mut().operation = RsaOperation::ModularExponentiation {
1265 x: NonNull::from(x.as_ref()),
1266 y: NonNull::from(y.as_ref()),
1267 m: NonNull::from(m.as_ref()),
1268 r_inv: NonNull::from(r.as_ref()),
1269 m_prime,
1270 };
1271 self.frontend.data_mut().result = NonNull::from(result.as_mut());
1272 self.post()
1273 }
1274
1275 pub fn modular_multiply<'t, OP>(
1291 &'t mut self,
1292 x: &'t OP::InputType,
1293 y: &'t OP::InputType,
1294 m: &'t OP::InputType,
1295 r: &'t OP::InputType,
1296 m_prime: u32,
1297 result: &'t mut OP::InputType,
1298 ) -> RsaHandle<'t>
1299 where
1300 OP: RsaMode,
1301 {
1302 self.frontend.data_mut().operation = RsaOperation::ModularMultiplication {
1303 x: NonNull::from(x.as_ref()),
1304 y: NonNull::from(y.as_ref()),
1305 m: NonNull::from(m.as_ref()),
1306 r: NonNull::from(r.as_ref()),
1307 m_prime,
1308 };
1309 self.frontend.data_mut().result = NonNull::from(result.as_mut());
1310 self.post()
1311 }
1312
1313 #[procmacros::doc_replace]
1314 pub fn multiply<'t, OP>(
1344 &'t mut self,
1345 x: &'t OP::InputType,
1346 y: &'t OP::InputType,
1347 result: &'t mut OP::OutputType,
1348 ) -> RsaHandle<'t>
1349 where
1350 OP: Multi,
1351 {
1352 self.frontend.data_mut().operation = RsaOperation::Multiplication {
1353 x: NonNull::from(x.as_ref()),
1354 y: NonNull::from(y.as_ref()),
1355 };
1356 self.frontend.data_mut().result = NonNull::from(result.as_mut());
1357 self.post()
1358 }
1359}
1360
1361pub struct RsaHandle<'t>(work_queue::Handle<'t, RsaWorkItem>);
1363
1364impl RsaHandle<'_> {
1365 #[inline]
1367 pub fn poll(&mut self) -> bool {
1368 self.0.poll()
1369 }
1370
1371 #[inline]
1373 pub fn wait_blocking(self) {
1374 self.0.wait_blocking();
1375 }
1376
1377 #[inline]
1379 pub fn wait(&mut self) -> impl Future<Output = Status> {
1380 self.0.wait()
1381 }
1382}