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