Skip to main content

esp_hal/rsa/
mod.rs

1//! # RSA (Rivest–Shamir–Adleman) accelerator.
2//!
3//! ## Overview
4//!
5//! The RSA accelerator provides hardware support for high precision computation
6//! used in various RSA asymmetric cipher algorithms by significantly reducing
7//! their software complexity. Compared with RSA algorithms implemented solely
8//! in software, this hardware accelerator can speed up RSA algorithms
9//! significantly.
10//!
11//! ## Configuration
12//!
13//! The RSA accelerator also supports operands of different lengths, which
14//! provides more flexibility during the computation.
15
16#[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
41/// RSA peripheral driver.
42pub struct Rsa<'d, Dm: DriverMode> {
43    rsa: RSA<'d>,
44    phantom: PhantomData<Dm>,
45    _guard: RsaGuard,
46}
47
48// There are two distinct peripheral versions: ESP32, and all else. There is a naming split in the
49// later devices, and they use different (memory size, operand size increment) parameters, but they
50// are largely the same.
51
52/// How many words are there in an operand size increment.
53///
54/// I.e. if the RSA hardware works with operands of 512, 1024, 1536, ... bits, the increment is 512
55/// bits, or 16 words.
56const 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            // Stopping the peripheral's clock source pends an interrupt. Since the clocks
87            // are stopped when the handler runs, we're not able to clear the interrupt flag,
88            // which means the interrupt handler keeps getting triggered indefinitely.
89            // To prevent this, we disable interrupts manually before stopping the peripheral.
90            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    /// Creates a new instance in [Blocking] mode.
111    ///
112    /// Optionally an interrupt handler can be bound.
113    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    /// Reconfigures the RSA driver to operate in asynchronous mode.
126    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    /// Enables or disables the RSA interrupt.
138    ///
139    /// When enabled rsa peripheral would generate an interrupt when a operation
140    /// is finished.
141    pub fn enable_disable_interrupt(&mut self, enable: bool) {
142        self.internal_enable_disable_interrupt(enable);
143    }
144
145    /// Registers an interrupt handler for the RSA peripheral.
146    ///
147    /// Replaces any previously registered interrupt handlers.
148    #[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    /// Reconfigures the RSA driver to operate in [`Blocking`] mode.
166    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    /// Returns whether RSA memory blocks are initialized after reset.
188    fn ready(&self) -> bool {
189        low_level::ready(self.regs())
190    }
191
192    /// Starts the modular exponentiation operation.
193    fn start_modexp(&self) {
194        low_level::start_modexp(self.regs());
195    }
196
197    /// Starts the multiplication operation.
198    fn start_multi(&self) {
199        low_level::start_multi(self.regs());
200    }
201
202    /// Starts the modular multiplication operation.
203    fn start_modmulti(&self) {
204        low_level::start_modmulti(self.regs());
205    }
206
207    /// Clears the RSA interrupt flag.
208    fn clear_interrupt(&mut self) {
209        low_level::clear_interrupt(self.regs());
210    }
211
212    /// Returns whether the RSA peripheral is idle.
213    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    /// Writes the result size of the multiplication.
223    fn write_multi_mode(&mut self, mode: u32, modular: bool) {
224        low_level::write_multi_mode(self.regs(), mode, modular);
225    }
226
227    /// Writes the result size of the modular exponentiation.
228    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    /// Removes the operands and intermediate results from the peripheral.
281    #[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    /// Enables or disables constant time operation.
303    ///
304    /// Disabling constant time operation increases the performance of modular
305    /// exponentiation by simplifying the calculation concerning the 0 bits
306    /// of the exponent. I.e. the less the Hamming weight, the greater the
307    /// performance.
308    ///
309    /// Compromises security by enabling timing-based side-channel attacks.
310    ///
311    /// For more information refer to the
312    #[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    /// Enables or disables search acceleration.
321    ///
322    /// When enabled it would increase the performance of modular
323    /// exponentiation by discarding the exponent's bits before the most
324    /// significant set bit.
325    ///
326    /// Compromises security by effectively decreasing the key length.
327    ///
328    /// For more information refer to the
329    #[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    /// Returns whether the search functionality is enabled in the RSA hardware.
338    #[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    /// Sets the search position in the RSA hardware.
348    #[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
356/// Defines the input size of an RSA operation.
357pub trait RsaMode: crate::private::Sealed {
358    /// The input data type used for the operation.
359    type InputType: AsRef<[u32]> + AsMut<[u32]>;
360}
361
362/// Defines the output type of RSA multiplications.
363pub trait Multi: RsaMode {
364    /// The type of the output produced by the operation.
365    type OutputType: AsRef<[u32]> + AsMut<[u32]>;
366}
367
368/// Defines the exponentiation and multiplication lengths for RSA operations.
369pub 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
393/// Support for the RSA peripheral's modular exponentiation feature that could be
394/// used to find the `(base ^ exponent) mod modulus`.
395///
396/// Each operand is a little endian byte array of the same size.
397pub 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    /// Creates an instance of `RsaModularExponentiation`.
407    ///
408    /// `m_prime` could be calculated using `-(modular multiplicative inverse of
409    /// modulus) mod 2^32`.
410    ///
411    /// For more information refer to the
412    #[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    /// Starts the modular exponentiation operation.
441    ///
442    /// `r` can be calculated using `2 ^ ( bitlength * 2 ) mod modulus`.
443    ///
444    /// For more information refer to the
445    #[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    /// Reads the result to the given buffer.
452    ///
453    /// This is a blocking function: it waits for the RSA operation to complete,
454    /// then reads the results into the provided buffer. `start_exponentiation` must be
455    /// called before calling this function.
456    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    /// Sets the modular exponentiation mode for the RSA hardware.
472    fn write_mode(rsa: &mut Rsa<'d, Dm>) {
473        rsa.write_modexp_mode(N as u32 / WORDS_PER_INCREMENT - 1);
474    }
475}
476
477/// Support for the RSA peripheral's modular multiplication feature that could be
478/// used to find the `(operand a * operand b) mod modulus`.
479///
480/// Each operand is a little endian byte array of the same size.
481pub 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    /// Creates an instance of `RsaModularMultiplication`.
496    ///
497    /// - `r` can be calculated using `2 ^ ( bitlength * 2 ) mod modulus`.
498    /// - `m_prime` can be calculated using `-(modular multiplicative inverse of modulus) mod 2^32`.
499    ///
500    /// For more information refer to the
501    #[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    /// Starts the modular multiplication operation.
523    ///
524    /// For more information refer to the
525    #[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    /// Reads the result to the given buffer.
532    ///
533    /// This is a blocking function: it waits for the RSA operation to complete,
534    /// then reads the results into the provided buffer. `start_modular_multiplication` must be
535    /// called before calling this function.
536    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
552/// Support for the RSA peripheral's large number multiplication feature that could
553/// be used to find the `operand a * operand b`.
554///
555/// Each operand is a little endian byte array of the same size.
556pub 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    /// Creates an instance of `RsaMultiplication`.
572    pub fn new(rsa: &'a mut Rsa<'d, Dm>, operand_a: &T::InputType) -> Self {
573        // Non-modular multiplication result is twice as wide as its operands.
574        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    /// Starts the multiplication operation.
584    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    /// Reads the result to the given buffer.
590    ///
591    /// This is a blocking function: it waits for the RSA operation to complete,
592    /// then reads the results into the provided buffer. `start_multiplication` must be
593    /// called before calling this function.
594    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/// `Future` that waits for the RSA operation to complete.
611#[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    /// Asynchronously performs an RSA modular exponentiation operation.
665    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    /// Asynchronously performs an RSA modular multiplication operation.
684    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    /// Asynchronously performs an RSA multiplication operation.
711    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]
727/// Interrupt handler for RSA.
728pub(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        // Start processing immediately.
743        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]
772/// RSA processing backend.
773///
774/// The backend processes work items placed in the RSA work queue. The backend needs to be created
775/// and started for operations to be processed. Operations can be performed on the RSA accelerator
776/// without carrying around the peripheral singleton, or the driver.
777///
778/// The [`RsaContext`] struct can enqueue work items that this backend will process.
779///
780/// # Examples
781///
782/// ```rust, no_run
783/// # {before_snippet}
784/// use esp_hal::rsa::{RsaBackend, RsaContext, operand_sizes::Op512};
785/// #
786/// let mut rsa_backend = RsaBackend::new(peripherals.RSA);
787/// let _driver = rsa_backend.start();
788///
789/// async fn perform_512bit_big_number_multiplication(
790///     operand_a: &[u32; 16],
791///     operand_b: &[u32; 16],
792///     result: &mut [u32; 32],
793/// ) {
794///     let mut rsa = RsaContext::new();
795///
796///     let mut handle = rsa.multiply::<Op512>(operand_a, operand_b, result);
797///     handle.wait().await;
798/// }
799/// # {after_snippet}
800/// ```
801pub struct RsaBackend<'d> {
802    peri: RSA<'d>,
803    state: RsaBackendState<'d>,
804}
805
806impl<'d> RsaBackend<'d> {
807    #[procmacros::doc_replace]
808    /// Creates a new RSA backend.
809    ///
810    /// # Examples
811    ///
812    /// ```rust, no_run
813    /// # {before_snippet}
814    /// use esp_hal::rsa::RsaBackend;
815    /// #
816    /// let mut rsa = RsaBackend::new(peripherals.RSA);
817    /// # {after_snippet}
818    /// ```
819    pub fn new(rsa: RSA<'d>) -> Self {
820        Self {
821            peri: rsa,
822            state: RsaBackendState::Idle,
823        }
824    }
825
826    #[procmacros::doc_replace]
827    /// Registers the RSA driver to process RSA operations.
828    ///
829    /// The driver stops operating when the returned object is dropped.
830    ///
831    /// # Examples
832    ///
833    /// ```rust, no_run
834    /// # {before_snippet}
835    /// use esp_hal::rsa::RsaBackend;
836    /// #
837    /// let mut rsa = RsaBackend::new(peripherals.RSA);
838    /// // Start the backend, which allows processing RSA operations.
839    /// let _backend = rsa.start();
840    /// # {after_snippet}
841    /// ```
842    pub fn start(&mut self) -> RsaWorkQueueDriver<'_, 'd> {
843        RsaWorkQueueDriver {
844            inner: WorkQueueDriver::new(self, RSA_VTABLE, &RSA_WORK_QUEUE),
845        }
846    }
847
848    // WorkQueue callbacks. They may run in any context.
849
850    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                // Wait for the peripheral to finish initializing. Ideally we need a way to
867                // instruct the work queue to wake the polling task immediately.
868                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                        // Non-modular multiplication result is twice as wide as its operands.
890                        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                            // ESP32 requires a two-step process where Y needs to be written to the
921                            // X memory.
922                            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                    // Y needs to be written to the X memory.
976                    rsa.write_operand_a(unsafe { y.as_ref() });
977                    rsa.start_modmulti();
978
979                    self.state = RsaBackendState::Processing(rsa);
980                } else {
981                    // Wait for the operation to complete
982                    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        // Drop the driver to reset it. We don't read the result, so the work item remains
1003        // unchanged, effectively cancelling it.
1004        self.state = RsaBackendState::Idle;
1005    }
1006
1007    fn deinitialize(&mut self) {
1008        self.state = RsaBackendState::Idle;
1009    }
1010}
1011
1012/// An active work queue driver.
1013///
1014/// This object must be kept around, otherwise RSA operations will never complete.
1015///
1016/// For a usage example, see [`RsaBackend`].
1017pub struct RsaWorkQueueDriver<'t, 'd> {
1018    inner: WorkQueueDriver<'t, RsaBackend<'d>, RsaWorkItem>,
1019}
1020
1021impl<'t, 'd> RsaWorkQueueDriver<'t, 'd> {
1022    /// Finishes processing the current work queue item, then stops the driver.
1023    pub fn stop(self) -> impl Future<Output = ()> {
1024        self.inner.stop()
1025    }
1026}
1027
1028#[derive(Clone)]
1029struct RsaWorkItem {
1030    // Acceleration options
1031    #[cfg(not(rsa_version = "1"))]
1032    search_acceleration: bool,
1033    #[cfg(not(rsa_version = "1"))]
1034    constant_time: bool,
1035
1036    // The operation to execute.
1037    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    // Z = X * Y
1047    // len(Z) = len(X) + len(Y)
1048    Multiplication {
1049        x: NonNull<[u32]>,
1050        y: NonNull<[u32]>,
1051    },
1052    // Z = X * Y mod M
1053    ModularMultiplication {
1054        x: NonNull<[u32]>,
1055        y: NonNull<[u32]>,
1056        m: NonNull<[u32]>,
1057        r: NonNull<[u32]>,
1058        m_prime: u32,
1059    },
1060    // Z = X ^ Y mod M
1061    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        // The queue may indicate that it needs to be polled again. In this case, we do not clear
1075        // the interrupt bit, which causes the interrupt to be re-handled.
1076        low_level::clear_interrupt(RSA::regs());
1077    }
1078}
1079
1080/// An RSA work queue user.
1081///
1082/// This object allows performing [big number multiplication][Self::multiply], [big number modular
1083/// multiplication][Self::modular_multiply] and [big number modular
1084/// exponentiation][Self::modular_exponentiate] with hardware acceleration. To perform these
1085/// operations, the [`RsaBackend`] must be started, otherwise these operations will never complete.
1086#[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    /// Creates a new context.
1105    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    /// Enables search acceleration.
1123    ///
1124    /// When enabled it would increase the performance of modular
1125    /// exponentiation by discarding the exponent's bits before the most
1126    /// significant set bit.
1127    ///
1128    /// Compromises security by effectively decreasing the key length.
1129    ///
1130    /// For more information refer to the
1131    #[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    /// Enables acceleration by disabling constant time operation.
1138    ///
1139    /// Disabling constant time operation increases the performance of modular
1140    /// exponentiation by simplifying the calculation concerning the 0 bits
1141    /// of the exponent. I.e. the less the Hamming weight, the greater the
1142    /// performance.
1143    ///
1144    /// Compromises security by enabling timing-based side-channel attacks.
1145    ///
1146    /// For more information refer to the
1147    #[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    /// Starts a modular exponentiation operation, performing `Z = X ^ Y mod M`.
1158    ///
1159    /// Software needs to pre-calculate the following values:
1160    ///
1161    /// - `r`: `2 ^ ( bitlength * 2 ) mod M`.
1162    /// - `m_prime` can be calculated using `-(modular multiplicative inverse of M) mod 2^32`.
1163    ///
1164    /// It is relatively easy to calculate these values using the `crypto-bigint` crate:
1165    ///
1166    /// ```rust,no_run
1167    /// # {before_snippet}
1168    /// use crypto_bigint::{U512, Uint};
1169    /// const fn compute_r(modulus: &U512) -> U512 {
1170    ///     let mut d = [0_u32; U512::LIMBS * 2 + 1];
1171    ///     d[d.len() - 1] = 1;
1172    ///     let d = Uint::from_words(d);
1173    ///     d.wrapping_rem_vartime(&modulus.resize()).resize()
1174    /// }
1175    ///
1176    /// const fn compute_mprime(modulus: &U512) -> u32 {
1177    ///     let m_inv = modulus
1178    ///         .invert_mod2k(32)
1179    ///         .expect_copied("modulus must be odd")
1180    ///         .to_words()[0];
1181    ///     (-1 * m_inv as i64 & (u32::MAX as i64)) as u32
1182    /// }
1183    ///
1184    /// // Inputs
1185    /// const X: U512 = Uint::from_be_hex(
1186    ///     "c7f61058f96db3bd87dbab08ab03b4f7f2f864eac249144adea6a65f97803b719d8ca980b7b3c0389c1c7c6\
1187    ///    7dc353c5e0ec11f5fc8ce7f6073796cc8f73fa878",
1188    /// );
1189    /// const Y: U512 = Uint::from_be_hex(
1190    ///     "1763db3344e97be15d04de4868badb12a38046bb793f7630d87cf100aa1c759afac15a01f3c4c83ec2d2f66\
1191    ///    6bd22f71c3c1f075ec0e2cb0cb29994d091b73f51",
1192    /// );
1193    /// const M: U512 = Uint::from_be_hex(
1194    ///     "6b6bb3d2b6cbeb45a769eaa0384e611e1b89b0c9b45a045aca1c5fd6e8785b38df7118cf5dd45b9b63d293b\
1195    ///    67aeafa9ba25feb8712f188cb139b7d9b9af1c361",
1196    /// );
1197    ///
1198    /// // Values derived using the functions we defined above:
1199    /// let r = compute_r(&M);
1200    /// let mprime = compute_mprime(&M);
1201    ///
1202    /// use esp_hal::rsa::{RsaContext, operand_sizes::Op512};
1203    ///
1204    /// // Now perform the actual computation:
1205    /// let mut rsa = RsaContext::new();
1206    /// let mut outbuf = [0; 16];
1207    /// let mut handle = rsa.modular_multiply::<Op512>(
1208    ///     X.as_words(),
1209    ///     Y.as_words(),
1210    ///     M.as_words(),
1211    ///     r.as_words(),
1212    ///     mprime,
1213    ///     &mut outbuf,
1214    /// );
1215    /// handle.wait_blocking();
1216    /// # {after_snippet}
1217    /// ```
1218    ///
1219    /// Returns an [`RsaHandle`] for the asynchronous calculation that can be used to poll the
1220    /// status of the calculation, to wait for it to finish, or to cancel the operation (by
1221    /// dropping the handle).
1222    ///
1223    /// When the operation is completed, the result is stored in `result`
1224    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    /// Starts a modular multiplication operation, performing `Z = X * Y mod M`.
1248    ///
1249    /// Software needs to pre-calculate the following values:
1250    ///
1251    /// - `r`: `2 ^ ( bitlength * 2 ) mod M`.
1252    /// - `m_prime` can be calculated using `-(modular multiplicative inverse of M) mod 2^32`.
1253    ///
1254    /// For an example how these values can be calculated and used, see
1255    /// [Self::modular_exponentiate].
1256    ///
1257    /// Returns an [`RsaHandle`] for the asynchronous calculation that can be used to poll the
1258    /// status of the calculation, to wait for it to finish, or to cancel the operation (by
1259    /// dropping the handle).
1260    ///
1261    /// When the operation is completed, the result is stored in `result`
1262    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    /// Starts a multiplication operation, performing `Z = X * Y`.
1287    ///
1288    /// Returns an [`RsaHandle`] for the asynchronous calculation that can be used to poll the
1289    /// status of the calculation, to wait for it to finish, or to cancel the operation (by
1290    /// dropping the handle).
1291    ///
1292    /// When the operation is completed, the result is stored in `result`. The `result` is twice as
1293    /// wide as the inputs.
1294    ///
1295    /// # Examples
1296    ///
1297    /// ```rust,no_run
1298    /// # {before_snippet}
1299    ///
1300    /// // Inputs
1301    /// # let x: [u32; 16] = [0; 16];
1302    /// # let y: [u32; 16] = [0; 16];
1303    /// // let x: [u32; 16] = [...];
1304    /// // let y: [u32; 16] = [...];
1305    /// let mut outbuf = [0; 32];
1306    ///
1307    /// use esp_hal::rsa::{RsaContext, operand_sizes::Op512};
1308    ///
1309    /// // Now perform the actual computation:
1310    /// let mut rsa = RsaContext::new();
1311    /// let mut handle = rsa.multiply::<Op512>(&x, &y, &mut outbuf);
1312    /// handle.wait_blocking();
1313    /// # {after_snippet}
1314    /// ```
1315    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
1333/// The handle to the pending RSA operation.
1334pub struct RsaHandle<'t>(work_queue::Handle<'t, RsaWorkItem>);
1335
1336impl RsaHandle<'_> {
1337    /// Polls the status of the work item.
1338    #[inline]
1339    pub fn poll(&mut self) -> bool {
1340        self.0.poll()
1341    }
1342
1343    /// Blocks until the work item is processed.
1344    #[inline]
1345    pub fn wait_blocking(self) {
1346        self.0.wait_blocking();
1347    }
1348
1349    /// Waits for the work item to be processed.
1350    #[inline]
1351    pub fn wait(&mut self) -> impl Future<Output = Status> {
1352        self.0.wait()
1353    }
1354}