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")]
19
mod low_level;
20

            
21
use core::{marker::PhantomData, ptr::NonNull, task::Poll};
22

            
23
#[cfg(rsa_version = "1")]
24
use portable_atomic::{AtomicBool, Ordering};
25
use procmacros::{handler, ram};
26

            
27
use 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.
42
pub struct Rsa<'d, Dm: DriverMode> {
43
    rsa: RSA<'d>,
44
    phantom: PhantomData<Dm>,
45
    _guard: RsaGuard,
46
}
47

            
48
// There are two distinct peripheral versions: ESP32, and all else. There is a naming split in the
49
// later devices, and they use different (memory size, operand size increment) parameters, but they
50
// are largely the same.
51

            
52
/// How many words are there in an operand size increment.
53
///
54
/// I.e. if the RSA hardware works with operands of 512, 1024, 1536, ... bits, the increment is 512
55
/// bits, or 16 words.
56
const WORDS_PER_INCREMENT: u32 = property!("rsa.size_increment") / 32;
57

            
58
struct RsaGuard {
59
    _guard: GenericPeripheralGuard<{ PeripheralEnable::Rsa as u8 }>,
60
    _clock_guard: CryptoClockGuard,
61
}
62

            
63
impl RsaGuard {
64
    fn new() -> Self {
65
        let _clock_guard = CryptoClockGuard::new();
66
        let _guard = GenericPeripheralGuard::new();
67
        cfg_select! {
68
            rsa_version = "1" => {}
69
            esp32s31 => {}
70
            _ => {
71
                crate::peripherals::SYSTEM::regs()
72
                    .rsa_pd_ctrl()
73
                    .modify(|_, w| {
74
                        w.rsa_mem_force_pd().clear_bit();
75
                        w.rsa_mem_force_pu().set_bit();
76
                        w.rsa_mem_pd().clear_bit()
77
                    });
78
            }
79
        }
80

            
81
        Self {
82
            _guard,
83
            _clock_guard,
84
        }
85
    }
86
}
87

            
88
impl Drop for RsaGuard {
89
5
    fn drop(&mut self) {
90
        unsafe {
91
            // Stopping the peripheral's clock source pends an interrupt. Since the clocks
92
            // are stopped when the handler runs, we're not able to clear the interrupt flag,
93
            // which means the interrupt handler keeps getting triggered indefinitely.
94
            // To prevent this, we disable interrupts manually before stopping the peripheral.
95
            crate::peripherals::RSA::steal().disable_peri_interrupt_on_all_cores();
96
        }
97

            
98
        cfg_select! {
99
            rsa_version = "1" => {}
100
            esp32s31 => {}
101
            _ => {
102
                crate::peripherals::SYSTEM::regs()
103
                    .rsa_pd_ctrl()
104
                    .modify(|_, w| {
105
                        w.rsa_mem_force_pd().clear_bit();
106
                        w.rsa_mem_force_pu().clear_bit();
107
                        w.rsa_mem_pd().set_bit()
108
                    });
109
            }
110
        }
111
5
    }
112
}
113

            
114
impl<'d> Rsa<'d, Blocking> {
115
    /// Creates a new instance in [Blocking] mode.
116
    ///
117
    /// Optionally an interrupt handler can be bound.
118
7
    pub fn new(rsa: RSA<'d>) -> Self {
119
        let this = Self {
120
            rsa,
121
            phantom: PhantomData,
122
            _guard: RsaGuard::new(),
123
        };
124

            
125
7
        while !this.ready() {}
126

            
127
        this
128
7
    }
129

            
130
    /// Reconfigures the RSA driver to operate in asynchronous mode.
131
3
    pub fn into_async(mut self) -> Rsa<'d, Async> {
132
        self.set_interrupt_handler(rsa_interrupt_handler);
133
        self.enable_disable_interrupt(true);
134

            
135
        Rsa {
136
            rsa: self.rsa,
137
            phantom: PhantomData,
138
            _guard: self._guard,
139
        }
140
3
    }
141

            
142
    /// Enables or disables the RSA interrupt.
143
    ///
144
    /// When enabled rsa peripheral would generate an interrupt when a operation
145
    /// is finished.
146
    pub fn enable_disable_interrupt(&mut self, enable: bool) {
147
        self.internal_enable_disable_interrupt(enable);
148
    }
149

            
150
    /// Registers an interrupt handler for the RSA peripheral.
151
    ///
152
    /// Replaces any previously registered interrupt handlers.
153
    #[instability::unstable]
154
    pub fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
155
        self.rsa.disable_peri_interrupt_on_all_cores();
156
        self.rsa.bind_peri_interrupt(handler);
157
    }
158
}
159

            
160
impl crate::private::Sealed for Rsa<'_, Blocking> {}
161

            
162
#[instability::unstable]
163
impl crate::interrupt::InterruptConfigurable for Rsa<'_, Blocking> {
164
    fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
165
        self.set_interrupt_handler(handler);
166
    }
167
}
168

            
169
impl<'d> Rsa<'d, Async> {
170
    /// Reconfigures the RSA driver to operate in [`Blocking`] mode.
171
    pub fn into_blocking(self) -> Rsa<'d, Blocking> {
172
        self.internal_enable_disable_interrupt(false);
173
        self.rsa.disable_peri_interrupt_on_all_cores();
174

            
175
        Rsa {
176
            rsa: self.rsa,
177
            phantom: PhantomData,
178
            _guard: self._guard,
179
        }
180
    }
181
}
182

            
183
impl<'d, Dm: DriverMode> Rsa<'d, Dm> {
184
    fn internal_enable_disable_interrupt(&self, enable: bool) {
185
        low_level::enable_disable_interrupt(self.regs(), enable);
186
    }
187

            
188
    fn regs(&self) -> &pac::rsa::RegisterBlock {
189
        self.rsa.register_block()
190
    }
191

            
192
    /// Returns whether RSA memory blocks are initialized after reset.
193
    fn ready(&self) -> bool {
194
        low_level::ready(self.regs())
195
    }
196

            
197
    /// Starts the modular exponentiation operation.
198
    fn start_modexp(&self) {
199
1
        low_level::start_modexp(self.regs());
200
    }
201

            
202
    /// Starts the multiplication operation.
203
    fn start_multi(&self) {
204
1
        low_level::start_multi(self.regs());
205
    }
206

            
207
    /// Starts the modular multiplication operation.
208
    fn start_modmulti(&self) {
209
1
        low_level::start_modmulti(self.regs());
210
    }
211

            
212
    /// Clears the RSA interrupt flag.
213
    fn clear_interrupt(&mut self) {
214
1
        low_level::clear_interrupt(self.regs());
215
    }
216

            
217
    /// Returns whether the RSA peripheral is idle.
218
    fn is_idle(&self) -> bool {
219
1
        low_level::is_idle(self.regs())
220
    }
221

            
222
    fn wait_for_idle(&mut self) {
223
1
        while !self.is_idle() {}
224
        self.clear_interrupt();
225
    }
226

            
227
    /// Writes the result size of the multiplication.
228
    fn write_multi_mode(&mut self, mode: u32, modular: bool) {
229
1
        low_level::write_multi_mode(self.regs(), mode, modular);
230
    }
231

            
232
    /// Writes the result size of the modular exponentiation.
233
    fn write_modexp_mode(&mut self, mode: u32) {
234
1
        low_level::write_modexp_mode(self.regs(), mode);
235
    }
236

            
237
2
    fn write_operand_b(&mut self, operand: &[u32]) {
238
        for (reg, op) in self.regs().y_mem_iter().zip(operand.iter().copied()) {
239
            reg.write(|w| unsafe { w.bits(op) });
240
        }
241
2
    }
242

            
243
2
    fn write_modulus(&mut self, modulus: &[u32]) {
244
        for (reg, op) in self.regs().m_mem_iter().zip(modulus.iter().copied()) {
245
            reg.write(|w| unsafe { w.bits(op) });
246
        }
247
2
    }
248

            
249
    fn write_mprime(&mut self, m_prime: u32) {
250
        self.regs().m_prime().write(|w| unsafe { w.bits(m_prime) });
251
    }
252

            
253
3
    fn write_operand_a(&mut self, operand: &[u32]) {
254
        for (reg, op) in self.regs().x_mem_iter().zip(operand.iter().copied()) {
255
            reg.write(|w| unsafe { w.bits(op) });
256
        }
257
3
    }
258

            
259
    fn write_multi_operand_b(&mut self, operand: &[u32]) {
260
        for (reg, op) in self
261
            .regs()
262
            .z_mem_iter()
263
            .skip(operand.len())
264
            .zip(operand.iter().copied())
265
        {
266
            reg.write(|w| unsafe { w.bits(op) });
267
        }
268
    }
269

            
270
2
    fn write_r(&mut self, r: &[u32]) {
271
        for (reg, op) in self.regs().z_mem_iter().zip(r.iter().copied()) {
272
            reg.write(|w| unsafe { w.bits(op) });
273
        }
274
2
    }
275

            
276
    fn read_out(&self, outbuf: &mut [u32]) {
277
        for (reg, op) in self.regs().z_mem_iter().zip(outbuf.iter_mut()) {
278
96
            *op = reg.read().bits();
279
        }
280

            
281
        #[cfg(clear_crypto_secrets)]
282
        self.clear_secrets();
283
    }
284

            
285
    /// Removes the operands and intermediate results from the peripheral.
286
    #[cfg(clear_crypto_secrets)]
287
    fn clear_secrets(&self) {
288
        for reg in self.regs().x_mem_iter() {
289
            reg.write(|w| unsafe { w.bits(0) });
290
        }
291
        for reg in self.regs().y_mem_iter() {
292
            reg.write(|w| unsafe { w.bits(0) });
293
        }
294
        for reg in self.regs().z_mem_iter() {
295
            reg.write(|w| unsafe { w.bits(0) });
296
        }
297
        for reg in self.regs().m_mem_iter() {
298
            reg.write(|w| unsafe { w.bits(0) });
299
        }
300
    }
301

            
302
    fn read_results(&mut self, outbuf: &mut [u32]) {
303
        self.wait_for_idle();
304
        self.read_out(outbuf);
305
    }
306

            
307
    /// Enables or disables constant time operation.
308
    ///
309
    /// Disabling constant time operation increases the performance of modular
310
    /// exponentiation by simplifying the calculation concerning the 0 bits
311
    /// of the exponent. I.e. the less the Hamming weight, the greater the
312
    /// performance.
313
    ///
314
    /// Compromises security by enabling timing-based side-channel attacks.
315
    ///
316
    /// For more information refer to the
317
    #[doc = trm_markdown_link!("rsa")]
318
    #[cfg(not(rsa_version = "1"))]
319
    pub fn disable_constant_time(&mut self, disable: bool) {
320
        self.regs()
321
            .constant_time()
322
            .write(|w| w.constant_time().bit(disable));
323
    }
324

            
325
    /// Enables or disables search acceleration.
326
    ///
327
    /// When enabled it would increase the performance of modular
328
    /// exponentiation by discarding the exponent's bits before the most
329
    /// significant set bit.
330
    ///
331
    /// Compromises security by effectively decreasing the key length.
332
    ///
333
    /// For more information refer to the
334
    #[doc = trm_markdown_link!("rsa")]
335
    #[cfg(not(rsa_version = "1"))]
336
    pub fn search_acceleration(&mut self, enable: bool) {
337
        self.regs()
338
            .search_enable()
339
            .write(|w| w.search_enable().bit(enable));
340
    }
341

            
342
    /// Returns whether the search functionality is enabled in the RSA hardware.
343
    #[cfg(not(rsa_version = "1"))]
344
    fn is_search_enabled(&mut self) -> bool {
345
        self.regs()
346
            .search_enable()
347
            .read()
348
            .search_enable()
349
            .bit_is_set()
350
    }
351

            
352
    /// Sets the search position in the RSA hardware.
353
    #[cfg(not(rsa_version = "1"))]
354
    fn write_search_position(&mut self, search_position: u32) {
355
        self.regs()
356
            .search_pos()
357
            .write(|w| unsafe { w.bits(search_position) });
358
    }
359
}
360

            
361
/// Defines the input size of an RSA operation.
362
pub trait RsaMode: crate::private::Sealed {
363
    /// The input data type used for the operation.
364
    type InputType: AsRef<[u32]> + AsMut<[u32]>;
365
}
366

            
367
/// Defines the output type of RSA multiplications.
368
pub trait Multi: RsaMode {
369
    /// The type of the output produced by the operation.
370
    type OutputType: AsRef<[u32]> + AsMut<[u32]>;
371
}
372

            
373
/// Defines the exponentiation and multiplication lengths for RSA operations.
374
pub mod operand_sizes {
375
    for_each_rsa_exponentiation!(
376
        ($x:literal) => {
377
            paste::paste! {
378
                #[doc = concat!(stringify!($x), "-bit RSA operation.")]
379
                pub struct [<Op $x>];
380

            
381
                impl crate::private::Sealed for [<Op $x>] {}
382
                impl crate::rsa::RsaMode for [<Op $x>] {
383
                    type InputType = [u32; $x / 32];
384
                }
385
            }
386
        };
387
    );
388

            
389
    for_each_rsa_multiplication!(
390
        ($x:literal) => {
391
            impl crate::rsa::Multi for paste::paste!( [<Op $x>] ) {
392
                type OutputType = [u32; $x * 2 / 32];
393
            }
394
        };
395
    );
396
}
397

            
398
/// Support for the RSA peripheral's modular exponentiation feature that could be
399
/// used to find the `(base ^ exponent) mod modulus`.
400
///
401
/// Each operand is a little endian byte array of the same size.
402
pub struct RsaModularExponentiation<'a, 'd, T: RsaMode, Dm: DriverMode> {
403
    rsa: &'a mut Rsa<'d, Dm>,
404
    phantom: PhantomData<T>,
405
}
406

            
407
impl<'a, 'd, T: RsaMode, Dm: DriverMode, const N: usize> RsaModularExponentiation<'a, 'd, T, Dm>
408
where
409
    T: RsaMode<InputType = [u32; N]>,
410
{
411
    /// Creates an instance of `RsaModularExponentiation`.
412
    ///
413
    /// `m_prime` could be calculated using `-(modular multiplicative inverse of
414
    /// modulus) mod 2^32`.
415
    ///
416
    /// For more information refer to the
417
    #[doc = trm_markdown_link!("rsa")]
418
    pub fn new(
419
        rsa: &'a mut Rsa<'d, Dm>,
420
        exponent: &T::InputType,
421
        modulus: &T::InputType,
422
        m_prime: u32,
423
    ) -> Self {
424
        Self::write_mode(rsa);
425
1
        rsa.write_operand_b(exponent);
426
1
        rsa.write_modulus(modulus);
427
        rsa.write_mprime(m_prime);
428

            
429
        #[cfg(not(rsa_version = "1"))]
430
1
        if rsa.is_search_enabled() {
431
            rsa.write_search_position(Self::find_search_pos(exponent));
432
        }
433

            
434
        Self {
435
            rsa,
436
            phantom: PhantomData,
437
        }
438
    }
439

            
440
    fn set_up_exponentiation(&mut self, base: &T::InputType, r: &T::InputType) {
441
1
        self.rsa.write_operand_a(base);
442
1
        self.rsa.write_r(r);
443
    }
444

            
445
    /// Starts the modular exponentiation operation.
446
    ///
447
    /// `r` can be calculated using `2 ^ ( bitlength * 2 ) mod modulus`.
448
    ///
449
    /// For more information refer to the
450
    #[doc = trm_markdown_link!("rsa")]
451
    pub fn start_exponentiation(&mut self, base: &T::InputType, r: &T::InputType) {
452
        self.set_up_exponentiation(base, r);
453
        self.rsa.start_modexp();
454
    }
455

            
456
    /// Reads the result to the given buffer.
457
    ///
458
    /// This is a blocking function: it waits for the RSA operation to complete,
459
    /// then reads the results into the provided buffer. `start_exponentiation` must be
460
    /// called before calling this function.
461
    pub fn read_results(&mut self, outbuf: &mut T::InputType) {
462
        self.rsa.read_results(outbuf);
463
    }
464

            
465
    #[cfg(not(rsa_version = "1"))]
466
    fn find_search_pos(exponent: &T::InputType) -> u32 {
467
        for (i, byte) in exponent.iter().rev().enumerate() {
468
            if *byte == 0 {
469
                continue;
470
            }
471
            return (exponent.len() * 32) as u32 - (byte.leading_zeros() + i as u32 * 32) - 1;
472
        }
473
        0
474
    }
475

            
476
    /// Sets the modular exponentiation mode for the RSA hardware.
477
    fn write_mode(rsa: &mut Rsa<'d, Dm>) {
478
        rsa.write_modexp_mode(N as u32 / WORDS_PER_INCREMENT - 1);
479
    }
480
}
481

            
482
/// Support for the RSA peripheral's modular multiplication feature that could be
483
/// used to find the `(operand a * operand b) mod modulus`.
484
///
485
/// Each operand is a little endian byte array of the same size.
486
pub struct RsaModularMultiplication<'a, 'd, T, Dm>
487
where
488
    T: RsaMode,
489
    Dm: DriverMode,
490
{
491
    rsa: &'a mut Rsa<'d, Dm>,
492
    phantom: PhantomData<T>,
493
}
494

            
495
impl<'a, 'd, T, Dm, const N: usize> RsaModularMultiplication<'a, 'd, T, Dm>
496
where
497
    T: RsaMode<InputType = [u32; N]>,
498
    Dm: DriverMode,
499
{
500
    /// Creates an instance of `RsaModularMultiplication`.
501
    ///
502
    /// - `r` can be calculated using `2 ^ ( bitlength * 2 ) mod modulus`.
503
    /// - `m_prime` can be calculated using `-(modular multiplicative inverse of modulus) mod 2^32`.
504
    ///
505
    /// For more information refer to the
506
    #[doc = trm_markdown_link!("rsa")]
507
    pub fn new(
508
        rsa: &'a mut Rsa<'d, Dm>,
509
        operand_a: &T::InputType,
510
        modulus: &T::InputType,
511
        r: &T::InputType,
512
        m_prime: u32,
513
    ) -> Self {
514
        rsa.write_multi_mode(N as u32 / WORDS_PER_INCREMENT - 1, true);
515

            
516
        rsa.write_mprime(m_prime);
517
1
        rsa.write_modulus(modulus);
518
1
        rsa.write_operand_a(operand_a);
519
1
        rsa.write_r(r);
520

            
521
        Self {
522
            rsa,
523
            phantom: PhantomData,
524
        }
525
    }
526

            
527
    /// Starts the modular multiplication operation.
528
    ///
529
    /// For more information refer to the
530
    #[doc = trm_markdown_link!("rsa")]
531
    pub fn start_modular_multiplication(&mut self, operand_b: &T::InputType) {
532
        self.set_up_modular_multiplication(operand_b);
533
        self.rsa.start_modmulti();
534
    }
535

            
536
    /// Reads the result to the given buffer.
537
    ///
538
    /// This is a blocking function: it waits for the RSA operation to complete,
539
    /// then reads the results into the provided buffer. `start_modular_multiplication` must be
540
    /// called before calling this function.
541
    pub fn read_results(&mut self, outbuf: &mut T::InputType) {
542
        self.rsa.read_results(outbuf);
543
    }
544

            
545
    fn set_up_modular_multiplication(&mut self, operand_b: &T::InputType) {
546
        if cfg!(rsa_version = "1") {
547
            self.rsa.start_multi();
548
            self.rsa.wait_for_idle();
549

            
550
            self.rsa.write_operand_a(operand_b);
551
        } else {
552
1
            self.rsa.write_operand_b(operand_b);
553
        }
554
    }
555
}
556

            
557
/// Support for the RSA peripheral's large number multiplication feature that could
558
/// be used to find the `operand a * operand b`.
559
///
560
/// Each operand is a little endian byte array of the same size.
561
pub struct RsaMultiplication<'a, 'd, T, Dm>
562
where
563
    T: RsaMode + Multi,
564
    Dm: DriverMode,
565
{
566
    rsa: &'a mut Rsa<'d, Dm>,
567
    phantom: PhantomData<T>,
568
}
569

            
570
impl<'a, 'd, T, Dm, const N: usize> RsaMultiplication<'a, 'd, T, Dm>
571
where
572
    T: RsaMode<InputType = [u32; N]>,
573
    T: Multi,
574
    Dm: DriverMode,
575
{
576
    /// Creates an instance of `RsaMultiplication`.
577
    pub fn new(rsa: &'a mut Rsa<'d, Dm>, operand_a: &T::InputType) -> Self {
578
        // Non-modular multiplication result is twice as wide as its operands.
579
        rsa.write_multi_mode(2 * N as u32 / WORDS_PER_INCREMENT - 1, false);
580
1
        rsa.write_operand_a(operand_a);
581

            
582
        Self {
583
            rsa,
584
            phantom: PhantomData,
585
        }
586
    }
587

            
588
    /// Starts the multiplication operation.
589
    pub fn start_multiplication(&mut self, operand_b: &T::InputType) {
590
        self.set_up_multiplication(operand_b);
591
        self.rsa.start_multi();
592
    }
593

            
594
    /// Reads the result to the given buffer.
595
    ///
596
    /// This is a blocking function: it waits for the RSA operation to complete,
597
    /// then reads the results into the provided buffer. `start_multiplication` must be
598
    /// called before calling this function.
599
    pub fn read_results<const O: usize>(&mut self, outbuf: &mut T::OutputType)
600
    where
601
        T: Multi<OutputType = [u32; O]>,
602
    {
603
        self.rsa.read_results(outbuf);
604
    }
605

            
606
    fn set_up_multiplication(&mut self, operand_b: &T::InputType) {
607
        self.rsa.write_multi_operand_b(operand_b);
608
    }
609
}
610

            
611
static WAKER: AtomicWaker = AtomicWaker::new();
612
#[cfg(rsa_version = "1")]
613
static SIGNALED: AtomicBool = AtomicBool::new(false);
614

            
615
/// `Future` that waits for the RSA operation to complete.
616
#[must_use = "futures do nothing unless you `.await` or poll them"]
617
struct RsaFuture<'a, 'd> {
618
    driver: &'a Rsa<'d, Async>,
619
    _wake_lock: WakeLock,
620
}
621

            
622
impl<'a, 'd> RsaFuture<'a, 'd> {
623
3
    fn new(driver: &'a Rsa<'d, Async>) -> Self {
624
        #[cfg(rsa_version = "1")]
625
        SIGNALED.store(false, Ordering::Relaxed);
626

            
627
        driver.internal_enable_disable_interrupt(true);
628

            
629
        Self {
630
            driver,
631
            _wake_lock: WakeLock::new(),
632
        }
633
3
    }
634

            
635
    fn is_done(&self) -> bool {
636
        cfg_select! {
637
            rsa_version = "1" => SIGNALED.load(Ordering::Acquire),
638
            _ => self.driver.is_idle(),
639
        }
640
    }
641
}
642

            
643
impl Drop for RsaFuture<'_, '_> {
644
3
    fn drop(&mut self) {
645
        self.driver.internal_enable_disable_interrupt(false);
646
3
    }
647
}
648

            
649
impl core::future::Future for RsaFuture<'_, '_> {
650
    type Output = ();
651

            
652
3
    fn poll(
653
        self: core::pin::Pin<&mut Self>,
654
        cx: &mut core::task::Context<'_>,
655
    ) -> core::task::Poll<Self::Output> {
656
        WAKER.register(cx.waker());
657
3
        if self.is_done() {
658
            Poll::Ready(())
659
        } else {
660
            Poll::Pending
661
        }
662
3
    }
663
}
664

            
665
impl<T: RsaMode, const N: usize> RsaModularExponentiation<'_, '_, T, Async>
666
where
667
    T: RsaMode<InputType = [u32; N]>,
668
{
669
    /// Asynchronously performs an RSA modular exponentiation operation.
670
    pub async fn exponentiation(
671
1
        &mut self,
672
        base: &T::InputType,
673
        r: &T::InputType,
674
1
        outbuf: &mut T::InputType,
675
    ) {
676
        self.set_up_exponentiation(base, r);
677
1
        let fut = RsaFuture::new(self.rsa);
678
        self.rsa.start_modexp();
679
1
        fut.await;
680
1
        self.rsa.read_out(outbuf);
681
    }
682
}
683

            
684
impl<T: RsaMode, const N: usize> RsaModularMultiplication<'_, '_, T, Async>
685
where
686
    T: RsaMode<InputType = [u32; N]>,
687
{
688
    /// Asynchronously performs an RSA modular multiplication operation.
689
    pub async fn modular_multiplication(
690
1
        &mut self,
691
1
        operand_b: &T::InputType,
692
1
        outbuf: &mut T::InputType,
693
    ) {
694
        if cfg!(rsa_version = "1") {
695
            let fut = RsaFuture::new(self.rsa);
696
            self.rsa.start_multi();
697
            fut.await;
698

            
699
            self.rsa.write_operand_a(operand_b);
700
        } else {
701
            self.set_up_modular_multiplication(operand_b);
702
        }
703

            
704
1
        let fut = RsaFuture::new(self.rsa);
705
        self.rsa.start_modmulti();
706
1
        fut.await;
707
1
        self.rsa.read_out(outbuf);
708
    }
709
}
710

            
711
impl<T: RsaMode + Multi, const N: usize> RsaMultiplication<'_, '_, T, Async>
712
where
713
    T: RsaMode<InputType = [u32; N]>,
714
{
715
    /// Asynchronously performs an RSA multiplication operation.
716
    pub async fn multiplication<const O: usize>(
717
1
        &mut self,
718
        operand_b: &T::InputType,
719
1
        outbuf: &mut T::OutputType,
720
    ) where
721
        T: Multi<OutputType = [u32; O]>,
722
    {
723
        self.set_up_multiplication(operand_b);
724
1
        let fut = RsaFuture::new(self.rsa);
725
        self.rsa.start_multi();
726
1
        fut.await;
727
1
        self.rsa.read_out(outbuf);
728
    }
729
}
730

            
731
#[handler]
732
/// Interrupt handler for RSA.
733
3
pub(super) fn rsa_interrupt_handler() {
734
    let rsa = RSA::regs();
735

            
736
    #[cfg(rsa_version = "1")]
737
    SIGNALED.store(true, Ordering::Release);
738

            
739
    low_level::clear_interrupt(rsa);
740

            
741
3
    WAKER.wake();
742
}
743

            
744
static RSA_WORK_QUEUE: WorkQueue<RsaWorkItem> = WorkQueue::new();
745
const RSA_VTABLE: VTable<RsaWorkItem> = VTable {
746
    post: |driver, item| {
747
        // Start processing immediately.
748
        let driver = unsafe { RsaBackend::from_raw(driver) };
749
4
        Some(driver.process_item(item))
750
    },
751
    poll: |driver, item| {
752
        let driver = unsafe { RsaBackend::from_raw(driver) };
753
12
        driver.process_item(item)
754
    },
755
    cancel: |driver, item| {
756
        let driver = unsafe { RsaBackend::from_raw(driver) };
757
        driver.cancel(item)
758
    },
759
    stop: |driver| {
760
        let driver = unsafe { RsaBackend::from_raw(driver) };
761
        driver.deinitialize()
762
    },
763
};
764

            
765
#[derive(Default)]
766
enum RsaBackendState<'d> {
767
    #[default]
768
    Idle,
769
    Initializing(Rsa<'d, Blocking>),
770
    Ready(Rsa<'d, Blocking>),
771
    #[cfg(rsa_version = "1")]
772
    ModularMultiplicationRoundOne(Rsa<'d, Blocking>),
773
    Processing(Rsa<'d, Blocking>),
774
}
775

            
776
#[procmacros::doc_replace]
777
/// RSA processing backend.
778
///
779
/// The backend processes work items placed in the RSA work queue. The backend needs to be created
780
/// and started for operations to be processed. Operations can be performed on the RSA accelerator
781
/// without carrying around the peripheral singleton, or the driver.
782
///
783
/// The [`RsaContext`] struct can enqueue work items that this backend will process.
784
///
785
/// # Examples
786
///
787
/// ```rust, no_run
788
/// # {before_snippet}
789
/// use esp_hal::rsa::{RsaBackend, RsaContext, operand_sizes::Op512};
790
/// #
791
/// let mut rsa_backend = RsaBackend::new(peripherals.RSA);
792
/// let _driver = rsa_backend.start();
793
///
794
/// async fn perform_512bit_big_number_multiplication(
795
///     operand_a: &[u32; 16],
796
///     operand_b: &[u32; 16],
797
///     result: &mut [u32; 32],
798
/// ) {
799
///     let mut rsa = RsaContext::new();
800
///
801
///     let mut handle = rsa.multiply::<Op512>(operand_a, operand_b, result);
802
///     handle.wait().await;
803
/// }
804
/// # {after_snippet}
805
/// ```
806
pub struct RsaBackend<'d> {
807
    peri: RSA<'d>,
808
    state: RsaBackendState<'d>,
809
}
810

            
811
impl<'d> RsaBackend<'d> {
812
    #[procmacros::doc_replace]
813
    /// Creates a new RSA backend.
814
    ///
815
    /// # Examples
816
    ///
817
    /// ```rust, no_run
818
    /// # {before_snippet}
819
    /// use esp_hal::rsa::RsaBackend;
820
    /// #
821
    /// let mut rsa = RsaBackend::new(peripherals.RSA);
822
    /// # {after_snippet}
823
    /// ```
824
    pub fn new(rsa: RSA<'d>) -> Self {
825
        Self {
826
            peri: rsa,
827
            state: RsaBackendState::Idle,
828
        }
829
    }
830

            
831
    #[procmacros::doc_replace]
832
    /// Registers the RSA driver to process RSA operations.
833
    ///
834
    /// The driver stops operating when the returned object is dropped.
835
    ///
836
    /// # Examples
837
    ///
838
    /// ```rust, no_run
839
    /// # {before_snippet}
840
    /// use esp_hal::rsa::RsaBackend;
841
    /// #
842
    /// let mut rsa = RsaBackend::new(peripherals.RSA);
843
    /// // Start the backend, which allows processing RSA operations.
844
    /// let _backend = rsa.start();
845
    /// # {after_snippet}
846
    /// ```
847
2
    pub fn start(&mut self) -> RsaWorkQueueDriver<'_, 'd> {
848
        RsaWorkQueueDriver {
849
            inner: WorkQueueDriver::new(self, RSA_VTABLE, &RSA_WORK_QUEUE),
850
        }
851
2
    }
852

            
853
    // WorkQueue callbacks. They may run in any context.
854

            
855
    unsafe fn from_raw<'any>(ptr: NonNull<()>) -> &'any mut Self {
856
        unsafe { ptr.cast::<RsaBackend<'_>>().as_mut() }
857
    }
858

            
859
16
    fn process_item(&mut self, item: &mut RsaWorkItem) -> work_queue::Poll {
860
16
        match core::mem::take(&mut self.state) {
861
            RsaBackendState::Idle => {
862
                let driver = Rsa {
863
                    rsa: unsafe { self.peri.clone_unchecked() },
864
                    phantom: PhantomData,
865
                    _guard: RsaGuard::new(),
866
                };
867
                self.state = RsaBackendState::Initializing(driver);
868
                work_queue::Poll::Pending(true)
869
            }
870
            RsaBackendState::Initializing(mut rsa) => {
871
                // Wait for the peripheral to finish initializing. Ideally we need a way to
872
                // instruct the work queue to wake the polling task immediately.
873
4
                self.state = if rsa.ready() {
874
                    rsa.set_interrupt_handler(rsa_work_queue_handler);
875
                    rsa.enable_disable_interrupt(true);
876
                    RsaBackendState::Ready(rsa)
877
                } else {
878
                    RsaBackendState::Initializing(rsa)
879
                };
880
                work_queue::Poll::Pending(true)
881
            }
882
            RsaBackendState::Ready(mut rsa) => {
883
                #[cfg(not(rsa_version = "1"))]
884
                {
885
4
                    rsa.disable_constant_time(!item.constant_time);
886
4
                    rsa.search_acceleration(item.search_acceleration);
887
                }
888

            
889
4
                match item.operation {
890
2
                    RsaOperation::Multiplication { x, y } => {
891
                        let n = x.len() as u32;
892
                        rsa.write_operand_a(unsafe { x.as_ref() });
893

            
894
                        // Non-modular multiplication result is twice as wide as its operands.
895
2
                        rsa.write_multi_mode(2 * n / WORDS_PER_INCREMENT - 1, false);
896
                        rsa.write_multi_operand_b(unsafe { y.as_ref() });
897
                        rsa.start_multi();
898
                    }
899

            
900
                    RsaOperation::ModularMultiplication {
901
2
                        x,
902
                        #[cfg(not(rsa_version = "1"))]
903
                        y,
904
                        m,
905
                        m_prime,
906
                        r: r_inv,
907
                        ..
908
                    } => {
909
                        let n = x.len() as u32;
910
                        rsa.write_operand_a(unsafe { x.as_ref() });
911

            
912
2
                        rsa.write_multi_mode(n / WORDS_PER_INCREMENT - 1, true);
913

            
914
                        #[cfg(not(rsa_version = "1"))]
915
                        rsa.write_operand_b(unsafe { y.as_ref() });
916

            
917
                        rsa.write_modulus(unsafe { m.as_ref() });
918
                        rsa.write_mprime(m_prime);
919
                        rsa.write_r(unsafe { r_inv.as_ref() });
920

            
921
                        rsa.start_modmulti();
922

            
923
                        #[cfg(rsa_version = "1")]
924
                        {
925
                            // ESP32 requires a two-step process where Y needs to be written to the
926
                            // X memory.
927
                            self.state = RsaBackendState::ModularMultiplicationRoundOne(rsa);
928

            
929
                            return work_queue::Poll::Pending(false);
930
                        }
931
                    }
932
                    RsaOperation::ModularExponentiation {
933
                        x,
934
                        y,
935
                        m,
936
                        m_prime,
937
                        r_inv,
938
                    } => {
939
                        let n = x.len() as u32;
940
                        rsa.write_operand_a(unsafe { x.as_ref() });
941

            
942
                        rsa.write_modexp_mode(n / WORDS_PER_INCREMENT - 1);
943
                        rsa.write_operand_b(unsafe { y.as_ref() });
944
                        rsa.write_modulus(unsafe { m.as_ref() });
945
                        rsa.write_mprime(m_prime);
946
                        rsa.write_r(unsafe { r_inv.as_ref() });
947

            
948
                        #[cfg(not(rsa_version = "1"))]
949
                        if item.search_acceleration {
950
                            fn find_search_pos(exponent: &[u32]) -> u32 {
951
                                for (i, byte) in exponent.iter().rev().enumerate() {
952
                                    if *byte == 0 {
953
                                        continue;
954
                                    }
955
                                    return (exponent.len() * 32) as u32
956
                                        - (byte.leading_zeros() + i as u32 * 32)
957
                                        - 1;
958
                                }
959
                                0
960
                            }
961
                            rsa.write_search_position(find_search_pos(unsafe { y.as_ref() }));
962
                        }
963

            
964
                        rsa.start_modexp();
965
                    }
966
                }
967

            
968
                self.state = RsaBackendState::Processing(rsa);
969

            
970
                work_queue::Poll::Pending(false)
971
            }
972

            
973
            #[cfg(rsa_version = "1")]
974
            RsaBackendState::ModularMultiplicationRoundOne(mut rsa) => {
975
                if rsa.is_idle() {
976
                    let RsaOperation::ModularMultiplication { y, .. } = item.operation else {
977
                        unreachable!();
978
                    };
979

            
980
                    // Y needs to be written to the X memory.
981
                    rsa.write_operand_a(unsafe { y.as_ref() });
982
                    rsa.start_modmulti();
983

            
984
                    self.state = RsaBackendState::Processing(rsa);
985
                } else {
986
                    // Wait for the operation to complete
987
                    self.state = RsaBackendState::ModularMultiplicationRoundOne(rsa);
988
                }
989
                work_queue::Poll::Pending(false)
990
            }
991

            
992
            RsaBackendState::Processing(rsa) => {
993
4
                if rsa.is_idle() {
994
                    rsa.read_out(unsafe { item.result.as_mut() });
995

            
996
                    self.state = RsaBackendState::Ready(rsa);
997
                    work_queue::Poll::Ready(Status::Completed)
998
                } else {
999
                    self.state = RsaBackendState::Processing(rsa);
                    work_queue::Poll::Pending(false)
                }
            }
        }
8
    }
    fn cancel(&mut self, _item: &mut RsaWorkItem) {
        // Drop the driver to reset it. We don't read the result, so the work item remains
        // unchanged, effectively cancelling it.
        self.state = RsaBackendState::Idle;
    }
    fn deinitialize(&mut self) {
4
        self.state = RsaBackendState::Idle;
    }
}
/// An active work queue driver.
///
/// This object must be kept around, otherwise RSA operations will never complete.
///
/// For a usage example, see [`RsaBackend`].
pub struct RsaWorkQueueDriver<'t, 'd> {
    inner: WorkQueueDriver<'t, RsaBackend<'d>, RsaWorkItem>,
}
impl<'t, 'd> RsaWorkQueueDriver<'t, 'd> {
    /// Finishes processing the current work queue item, then stops the driver.
    pub fn stop(self) -> impl Future<Output = ()> {
        self.inner.stop()
    }
}
#[derive(Clone)]
struct RsaWorkItem {
    // Acceleration options
    #[cfg(not(rsa_version = "1"))]
    search_acceleration: bool,
    #[cfg(not(rsa_version = "1"))]
    constant_time: bool,
    // The operation to execute.
    operation: RsaOperation,
    result: NonNull<[u32]>,
}
unsafe impl Sync for RsaWorkItem {}
unsafe impl Send for RsaWorkItem {}
#[derive(Clone)]
enum RsaOperation {
    // Z = X * Y
    // len(Z) = len(X) + len(Y)
    Multiplication {
        x: NonNull<[u32]>,
        y: NonNull<[u32]>,
    },
    // Z = X * Y mod M
    ModularMultiplication {
        x: NonNull<[u32]>,
        y: NonNull<[u32]>,
        m: NonNull<[u32]>,
        r: NonNull<[u32]>,
        m_prime: u32,
    },
    // Z = X ^ Y mod M
    ModularExponentiation {
        x: NonNull<[u32]>,
        y: NonNull<[u32]>,
        m: NonNull<[u32]>,
        r_inv: NonNull<[u32]>,
        m_prime: u32,
    },
}
#[handler]
4
#[ram]
fn rsa_work_queue_handler() {
4
    if !RSA_WORK_QUEUE.process() {
        // The queue may indicate that it needs to be polled again. In this case, we do not clear
        // the interrupt bit, which causes the interrupt to be re-handled.
        low_level::clear_interrupt(RSA::regs());
    }
4
}
/// An RSA work queue user.
///
/// This object allows performing [big number multiplication][Self::multiply], [big number modular
/// multiplication][Self::modular_multiply] and [big number modular
/// exponentiation][Self::modular_exponentiate] with hardware acceleration. To perform these
/// operations, the [`RsaBackend`] must be started, otherwise these operations will never complete.
#[cfg_attr(
    not(rsa_version = "1"),
    doc = " \nThe context is created with a secure configuration by default. You can enable hardware acceleration
    options using [enable_search_acceleration][Self::enable_search_acceleration] and
    [enable_acceleration][Self::enable_acceleration] when appropriate."
)]
#[derive(Clone)]
pub struct RsaContext {
    frontend: WorkQueueFrontend<RsaWorkItem>,
}
impl Default for RsaContext {
    fn default() -> Self {
        Self::new()
    }
}
impl RsaContext {
    /// Creates a new context.
    pub fn new() -> Self {
1
        Self {
            frontend: WorkQueueFrontend::new(RsaWorkItem {
                #[cfg(not(rsa_version = "1"))]
                search_acceleration: false,
                #[cfg(not(rsa_version = "1"))]
                constant_time: true,
                operation: RsaOperation::Multiplication {
                    x: NonNull::from(&[]),
                    y: NonNull::from(&[]),
                },
                result: NonNull::from(&mut []),
            }),
        }
    }
    #[cfg(not(rsa_version = "1"))]
    /// Enables search acceleration.
    ///
    /// When enabled it would increase the performance of modular
    /// exponentiation by discarding the exponent's bits before the most
    /// significant set bit.
    ///
    /// Compromises security by effectively decreasing the key length.
    ///
    /// For more information refer to the
    #[doc = trm_markdown_link!("rsa")]
    pub fn enable_search_acceleration(&mut self) {
1
        self.frontend.data_mut().search_acceleration = true;
    }
    #[cfg(not(rsa_version = "1"))]
    /// Enables acceleration by disabling constant time operation.
    ///
    /// Disabling constant time operation increases the performance of modular
    /// exponentiation by simplifying the calculation concerning the 0 bits
    /// of the exponent. I.e. the less the Hamming weight, the greater the
    /// performance.
    ///
    /// Compromises security by enabling timing-based side-channel attacks.
    ///
    /// For more information refer to the
    #[doc = trm_markdown_link!("rsa")]
    pub fn enable_acceleration(&mut self) {
        self.frontend.data_mut().constant_time = false;
    }
4
    fn post(&mut self) -> RsaHandle<'_> {
        RsaHandle(self.frontend.post(&RSA_WORK_QUEUE))
4
    }
    #[procmacros::doc_replace]
    /// Starts a modular exponentiation operation, performing `Z = X ^ Y mod M`.
    ///
    /// Software needs to pre-calculate the following values:
    ///
    /// - `r`: `2 ^ ( bitlength * 2 ) mod M`.
    /// - `m_prime` can be calculated using `-(modular multiplicative inverse of M) mod 2^32`.
    ///
    /// It is relatively easy to calculate these values using the `crypto-bigint` crate:
    ///
    /// ```rust,no_run
    /// # {before_snippet}
    /// use crypto_bigint::{U512, Uint};
    /// const fn compute_r(modulus: &U512) -> U512 {
    ///     let mut d = [0_u32; U512::LIMBS * 2 + 1];
    ///     d[d.len() - 1] = 1;
    ///     let d = Uint::from_words(d);
    ///     d.wrapping_rem_vartime(&modulus.resize()).resize()
    /// }
    ///
    /// const fn compute_mprime(modulus: &U512) -> u32 {
    ///     let m_inv = modulus
    ///         .invert_mod2k(32)
    ///         .expect_copied("modulus must be odd")
    ///         .to_words()[0];
    ///     (-1 * m_inv as i64 & (u32::MAX as i64)) as u32
    /// }
    ///
    /// // Inputs
    /// const X: U512 = Uint::from_be_hex(
    ///     "c7f61058f96db3bd87dbab08ab03b4f7f2f864eac249144adea6a65f97803b719d8ca980b7b3c0389c1c7c6\
    ///    7dc353c5e0ec11f5fc8ce7f6073796cc8f73fa878",
    /// );
    /// const Y: U512 = Uint::from_be_hex(
    ///     "1763db3344e97be15d04de4868badb12a38046bb793f7630d87cf100aa1c759afac15a01f3c4c83ec2d2f66\
    ///    6bd22f71c3c1f075ec0e2cb0cb29994d091b73f51",
    /// );
    /// const M: U512 = Uint::from_be_hex(
    ///     "6b6bb3d2b6cbeb45a769eaa0384e611e1b89b0c9b45a045aca1c5fd6e8785b38df7118cf5dd45b9b63d293b\
    ///    67aeafa9ba25feb8712f188cb139b7d9b9af1c361",
    /// );
    ///
    /// // Values derived using the functions we defined above:
    /// let r = compute_r(&M);
    /// let mprime = compute_mprime(&M);
    ///
    /// use esp_hal::rsa::{RsaContext, operand_sizes::Op512};
    ///
    /// // Now perform the actual computation:
    /// let mut rsa = RsaContext::new();
    /// let mut outbuf = [0; 16];
    /// let mut handle = rsa.modular_multiply::<Op512>(
    ///     X.as_words(),
    ///     Y.as_words(),
    ///     M.as_words(),
    ///     r.as_words(),
    ///     mprime,
    ///     &mut outbuf,
    /// );
    /// handle.wait_blocking();
    /// # {after_snippet}
    /// ```
    ///
    /// Returns an [`RsaHandle`] for the asynchronous calculation that can be used to poll the
    /// status of the calculation, to wait for it to finish, or to cancel the operation (by
    /// dropping the handle).
    ///
    /// When the operation is completed, the result is stored in `result`
    pub fn modular_exponentiate<'t, OP>(
        &'t mut self,
        x: &'t OP::InputType,
        y: &'t OP::InputType,
        m: &'t OP::InputType,
        r: &'t OP::InputType,
        m_prime: u32,
        result: &'t mut OP::InputType,
    ) -> RsaHandle<'t>
    where
        OP: RsaMode,
    {
        self.frontend.data_mut().operation = RsaOperation::ModularExponentiation {
            x: NonNull::from(x.as_ref()),
            y: NonNull::from(y.as_ref()),
            m: NonNull::from(m.as_ref()),
            r_inv: NonNull::from(r.as_ref()),
            m_prime,
        };
        self.frontend.data_mut().result = NonNull::from(result.as_mut());
        self.post()
    }
    /// Starts a modular multiplication operation, performing `Z = X * Y mod M`.
    ///
    /// Software needs to pre-calculate the following values:
    ///
    /// - `r`: `2 ^ ( bitlength * 2 ) mod M`.
    /// - `m_prime` can be calculated using `-(modular multiplicative inverse of M) mod 2^32`.
    ///
    /// For an example how these values can be calculated and used, see
    /// [Self::modular_exponentiate].
    ///
    /// Returns an [`RsaHandle`] for the asynchronous calculation that can be used to poll the
    /// status of the calculation, to wait for it to finish, or to cancel the operation (by
    /// dropping the handle).
    ///
    /// When the operation is completed, the result is stored in `result`
    pub fn modular_multiply<'t, OP>(
        &'t mut self,
        x: &'t OP::InputType,
        y: &'t OP::InputType,
        m: &'t OP::InputType,
        r: &'t OP::InputType,
        m_prime: u32,
        result: &'t mut OP::InputType,
    ) -> RsaHandle<'t>
    where
        OP: RsaMode,
    {
1
        self.frontend.data_mut().operation = RsaOperation::ModularMultiplication {
            x: NonNull::from(x.as_ref()),
            y: NonNull::from(y.as_ref()),
            m: NonNull::from(m.as_ref()),
            r: NonNull::from(r.as_ref()),
            m_prime,
        };
1
        self.frontend.data_mut().result = NonNull::from(result.as_mut());
1
        self.post()
    }
    #[procmacros::doc_replace]
    /// Starts a multiplication operation, performing `Z = X * Y`.
    ///
    /// Returns an [`RsaHandle`] for the asynchronous calculation that can be used to poll the
    /// status of the calculation, to wait for it to finish, or to cancel the operation (by
    /// dropping the handle).
    ///
    /// When the operation is completed, the result is stored in `result`. The `result` is twice as
    /// wide as the inputs.
    ///
    /// # Examples
    ///
    /// ```rust,no_run
    /// # {before_snippet}
    ///
    /// // Inputs
    /// # let x: [u32; 16] = [0; 16];
    /// # let y: [u32; 16] = [0; 16];
    /// // let x: [u32; 16] = [...];
    /// // let y: [u32; 16] = [...];
    /// let mut outbuf = [0; 32];
    ///
    /// use esp_hal::rsa::{RsaContext, operand_sizes::Op512};
    ///
    /// // Now perform the actual computation:
    /// let mut rsa = RsaContext::new();
    /// let mut handle = rsa.multiply::<Op512>(&x, &y, &mut outbuf);
    /// handle.wait_blocking();
    /// # {after_snippet}
    /// ```
    pub fn multiply<'t, OP>(
        &'t mut self,
        x: &'t OP::InputType,
        y: &'t OP::InputType,
        result: &'t mut OP::OutputType,
    ) -> RsaHandle<'t>
    where
        OP: Multi,
    {
1
        self.frontend.data_mut().operation = RsaOperation::Multiplication {
            x: NonNull::from(x.as_ref()),
            y: NonNull::from(y.as_ref()),
        };
1
        self.frontend.data_mut().result = NonNull::from(result.as_mut());
1
        self.post()
    }
}
/// The handle to the pending RSA operation.
pub struct RsaHandle<'t>(work_queue::Handle<'t, RsaWorkItem>);
impl RsaHandle<'_> {
    /// Polls the status of the work item.
    #[inline]
    pub fn poll(&mut self) -> bool {
        self.0.poll()
    }
    /// Blocks until the work item is processed.
    #[inline]
    pub fn wait_blocking(self) {
        self.0.wait_blocking();
    }
    /// Waits for the work item to be processed.
    #[inline]
    pub fn wait(&mut self) -> impl Future<Output = Status> {
        self.0.wait()
    }
}