esp-rs / esp-hal

no_std Hardware Abstraction Layers for ESP32 microcontrollers
https://docs.esp-rs.org/esp-hal/
Apache License 2.0
626 stars 172 forks source link

`esp32` - issue with `RSA` peripheral #822

Open playfulFence opened 9 months ago

playfulFence commented 9 months ago

Encountered a problem during implementing https://github.com/esp-rs/esp-hal/pull/790 : Program run hangs in this or similar blocks -> seems to be stuck in non-idle mode.

One idea where the problem is: Every other chip (except of esp32) has a separate register for handling IDLE state (RSA_IDLE_REG for esp32sX or RSA_QUERY_IDLE for esp32cX), but on esp32 it's checked through the interrupt register on which async functionality depends -> conflict

playfulFence commented 1 week ago

This one is still valid though. Made some tests on this code:

#[main]
async fn main(spawner: Spawner) -> ! {
    let peripherals = Peripherals::take();
    let system = SystemControl::new(peripherals.SYSTEM);
    let clocks = ClockControl::boot_defaults(system.clock_control).freeze();

    let mut rsa = Rsa::new_async(peripherals.RSA);

    test_modular_exponentiation(rsa).await;
    // test_modular_multiplication(rsa);
    // test_multiplication(rsa);

    loop {
    }
}

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 % 4294967296) as u32
}

async fn test_modular_exponentiation(mut rsa: Rsa<'static, Async>) {
    const EXPECTED_OUTPUT: [u32; U512::LIMBS] = [
        1601059419, 3994655875, 2600857657, 1530060852, 64828275, 4221878473, 2751381085,
        1938128086, 625895085, 2087010412, 2133352910, 101578249, 3798099415, 3357588690,
        2065243474, 330914193,
    ];

    #[cfg(not(feature = "esp32"))]
    {
        rsa.enable_disable_constant_time_acceleration(true);
        rsa.enable_disable_search_acceleration(true);
    }
    let mut outbuf = [0_u32; U512::LIMBS];
    let mut mod_exp = RsaModularExponentiation::<operand_sizes::Op512, esp_hal::Async>::new(
        &mut rsa,
        BIGNUM_2.as_words(),
        BIGNUM_3.as_words(),
        compute_mprime(&BIGNUM_3),
    );
    let r = compute_r(&BIGNUM_3);
    let base = &BIGNUM_1.as_words();
    mod_exp.exponentiation(&base, r.as_words(), &mut outbuf).await;
    assert_eq!(EXPECTED_OUTPUT, outbuf);
    esp_println::println!("Yep");
}

Output on esp32c6: image

On esp32: image

playfulFence commented 1 week ago

I don't see any "clean" way out of here. The whole async functionality depends on INTERRUPT register in RSA peripheral, which at the same time signalizes about the IDLE state of peripheral.

Maybe there's any option to add some simple "arbitration" (flag) like what event provoked the change of this reg. Just thoughts out loud anyways 😄

jessebraham commented 1 week ago

This is very low priority so I would not spend too much effort on it right now.

playfulFence commented 1 week ago

This is very low priority so I would not spend too much effort on it right now.

Yeah, for sure. I've only checked if this issue is still valid at all