RsaContext

Struct RsaContext 

Source
pub struct RsaContext { /* private fields */ }
Expand description

An RSA work queue user.

This object allows performing big number multiplication, big number modular multiplication and big number modular exponentiation with hardware acceleration. To perform these operations, the RsaBackend must be started, otherwise these operations will never complete.

The context is created with a secure configuration by default. You can enable hardware acceleration options using enable_search_acceleration and enable_acceleration when appropriate.

Implementations§

Source§

impl RsaContext

Source

pub fn new() -> Self

Creates a new context.

Source

pub fn enable_search_acceleration(&mut self)

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.

⚠️ Note: this compromises security by effectively decreasing the key length.

For more information refer to the Technical Reference Manual

Source

pub fn enable_acceleration(&mut self)

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.

⚠️ Note: this compromises security by enabling timing-based side-channel attacks.

For more information refer to the Technical Reference Manual

Source

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,

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:

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.const_rem(&modulus.resize()).0.resize()
}

const fn compute_mprime(modulus: &U512) -> u32 {
    let m_inv = modulus.inv_mod2k(32).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();

The calculation is done asynchronously. This function returns an RsaHandle 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 will be stored in result.

Source

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,

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.

The calculation is done asynchronously. This function returns an RsaHandle 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 will be stored in result.

Source

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,

Starts a multiplication operation, performing Z = X * Y.

The calculation is done asynchronously. This function returns an RsaHandle 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 will be stored in result. The result is twice as wide as the inputs.

§Example

// Inputs
// 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();

Trait Implementations§

Source§

impl Default for RsaContext

Available on crate feature unstable only.
Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

§

impl Freeze for RsaContext

§

impl RefUnwindSafe for RsaContext

§

impl !Send for RsaContext

§

impl !Sync for RsaContext

§

impl Unpin for RsaContext

§

impl UnwindSafe for RsaContext

Blanket Implementations§

§

impl<T> Any for T
where T: 'static + ?Sized,

§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
§

impl<T> Borrow<T> for T
where T: ?Sized,

§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
§

impl<T> BorrowMut<T> for T
where T: ?Sized,

§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<T> From<T> for T

§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T, U> Into<U> for T
where U: From<T>,

§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of [From]<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.