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