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//! ## Examples
17//!
18//! ### Modular Exponentiation, Modular Multiplication, and Multiplication
19//! Visit the [RSA test suite] for an example of using the peripheral.
20//!
21//! [nb]: https://docs.rs/nb/1.1.0/nb/
22//! [RSA test suite]: https://github.com/esp-rs/esp-hal/blob/main/hil-test/tests/rsa.rs
23
24use core::{marker::PhantomData, ptr::copy_nonoverlapping};
25
26use crate::{
27    Async,
28    Blocking,
29    interrupt::InterruptHandler,
30    pac,
31    peripherals::{Interrupt, RSA},
32    system::{Cpu, GenericPeripheralGuard, Peripheral as PeripheralEnable},
33};
34
35#[cfg_attr(esp32s2, path = "esp32sX.rs")]
36#[cfg_attr(esp32s3, path = "esp32sX.rs")]
37#[cfg_attr(esp32c3, path = "esp32cX.rs")]
38#[cfg_attr(esp32c6, path = "esp32cX.rs")]
39#[cfg_attr(esp32h2, path = "esp32cX.rs")]
40#[cfg_attr(esp32, path = "esp32.rs")]
41mod rsa_spec_impl;
42
43pub use rsa_spec_impl::operand_sizes;
44
45/// RSA peripheral container
46pub struct Rsa<'d, Dm: crate::DriverMode> {
47    rsa: RSA<'d>,
48    phantom: PhantomData<Dm>,
49    _guard: GenericPeripheralGuard<{ PeripheralEnable::Rsa as u8 }>,
50}
51
52impl<'d> Rsa<'d, Blocking> {
53    /// Create a new instance in [crate::Blocking] mode.
54    ///
55    /// Optionally an interrupt handler can be bound.
56    pub fn new(rsa: RSA<'d>) -> Self {
57        Self::new_internal(rsa)
58    }
59
60    /// Reconfigures the RSA driver to operate in asynchronous mode.
61    pub fn into_async(mut self) -> Rsa<'d, Async> {
62        self.set_interrupt_handler(asynch::rsa_interrupt_handler);
63        Rsa {
64            rsa: self.rsa,
65            phantom: PhantomData,
66            _guard: self._guard,
67        }
68    }
69
70    /// Registers an interrupt handler for the RSA peripheral.
71    ///
72    /// Note that this will replace any previously registered interrupt
73    /// handlers.
74    #[instability::unstable]
75    pub fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
76        for core in crate::system::Cpu::other() {
77            crate::interrupt::disable(core, Interrupt::RSA);
78        }
79        unsafe { crate::interrupt::bind_interrupt(Interrupt::RSA, handler.handler()) };
80        unwrap!(crate::interrupt::enable(Interrupt::RSA, handler.priority()));
81    }
82}
83
84impl crate::private::Sealed for Rsa<'_, Blocking> {}
85
86#[instability::unstable]
87impl crate::interrupt::InterruptConfigurable for Rsa<'_, Blocking> {
88    fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
89        self.set_interrupt_handler(handler);
90    }
91}
92
93impl<'d> Rsa<'d, Async> {
94    /// Create a new instance in [crate::Blocking] mode.
95    pub fn into_blocking(self) -> Rsa<'d, Blocking> {
96        crate::interrupt::disable(Cpu::current(), Interrupt::RSA);
97        Rsa {
98            rsa: self.rsa,
99            phantom: PhantomData,
100            _guard: self._guard,
101        }
102    }
103}
104
105impl<'d, Dm: crate::DriverMode> Rsa<'d, Dm> {
106    fn new_internal(rsa: RSA<'d>) -> Self {
107        let guard = GenericPeripheralGuard::new();
108
109        Self {
110            rsa,
111            phantom: PhantomData,
112            _guard: guard,
113        }
114    }
115
116    fn regs(&self) -> &pac::rsa::RegisterBlock {
117        self.rsa.register_block()
118    }
119
120    fn write_operand_b<const N: usize>(&mut self, operand_b: &[u32; N]) {
121        unsafe { copy_nonoverlapping(operand_b.as_ptr(), self.regs().y_mem(0).as_ptr(), N) };
122    }
123
124    fn write_modulus<const N: usize>(&mut self, modulus: &[u32; N]) {
125        unsafe { copy_nonoverlapping(modulus.as_ptr(), self.regs().m_mem(0).as_ptr(), N) };
126    }
127
128    fn write_mprime(&mut self, m_prime: u32) {
129        self.regs().m_prime().write(|w| unsafe { w.bits(m_prime) });
130    }
131
132    fn write_operand_a<const N: usize>(&mut self, operand_a: &[u32; N]) {
133        unsafe { copy_nonoverlapping(operand_a.as_ptr(), self.regs().x_mem(0).as_ptr(), N) };
134    }
135
136    fn write_multi_operand_b<const N: usize>(&mut self, operand_b: &[u32; N]) {
137        unsafe { copy_nonoverlapping(operand_b.as_ptr(), self.regs().z_mem(0).as_ptr().add(N), N) };
138    }
139
140    fn write_r<const N: usize>(&mut self, r: &[u32; N]) {
141        unsafe { copy_nonoverlapping(r.as_ptr(), self.regs().z_mem(0).as_ptr(), N) };
142    }
143
144    fn read_out<const N: usize>(&self, outbuf: &mut [u32; N]) {
145        unsafe {
146            copy_nonoverlapping(
147                self.regs().z_mem(0).as_ptr() as *const u32,
148                outbuf.as_ptr() as *mut u32,
149                N,
150            );
151        }
152    }
153    fn wait_for_idle(&mut self) {
154        while !self.is_idle() {}
155        self.clear_interrupt();
156    }
157
158    fn read_results<const N: usize>(&mut self, outbuf: &mut [u32; N]) {
159        self.wait_for_idle();
160        self.read_out(outbuf);
161    }
162}
163
164/// Defines the input size of an RSA operation.
165pub trait RsaMode: crate::private::Sealed {
166    /// The input data type used for the operation.
167    type InputType;
168}
169
170/// Defines the output type of RSA multiplications.
171pub trait Multi: RsaMode {
172    /// The type of the output produced by the operation.
173    type OutputType;
174}
175
176macro_rules! implement_op {
177    (($x:literal, multi)) => {
178        paste! {
179            #[doc = concat!($x, "-bit RSA operation.")]
180            pub struct [<Op $x>];
181
182            impl Multi for [<Op $x>] {
183                type OutputType = [u32; $x * 2 / 32];
184            }
185
186            impl crate::private::Sealed for [<Op $x>] {}
187
188            impl RsaMode for [<Op $x>] {
189                type InputType = [u32; $x / 32];
190            }
191        }
192    };
193
194    (($x:literal)) => {
195        paste! {
196            /// Represents an RSA operation for the given bit size.
197            pub struct [<Op $x>];
198
199            impl crate::private::Sealed for [<Op $x>] {}
200
201            impl RsaMode for [<Op $x>] {
202                type InputType = [u32; $x / 32];
203            }
204        }
205    };
206
207    ($x:tt, $($y:tt),+) => {
208        implement_op!($x);
209        implement_op!($($y),+);
210    };
211}
212
213use implement_op;
214
215/// Support for RSA peripheral's modular exponentiation feature that could be
216/// used to find the `(base ^ exponent) mod modulus`.
217///
218/// Each operand is a little endian byte array of the same size
219pub struct RsaModularExponentiation<'a, 'd, T: RsaMode, Dm: crate::DriverMode> {
220    rsa: &'a mut Rsa<'d, Dm>,
221    phantom: PhantomData<T>,
222}
223
224impl<'a, 'd, T: RsaMode, Dm: crate::DriverMode, const N: usize>
225    RsaModularExponentiation<'a, 'd, T, Dm>
226where
227    T: RsaMode<InputType = [u32; N]>,
228{
229    /// Creates an instance of `RsaModularExponentiation`.
230    ///
231    /// `m_prime` could be calculated using `-(modular multiplicative inverse of
232    /// modulus) mod 2^32`.
233    ///
234    /// For more information refer to 24.3.2 of <https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf>.
235    pub fn new(
236        rsa: &'a mut Rsa<'d, Dm>,
237        exponent: &T::InputType,
238        modulus: &T::InputType,
239        m_prime: u32,
240    ) -> Self {
241        Self::write_mode(rsa);
242        rsa.write_operand_b(exponent);
243        rsa.write_modulus(modulus);
244        rsa.write_mprime(m_prime);
245
246        #[cfg(not(esp32))]
247        if rsa.is_search_enabled() {
248            rsa.write_search_position(Self::find_search_pos(exponent));
249        }
250
251        Self {
252            rsa,
253            phantom: PhantomData,
254        }
255    }
256
257    fn set_up_exponentiation(&mut self, base: &T::InputType, r: &T::InputType) {
258        self.rsa.write_operand_a(base);
259        self.rsa.write_r(r);
260    }
261
262    /// Starts the modular exponentiation operation.
263    ///
264    /// `r` can be calculated using `2 ^ ( bitlength * 2 ) mod modulus`.
265    ///
266    /// For more information refer to 24.3.2 of <https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf>.
267    pub fn start_exponentiation(&mut self, base: &T::InputType, r: &T::InputType) {
268        self.set_up_exponentiation(base, r);
269        self.rsa.write_modexp_start();
270    }
271
272    /// Reads the result to the given buffer.
273    ///
274    /// This is a non blocking function that returns without an error if
275    /// operation is completed successfully. `start_exponentiation` must be
276    /// called before calling this function.
277    pub fn read_results(&mut self, outbuf: &mut T::InputType) {
278        self.rsa.read_results(outbuf);
279    }
280}
281
282/// Support for RSA peripheral's modular multiplication feature that could be
283/// used to find the `(operand a * operand b) mod modulus`.
284///
285/// Each operand is a little endian byte array of the same size
286pub struct RsaModularMultiplication<'a, 'd, T: RsaMode, Dm: crate::DriverMode> {
287    rsa: &'a mut Rsa<'d, Dm>,
288    phantom: PhantomData<T>,
289}
290
291impl<'a, 'd, T: RsaMode, Dm: crate::DriverMode, const N: usize>
292    RsaModularMultiplication<'a, 'd, T, Dm>
293where
294    T: RsaMode<InputType = [u32; N]>,
295{
296    /// Creates an instance of `RsaModularMultiplication`.
297    ///
298    /// - `r` can be calculated using `2 ^ ( bitlength * 2 ) mod modulus`.
299    /// - `m_prime` can be calculated using `-(modular multiplicative inverse of
300    ///   modulus) mod 2^32`.
301    ///
302    /// For more information refer to 20.3.1 of <https://www.espressif.com/sites/default/files/documentation/esp32-s3_technical_reference_manual_en.pdf>.
303    pub fn new(
304        rsa: &'a mut Rsa<'d, Dm>,
305        operand_a: &T::InputType,
306        modulus: &T::InputType,
307        r: &T::InputType,
308        m_prime: u32,
309    ) -> Self {
310        Self::write_mode(rsa);
311        rsa.write_mprime(m_prime);
312        rsa.write_modulus(modulus);
313        rsa.write_operand_a(operand_a);
314        rsa.write_r(r);
315
316        Self {
317            rsa,
318            phantom: PhantomData,
319        }
320    }
321
322    /// Starts the modular multiplication operation.
323    ///
324    /// For more information refer to 19.3.1 of <https://www.espressif.com/sites/default/files/documentation/esp32-c3_technical_reference_manual_en.pdf>.
325    pub fn start_modular_multiplication(&mut self, operand_b: &T::InputType) {
326        self.set_up_modular_multiplication(operand_b);
327        self.rsa.write_modmulti_start();
328    }
329
330    /// Reads the result to the given buffer.
331    /// This is a non blocking function that returns without an error if
332    /// operation is completed successfully.
333    pub fn read_results(&mut self, outbuf: &mut T::InputType) {
334        self.rsa.read_results(outbuf);
335    }
336}
337
338/// Support for RSA peripheral's large number multiplication feature that could
339/// be used to find the `operand a * operand b`.
340///
341/// Each operand is a little endian byte array of the same size
342pub struct RsaMultiplication<'a, 'd, T: RsaMode + Multi, Dm: crate::DriverMode> {
343    rsa: &'a mut Rsa<'d, Dm>,
344    phantom: PhantomData<T>,
345}
346
347impl<'a, 'd, T: RsaMode + Multi, Dm: crate::DriverMode, const N: usize>
348    RsaMultiplication<'a, 'd, T, Dm>
349where
350    T: RsaMode<InputType = [u32; N]>,
351{
352    /// Creates an instance of `RsaMultiplication`.
353    pub fn new(rsa: &'a mut Rsa<'d, Dm>, operand_a: &T::InputType) -> Self {
354        Self::write_mode(rsa);
355        rsa.write_operand_a(operand_a);
356
357        Self {
358            rsa,
359            phantom: PhantomData,
360        }
361    }
362
363    /// Starts the multiplication operation.
364    pub fn start_multiplication(&mut self, operand_b: &T::InputType) {
365        self.set_up_multiplication(operand_b);
366        self.rsa.write_multi_start();
367    }
368
369    /// Reads the result to the given buffer.
370    /// This is a non blocking function that returns without an error if
371    /// operation is completed successfully. `start_multiplication` must be
372    /// called before calling this function.
373    pub fn read_results<const O: usize>(&mut self, outbuf: &mut T::OutputType)
374    where
375        T: Multi<OutputType = [u32; O]>,
376    {
377        self.rsa.read_results(outbuf);
378    }
379}
380
381/// Async functionality
382pub(crate) mod asynch {
383    use core::task::Poll;
384
385    use portable_atomic::{AtomicBool, Ordering};
386    use procmacros::handler;
387
388    use crate::{
389        Async,
390        asynch::AtomicWaker,
391        peripherals::RSA,
392        rsa::{
393            Multi,
394            Rsa,
395            RsaMode,
396            RsaModularExponentiation,
397            RsaModularMultiplication,
398            RsaMultiplication,
399        },
400    };
401
402    static WAKER: AtomicWaker = AtomicWaker::new();
403
404    static SIGNALED: AtomicBool = AtomicBool::new(false);
405
406    /// `Future` that waits for the RSA operation to complete.
407    #[must_use = "futures do nothing unless you `.await` or poll them"]
408    struct RsaFuture<'a, 'd> {
409        #[cfg_attr(esp32, allow(dead_code))]
410        driver: &'a Rsa<'d, Async>,
411    }
412
413    impl<'a, 'd> RsaFuture<'a, 'd> {
414        fn new(driver: &'a Rsa<'d, Async>) -> Self {
415            SIGNALED.store(false, Ordering::Relaxed);
416
417            #[cfg(not(esp32))]
418            driver.regs().int_ena().write(|w| w.int_ena().set_bit());
419
420            Self { driver }
421        }
422
423        fn is_done(&self) -> bool {
424            SIGNALED.load(Ordering::Acquire)
425        }
426    }
427
428    impl Drop for RsaFuture<'_, '_> {
429        fn drop(&mut self) {
430            #[cfg(not(esp32))]
431            self.driver
432                .regs()
433                .int_ena()
434                .write(|w| w.int_ena().clear_bit());
435        }
436    }
437
438    impl core::future::Future for RsaFuture<'_, '_> {
439        type Output = ();
440
441        fn poll(
442            self: core::pin::Pin<&mut Self>,
443            cx: &mut core::task::Context<'_>,
444        ) -> core::task::Poll<Self::Output> {
445            WAKER.register(cx.waker());
446            if self.is_done() {
447                Poll::Ready(())
448            } else {
449                Poll::Pending
450            }
451        }
452    }
453
454    impl<T: RsaMode, const N: usize> RsaModularExponentiation<'_, '_, T, Async>
455    where
456        T: RsaMode<InputType = [u32; N]>,
457    {
458        /// Asynchronously performs an RSA modular exponentiation operation.
459        pub async fn exponentiation(
460            &mut self,
461            base: &T::InputType,
462            r: &T::InputType,
463            outbuf: &mut T::InputType,
464        ) {
465            self.set_up_exponentiation(base, r);
466            let fut = RsaFuture::new(self.rsa);
467            self.rsa.write_modexp_start();
468            fut.await;
469            self.rsa.read_out(outbuf);
470        }
471    }
472
473    impl<T: RsaMode, const N: usize> RsaModularMultiplication<'_, '_, T, Async>
474    where
475        T: RsaMode<InputType = [u32; N]>,
476    {
477        /// Asynchronously performs an RSA modular multiplication operation.
478        pub async fn modular_multiplication(
479            &mut self,
480            operand_b: &T::InputType,
481            outbuf: &mut T::InputType,
482        ) {
483            cfg_if::cfg_if! {
484                if #[cfg(esp32)] {
485                    let fut = RsaFuture::new(self.rsa);
486                    self.rsa.write_multi_start();
487                    fut.await;
488
489                    self.rsa.write_operand_a(operand_b);
490                } else {
491                    self.set_up_modular_multiplication(operand_b);
492                }
493            }
494
495            let fut = RsaFuture::new(self.rsa);
496            self.rsa.write_modmulti_start();
497            fut.await;
498            self.rsa.read_out(outbuf);
499        }
500    }
501
502    impl<T: RsaMode + Multi, const N: usize> RsaMultiplication<'_, '_, T, Async>
503    where
504        T: RsaMode<InputType = [u32; N]>,
505    {
506        /// Asynchronously performs an RSA multiplication operation.
507        pub async fn multiplication<const O: usize>(
508            &mut self,
509            operand_b: &T::InputType,
510            outbuf: &mut T::OutputType,
511        ) where
512            T: Multi<OutputType = [u32; O]>,
513        {
514            self.set_up_multiplication(operand_b);
515            let fut = RsaFuture::new(self.rsa);
516            self.rsa.write_multi_start();
517            fut.await;
518            self.rsa.read_out(outbuf);
519        }
520    }
521
522    #[handler]
523    /// Interrupt handler for RSA.
524    pub(super) fn rsa_interrupt_handler() {
525        let rsa = RSA::regs();
526        SIGNALED.store(true, Ordering::Release);
527        cfg_if::cfg_if! {
528            if #[cfg(esp32)] {
529                rsa.interrupt().write(|w| w.interrupt().set_bit());
530            } else  {
531                rsa.int_clr().write(|w| w.int_clr().set_bit());
532            }
533        }
534
535        WAKER.wake();
536    }
537}