diff --git a/libraries/crypto/Cargo.toml b/libraries/crypto/Cargo.toml index 989a8dee..cf66bd46 100644 --- a/libraries/crypto/Cargo.toml +++ b/libraries/crypto/Cargo.toml @@ -25,3 +25,4 @@ zeroize = { version = "1.5.7", features = ["derive"] } [features] std = ["hex", "ring", "untrusted", "serde", "serde_json", "regex", "rand_core/getrandom"] with_ctap1 = [] +acvp = [] diff --git a/libraries/crypto/src/ecdh.rs b/libraries/crypto/src/ecdh.rs index ed5bec03..28772fbe 100644 --- a/libraries/crypto/src/ecdh.rs +++ b/libraries/crypto/src/ecdh.rs @@ -78,6 +78,18 @@ impl SecKey { p.getx().to_int().to_bin(&mut x); x } + + /// Creates a private key from the exponent's bytes, or None if checks fail. + #[cfg(any(feature = "std", feature = "acvp"))] + pub fn from_bytes(bytes: &[u8; 32]) -> Option { + let a = NonZeroExponentP256::from_int_checked(Int256::from_bin(bytes)); + // The branching here is fine because all this reveals is whether the key was invalid. + if bool::from(a.is_none()) { + return None; + } + let a = a.unwrap(); + Some(SecKey { a }) + } } impl PubKey { diff --git a/libraries/crypto/src/ecdsa.rs b/libraries/crypto/src/ecdsa.rs index f4e66211..cdf7c54e 100644 --- a/libraries/crypto/src/ecdsa.rs +++ b/libraries/crypto/src/ecdsa.rs @@ -19,7 +19,7 @@ use super::ec::point::PointP256; use super::Hash256; use alloc::vec; use alloc::vec::Vec; -#[cfg(feature = "std")] +#[cfg(any(feature = "std", feature = "acvp"))] use arrayref::array_mut_ref; use arrayref::{array_ref, mut_array_refs}; use core::marker::PhantomData; @@ -220,7 +220,7 @@ impl Signature { Some(Signature { r, s }) } - #[cfg(feature = "std")] + #[cfg(any(feature = "std", feature = "acvp"))] pub fn to_bytes(&self, bytes: &mut [u8; Signature::BYTES_LENGTH]) { self.r .to_int() diff --git a/libraries/opensk/Cargo.toml b/libraries/opensk/Cargo.toml index 707af94e..8909f28a 100644 --- a/libraries/opensk/Cargo.toml +++ b/libraries/opensk/Cargo.toml @@ -45,6 +45,7 @@ vendor_hid = [] fuzz = ["arbitrary", "std"] ed25519 = ["ed25519-compact"] rust_crypto = ["p256", "sha2", "hmac", "hkdf", "aes", "cbc"] +acvp = ["crypto/acvp"] [dev-dependencies] enum-iterator = "0.6.0" diff --git a/libraries/opensk/src/api/crypto/ecdh.rs b/libraries/opensk/src/api/crypto/ecdh.rs index 1c4b74fb..b6010ae7 100644 --- a/libraries/opensk/src/api/crypto/ecdh.rs +++ b/libraries/opensk/src/api/crypto/ecdh.rs @@ -23,7 +23,7 @@ pub trait Ecdh { } /// ECDH ephemeral key. -pub trait SecretKey { +pub trait SecretKey: Sized { type PublicKey: PublicKey; type SharedSecret: SharedSecret; @@ -35,6 +35,10 @@ pub trait SecretKey { /// Computes the shared secret when using Elliptic-curve Diffie–Hellman. fn diffie_hellman(&self, public_key: &Self::PublicKey) -> Self::SharedSecret; + + /// Creates a signing key from its representation in bytes. + #[cfg(feature = "acvp")] + fn from_slice(bytes: &[u8; EC_FIELD_SIZE]) -> Option; } /// ECDH public key. diff --git a/libraries/opensk/src/api/crypto/ecdsa.rs b/libraries/opensk/src/api/crypto/ecdsa.rs index 1dad533b..e6e38c28 100644 --- a/libraries/opensk/src/api/crypto/ecdsa.rs +++ b/libraries/opensk/src/api/crypto/ecdsa.rs @@ -73,7 +73,7 @@ pub trait Signature: Sized { fn from_slice(bytes: &[u8; EC_SIGNATURE_SIZE]) -> Option; /// Writes the signature bytes into the passed in parameter. - #[cfg(feature = "std")] + #[cfg(any(feature = "std", feature = "acvp"))] fn to_slice(&self, bytes: &mut [u8; EC_SIGNATURE_SIZE]); /// Encodes the signatures as ASN1 DER. diff --git a/libraries/opensk/src/api/crypto/software_crypto.rs b/libraries/opensk/src/api/crypto/software_crypto.rs index f0cd2216..2f9ff356 100644 --- a/libraries/opensk/src/api/crypto/software_crypto.rs +++ b/libraries/opensk/src/api/crypto/software_crypto.rs @@ -69,6 +69,11 @@ impl ecdh::SecretKey for SoftwareEcdhSecretKey { let shared_secret = self.sec_key.exchange_x(&public_key.pub_key); SoftwareEcdhSharedSecret { shared_secret } } + + #[cfg(feature = "acvp")] + fn from_slice(bytes: &[u8; EC_FIELD_SIZE]) -> Option { + crypto::ecdh::SecKey::from_bytes(bytes).map(|k| Self { sec_key: k }) + } } pub struct SoftwareEcdhPublicKey { @@ -169,7 +174,7 @@ impl ecdsa::Signature for SoftwareEcdsaSignature { crypto::ecdsa::Signature::from_bytes(bytes).map(|s| SoftwareEcdsaSignature { signature: s }) } - #[cfg(feature = "std")] + #[cfg(any(feature = "std", feature = "acvp"))] fn to_slice(&self, bytes: &mut [u8; EC_SIGNATURE_SIZE]) { self.signature.to_bytes(bytes); } diff --git a/libraries/opensk/src/ctap/hid/receive.rs b/libraries/opensk/src/ctap/hid/receive.rs index c3689c31..3d07c066 100644 --- a/libraries/opensk/src/ctap/hid/receive.rs +++ b/libraries/opensk/src/ctap/hid/receive.rs @@ -83,6 +83,7 @@ impl MessageAssembler { let (cid, processed_packet) = CtapHid::::process_single_packet(packet); if let Some(locked_cid) = locked_cid { if locked_cid != cid { + #[cfg(not(feature = "acvp"))] return Err((cid, CtapHidError::ChannelBusy)); } }