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    /// Create 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/disables 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    /// Note that this will replace any previously registered interrupt
148    /// handlers.
149    #[instability::unstable]
150    pub fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
151        self.rsa.disable_peri_interrupt_on_all_cores();
152        self.rsa.bind_peri_interrupt(handler);
153    }
154}
155
156impl crate::private::Sealed for Rsa<'_, Blocking> {}
157
158#[instability::unstable]
159impl crate::interrupt::InterruptConfigurable for Rsa<'_, Blocking> {
160    fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
161        self.set_interrupt_handler(handler);
162    }
163}
164
165impl<'d> Rsa<'d, Async> {
166    /// Create a new instance in [crate::Blocking] mode.
167    pub fn into_blocking(self) -> Rsa<'d, Blocking> {
168        self.internal_enable_disable_interrupt(false);
169        self.rsa.disable_peri_interrupt_on_all_cores();
170
171        Rsa {
172            rsa: self.rsa,
173            phantom: PhantomData,
174            _guard: self._guard,
175        }
176    }
177}
178
179impl<'d, Dm: DriverMode> Rsa<'d, Dm> {
180    fn internal_enable_disable_interrupt(&self, enable: bool) {
181        low_level::enable_disable_interrupt(self.regs(), enable);
182    }
183
184    fn regs(&self) -> &pac::rsa::RegisterBlock {
185        self.rsa.register_block()
186    }
187
188    /// After the RSA accelerator is released from reset, the memory blocks
189    /// needs to be initialized, only after that peripheral should be used.
190    /// This function would return without an error if the memory is
191    /// initialized.
192    fn ready(&self) -> bool {
193        low_level::ready(self.regs())
194    }
195
196    /// Starts the modular exponentiation operation.
197    fn start_modexp(&self) {
198        low_level::start_modexp(self.regs());
199    }
200
201    /// Starts the multiplication operation.
202    fn start_multi(&self) {
203        low_level::start_multi(self.regs());
204    }
205
206    /// Starts the modular multiplication operation.
207    fn start_modmulti(&self) {
208        low_level::start_modmulti(self.regs());
209    }
210
211    /// Clears the RSA interrupt flag.
212    fn clear_interrupt(&mut self) {
213        low_level::clear_interrupt(self.regs());
214    }
215
216    /// Checks if the RSA peripheral is idle.
217    fn is_idle(&self) -> bool {
218        low_level::is_idle(self.regs())
219    }
220
221    fn wait_for_idle(&mut self) {
222        while !self.is_idle() {}
223        self.clear_interrupt();
224    }
225
226    /// Writes the result size of the multiplication.
227    fn write_multi_mode(&mut self, mode: u32, modular: bool) {
228        low_level::write_multi_mode(self.regs(), mode, modular);
229    }
230
231    /// Writes the result size of the modular exponentiation.
232    fn write_modexp_mode(&mut self, mode: u32) {
233        low_level::write_modexp_mode(self.regs(), mode);
234    }
235
236    fn write_operand_b(&mut self, operand: &[u32]) {
237        for (reg, op) in self.regs().y_mem_iter().zip(operand.iter().copied()) {
238            reg.write(|w| unsafe { w.bits(op) });
239        }
240    }
241
242    fn write_modulus(&mut self, modulus: &[u32]) {
243        for (reg, op) in self.regs().m_mem_iter().zip(modulus.iter().copied()) {
244            reg.write(|w| unsafe { w.bits(op) });
245        }
246    }
247
248    fn write_mprime(&mut self, m_prime: u32) {
249        self.regs().m_prime().write(|w| unsafe { w.bits(m_prime) });
250    }
251
252    fn write_operand_a(&mut self, operand: &[u32]) {
253        for (reg, op) in self.regs().x_mem_iter().zip(operand.iter().copied()) {
254            reg.write(|w| unsafe { w.bits(op) });
255        }
256    }
257
258    fn write_multi_operand_b(&mut self, operand: &[u32]) {
259        for (reg, op) in self
260            .regs()
261            .z_mem_iter()
262            .skip(operand.len())
263            .zip(operand.iter().copied())
264        {
265            reg.write(|w| unsafe { w.bits(op) });
266        }
267    }
268
269    fn write_r(&mut self, r: &[u32]) {
270        for (reg, op) in self.regs().z_mem_iter().zip(r.iter().copied()) {
271            reg.write(|w| unsafe { w.bits(op) });
272        }
273    }
274
275    fn read_out(&self, outbuf: &mut [u32]) {
276        for (reg, op) in self.regs().z_mem_iter().zip(outbuf.iter_mut()) {
277            *op = reg.read().bits();
278        }
279
280        #[cfg(clear_crypto_secrets)]
281        self.clear_secrets();
282    }
283
284    /// Removes the operands and intermediate results from the peripheral.
285    #[cfg(clear_crypto_secrets)]
286    fn clear_secrets(&self) {
287        for reg in self.regs().x_mem_iter() {
288            reg.write(|w| unsafe { w.bits(0) });
289        }
290        for reg in self.regs().y_mem_iter() {
291            reg.write(|w| unsafe { w.bits(0) });
292        }
293        for reg in self.regs().z_mem_iter() {
294            reg.write(|w| unsafe { w.bits(0) });
295        }
296        for reg in self.regs().m_mem_iter() {
297            reg.write(|w| unsafe { w.bits(0) });
298        }
299    }
300
301    fn read_results(&mut self, outbuf: &mut [u32]) {
302        self.wait_for_idle();
303        self.read_out(outbuf);
304    }
305
306    /// Enables/disables constant time operation.
307    ///
308    /// Disabling constant time operation increases the performance of modular
309    /// exponentiation by simplifying the calculation concerning the 0 bits
310    /// of the exponent. I.e. the less the Hamming weight, the greater the
311    /// performance.
312    ///
313    /// Note: this compromises security by enabling timing-based side-channel attacks.
314    ///
315    /// For more information refer to the
316    #[doc = trm_markdown_link!("rsa")]
317    #[cfg(not(rsa_version = "1"))]
318    pub fn disable_constant_time(&mut self, disable: bool) {
319        self.regs()
320            .constant_time()
321            .write(|w| w.constant_time().bit(disable));
322    }
323
324    /// Enables/disables search acceleration.
325    ///
326    /// When enabled it would increase the performance of modular
327    /// exponentiation by discarding the exponent's bits before the most
328    /// significant set bit.
329    ///
330    /// Note: this compromises security by effectively decreasing the key length.
331    ///
332    /// For more information refer to the
333    #[doc = trm_markdown_link!("rsa")]
334    #[cfg(not(rsa_version = "1"))]
335    pub fn search_acceleration(&mut self, enable: bool) {
336        self.regs()
337            .search_enable()
338            .write(|w| w.search_enable().bit(enable));
339    }
340
341    /// Checks if the search functionality is enabled in the RSA hardware.
342    #[cfg(not(rsa_version = "1"))]
343    fn is_search_enabled(&mut self) -> bool {
344        self.regs()
345            .search_enable()
346            .read()
347            .search_enable()
348            .bit_is_set()
349    }
350
351    /// Sets the search position in the RSA hardware.
352    #[cfg(not(rsa_version = "1"))]
353    fn write_search_position(&mut self, search_position: u32) {
354        self.regs()
355            .search_pos()
356            .write(|w| unsafe { w.bits(search_position) });
357    }
358}
359
360/// Defines the input size of an RSA operation.
361pub trait RsaMode: crate::private::Sealed {
362    /// The input data type used for the operation.
363    type InputType: AsRef<[u32]> + AsMut<[u32]>;
364}
365
366/// Defines the output type of RSA multiplications.
367pub trait Multi: RsaMode {
368    /// The type of the output produced by the operation.
369    type OutputType: AsRef<[u32]> + AsMut<[u32]>;
370}
371
372/// Defines the exponentiation and multiplication lengths for RSA operations.
373pub mod operand_sizes {
374    for_each_rsa_exponentiation!(
375        ($x:literal) => {
376            paste::paste! {
377                #[doc = concat!(stringify!($x), "-bit RSA operation.")]
378                pub struct [<Op $x>];
379
380                impl crate::private::Sealed for [<Op $x>] {}
381                impl crate::rsa::RsaMode for [<Op $x>] {
382                    type InputType = [u32; $x / 32];
383                }
384            }
385        };
386    );
387
388    for_each_rsa_multiplication!(
389        ($x:literal) => {
390            impl crate::rsa::Multi for paste::paste!( [<Op $x>] ) {
391                type OutputType = [u32; $x * 2 / 32];
392            }
393        };
394    );
395}
396
397/// Support for RSA peripheral's modular exponentiation feature that could be
398/// used to find the `(base ^ exponent) mod modulus`.
399///
400/// Each operand is a little endian byte array of the same size
401pub struct RsaModularExponentiation<'a, 'd, T: RsaMode, Dm: DriverMode> {
402    rsa: &'a mut Rsa<'d, Dm>,
403    phantom: PhantomData<T>,
404}
405
406impl<'a, 'd, T: RsaMode, Dm: DriverMode, const N: usize> RsaModularExponentiation<'a, 'd, T, Dm>
407where
408    T: RsaMode<InputType = [u32; N]>,
409{
410    /// Creates an instance of `RsaModularExponentiation`.
411    ///
412    /// `m_prime` could be calculated using `-(modular multiplicative inverse of
413    /// modulus) mod 2^32`.
414    ///
415    /// For more information refer to the
416    #[doc = trm_markdown_link!("rsa")]
417    pub fn new(
418        rsa: &'a mut Rsa<'d, Dm>,
419        exponent: &T::InputType,
420        modulus: &T::InputType,
421        m_prime: u32,
422    ) -> Self {
423        Self::write_mode(rsa);
424        rsa.write_operand_b(exponent);
425        rsa.write_modulus(modulus);
426        rsa.write_mprime(m_prime);
427
428        #[cfg(not(rsa_version = "1"))]
429        if rsa.is_search_enabled() {
430            rsa.write_search_position(Self::find_search_pos(exponent));
431        }
432
433        Self {
434            rsa,
435            phantom: PhantomData,
436        }
437    }
438
439    fn set_up_exponentiation(&mut self, base: &T::InputType, r: &T::InputType) {
440        self.rsa.write_operand_a(base);
441        self.rsa.write_r(r);
442    }
443
444    /// Starts the modular exponentiation operation.
445    ///
446    /// `r` can be calculated using `2 ^ ( bitlength * 2 ) mod modulus`.
447    ///
448    /// For more information refer to the
449    #[doc = trm_markdown_link!("rsa")]
450    pub fn start_exponentiation(&mut self, base: &T::InputType, r: &T::InputType) {
451        self.set_up_exponentiation(base, r);
452        self.rsa.start_modexp();
453    }
454
455    /// Reads the result to the given buffer.
456    ///
457    /// This is a blocking function: it waits for the RSA operation to complete,
458    /// then reads the results into the provided buffer. `start_exponentiation` must be
459    /// called before calling this function.
460    pub fn read_results(&mut self, outbuf: &mut T::InputType) {
461        self.rsa.read_results(outbuf);
462    }
463
464    #[cfg(not(rsa_version = "1"))]
465    fn find_search_pos(exponent: &T::InputType) -> u32 {
466        for (i, byte) in exponent.iter().rev().enumerate() {
467            if *byte == 0 {
468                continue;
469            }
470            return (exponent.len() * 32) as u32 - (byte.leading_zeros() + i as u32 * 32) - 1;
471        }
472        0
473    }
474
475    /// Sets the modular exponentiation mode for the RSA hardware.
476    fn write_mode(rsa: &mut Rsa<'d, Dm>) {
477        rsa.write_modexp_mode(N as u32 / WORDS_PER_INCREMENT - 1);
478    }
479}
480
481/// Support for RSA peripheral's modular multiplication feature that could be
482/// used to find the `(operand a * operand b) mod modulus`.
483///
484/// Each operand is a little endian byte array of the same size
485pub struct RsaModularMultiplication<'a, 'd, T, Dm>
486where
487    T: RsaMode,
488    Dm: DriverMode,
489{
490    rsa: &'a mut Rsa<'d, Dm>,
491    phantom: PhantomData<T>,
492}
493
494impl<'a, 'd, T, Dm, const N: usize> RsaModularMultiplication<'a, 'd, T, Dm>
495where
496    T: RsaMode<InputType = [u32; N]>,
497    Dm: DriverMode,
498{
499    /// Creates an instance of `RsaModularMultiplication`.
500    ///
501    /// - `r` can be calculated using `2 ^ ( bitlength * 2 ) mod modulus`.
502    /// - `m_prime` can be calculated using `-(modular multiplicative inverse of modulus) mod 2^32`.
503    ///
504    /// For more information refer to the
505    #[doc = trm_markdown_link!("rsa")]
506    pub fn new(
507        rsa: &'a mut Rsa<'d, Dm>,
508        operand_a: &T::InputType,
509        modulus: &T::InputType,
510        r: &T::InputType,
511        m_prime: u32,
512    ) -> Self {
513        rsa.write_multi_mode(N as u32 / WORDS_PER_INCREMENT - 1, true);
514
515        rsa.write_mprime(m_prime);
516        rsa.write_modulus(modulus);
517        rsa.write_operand_a(operand_a);
518        rsa.write_r(r);
519
520        Self {
521            rsa,
522            phantom: PhantomData,
523        }
524    }
525
526    /// Starts the modular multiplication operation.
527    ///
528    /// For more information refer to the
529    #[doc = trm_markdown_link!("rsa")]
530    pub fn start_modular_multiplication(&mut self, operand_b: &T::InputType) {
531        self.set_up_modular_multiplication(operand_b);
532        self.rsa.start_modmulti();
533    }
534
535    /// Reads the result to the given buffer.
536    ///
537    /// This is a blocking function: it waits for the RSA operation to complete,
538    /// then reads the results into the provided buffer. `start_modular_multiplication` must be
539    /// called before calling this function.
540    pub fn read_results(&mut self, outbuf: &mut T::InputType) {
541        self.rsa.read_results(outbuf);
542    }
543
544    fn set_up_modular_multiplication(&mut self, operand_b: &T::InputType) {
545        if cfg!(rsa_version = "1") {
546            self.rsa.start_multi();
547            self.rsa.wait_for_idle();
548
549            self.rsa.write_operand_a(operand_b);
550        } else {
551            self.rsa.write_operand_b(operand_b);
552        }
553    }
554}
555
556/// Support for RSA peripheral's large number multiplication feature that could
557/// be used to find the `operand a * operand b`.
558///
559/// Each operand is a little endian byte array of the same size
560pub struct RsaMultiplication<'a, 'd, T, Dm>
561where
562    T: RsaMode + Multi,
563    Dm: DriverMode,
564{
565    rsa: &'a mut Rsa<'d, Dm>,
566    phantom: PhantomData<T>,
567}
568
569impl<'a, 'd, T, Dm, const N: usize> RsaMultiplication<'a, 'd, T, Dm>
570where
571    T: RsaMode<InputType = [u32; N]>,
572    T: Multi,
573    Dm: DriverMode,
574{
575    /// Creates an instance of `RsaMultiplication`.
576    pub fn new(rsa: &'a mut Rsa<'d, Dm>, operand_a: &T::InputType) -> Self {
577        // Non-modular multiplication result is twice as wide as its operands.
578        rsa.write_multi_mode(2 * N as u32 / WORDS_PER_INCREMENT - 1, false);
579        rsa.write_operand_a(operand_a);
580
581        Self {
582            rsa,
583            phantom: PhantomData,
584        }
585    }
586
587    /// Starts the multiplication operation.
588    pub fn start_multiplication(&mut self, operand_b: &T::InputType) {
589        self.set_up_multiplication(operand_b);
590        self.rsa.start_multi();
591    }
592
593    /// Reads the result to the given buffer.
594    ///
595    /// This is a blocking function: it waits for the RSA operation to complete,
596    /// then reads the results into the provided buffer. `start_multiplication` must be
597    /// called before calling this function.
598    pub fn read_results<const O: usize>(&mut self, outbuf: &mut T::OutputType)
599    where
600        T: Multi<OutputType = [u32; O]>,
601    {
602        self.rsa.read_results(outbuf);
603    }
604
605    fn set_up_multiplication(&mut self, operand_b: &T::InputType) {
606        self.rsa.write_multi_operand_b(operand_b);
607    }
608}
609
610static WAKER: AtomicWaker = AtomicWaker::new();
611#[cfg(rsa_version = "1")]
612static SIGNALED: AtomicBool = AtomicBool::new(false);
613
614/// `Future` that waits for the RSA operation to complete.
615#[must_use = "futures do nothing unless you `.await` or poll them"]
616struct RsaFuture<'a, 'd> {
617    driver: &'a Rsa<'d, Async>,
618    _wake_lock: WakeLock,
619}
620
621impl<'a, 'd> RsaFuture<'a, 'd> {
622    fn new(driver: &'a Rsa<'d, Async>) -> Self {
623        #[cfg(rsa_version = "1")]
624        SIGNALED.store(false, Ordering::Relaxed);
625
626        driver.internal_enable_disable_interrupt(true);
627
628        Self {
629            driver,
630            _wake_lock: WakeLock::new(),
631        }
632    }
633
634    fn is_done(&self) -> bool {
635        cfg_select! {
636            rsa_version = "1" => SIGNALED.load(Ordering::Acquire),
637            _ => self.driver.is_idle(),
638        }
639    }
640}
641
642impl Drop for RsaFuture<'_, '_> {
643    fn drop(&mut self) {
644        self.driver.internal_enable_disable_interrupt(false);
645    }
646}
647
648impl core::future::Future for RsaFuture<'_, '_> {
649    type Output = ();
650
651    fn poll(
652        self: core::pin::Pin<&mut Self>,
653        cx: &mut core::task::Context<'_>,
654    ) -> core::task::Poll<Self::Output> {
655        WAKER.register(cx.waker());
656        if self.is_done() {
657            Poll::Ready(())
658        } else {
659            Poll::Pending
660        }
661    }
662}
663
664impl<T: RsaMode, const N: usize> RsaModularExponentiation<'_, '_, T, Async>
665where
666    T: RsaMode<InputType = [u32; N]>,
667{
668    /// Asynchronously performs an RSA modular exponentiation operation.
669    pub async fn exponentiation(
670        &mut self,
671        base: &T::InputType,
672        r: &T::InputType,
673        outbuf: &mut T::InputType,
674    ) {
675        self.set_up_exponentiation(base, r);
676        let fut = RsaFuture::new(self.rsa);
677        self.rsa.start_modexp();
678        fut.await;
679        self.rsa.read_out(outbuf);
680    }
681}
682
683impl<T: RsaMode, const N: usize> RsaModularMultiplication<'_, '_, T, Async>
684where
685    T: RsaMode<InputType = [u32; N]>,
686{
687    /// Asynchronously performs an RSA modular multiplication operation.
688    pub async fn modular_multiplication(
689        &mut self,
690        operand_b: &T::InputType,
691        outbuf: &mut T::InputType,
692    ) {
693        if cfg!(rsa_version = "1") {
694            let fut = RsaFuture::new(self.rsa);
695            self.rsa.start_multi();
696            fut.await;
697
698            self.rsa.write_operand_a(operand_b);
699        } else {
700            self.set_up_modular_multiplication(operand_b);
701        }
702
703        let fut = RsaFuture::new(self.rsa);
704        self.rsa.start_modmulti();
705        fut.await;
706        self.rsa.read_out(outbuf);
707    }
708}
709
710impl<T: RsaMode + Multi, const N: usize> RsaMultiplication<'_, '_, T, Async>
711where
712    T: RsaMode<InputType = [u32; N]>,
713{
714    /// Asynchronously performs an RSA multiplication operation.
715    pub async fn multiplication<const O: usize>(
716        &mut self,
717        operand_b: &T::InputType,
718        outbuf: &mut T::OutputType,
719    ) where
720        T: Multi<OutputType = [u32; O]>,
721    {
722        self.set_up_multiplication(operand_b);
723        let fut = RsaFuture::new(self.rsa);
724        self.rsa.start_multi();
725        fut.await;
726        self.rsa.read_out(outbuf);
727    }
728}
729
730#[handler]
731/// Interrupt handler for RSA.
732pub(super) fn rsa_interrupt_handler() {
733    let rsa = RSA::regs();
734
735    #[cfg(rsa_version = "1")]
736    SIGNALED.store(true, Ordering::Release);
737
738    low_level::clear_interrupt(rsa);
739
740    WAKER.wake();
741}
742
743static RSA_WORK_QUEUE: WorkQueue<RsaWorkItem> = WorkQueue::new();
744const RSA_VTABLE: VTable<RsaWorkItem> = VTable {
745    post: |driver, item| {
746        // Start processing immediately.
747        let driver = unsafe { RsaBackend::from_raw(driver) };
748        Some(driver.process_item(item))
749    },
750    poll: |driver, item| {
751        let driver = unsafe { RsaBackend::from_raw(driver) };
752        driver.process_item(item)
753    },
754    cancel: |driver, item| {
755        let driver = unsafe { RsaBackend::from_raw(driver) };
756        driver.cancel(item)
757    },
758    stop: |driver| {
759        let driver = unsafe { RsaBackend::from_raw(driver) };
760        driver.deinitialize()
761    },
762};
763
764#[derive(Default)]
765enum RsaBackendState<'d> {
766    #[default]
767    Idle,
768    Initializing(Rsa<'d, Blocking>),
769    Ready(Rsa<'d, Blocking>),
770    #[cfg(rsa_version = "1")]
771    ModularMultiplicationRoundOne(Rsa<'d, Blocking>),
772    Processing(Rsa<'d, Blocking>),
773}
774
775#[procmacros::doc_replace]
776/// RSA processing backend.
777///
778/// The backend processes work items placed in the RSA work queue. The backend needs to be created
779/// and started for operations to be processed. This allows you to perform operations on the RSA
780/// accelerator without carrying around the peripheral singleton, or the driver.
781///
782/// The [`RsaContext`] struct can enqueue work items that this backend will process.
783///
784/// ## Example
785///
786/// ```rust, no_run
787/// # {before_snippet}
788/// use esp_hal::rsa::{RsaBackend, RsaContext, operand_sizes::Op512};
789/// #
790/// let mut rsa_backend = RsaBackend::new(peripherals.RSA);
791/// let _driver = rsa_backend.start();
792///
793/// async fn perform_512bit_big_number_multiplication(
794///     operand_a: &[u32; 16],
795///     operand_b: &[u32; 16],
796///     result: &mut [u32; 32],
797/// ) {
798///     let mut rsa = RsaContext::new();
799///
800///     let mut handle = rsa.multiply::<Op512>(operand_a, operand_b, result);
801///     handle.wait().await;
802/// }
803/// # {after_snippet}
804/// ```
805pub struct RsaBackend<'d> {
806    peri: RSA<'d>,
807    state: RsaBackendState<'d>,
808}
809
810impl<'d> RsaBackend<'d> {
811    #[procmacros::doc_replace]
812    /// Creates a new RSA backend.
813    ///
814    /// ## Example
815    ///
816    /// ```rust, no_run
817    /// # {before_snippet}
818    /// use esp_hal::rsa::RsaBackend;
819    /// #
820    /// let mut rsa = RsaBackend::new(peripherals.RSA);
821    /// # {after_snippet}
822    /// ```
823    pub fn new(rsa: RSA<'d>) -> Self {
824        Self {
825            peri: rsa,
826            state: RsaBackendState::Idle,
827        }
828    }
829
830    #[procmacros::doc_replace]
831    /// Registers the RSA driver to process RSA operations.
832    ///
833    /// The driver stops operating when the returned object is dropped.
834    ///
835    /// ## Example
836    ///
837    /// ```rust, no_run
838    /// # {before_snippet}
839    /// use esp_hal::rsa::RsaBackend;
840    /// #
841    /// let mut rsa = RsaBackend::new(peripherals.RSA);
842    /// // Start the backend, which allows processing RSA operations.
843    /// let _backend = rsa.start();
844    /// # {after_snippet}
845    /// ```
846    pub fn start(&mut self) -> RsaWorkQueueDriver<'_, 'd> {
847        RsaWorkQueueDriver {
848            inner: WorkQueueDriver::new(self, RSA_VTABLE, &RSA_WORK_QUEUE),
849        }
850    }
851
852    // WorkQueue callbacks. They may run in any context.
853
854    unsafe fn from_raw<'any>(ptr: NonNull<()>) -> &'any mut Self {
855        unsafe { ptr.cast::<RsaBackend<'_>>().as_mut() }
856    }
857
858    fn process_item(&mut self, item: &mut RsaWorkItem) -> work_queue::Poll {
859        match core::mem::take(&mut self.state) {
860            RsaBackendState::Idle => {
861                let driver = Rsa {
862                    rsa: unsafe { self.peri.clone_unchecked() },
863                    phantom: PhantomData,
864                    _guard: RsaGuard::new(),
865                };
866                self.state = RsaBackendState::Initializing(driver);
867                work_queue::Poll::Pending(true)
868            }
869            RsaBackendState::Initializing(mut rsa) => {
870                // Wait for the peripheral to finish initializing. Ideally we need a way to
871                // instruct the work queue to wake the polling task immediately.
872                self.state = if rsa.ready() {
873                    rsa.set_interrupt_handler(rsa_work_queue_handler);
874                    rsa.enable_disable_interrupt(true);
875                    RsaBackendState::Ready(rsa)
876                } else {
877                    RsaBackendState::Initializing(rsa)
878                };
879                work_queue::Poll::Pending(true)
880            }
881            RsaBackendState::Ready(mut rsa) => {
882                #[cfg(not(rsa_version = "1"))]
883                {
884                    rsa.disable_constant_time(!item.constant_time);
885                    rsa.search_acceleration(item.search_acceleration);
886                }
887
888                match item.operation {
889                    RsaOperation::Multiplication { x, y } => {
890                        let n = x.len() as u32;
891                        rsa.write_operand_a(unsafe { x.as_ref() });
892
893                        // Non-modular multiplication result is twice as wide as its operands.
894                        rsa.write_multi_mode(2 * n / WORDS_PER_INCREMENT - 1, false);
895                        rsa.write_multi_operand_b(unsafe { y.as_ref() });
896                        rsa.start_multi();
897                    }
898
899                    RsaOperation::ModularMultiplication {
900                        x,
901                        #[cfg(not(rsa_version = "1"))]
902                        y,
903                        m,
904                        m_prime,
905                        r: r_inv,
906                        ..
907                    } => {
908                        let n = x.len() as u32;
909                        rsa.write_operand_a(unsafe { x.as_ref() });
910
911                        rsa.write_multi_mode(n / WORDS_PER_INCREMENT - 1, true);
912
913                        #[cfg(not(rsa_version = "1"))]
914                        rsa.write_operand_b(unsafe { y.as_ref() });
915
916                        rsa.write_modulus(unsafe { m.as_ref() });
917                        rsa.write_mprime(m_prime);
918                        rsa.write_r(unsafe { r_inv.as_ref() });
919
920                        rsa.start_modmulti();
921
922                        #[cfg(rsa_version = "1")]
923                        {
924                            // ESP32 requires a two-step process where Y needs to be written to the
925                            // X memory.
926                            self.state = RsaBackendState::ModularMultiplicationRoundOne(rsa);
927
928                            return work_queue::Poll::Pending(false);
929                        }
930                    }
931                    RsaOperation::ModularExponentiation {
932                        x,
933                        y,
934                        m,
935                        m_prime,
936                        r_inv,
937                    } => {
938                        let n = x.len() as u32;
939                        rsa.write_operand_a(unsafe { x.as_ref() });
940
941                        rsa.write_modexp_mode(n / WORDS_PER_INCREMENT - 1);
942                        rsa.write_operand_b(unsafe { y.as_ref() });
943                        rsa.write_modulus(unsafe { m.as_ref() });
944                        rsa.write_mprime(m_prime);
945                        rsa.write_r(unsafe { r_inv.as_ref() });
946
947                        #[cfg(not(rsa_version = "1"))]
948                        if item.search_acceleration {
949                            fn find_search_pos(exponent: &[u32]) -> u32 {
950                                for (i, byte) in exponent.iter().rev().enumerate() {
951                                    if *byte == 0 {
952                                        continue;
953                                    }
954                                    return (exponent.len() * 32) as u32
955                                        - (byte.leading_zeros() + i as u32 * 32)
956                                        - 1;
957                                }
958                                0
959                            }
960                            rsa.write_search_position(find_search_pos(unsafe { y.as_ref() }));
961                        }
962
963                        rsa.start_modexp();
964                    }
965                }
966
967                self.state = RsaBackendState::Processing(rsa);
968
969                work_queue::Poll::Pending(false)
970            }
971
972            #[cfg(rsa_version = "1")]
973            RsaBackendState::ModularMultiplicationRoundOne(mut rsa) => {
974                if rsa.is_idle() {
975                    let RsaOperation::ModularMultiplication { y, .. } = item.operation else {
976                        unreachable!();
977                    };
978
979                    // Y needs to be written to the X memory.
980                    rsa.write_operand_a(unsafe { y.as_ref() });
981                    rsa.start_modmulti();
982
983                    self.state = RsaBackendState::Processing(rsa);
984                } else {
985                    // Wait for the operation to complete
986                    self.state = RsaBackendState::ModularMultiplicationRoundOne(rsa);
987                }
988                work_queue::Poll::Pending(false)
989            }
990
991            RsaBackendState::Processing(rsa) => {
992                if rsa.is_idle() {
993                    rsa.read_out(unsafe { item.result.as_mut() });
994
995                    self.state = RsaBackendState::Ready(rsa);
996                    work_queue::Poll::Ready(Status::Completed)
997                } else {
998                    self.state = RsaBackendState::Processing(rsa);
999                    work_queue::Poll::Pending(false)
1000                }
1001            }
1002        }
1003    }
1004
1005    fn cancel(&mut self, _item: &mut RsaWorkItem) {
1006        // Drop the driver to reset it. We don't read the result, so the work item remains
1007        // unchanged, effectively cancelling it.
1008        self.state = RsaBackendState::Idle;
1009    }
1010
1011    fn deinitialize(&mut self) {
1012        self.state = RsaBackendState::Idle;
1013    }
1014}
1015
1016/// An active work queue driver.
1017///
1018/// This object must be kept around, otherwise RSA operations will never complete.
1019///
1020/// For a usage example, see [`RsaBackend`].
1021pub struct RsaWorkQueueDriver<'t, 'd> {
1022    inner: WorkQueueDriver<'t, RsaBackend<'d>, RsaWorkItem>,
1023}
1024
1025impl<'t, 'd> RsaWorkQueueDriver<'t, 'd> {
1026    /// Finishes processing the current work queue item, then stops the driver.
1027    pub fn stop(self) -> impl Future<Output = ()> {
1028        self.inner.stop()
1029    }
1030}
1031
1032#[derive(Clone)]
1033struct RsaWorkItem {
1034    // Acceleration options
1035    #[cfg(not(rsa_version = "1"))]
1036    search_acceleration: bool,
1037    #[cfg(not(rsa_version = "1"))]
1038    constant_time: bool,
1039
1040    // The operation to execute.
1041    operation: RsaOperation,
1042    result: NonNull<[u32]>,
1043}
1044
1045unsafe impl Sync for RsaWorkItem {}
1046unsafe impl Send for RsaWorkItem {}
1047
1048#[derive(Clone)]
1049enum RsaOperation {
1050    // Z = X * Y
1051    // len(Z) = len(X) + len(Y)
1052    Multiplication {
1053        x: NonNull<[u32]>,
1054        y: NonNull<[u32]>,
1055    },
1056    // Z = X * Y mod M
1057    ModularMultiplication {
1058        x: NonNull<[u32]>,
1059        y: NonNull<[u32]>,
1060        m: NonNull<[u32]>,
1061        r: NonNull<[u32]>,
1062        m_prime: u32,
1063    },
1064    // Z = X ^ Y mod M
1065    ModularExponentiation {
1066        x: NonNull<[u32]>,
1067        y: NonNull<[u32]>,
1068        m: NonNull<[u32]>,
1069        r_inv: NonNull<[u32]>,
1070        m_prime: u32,
1071    },
1072}
1073
1074#[handler]
1075#[ram]
1076fn rsa_work_queue_handler() {
1077    if !RSA_WORK_QUEUE.process() {
1078        // The queue may indicate that it needs to be polled again. In this case, we do not clear
1079        // the interrupt bit, which causes the interrupt to be re-handled.
1080        low_level::clear_interrupt(RSA::regs());
1081    }
1082}
1083
1084/// An RSA work queue user.
1085///
1086/// This object allows performing [big number multiplication][Self::multiply], [big number modular
1087/// multiplication][Self::modular_multiply] and [big number modular
1088/// exponentiation][Self::modular_exponentiate] with hardware acceleration. To perform these
1089/// operations, the [`RsaBackend`] must be started, otherwise these operations will never complete.
1090#[cfg_attr(
1091    not(rsa_version = "1"),
1092    doc = " \nThe context is created with a secure configuration by default. You can enable hardware acceleration
1093    options using [enable_search_acceleration][Self::enable_search_acceleration] and
1094    [enable_acceleration][Self::enable_acceleration] when appropriate."
1095)]
1096#[derive(Clone)]
1097pub struct RsaContext {
1098    frontend: WorkQueueFrontend<RsaWorkItem>,
1099}
1100
1101impl Default for RsaContext {
1102    fn default() -> Self {
1103        Self::new()
1104    }
1105}
1106
1107impl RsaContext {
1108    /// Creates a new context.
1109    pub fn new() -> Self {
1110        Self {
1111            frontend: WorkQueueFrontend::new(RsaWorkItem {
1112                #[cfg(not(rsa_version = "1"))]
1113                search_acceleration: false,
1114                #[cfg(not(rsa_version = "1"))]
1115                constant_time: true,
1116                operation: RsaOperation::Multiplication {
1117                    x: NonNull::from(&[]),
1118                    y: NonNull::from(&[]),
1119                },
1120                result: NonNull::from(&mut []),
1121            }),
1122        }
1123    }
1124
1125    #[cfg(not(rsa_version = "1"))]
1126    /// Enables search acceleration.
1127    ///
1128    /// When enabled it would increase the performance of modular
1129    /// exponentiation by discarding the exponent's bits before the most
1130    /// significant set bit.
1131    ///
1132    /// > ⚠️ Note: this compromises security by effectively decreasing the key length.
1133    ///
1134    /// For more information refer to the
1135    #[doc = trm_markdown_link!("rsa")]
1136    pub fn enable_search_acceleration(&mut self) {
1137        self.frontend.data_mut().search_acceleration = true;
1138    }
1139
1140    #[cfg(not(rsa_version = "1"))]
1141    /// Enables acceleration by disabling constant time operation.
1142    ///
1143    /// Disabling constant time operation increases the performance of modular
1144    /// exponentiation by simplifying the calculation concerning the 0 bits
1145    /// of the exponent. I.e. the less the Hamming weight, the greater the
1146    /// performance.
1147    ///
1148    /// > ⚠️ Note: this compromises security by enabling timing-based side-channel attacks.
1149    ///
1150    /// For more information refer to the
1151    #[doc = trm_markdown_link!("rsa")]
1152    pub fn enable_acceleration(&mut self) {
1153        self.frontend.data_mut().constant_time = false;
1154    }
1155
1156    fn post(&mut self) -> RsaHandle<'_> {
1157        RsaHandle(self.frontend.post(&RSA_WORK_QUEUE))
1158    }
1159
1160    #[procmacros::doc_replace]
1161    /// Starts a modular exponentiation operation, performing `Z = X ^ Y mod M`.
1162    ///
1163    /// Software needs to pre-calculate the following values:
1164    ///
1165    /// - `r`: `2 ^ ( bitlength * 2 ) mod M`.
1166    /// - `m_prime` can be calculated using `-(modular multiplicative inverse of M) mod 2^32`.
1167    ///
1168    /// It is relatively easy to calculate these values using the `crypto-bigint` crate:
1169    ///
1170    /// ```rust,no_run
1171    /// # {before_snippet}
1172    /// use crypto_bigint::{U512, Uint};
1173    /// const fn compute_r(modulus: &U512) -> U512 {
1174    ///     let mut d = [0_u32; U512::LIMBS * 2 + 1];
1175    ///     d[d.len() - 1] = 1;
1176    ///     let d = Uint::from_words(d);
1177    ///     d.wrapping_rem_vartime(&modulus.resize()).resize()
1178    /// }
1179    ///
1180    /// const fn compute_mprime(modulus: &U512) -> u32 {
1181    ///     let m_inv = modulus
1182    ///         .invert_mod2k(32)
1183    ///         .expect_copied("modulus must be odd")
1184    ///         .to_words()[0];
1185    ///     (-1 * m_inv as i64 & (u32::MAX as i64)) as u32
1186    /// }
1187    ///
1188    /// // Inputs
1189    /// const X: U512 = Uint::from_be_hex(
1190    ///     "c7f61058f96db3bd87dbab08ab03b4f7f2f864eac249144adea6a65f97803b719d8ca980b7b3c0389c1c7c6\
1191    ///    7dc353c5e0ec11f5fc8ce7f6073796cc8f73fa878",
1192    /// );
1193    /// const Y: U512 = Uint::from_be_hex(
1194    ///     "1763db3344e97be15d04de4868badb12a38046bb793f7630d87cf100aa1c759afac15a01f3c4c83ec2d2f66\
1195    ///    6bd22f71c3c1f075ec0e2cb0cb29994d091b73f51",
1196    /// );
1197    /// const M: U512 = Uint::from_be_hex(
1198    ///     "6b6bb3d2b6cbeb45a769eaa0384e611e1b89b0c9b45a045aca1c5fd6e8785b38df7118cf5dd45b9b63d293b\
1199    ///    67aeafa9ba25feb8712f188cb139b7d9b9af1c361",
1200    /// );
1201    ///
1202    /// // Values derived using the functions we defined above:
1203    /// let r = compute_r(&M);
1204    /// let mprime = compute_mprime(&M);
1205    ///
1206    /// use esp_hal::rsa::{RsaContext, operand_sizes::Op512};
1207    ///
1208    /// // Now perform the actual computation:
1209    /// let mut rsa = RsaContext::new();
1210    /// let mut outbuf = [0; 16];
1211    /// let mut handle = rsa.modular_multiply::<Op512>(
1212    ///     X.as_words(),
1213    ///     Y.as_words(),
1214    ///     M.as_words(),
1215    ///     r.as_words(),
1216    ///     mprime,
1217    ///     &mut outbuf,
1218    /// );
1219    /// handle.wait_blocking();
1220    /// # {after_snippet}
1221    /// ```
1222    ///
1223    /// The calculation is done asynchronously. This function returns an [`RsaHandle`] that can be
1224    /// used to poll the status of the calculation, to wait for it to finish, or to cancel the
1225    /// operation (by dropping the handle).
1226    ///
1227    /// When the operation is completed, the result will be stored in `result`.
1228    pub fn modular_exponentiate<'t, OP>(
1229        &'t mut self,
1230        x: &'t OP::InputType,
1231        y: &'t OP::InputType,
1232        m: &'t OP::InputType,
1233        r: &'t OP::InputType,
1234        m_prime: u32,
1235        result: &'t mut OP::InputType,
1236    ) -> RsaHandle<'t>
1237    where
1238        OP: RsaMode,
1239    {
1240        self.frontend.data_mut().operation = RsaOperation::ModularExponentiation {
1241            x: NonNull::from(x.as_ref()),
1242            y: NonNull::from(y.as_ref()),
1243            m: NonNull::from(m.as_ref()),
1244            r_inv: NonNull::from(r.as_ref()),
1245            m_prime,
1246        };
1247        self.frontend.data_mut().result = NonNull::from(result.as_mut());
1248        self.post()
1249    }
1250
1251    /// Starts a modular multiplication operation, performing `Z = X * Y mod M`.
1252    ///
1253    /// Software needs to pre-calculate the following values:
1254    ///
1255    /// - `r`: `2 ^ ( bitlength * 2 ) mod M`.
1256    /// - `m_prime` can be calculated using `-(modular multiplicative inverse of M) mod 2^32`.
1257    ///
1258    /// For an example how these values can be calculated and used, see
1259    /// [Self::modular_exponentiate].
1260    ///
1261    /// The calculation is done asynchronously. This function returns an [`RsaHandle`] that can be
1262    /// used to poll the status of the calculation, to wait for it to finish, or to cancel the
1263    /// operation (by dropping the handle).
1264    ///
1265    /// When the operation is completed, the result will be stored in `result`.
1266    pub fn modular_multiply<'t, OP>(
1267        &'t mut self,
1268        x: &'t OP::InputType,
1269        y: &'t OP::InputType,
1270        m: &'t OP::InputType,
1271        r: &'t OP::InputType,
1272        m_prime: u32,
1273        result: &'t mut OP::InputType,
1274    ) -> RsaHandle<'t>
1275    where
1276        OP: RsaMode,
1277    {
1278        self.frontend.data_mut().operation = RsaOperation::ModularMultiplication {
1279            x: NonNull::from(x.as_ref()),
1280            y: NonNull::from(y.as_ref()),
1281            m: NonNull::from(m.as_ref()),
1282            r: NonNull::from(r.as_ref()),
1283            m_prime,
1284        };
1285        self.frontend.data_mut().result = NonNull::from(result.as_mut());
1286        self.post()
1287    }
1288
1289    #[procmacros::doc_replace]
1290    /// Starts a multiplication operation, performing `Z = X * Y`.
1291    ///
1292    /// The calculation is done asynchronously. This function returns an [`RsaHandle`] that can be
1293    /// used to poll the status of the calculation, to wait for it to finish, or to cancel the
1294    /// operation (by dropping the handle).
1295    ///
1296    /// When the operation is completed, the result will be stored in `result`. The `result` is
1297    /// twice as wide as the inputs.
1298    ///
1299    /// ## Example
1300    ///
1301    /// ```rust,no_run
1302    /// # {before_snippet}
1303    ///
1304    /// // Inputs
1305    /// # let x: [u32; 16] = [0; 16];
1306    /// # let y: [u32; 16] = [0; 16];
1307    /// // let x: [u32; 16] = [...];
1308    /// // let y: [u32; 16] = [...];
1309    /// let mut outbuf = [0; 32];
1310    ///
1311    /// use esp_hal::rsa::{RsaContext, operand_sizes::Op512};
1312    ///
1313    /// // Now perform the actual computation:
1314    /// let mut rsa = RsaContext::new();
1315    /// let mut handle = rsa.multiply::<Op512>(&x, &y, &mut outbuf);
1316    /// handle.wait_blocking();
1317    /// # {after_snippet}
1318    /// ```
1319    pub fn multiply<'t, OP>(
1320        &'t mut self,
1321        x: &'t OP::InputType,
1322        y: &'t OP::InputType,
1323        result: &'t mut OP::OutputType,
1324    ) -> RsaHandle<'t>
1325    where
1326        OP: Multi,
1327    {
1328        self.frontend.data_mut().operation = RsaOperation::Multiplication {
1329            x: NonNull::from(x.as_ref()),
1330            y: NonNull::from(y.as_ref()),
1331        };
1332        self.frontend.data_mut().result = NonNull::from(result.as_mut());
1333        self.post()
1334    }
1335}
1336
1337/// The handle to the pending RSA operation.
1338pub struct RsaHandle<'t>(work_queue::Handle<'t, RsaWorkItem>);
1339
1340impl RsaHandle<'_> {
1341    /// Polls the status of the work item.
1342    #[inline]
1343    pub fn poll(&mut self) -> bool {
1344        self.0.poll()
1345    }
1346
1347    /// Blocks until the work item is processed.
1348    #[inline]
1349    pub fn wait_blocking(self) {
1350        self.0.wait_blocking();
1351    }
1352
1353    /// Waits for the work item to be processed.
1354    #[inline]
1355    pub fn wait(&mut self) -> impl Future<Output = Status> {
1356        self.0.wait()
1357    }
1358}