From f3bd36e33c4d53a418e026e4fd674774e16dd0ed Mon Sep 17 00:00:00 2001 From: Berend Sliedrecht Date: Wed, 15 May 2024 13:32:43 +0200 Subject: [PATCH] fix: hold reference to which backend is used for any key Signed-off-by: Berend Sliedrecht --- Cargo.lock | 147 +----------------- askar-crypto/Cargo.toml | 2 +- askar-crypto/src/alg/aes/mod.rs | 4 +- askar-crypto/src/alg/any.rs | 35 +++-- askar-crypto/src/alg/bls.rs | 4 +- askar-crypto/src/alg/chacha20.rs | 4 +- askar-crypto/src/alg/ed25519.rs | 4 +- askar-crypto/src/alg/k256.rs | 4 +- askar-crypto/src/alg/mod.rs | 10 ++ askar-crypto/src/alg/p256.rs | 4 +- askar-crypto/src/alg/p256_hardware.rs | 8 +- askar-crypto/src/alg/p384.rs | 4 +- askar-crypto/src/alg/x25519.rs | 4 +- askar-crypto/src/backend/mod.rs | 42 +++++ askar-crypto/src/lib.rs | 8 + src/kms/entry.rs | 36 ++--- src/kms/local_key.rs | 39 +---- .../src/NodeJSAriesAskar.ts | 4 +- .../aries-askar-react-native-example/app.json | 4 +- .../src/App.tsx | 17 +- .../cpp/ariesAskar.cpp | 8 +- .../cpp/include/libaries_askar.h | 48 ++++-- .../src/ariesAskar/AriesAskar.ts | 2 +- .../aries-askar-shared/src/crypto/Key.ts | 55 +++++-- 24 files changed, 242 insertions(+), 255 deletions(-) create mode 100644 askar-crypto/src/backend/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 313abd1b..863343c1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -80,30 +80,6 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" -[[package]] -name = "android-activity" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64529721f27c2314ced0890ce45e469574a73e5e6fdd6e9da1860eb29285f5e0" -dependencies = [ - "android-properties", - "bitflags 1.3.2", - "cc", - "jni-sys", - "libc", - "log", - "ndk", - "ndk-context", - "ndk-sys", - "num_enum 0.6.1", -] - -[[package]] -name = "android-properties" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" - [[package]] name = "android-tzdata" version = "0.1.1" @@ -127,14 +103,15 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "animo-secure-env" -version = "0.3.0" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ac0649cf766da50afbf5566e8458edc3caf19c43fc26d8eabd18642e181377d" +checksum = "d8d007a91a32fee1a7608d63411ca9aa6d6f4c30b321cc9f75fcfd2e6f416644" dependencies = [ - "android-activity", "jni", "lazy_static", + "libc", "ndk-context", + "ndk-sys", "p256", "paste", "security-framework", @@ -509,7 +486,6 @@ version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" dependencies = [ - "jobserver", "libc", ] @@ -1487,15 +1463,6 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" -[[package]] -name = "jobserver" -version = "0.1.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e" -dependencies = [ - "libc", -] - [[package]] name = "js-sys" version = "0.3.66" @@ -1528,9 +1495,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.151" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "libloading" @@ -1632,20 +1599,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "ndk" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "451422b7e4718271c8b5b3aadf5adedba43dc76312454b387e98fae0fc951aa0" -dependencies = [ - "bitflags 1.3.2", - "jni-sys", - "ndk-sys", - "num_enum 0.5.11", - "raw-window-handle", - "thiserror", -] - [[package]] name = "ndk-context" version = "0.1.1" @@ -1654,9 +1607,9 @@ checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" [[package]] name = "ndk-sys" -version = "0.4.1+23.1.7779620" +version = "0.6.0+11769913" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cf2aae958bd232cac5069850591667ad422d263686d75b52a065f9badeee5a3" +checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" dependencies = [ "jni-sys", ] @@ -1751,48 +1704,6 @@ dependencies = [ "libc", ] -[[package]] -name = "num_enum" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9" -dependencies = [ - "num_enum_derive 0.5.11", -] - -[[package]] -name = "num_enum" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a015b430d3c108a207fd776d2e2196aaf8b1cf8cf93253e3a097ff3085076a1" -dependencies = [ - "num_enum_derive 0.6.1", -] - -[[package]] -name = "num_enum_derive" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "num_enum_derive" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96667db765a921f7b295ffee8b60472b686a51d4f21c2ee4ffdb94c7013b65a6" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn 2.0.61", -] - [[package]] name = "object" version = "0.32.1" @@ -2025,16 +1936,6 @@ dependencies = [ "elliptic-curve", ] -[[package]] -name = "proc-macro-crate" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" -dependencies = [ - "once_cell", - "toml_edit", -] - [[package]] name = "proc-macro2" version = "1.0.82" @@ -2083,12 +1984,6 @@ dependencies = [ "getrandom", ] -[[package]] -name = "raw-window-handle" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9" - [[package]] name = "rayon" version = "1.8.0" @@ -2882,23 +2777,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "toml_datetime" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" - -[[package]] -name = "toml_edit" -version = "0.19.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" -dependencies = [ - "indexmap", - "toml_datetime", - "winnow", -] - [[package]] name = "tracing" version = "0.1.40" @@ -3364,15 +3242,6 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" -[[package]] -name = "winnow" -version = "0.5.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" -dependencies = [ - "memchr", -] - [[package]] name = "x25519-dalek" version = "2.0.0" diff --git a/askar-crypto/Cargo.toml b/askar-crypto/Cargo.toml index 8ac687ff..4d43c62f 100644 --- a/askar-crypto/Cargo.toml +++ b/askar-crypto/Cargo.toml @@ -101,7 +101,7 @@ p384 = { version = "0.13", default-features = false, features = [ "ecdh", ], optional = true } rand = { version = "0.8", default-features = false } -secure-env = { package = "animo-secure-env", version = "0.3", optional = true } +secure-env = { package = "animo-secure-env", version = "0.3.3", optional = true } serde = { version = "1.0", default-features = false, features = ["derive"] } serde-json-core = { version = "0.5", default-features = false } sha2 = { version = "0.10", default-features = false } diff --git a/askar-crypto/src/alg/aes/mod.rs b/askar-crypto/src/alg/aes/mod.rs index 12013120..93c8f66e 100644 --- a/askar-crypto/src/alg/aes/mod.rs +++ b/askar-crypto/src/alg/aes/mod.rs @@ -7,7 +7,7 @@ use aes_gcm::{Aes128Gcm, Aes256Gcm}; use serde::{Deserialize, Serialize}; use zeroize::Zeroize; -use super::{AesTypes, HasKeyAlg, KeyAlg}; +use super::{AesTypes, HasKeyAlg, HasKeyBackend, KeyAlg}; use crate::{ buffer::{ArrayKey, ResizeBuffer, Writer}, encrypt::{KeyAeadInPlace, KeyAeadMeta, KeyAeadParams}, @@ -80,6 +80,8 @@ impl PartialEq for AesKey { impl Eq for AesKey {} +impl HasKeyBackend for AesKey {} + impl HasKeyAlg for AesKey { fn algorithm(&self) -> KeyAlg { KeyAlg::Aes(T::ALG_TYPE) diff --git a/askar-crypto/src/alg/any.rs b/askar-crypto/src/alg/any.rs index 091279d4..06e80240 100644 --- a/askar-crypto/src/alg/any.rs +++ b/askar-crypto/src/alg/any.rs @@ -40,8 +40,9 @@ use super::p384::{self, P384KeyPair}; #[cfg(feature = "p256_hardware")] use super::p256_hardware::P256HardwareKeyPair; -use super::{HasKeyAlg, KeyAlg}; +use super::{HasKeyAlg, HasKeyBackend, KeyAlg}; use crate::{ + backend::KeyBackend, buffer::{ResizeBuffer, WriteBuffer}, encrypt::{KeyAeadInPlace, KeyAeadParams}, error::Error, @@ -74,6 +75,10 @@ impl AnyKey { self.0.algorithm() } + pub fn backend(&self) -> KeyBackend { + self.0.key_backend() + } + fn assume(&self) -> &K { self.downcast_ref().expect("Error assuming key type") } @@ -118,7 +123,9 @@ pub trait AnyKeyCreate: Sized { fn from_secret_bytes(alg: KeyAlg, secret: &[u8]) -> Result; /// Convert from a concrete key instance - fn from_key(key: K) -> Self; + fn from_key( + key: K, + ) -> Self; /// Create a new key instance from a key exchange fn from_key_exchange(alg: KeyAlg, secret: &Sk, public: &Pk) -> Result @@ -155,7 +162,11 @@ impl AnyKeyCreate for Box { } #[inline(always)] - fn from_key(key: K) -> Self { + fn from_key< + K: HasKeyAlg + HasKeyBackend + Send + Sync + RefUnwindSafe + UnwindSafe + 'static, + >( + key: K, + ) -> Self { Box::new(KeyT(key)) } @@ -198,7 +209,11 @@ impl AnyKeyCreate for Arc { } #[inline(always)] - fn from_key(key: K) -> Self { + fn from_key< + K: HasKeyAlg + HasKeyBackend + Send + Sync + RefUnwindSafe + UnwindSafe + 'static, + >( + key: K, + ) -> Self { Arc::new(KeyT(key)) } @@ -288,10 +303,10 @@ fn generate_any_for_hardware(alg: KeyAlg) -> Result { } #[inline] -fn get_any_with_id(alg: KeyAlg, id: &str) -> Result { +fn get_any_with_id(alg: KeyAlg, _id: &str) -> Result { let key = match alg { #[cfg(feature = "p256_hardware")] - KeyAlg::EcCurve(EcCurves::Secp256r1) => P256HardwareKeyPair::from_id(id).map(R::alloc_key), + KeyAlg::EcCurve(EcCurves::Secp256r1) => P256HardwareKeyPair::from_id(_id).map(R::alloc_key), _ => Err(err_msg!( Unsupported, "Unsupported algorithm for key retrieval by id" @@ -688,14 +703,14 @@ macro_rules! match_key_alg { }}; (@ P256 $($rest:ident)*; $key:ident, $alg:ident) => {{ #[cfg(feature = "p256")] - if $alg == KeyAlg::EcCurve(EcCurves::Secp256r1) { + if $alg == KeyAlg::EcCurve(EcCurves::Secp256r1) && $key.backend() == KeyBackend::Software { return Ok($key.assume::()) } match_key_alg!(@ $($rest)*; $key, $alg) }}; (@ P256Hardware $($rest:ident)*; $key:ident, $alg:ident) => {{ #[cfg(feature = "p256_hardware")] - if $alg == KeyAlg::EcCurve(EcCurves::Secp256r1) { + if $alg == KeyAlg::EcCurve(EcCurves::Secp256r1) && $key.backend() == KeyBackend::SecureElement { return Ok($key.assume::()) } match_key_alg!(@ $($rest)*; $key, $alg) @@ -920,12 +935,12 @@ impl AllocKey for Box { } } -pub trait AnyKeyAlg: HasKeyAlg + 'static { +pub trait AnyKeyAlg: HasKeyAlg + HasKeyBackend + 'static { fn as_any(&self) -> &dyn Any; } // implement for all concrete key types -impl AnyKeyAlg for K { +impl AnyKeyAlg for K { fn as_any(&self) -> &dyn Any { self } diff --git a/askar-crypto/src/alg/bls.rs b/askar-crypto/src/alg/bls.rs index 97d07ff9..fc8b609f 100644 --- a/askar-crypto/src/alg/bls.rs +++ b/askar-crypto/src/alg/bls.rs @@ -18,7 +18,7 @@ use crate::generic_array::{ ArrayLength, }; -use super::{BlsCurves, HasKeyAlg, KeyAlg}; +use super::{BlsCurves, HasKeyAlg, HasKeyBackend, KeyAlg}; use crate::{ buffer::ArrayKey, error::Error, @@ -91,6 +91,8 @@ impl PartialEq for BlsKeyPair { impl Eq for BlsKeyPair {} +impl HasKeyBackend for BlsKeyPair {} + impl HasKeyAlg for BlsKeyPair { fn algorithm(&self) -> KeyAlg { KeyAlg::Bls12_381(Pk::ALG_TYPE) diff --git a/askar-crypto/src/alg/chacha20.rs b/askar-crypto/src/alg/chacha20.rs index e61d4164..c3f57297 100644 --- a/askar-crypto/src/alg/chacha20.rs +++ b/askar-crypto/src/alg/chacha20.rs @@ -7,7 +7,7 @@ use chacha20poly1305::{ChaCha20Poly1305, XChaCha20Poly1305}; use serde::{Deserialize, Serialize}; use zeroize::Zeroize; -use super::{Chacha20Types, HasKeyAlg, KeyAlg}; +use super::{Chacha20Types, HasKeyAlg, HasKeyBackend, KeyAlg}; use crate::{ buffer::{ArrayKey, ResizeBuffer, Writer}, encrypt::{KeyAeadInPlace, KeyAeadMeta, KeyAeadParams}, @@ -105,6 +105,8 @@ impl PartialEq for Chacha20Key { impl Eq for Chacha20Key {} +impl HasKeyBackend for Chacha20Key {} + impl HasKeyAlg for Chacha20Key { fn algorithm(&self) -> KeyAlg { KeyAlg::Chacha20(T::ALG_TYPE) diff --git a/askar-crypto/src/alg/ed25519.rs b/askar-crypto/src/alg/ed25519.rs index d8fa83d7..e574f8cf 100644 --- a/askar-crypto/src/alg/ed25519.rs +++ b/askar-crypto/src/alg/ed25519.rs @@ -15,7 +15,7 @@ use subtle::ConstantTimeEq; use x25519_dalek::{PublicKey as XPublicKey, StaticSecret as XSecretKey}; use zeroize::{Zeroize, ZeroizeOnDrop}; -use super::{x25519::X25519KeyPair, HasKeyAlg, KeyAlg}; +use super::{x25519::X25519KeyPair, HasKeyAlg, HasKeyBackend, KeyAlg}; use crate::{ buffer::{ArrayKey, WriteBuffer}, error::Error, @@ -124,6 +124,8 @@ impl KeyGen for Ed25519KeyPair { } } +impl HasKeyBackend for Ed25519KeyPair {} + impl HasKeyAlg for Ed25519KeyPair { fn algorithm(&self) -> KeyAlg { KeyAlg::Ed25519 diff --git a/askar-crypto/src/alg/k256.rs b/askar-crypto/src/alg/k256.rs index e90a3e9f..ffb6aa6a 100644 --- a/askar-crypto/src/alg/k256.rs +++ b/askar-crypto/src/alg/k256.rs @@ -14,7 +14,7 @@ use k256::{ }; use subtle::ConstantTimeEq; -use super::{ec_common, EcCurves, HasKeyAlg, KeyAlg}; +use super::{ec_common, EcCurves, HasKeyAlg, HasKeyBackend, KeyAlg}; use crate::{ buffer::{ArrayKey, WriteBuffer}, error::Error, @@ -103,6 +103,8 @@ impl K256KeyPair { } } +impl HasKeyBackend for K256KeyPair {} + impl HasKeyAlg for K256KeyPair { fn algorithm(&self) -> KeyAlg { KeyAlg::EcCurve(EcCurves::Secp256k1) diff --git a/askar-crypto/src/alg/mod.rs b/askar-crypto/src/alg/mod.rs index 87be313f..1026a0c7 100644 --- a/askar-crypto/src/alg/mod.rs +++ b/askar-crypto/src/alg/mod.rs @@ -10,6 +10,7 @@ use arbitrary::Arbitrary; use zeroize::Zeroize; use crate::{ + backend::KeyBackend, buffer::{WriteBuffer, Writer}, error::Error, }; @@ -270,6 +271,15 @@ pub trait HasKeyAlg: Debug { fn algorithm(&self) -> KeyAlg; } +/// A trait for accessing the backend of a key, used when +/// converting to generic `AnyKey` instances. +pub trait HasKeyBackend: Debug { + /// Get the corresponding key algorithm. + fn key_backend(&self) -> KeyBackend { + KeyBackend::default() + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/askar-crypto/src/alg/p256.rs b/askar-crypto/src/alg/p256.rs index c74ebe85..72216147 100644 --- a/askar-crypto/src/alg/p256.rs +++ b/askar-crypto/src/alg/p256.rs @@ -16,7 +16,7 @@ use p256::{ }; use subtle::ConstantTimeEq; -use super::{ec_common, EcCurves, HasKeyAlg, KeyAlg}; +use super::{ec_common, EcCurves, HasKeyAlg, HasKeyBackend, KeyAlg}; use crate::{ buffer::{ArrayKey, WriteBuffer}, error::Error, @@ -105,6 +105,8 @@ impl P256KeyPair { } } +impl HasKeyBackend for P256KeyPair {} + impl HasKeyAlg for P256KeyPair { fn algorithm(&self) -> KeyAlg { KeyAlg::EcCurve(EcCurves::Secp256r1) diff --git a/askar-crypto/src/alg/p256_hardware.rs b/askar-crypto/src/alg/p256_hardware.rs index 7756a914..4c196501 100644 --- a/askar-crypto/src/alg/p256_hardware.rs +++ b/askar-crypto/src/alg/p256_hardware.rs @@ -5,7 +5,7 @@ use super::{ p256::{self, P256KeyPair, ES256_SIGNATURE_LENGTH}, - EcCurves, HasKeyAlg, KeyAlg, + EcCurves, HasKeyAlg, HasKeyBackend, KeyAlg, KeyBackend, }; use crate::{ buffer::WriteBuffer, @@ -132,6 +132,12 @@ impl KeySign for P256HardwareKeyPair { } } +impl HasKeyBackend for P256HardwareKeyPair { + fn key_backend(&self) -> KeyBackend { + KeyBackend::SecureElement + } +} + impl HasKeyAlg for P256HardwareKeyPair { fn algorithm(&self) -> KeyAlg { KeyAlg::EcCurve(EcCurves::Secp256r1) diff --git a/askar-crypto/src/alg/p384.rs b/askar-crypto/src/alg/p384.rs index d0a48e07..e20a8001 100644 --- a/askar-crypto/src/alg/p384.rs +++ b/askar-crypto/src/alg/p384.rs @@ -16,7 +16,7 @@ use p384::{ }; use subtle::ConstantTimeEq; -use super::{ec_common, EcCurves, HasKeyAlg, KeyAlg}; +use super::{ec_common, EcCurves, HasKeyAlg, HasKeyBackend, KeyAlg}; use crate::{ buffer::{ArrayKey, WriteBuffer}, error::Error, @@ -105,6 +105,8 @@ impl P384KeyPair { } } +impl HasKeyBackend for P384KeyPair {} + impl HasKeyAlg for P384KeyPair { fn algorithm(&self) -> KeyAlg { KeyAlg::EcCurve(EcCurves::Secp384r1) diff --git a/askar-crypto/src/alg/x25519.rs b/askar-crypto/src/alg/x25519.rs index ff46ebb8..0752d8f8 100644 --- a/askar-crypto/src/alg/x25519.rs +++ b/askar-crypto/src/alg/x25519.rs @@ -9,7 +9,7 @@ use subtle::ConstantTimeEq; use x25519_dalek::{PublicKey, StaticSecret as SecretKey}; use zeroize::Zeroizing; -use super::{ed25519::Ed25519KeyPair, HasKeyAlg, KeyAlg}; +use super::{ed25519::Ed25519KeyPair, HasKeyAlg, HasKeyBackend, KeyAlg}; use crate::{ buffer::{ArrayKey, WriteBuffer}, error::Error, @@ -87,6 +87,8 @@ impl Debug for X25519KeyPair { } } +impl HasKeyBackend for X25519KeyPair {} + impl HasKeyAlg for X25519KeyPair { fn algorithm(&self) -> KeyAlg { KeyAlg::X25519 diff --git a/askar-crypto/src/backend/mod.rs b/askar-crypto/src/backend/mod.rs new file mode 100644 index 00000000..1973820c --- /dev/null +++ b/askar-crypto/src/backend/mod.rs @@ -0,0 +1,42 @@ +//! Supported key backends + +use crate::Error; +use core::str::FromStr; + +/// Backend of the key +#[derive(Debug, Clone, PartialEq, Eq, Default)] +pub enum KeyBackend { + /// Software based keys + #[default] + Software, + + /// Keys generated and store in the secure element of the device + SecureElement, +} + +impl From for &str { + fn from(key_backend: KeyBackend) -> Self { + match key_backend { + KeyBackend::Software => "software", + KeyBackend::SecureElement => "secure_element", + } + } +} + +impl FromStr for KeyBackend { + type Err = Error; + + fn from_str(s: &str) -> Result { + match s { + "software" => Ok(Self::Software), + "secure_element" => Ok(Self::SecureElement), + _ => Err(err_msg!(Invalid, "Invalid key backend.")), + } + } +} + +impl core::fmt::Display for KeyBackend { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{}", >::into(self.clone())) + } +} diff --git a/askar-crypto/src/lib.rs b/askar-crypto/src/lib.rs index 721ce18b..55931752 100644 --- a/askar-crypto/src/lib.rs +++ b/askar-crypto/src/lib.rs @@ -4,6 +4,12 @@ #![cfg_attr(docsrs, feature(doc_cfg))] #![deny(missing_docs, missing_debug_implementations, rust_2018_idioms)] +// `extern crate secure_env` is used here to include a symbol `ANativeActivity_onCreate` +// So we can get a pointer to `activity` on android, which is required to initialize the +// binding to the JVM. +#[cfg(all(target_os = "android", feature = "p256_hardware"))] +extern crate secure_env; + #[cfg(feature = "alloc")] extern crate alloc; @@ -24,6 +30,8 @@ pub use aead::generic_array; pub mod alg; +pub mod backend; + pub mod buffer; pub mod encrypt; diff --git a/src/kms/entry.rs b/src/kms/entry.rs index ea0d053e..bb093a22 100644 --- a/src/kms/entry.rs +++ b/src/kms/entry.rs @@ -25,11 +25,11 @@ impl From<&str> for KeyReference { } } -impl Into for KeyReference { - fn into(self) -> String { - match self { - Self::MobileSecureElement => String::from("mobile_secure_element"), - Self::Any(s) => s, +impl From for String { + fn from(key_reference: KeyReference) -> Self { + match key_reference { + KeyReference::MobileSecureElement => String::from("mobile_secure_element"), + KeyReference::Any(s) => s, } } } @@ -153,22 +153,16 @@ impl KeyEntry { pub fn load_local_key(&self) -> Result { if let Some(key_data) = self.params.data.as_ref() { match &self.params.reference { - Some(r) => match r { - KeyReference::MobileSecureElement => { - let id = self.params.to_id()?; - let alg = self - .alg - .as_ref() - .ok_or(err_msg!(Input, "Algorithm is required to get key by id"))?; - let alg = KeyAlg::from_str(&alg)?; - Ok(LocalKey::from_id(alg, &id)?) - } - _ => Ok(LocalKey { - inner: Box::::from_jwk_slice(key_data.as_ref())?, - ephemeral: false, - }), - }, - None => Ok(LocalKey { + Some(KeyReference::MobileSecureElement) => { + let id = self.params.to_id()?; + let alg = self + .alg + .as_ref() + .ok_or(err_msg!(Input, "Algorithm is required to get key by id"))?; + let alg = KeyAlg::from_str(alg)?; + Ok(LocalKey::from_id(alg, &id)?) + } + _ => Ok(LocalKey { inner: Box::::from_jwk_slice(key_data.as_ref())?, ephemeral: false, }), diff --git a/src/kms/local_key.rs b/src/kms/local_key.rs index 0ee05e2c..8f259498 100644 --- a/src/kms/local_key.rs +++ b/src/kms/local_key.rs @@ -4,6 +4,7 @@ use std::str::FromStr; use super::enc::{Encrypted, ToDecrypt}; pub use crate::crypto::{ alg::KeyAlg, + backend::KeyBackend, buffer::{SecretBytes, WriteBuffer}, encrypt::KeyAeadParams, }; @@ -24,44 +25,6 @@ use crate::{ #[cfg(feature = "mobile_secure_element")] use crate::crypto::alg::p256_hardware::P256HardwareKeyPair; -/// Backend of the key -#[derive(Debug, Clone, PartialEq, Eq, Default)] -pub enum KeyBackend { - /// Software based keys - #[default] - Software, - - /// Keys generated and store in the secure element of the device - SecureElement, -} - -impl Into<&str> for KeyBackend { - fn into(self) -> &'static str { - match self { - KeyBackend::Software => "software", - KeyBackend::SecureElement => "secure_element", - } - } -} - -impl FromStr for KeyBackend { - type Err = Error; - - fn from_str(s: &str) -> Result { - match s { - "software" => Ok(Self::Software), - "secure_element" => Ok(Self::SecureElement), - s => Err(err_msg!(Input, "'{s}' is not a valid key backend.")), - } - } -} - -impl core::fmt::Display for KeyBackend { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", >::into(self.clone())) - } -} - /// A stored key entry #[derive(Debug)] pub struct LocalKey { diff --git a/wrappers/javascript/packages/aries-askar-nodejs/src/NodeJSAriesAskar.ts b/wrappers/javascript/packages/aries-askar-nodejs/src/NodeJSAriesAskar.ts index 75d116d4..8f221e30 100644 --- a/wrappers/javascript/packages/aries-askar-nodejs/src/NodeJSAriesAskar.ts +++ b/wrappers/javascript/packages/aries-askar-nodejs/src/NodeJSAriesAskar.ts @@ -617,10 +617,10 @@ export class NodeJSAriesAskar implements AriesAskar { } public keyGenerate(options: KeyGenerateOptions): LocalKeyHandle { - const { algorithm, ephemeral, backend } = serializeArguments(options) + const { algorithm, ephemeral, keyBackend } = serializeArguments(options) const ret = allocatePointer() - const errorCode = this.nativeAriesAskar.askar_key_generate(algorithm, backend, ephemeral, ret) + const errorCode = this.nativeAriesAskar.askar_key_generate(algorithm, keyBackend, ephemeral, ret) this.handleError(errorCode) const handle = handleReturnPointer(ret) diff --git a/wrappers/javascript/packages/aries-askar-react-native-example/app.json b/wrappers/javascript/packages/aries-askar-react-native-example/app.json index a8b34d08..7caf588f 100644 --- a/wrappers/javascript/packages/aries-askar-react-native-example/app.json +++ b/wrappers/javascript/packages/aries-askar-react-native-example/app.json @@ -14,14 +14,14 @@ "assetBundlePatterns": ["**/*"], "ios": { "supportsTablet": true, - "bundleIdentifier": "org.hyperledger.aries_askar.example" + "bundleIdentifier": "org.hyperledger.ariesaskar.example" }, "android": { "adaptiveIcon": { "foregroundImage": "./assets/adaptive-icon.png", "backgroundColor": "#ffffff" }, - "package": "org.hyperledger.aries_askar.example" + "package": "org.hyperledger.ariesaskar.example" } } } diff --git a/wrappers/javascript/packages/aries-askar-react-native-example/src/App.tsx b/wrappers/javascript/packages/aries-askar-react-native-example/src/App.tsx index f656fc88..42330f29 100644 --- a/wrappers/javascript/packages/aries-askar-react-native-example/src/App.tsx +++ b/wrappers/javascript/packages/aries-askar-react-native-example/src/App.tsx @@ -1,4 +1,4 @@ -import { ariesAskar } from '@hyperledger/aries-askar-react-native' +import { Key, KeyAlgs, KeyBackend, ariesAskar } from '@hyperledger/aries-askar-react-native' import { StyleSheet, Text, View } from 'react-native' const styles = StyleSheet.create({ @@ -10,8 +10,13 @@ const styles = StyleSheet.create({ }, }) -export const App = () => ( - - {ariesAskar.version()} - -) +export const App = () => { + const key = Key.generate(KeyAlgs.EcSecp256r1, KeyBackend.SecureElement) + + return ( + + {ariesAskar.version()} + Key: {key.publicBytes.join(',')} + + ) +} diff --git a/wrappers/javascript/packages/aries-askar-react-native/cpp/ariesAskar.cpp b/wrappers/javascript/packages/aries-askar-react-native/cpp/ariesAskar.cpp index cb20f253..e32d5622 100644 --- a/wrappers/javascript/packages/aries-askar-react-native/cpp/ariesAskar.cpp +++ b/wrappers/javascript/packages/aries-askar-react-native/cpp/ariesAskar.cpp @@ -598,11 +598,17 @@ jsi::Value keyFromSeed(jsi::Runtime &rt, jsi::Object options) { jsi::Value keyGenerate(jsi::Runtime &rt, jsi::Object options) { auto algorithm = jsiToValue(rt, options, "algorithm"); + auto keyBackend = jsiToValue(rt, options, "keyBackend"); auto ephemeral = jsiToValue(rt, options, "ephemeral"); LocalKeyHandle out; - ErrorCode code = askar_key_generate(algorithm.c_str(), ephemeral, &out); + ErrorCode code = askar_key_generate( + algorithm.c_str(), + keyBackend.length() ? keyBackend.c_str() : nullptr, + ephemeral, + &out + ); return createReturnValue(rt, code, &out); } diff --git a/wrappers/javascript/packages/aries-askar-react-native/cpp/include/libaries_askar.h b/wrappers/javascript/packages/aries-askar-react-native/cpp/include/libaries_askar.h index 974b4ac4..103dc47f 100644 --- a/wrappers/javascript/packages/aries-askar-react-native/cpp/include/libaries_askar.h +++ b/wrappers/javascript/packages/aries-askar-react-native/cpp/include/libaries_askar.h @@ -219,10 +219,6 @@ typedef struct ArcHandle_FfiKeyEntryList { typedef struct ArcHandle_FfiKeyEntryList KeyEntryListHandle; -typedef int64_t CallbackId; - -typedef void (*LogCallback)(const void *context, int32_t level, const char *target, const char *message, const char *module_path, const char *file, int32_t line); - typedef struct FfiResultList_String FfiStringList; typedef struct ArcHandle_FfiStringList { @@ -231,6 +227,16 @@ typedef struct ArcHandle_FfiStringList { typedef struct ArcHandle_FfiStringList StringListHandle; +typedef int64_t CallbackId; + +typedef void (*LogCallback)(const void *context, + int32_t level, + const char *target, + const char *message, + const char *module_path, + const char *file, + int32_t line); + #ifdef __cplusplus extern "C" { #endif // __cplusplus @@ -362,7 +368,7 @@ ErrorCode askar_key_from_seed(FfiStr alg, FfiStr method, LocalKeyHandle *out); -ErrorCode askar_key_generate(FfiStr alg, int8_t ephemeral, LocalKeyHandle *out); +ErrorCode askar_key_generate(FfiStr alg, FfiStr key_backend, int8_t ephemeral, LocalKeyHandle *out); ErrorCode askar_key_get_algorithm(LocalKeyHandle handle, const char **out); @@ -378,6 +384,8 @@ ErrorCode askar_key_get_public_bytes(LocalKeyHandle handle, struct SecretBuffer ErrorCode askar_key_get_secret_bytes(LocalKeyHandle handle, struct SecretBuffer *out); +ErrorCode skar_key_get_supported_backends(StringListHandle *out); + ErrorCode askar_key_sign_message(LocalKeyHandle handle, struct ByteBuffer message, FfiStr sig_type, @@ -422,9 +430,9 @@ ErrorCode askar_migrate_indy_sdk(FfiStr spec_uri, ErrorCode askar_scan_free(ScanHandle handle); -ErrorCode askar_scan_next(ScanHandle handle, - void (*cb)(CallbackId cb_id, ErrorCode err, EntryListHandle results), - CallbackId cb_id); +ErrorCode askar_scan_next(ScanHandle handle, void (*cb)(CallbackId cb_id, + ErrorCode err, + EntryListHandle results), CallbackId cb_id); ErrorCode askar_scan_start(StoreHandle handle, FfiStr profile, @@ -458,7 +466,9 @@ ErrorCode askar_session_fetch_all(SessionHandle handle, FfiStr tag_filter, int64_t limit, int8_t for_update, - void (*cb)(CallbackId cb_id, ErrorCode err, EntryListHandle results), + void (*cb)(CallbackId cb_id, + ErrorCode err, + EntryListHandle results), CallbackId cb_id); ErrorCode askar_session_fetch_all_keys(SessionHandle handle, @@ -467,13 +477,17 @@ ErrorCode askar_session_fetch_all_keys(SessionHandle handle, FfiStr tag_filter, int64_t limit, int8_t for_update, - void (*cb)(CallbackId cb_id, ErrorCode err, KeyEntryListHandle results), + void (*cb)(CallbackId cb_id, + ErrorCode err, + KeyEntryListHandle results), CallbackId cb_id); ErrorCode askar_session_fetch_key(SessionHandle handle, FfiStr name, int8_t for_update, - void (*cb)(CallbackId cb_id, ErrorCode err, KeyEntryListHandle results), + void (*cb)(CallbackId cb_id, + ErrorCode err, + KeyEntryListHandle results), CallbackId cb_id); ErrorCode askar_session_insert_key(SessionHandle handle, @@ -544,13 +558,17 @@ ErrorCode askar_store_copy(StoreHandle handle, ErrorCode askar_store_create_profile(StoreHandle handle, FfiStr profile, - void (*cb)(CallbackId cb_id, ErrorCode err, const char *result_p), + void (*cb)(CallbackId cb_id, + ErrorCode err, + const char *result_p), CallbackId cb_id); ErrorCode askar_store_generate_raw_key(struct ByteBuffer seed, const char **out); ErrorCode askar_store_get_default_profile(StoreHandle handle, - void (*cb)(CallbackId cb_id, ErrorCode err, const char *profile), + void (*cb)(CallbackId cb_id, + ErrorCode err, + const char *profile), CallbackId cb_id); ErrorCode askar_store_get_profile_name(StoreHandle handle, @@ -558,7 +576,9 @@ ErrorCode askar_store_get_profile_name(StoreHandle handle, CallbackId cb_id); ErrorCode askar_store_list_profiles(StoreHandle handle, - void (*cb)(CallbackId cb_id, ErrorCode err, StringListHandle results), + void (*cb)(CallbackId cb_id, + ErrorCode err, + StringListHandle results), CallbackId cb_id); ErrorCode askar_store_open(FfiStr spec_uri, diff --git a/wrappers/javascript/packages/aries-askar-shared/src/ariesAskar/AriesAskar.ts b/wrappers/javascript/packages/aries-askar-shared/src/ariesAskar/AriesAskar.ts index d52e65d0..06d9d5ae 100644 --- a/wrappers/javascript/packages/aries-askar-shared/src/ariesAskar/AriesAskar.ts +++ b/wrappers/javascript/packages/aries-askar-shared/src/ariesAskar/AriesAskar.ts @@ -162,7 +162,7 @@ export type KeyFromSeedOptions = { } export type KeyGenerateOptions = { algorithm: KeyAlgs - backend?: KeyBackend + keyBackend?: KeyBackend ephemeral: boolean } export type KeyGetAlgorithmOptions = { localKeyHandle: LocalKeyHandle } diff --git a/wrappers/javascript/packages/aries-askar-shared/src/crypto/Key.ts b/wrappers/javascript/packages/aries-askar-shared/src/crypto/Key.ts index dc87ed6c..9271708e 100644 --- a/wrappers/javascript/packages/aries-askar-shared/src/crypto/Key.ts +++ b/wrappers/javascript/packages/aries-askar-shared/src/crypto/Key.ts @@ -1,5 +1,6 @@ import type { LocalKeyHandle } from './handles' import type { KeyAlgs, SigAlgs } from '../enums' +import type { KeyBackend } from '../enums' import { Buffer } from 'buffer' @@ -15,8 +16,8 @@ export class Key { this.localKeyHandle = handle } - public static generate(algorithm: KeyAlgs, ephemeral = false) { - return new Key(ariesAskar.keyGenerate({ algorithm, ephemeral })) + public static generate(algorithm: KeyAlgs, keyBackend?: KeyBackend, ephemeral = false) { + return new Key(ariesAskar.keyGenerate({ algorithm, keyBackend, ephemeral })) } public static fromSeed({ @@ -48,7 +49,13 @@ export class Key { } public keyFromKeyExchange({ algorithm, publicKey }: { algorithm: KeyAlgs; publicKey: Key }) { - return new Key(ariesAskar.keyFromKeyExchange({ skHandle: this.handle, pkHandle: publicKey.handle, algorithm })) + return new Key( + ariesAskar.keyFromKeyExchange({ + skHandle: this.handle, + pkHandle: publicKey.handle, + algorithm, + }), + ) } public get handle() { @@ -73,16 +80,26 @@ export class Key { } public get jwkPublic(): Jwk { - return Jwk.fromString(ariesAskar.keyGetJwkPublic({ localKeyHandle: this.handle, algorithm: this.algorithm })) + return Jwk.fromString( + ariesAskar.keyGetJwkPublic({ + localKeyHandle: this.handle, + algorithm: this.algorithm, + }), + ) } public get jwkSecret() { - const secretBytes = ariesAskar.keyGetJwkSecret({ localKeyHandle: this.handle }) + const secretBytes = ariesAskar.keyGetJwkSecret({ + localKeyHandle: this.handle, + }) return Jwk.fromString(Buffer.from(secretBytes).toString()) } public get jwkThumbprint() { - return ariesAskar.keyGetJwkThumbprint({ localKeyHandle: this.handle, algorithm: this.algorithm }) + return ariesAskar.keyGetJwkThumbprint({ + localKeyHandle: this.handle, + algorithm: this.algorithm, + }) } public get aeadParams() { @@ -94,23 +111,39 @@ export class Key { } public aeadEncrypt(options: { message: Uint8Array; nonce?: Uint8Array; aad?: Uint8Array }) { - return ariesAskar.keyAeadEncrypt({ localKeyHandle: this.handle, ...options }) + return ariesAskar.keyAeadEncrypt({ + localKeyHandle: this.handle, + ...options, + }) } public aeadDecrypt(options: { ciphertext: Uint8Array; nonce: Uint8Array; tag?: Uint8Array; aad?: Uint8Array }) { - return ariesAskar.keyAeadDecrypt({ localKeyHandle: this.handle, ...options }) + return ariesAskar.keyAeadDecrypt({ + localKeyHandle: this.handle, + ...options, + }) } public signMessage(options: { message: Uint8Array; sigType?: SigAlgs }) { - return ariesAskar.keySignMessage({ localKeyHandle: this.handle, ...options }) + return ariesAskar.keySignMessage({ + localKeyHandle: this.handle, + ...options, + }) } public verifySignature(options: { message: Uint8Array; signature: Uint8Array; sigType?: SigAlgs }) { - return ariesAskar.keyVerifySignature({ localKeyHandle: this.handle, ...options }) + return ariesAskar.keyVerifySignature({ + localKeyHandle: this.handle, + ...options, + }) } public wrapKey({ other, nonce }: { other: Key; nonce?: Uint8Array }) { - return ariesAskar.keyWrapKey({ localKeyHandle: this.handle, other: other.handle, nonce }) + return ariesAskar.keyWrapKey({ + localKeyHandle: this.handle, + other: other.handle, + nonce, + }) } public unwrapKey(options: { algorithm: KeyAlgs; tag?: Uint8Array; ciphertext: Uint8Array; nonce?: Uint8Array }) {