openwallet-foundation / askar

Secure storage designed for Hyperledger Aries agents.
Apache License 2.0
63 stars 51 forks source link

Support for iOS Secure Enclave and Android Strongbox #242

Closed berendsliedrecht closed 6 months ago

berendsliedrecht commented 7 months ago

In the upcoming weeks we would like to add support for hardware-backed keys (p256 only) for iOS and Android using https://github.com/animo/secure-env (this will be proposed to move to OWF in the near future).

I am making this issue more to track the progress, but there are also some questions.

Points for crypto

  1. askar-crypto/src/alg/any.rs defines AnyKeyCreate which can generate keys based on a seed. when interacting with Android Strongbox and iOS Secure Enclave a seed, or RNG source, may not be provided for key generation. Because of this, we do not need a RNG source, or seed, as all keys created won't be based on a provided source. My suggestion would be to implement generate and random for the hardware-backed key and throw an error on random_det.
  2. A new KeyPair struct called P256HardwareKeyPair will be created and it will be guarded by a feature p256-hardware.

Points for storage (TODO)


Open Questions

  1. When generating a key for the Secure Element of the device, we need to provide an id so we can fetch it later. The current implementation does not allow for this as generate only accepts an RNG source. I currently have the following idea to fix this, feedback would be appriciated.
pub enum Error {}

pub trait KeyMaterial {
    /// Read key material from the generator
    fn read_okm(&mut self, buf: &mut [u8]);
}

pub trait OldKeyGen: Sized {
    /// Create a new key from a key material generator.
    fn generate(rng: impl KeyMaterial) -> Result<Self, Error>;

    /// Generate a new random key.
    #[cfg(feature = "getrandom")]
    fn random() -> Result<Self, Error> {
        Self::generate(crate::random::default_rng())
    }
}

pub trait NewKeyGen: Sized {
    /// Create a new key from a key material generator.
    fn generate(ops: KeyGenOps) -> Result<Self, Error>;

    /// Generate a new random key.
    #[cfg(feature = "getrandom")]
    fn random(ops: KeyGenOps) -> Result<Self, Error> {
        let ops = ops.with_default_rng();
        Self::generate(ops)
    }
}

pub struct KeyGenOps {
    rng: Option<Box<dyn KeyMaterial>>,
    id: Option<String>
}
swcurran commented 7 months ago

@andrewwhitehead ^^^^