From b410cb9da6596cc14b5f6420e0b74764dd0e6012 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sosth=C3=A8ne=20Gu=C3=A9don?= Date: Wed, 24 Apr 2024 10:56:57 +0200 Subject: [PATCH 1/3] Add support for more curves TODO: find a way to get the public key without the software implementation --- Cargo.toml | 3 +- src/core_api.rs | 381 +++++++++++++++++++++++++++++++++++--- src/core_api/ecdsa_der.rs | 39 ++++ src/lib.rs | 20 +- src/namespacing.rs | 4 + 5 files changed, 421 insertions(+), 26 deletions(-) create mode 100644 src/core_api/ecdsa_der.rs diff --git a/Cargo.toml b/Cargo.toml index 117cda4..dcbcbe2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,6 +48,7 @@ salty = "0.3.0" p256-cortex-m4 = { version = "0.1.0-alpha.6", features = ["prehash", "sec1-signatures"] } admin-app = "0.1.0" bitflags = "2.5.0" +der = "0.7.9" [dev-dependencies] admin-app = { version = "0.1.0", features = ["migration-tests"] } @@ -57,7 +58,7 @@ serde_test = "1.0.176" littlefs2 = { git = "https://github.com/trussed-dev/littlefs2.git", rev = "960e57d9fc0d209308c8e15dc26252bbe1ff6ba8" } apdu-dispatch = { git = "https://github.com/trussed-dev/apdu-dispatch.git", rev = "915fc237103fcecc29d0f0b73391f19abf6576de" } ctaphid-dispatch = { git = "https://github.com/trussed-dev/ctaphid-dispatch.git", rev = "57cb3317878a8593847595319aa03ef17c29ec5b" } -trussed = { git = "https://github.com/trussed-dev/trussed.git", rev = "667d60c019d485524a276f2a4dd07aaa66e71021" } +trussed = { git = "https://github.com/nitrokey/trussed.git", rev = "0ccdd468859ea14b43e2e95790b9712c398ae5e1" } trussed-auth = { git = "https://github.com/trussed-dev/trussed-auth.git", tag = "v0.3.0"} trussed-manage = { git = "https://github.com/trussed-dev/trussed-staging.git", tag = "manage-v0.1.0" } trussed-rsa-alloc = { git = "https://github.com/trussed-dev/trussed-rsa-backend.git", tag = "v0.2.1" } diff --git a/src/core_api.rs b/src/core_api.rs index 598e782..28ac46c 100644 --- a/src/core_api.rs +++ b/src/core_api.rs @@ -44,6 +44,8 @@ use crate::{ object_in_range, Context, Se050Backend, BACKEND_DIR, }; +mod ecdsa_der; + pub(crate) const BUFFER_LEN: usize = 2048; pub(crate) const CORE_DIR: &str = "se050-core"; @@ -195,6 +197,10 @@ fn prepare_rsa_pkcs1v15(message: &[u8], keysize: usize) -> Result, Er Ok(data) } +const SERIALIZED_P256_LEN: usize = 64; +const SERIALIZED_P384_LEN: usize = 96; +const SERIALIZED_P521_LEN: usize = 128; + #[allow(clippy::too_many_arguments)] impl> Se050Backend { fn random_bytes(&mut self, count: usize) -> Result { @@ -550,6 +556,42 @@ impl> Se050Backend { Ok(reply::DeriveKey { key: result }) } + KeyType::P384 => { + let material = self + .se + .run_command(&ReadObject::builder().object_id(key).build(), buf) + .map_err(|_err| { + error!("Failed to read key for derive: {_err:?}"); + Error::FunctionFailed + })?; + + let result = core_keystore.store_key( + req.attributes.persistence, + Secrecy::Public, + Kind::P384, + material.data, + )?; + + Ok(reply::DeriveKey { key: result }) + } + KeyType::P521 => { + let material = self + .se + .run_command(&ReadObject::builder().object_id(key).build(), buf) + .map_err(|_err| { + error!("Failed to read key for derive: {_err:?}"); + Error::FunctionFailed + })?; + + let result = core_keystore.store_key( + req.attributes.persistence, + Secrecy::Public, + Kind::P521, + material.data, + )?; + + Ok(reply::DeriveKey { key: result }) + } KeyType::Rsa2048 | KeyType::Rsa3072 | KeyType::Rsa4096 => { self.derive_rsa_key(req, key, ty, core_keystore) } @@ -626,6 +668,8 @@ impl> Se050Backend { KeyType::Ed255 => Kind::Ed255, KeyType::X255 => Kind::X255, KeyType::P256 => Kind::P256, + KeyType::P384 => Kind::P384, + KeyType::P521 => Kind::P521, KeyType::Rsa2048 | KeyType::Rsa3072 | KeyType::Rsa4096 => { unreachable!("Volatile rsa keys are derived in a separate function") } @@ -847,6 +891,8 @@ impl> Se050Backend { Mechanism::Ed255 => (Kind::Ed255, KeyType::Ed255), Mechanism::X255 => (Kind::X255, KeyType::X255), Mechanism::P256 => (Kind::P256, KeyType::P256), + Mechanism::P384 => (Kind::P384, KeyType::P384), + Mechanism::P521 => (Kind::P521, KeyType::P521), Mechanism::Rsa2048Raw | Mechanism::Rsa2048Pkcs1v15 => { return self.generate_volatile_rsa_key( se050_keystore, @@ -905,19 +951,39 @@ impl> Se050Backend { error!("Failed to generate volatile key: {_err:?}"); Error::FunctionFailed })?, + Mechanism::P384 => self + .se + .run_command(&generate_p384(object_id.0, true), buf) + .map_err(|_err| { + error!("Failed to generate volatile key: {_err:?}"); + Error::FunctionFailed + })?, + Mechanism::P521 => self + .se + .run_command(&generate_p521(object_id.0, true), buf) + .map_err(|_err| { + error!("Failed to generate volatile key: {_err:?}"); + Error::FunctionFailed + })?, _ => unreachable!(), } let exported = self .se .run_command(&ExportObject::builder().object_id(object_id.0).build(), buf) - .or(Err(Error::FunctionFailed))? + .map_err(|_err| { + error!("Failed to export generated key: {_err:?}"); + Error::FunctionFailed + })? .data; let key = key_id_for_obj(object_id.0, ty); let material: Bytes<1024> = trussed::cbor_serialize_bytes(&VolatileKeyMaterialRef { object_id, exported_material: exported, }) - .or(Err(Error::FunctionFailed))?; + .map_err(|_err| { + error!("Failed to serialize exported key: {_err:?}"); + Error::FunctionFailed + })?; se050_keystore.overwrite_key(Location::Volatile, Secrecy::Secret, kind, &key, &material)?; // Remove any data from the transient storage @@ -960,6 +1026,22 @@ impl> Se050Backend { Error::FunctionFailed })?, Mechanism::P256Prehashed => return Err(Error::MechanismParamInvalid), + Mechanism::P384 => self + .se + .run_command(&generate_p384(object_id.0, false), buf) + .map_err(|_err| { + error!("Failed to generate key: {_err:?}"); + Error::FunctionFailed + })?, + Mechanism::P384Prehashed => return Err(Error::MechanismParamInvalid), + Mechanism::P521 => self + .se + .run_command(&generate_p521(object_id.0, false), buf) + .map_err(|_err| { + error!("Failed to generate key: {_err:?}"); + Error::FunctionFailed + })?, + Mechanism::P521Prehashed => return Err(Error::MechanismParamInvalid), Mechanism::Rsa2048Raw | Mechanism::Rsa2048Pkcs1v15 => self .se .run_command(&generate_rsa(object_id.0, 2048), buf) @@ -992,6 +1074,8 @@ impl> Se050Backend { // TODO First write curve somehow Mechanism::P256 => KeyType::P256, + Mechanism::P384 => KeyType::P384, + Mechanism::P521 => KeyType::P521, Mechanism::Rsa2048Raw | Mechanism::Rsa2048Pkcs1v15 => KeyType::Rsa2048, Mechanism::Rsa3072Raw | Mechanism::Rsa3072Pkcs1v15 => KeyType::Rsa3072, Mechanism::Rsa4096Raw | Mechanism::Rsa4096Pkcs1v15 => KeyType::Rsa4096, @@ -1016,6 +1100,8 @@ impl> Se050Backend { let kind = match (req.mechanism, priv_parsed_ty) { (Mechanism::P256, KeyType::P256) => Kind::P256, + (Mechanism::P384, KeyType::P384) => Kind::P384, + (Mechanism::P521, KeyType::P521) => Kind::P521, (Mechanism::X255, KeyType::X255) => Kind::X255, _ => return Err(Error::WrongKeyKind), }; @@ -1300,6 +1386,16 @@ impl> Se050Backend { Err(Error::FunctionNotSupported) } Mechanism::P256Prehashed => self.sign_ecdsa(req, se050_keystore, ns), + Mechanism::P384 => { + debug!("TODO: Implement P384 without prehashing"); + Err(Error::FunctionNotSupported) + } + Mechanism::P384Prehashed => self.sign_ecdsa(req, se050_keystore, ns), + Mechanism::P521 => { + debug!("TODO: Implement P521 without prehashing"); + Err(Error::FunctionNotSupported) + } + Mechanism::P521Prehashed => self.sign_ecdsa(req, se050_keystore, ns), Mechanism::Ed255 => self.sign_eddsa(req, se050_keystore, ns), Mechanism::Rsa2048Pkcs1v15 | Mechanism::Rsa3072Pkcs1v15 @@ -1443,8 +1539,16 @@ impl> Se050Backend { let (parsed_key, parsed_ty) = parse_key_id(req.key, ns).ok_or(Error::RequestNotAvailable)?; - let (kind, algo) = match (req.mechanism, parsed_ty) { - (Mechanism::P256Prehashed, KeyType::P256) => (Kind::P256, EcDsaSignatureAlgo::Sha256), + let (kind, algo, field_byte_size) = match (req.mechanism, parsed_ty) { + (Mechanism::P256Prehashed, KeyType::P256) => { + (Kind::P256, EcDsaSignatureAlgo::Sha256, 32) + } + (Mechanism::P384Prehashed, KeyType::P384) => { + (Kind::P384, EcDsaSignatureAlgo::Sha384, 48) + } + (Mechanism::P521Prehashed, KeyType::P521) => { + (Kind::P521, EcDsaSignatureAlgo::Sha512, 66) + } _ => return Err(Error::WrongKeyKind), }; @@ -1474,14 +1578,13 @@ impl> Se050Backend { Error::FunctionFailed })?; - let signature_der = p256::ecdsa::Signature::from_der(res.signature).map_err(|_err| { - error!("Failed to parse p256 signature: {_err:?}"); + let signature_der = ecdsa_der::DerSignature::from_der(res.signature).map_err(|_err| { + error!("Failed to parse DER signature: {_err:?}"); Error::FunctionFailed })?; let mut signature = Bytes::new(); - signature - .extend_from_slice(&signature_der.to_bytes()) - .unwrap(); + assert!(signature.capacity() > 2 * field_byte_size); + signature.extend(signature_der.to_bytes(field_byte_size)); if let ParsedObjectId::VolatileKey(_) = parsed_key { self.reselect()?; @@ -1565,6 +1668,30 @@ impl> Se050Backend { core_keystore, ns, ), + Mechanism::P384 => { + debug!("Implement P384 without prehashing"); + Err(Error::FunctionNotSupported) + } + Mechanism::P384Prehashed => self.verify_ecdsa_prehashed( + req, + Kind::P384, + EcCurve::NistP384, + EcDsaSignatureAlgo::Sha384, + core_keystore, + ns, + ), + Mechanism::P521 => { + debug!("Implement P521 without prehashing"); + Err(Error::FunctionNotSupported) + } + Mechanism::P521Prehashed => self.verify_ecdsa_prehashed( + req, + Kind::P521, + EcCurve::NistP521, + EcDsaSignatureAlgo::Sha512, + core_keystore, + ns, + ), Mechanism::Ed255 => { self.verify_eddsa(req, Kind::Ed255, EcCurve::IdEccEd25519, core_keystore, ns) } @@ -1804,6 +1931,8 @@ impl> Se050Backend { ) -> Result { match req.mechanism { Mechanism::P256 => self.deserialize_p256_key(req, core_keystore), + Mechanism::P384 => self.deserialize_p384_key(req, core_keystore), + Mechanism::P521 => self.deserialize_p521_key(req, core_keystore), Mechanism::X255 => self.deserialize_x255_key(req, core_keystore), Mechanism::Ed255 => self.deserialize_ed255_key(req, core_keystore), Mechanism::Rsa2048Pkcs1v15 => { @@ -1829,14 +1958,14 @@ impl> Se050Backend { return Err(Error::FunctionFailed); } - if req.serialized_key.len() != 64 { + if req.serialized_key.len() != SERIALIZED_P256_LEN { debug!( "Unsupported P256 public key length: {}", req.serialized_key.len() ); return Err(Error::MechanismParamInvalid); } - let mut material = Bytes::<65>::new(); + let mut material = Bytes::<{ SERIALIZED_P256_LEN + 1 }>::new(); material.push(0x04).unwrap(); material.extend_from_slice(&req.serialized_key).unwrap(); let key = core_keystore.store_key( @@ -1847,6 +1976,65 @@ impl> Se050Backend { )?; Ok(reply::DeserializeKey { key }) } + + fn deserialize_p384_key( + &mut self, + req: &request::DeserializeKey, + core_keystore: &mut impl Keystore, + ) -> Result { + if req.format != KeySerialization::Raw { + debug!("Unsupported P384 public format: {:?}", req.format); + return Err(Error::FunctionFailed); + } + + if req.serialized_key.len() != SERIALIZED_P384_LEN { + debug!( + "Unsupported P384 public key length: {}", + req.serialized_key.len() + ); + return Err(Error::MechanismParamInvalid); + } + let mut material = Bytes::<{ SERIALIZED_P384_LEN + 1 }>::new(); + material.push(0x04).unwrap(); + material.extend_from_slice(&req.serialized_key).unwrap(); + let key = core_keystore.store_key( + req.attributes.persistence, + Secrecy::Public, + Kind::P384, + &material, + )?; + Ok(reply::DeserializeKey { key }) + } + + fn deserialize_p521_key( + &mut self, + req: &request::DeserializeKey, + core_keystore: &mut impl Keystore, + ) -> Result { + if req.format != KeySerialization::Raw { + debug!("Unsupported P521 public format: {:?}", req.format); + return Err(Error::FunctionFailed); + } + + if req.serialized_key.len() != SERIALIZED_P521_LEN { + debug!( + "Unsupported P521 public key length: {}", + req.serialized_key.len() + ); + return Err(Error::MechanismParamInvalid); + } + let mut material = Bytes::<{ SERIALIZED_P521_LEN + 1 }>::new(); + material.push(0x04).unwrap(); + material.extend_from_slice(&req.serialized_key).unwrap(); + let key = core_keystore.store_key( + req.attributes.persistence, + Secrecy::Public, + Kind::P521, + &material, + )?; + Ok(reply::DeserializeKey { key }) + } + fn deserialize_x255_key( &mut self, req: &request::DeserializeKey, @@ -1926,6 +2114,8 @@ impl> Se050Backend { ) -> Result { match req.mechanism { Mechanism::P256 => self.serialize_p256_key(req, core_keystore), + Mechanism::P384 => self.serialize_p384_key(req, core_keystore), + Mechanism::P521 => self.serialize_p521_key(req, core_keystore), Mechanism::X255 => self.serialize_x255_key(req, core_keystore), Mechanism::Ed255 => self.serialize_ed255_key(req, core_keystore), Mechanism::Rsa2048Pkcs1v15 | Mechanism::Rsa2048Raw => { @@ -1940,6 +2130,7 @@ impl> Se050Backend { _ => Err(Error::MechanismParamInvalid), } } + fn serialize_p256_key( &mut self, req: &request::SerializeKey, @@ -1951,12 +2142,54 @@ impl> Se050Backend { } let mut data = core_keystore.load_key(Secrecy::Public, Some(Kind::P256), &req.key)?; - if data.material.len() != 65 { + if data.material.len() != SERIALIZED_P256_LEN + 1 { debug!("Incorrect P256 public key length: {}", data.material.len()); return Err(Error::FunctionFailed); } data.material.rotate_left(1); - data.material.resize(64, 0).unwrap(); + data.material.resize(SERIALIZED_P256_LEN, 0).unwrap(); + Ok(reply::SerializeKey { + serialized_key: data.material.into(), + }) + } + fn serialize_p384_key( + &mut self, + req: &request::SerializeKey, + core_keystore: &mut impl Keystore, + ) -> Result { + if req.format != KeySerialization::Raw { + debug!("Unsupported P384 public format: {:?}", req.format); + return Err(Error::FunctionFailed); + } + + let mut data = core_keystore.load_key(Secrecy::Public, Some(Kind::P384), &req.key)?; + if data.material.len() != SERIALIZED_P384_LEN + 1 { + debug!("Incorrect P384 public key length: {}", data.material.len()); + return Err(Error::FunctionFailed); + } + data.material.rotate_left(1); + data.material.resize(SERIALIZED_P384_LEN, 0).unwrap(); + Ok(reply::SerializeKey { + serialized_key: data.material.into(), + }) + } + fn serialize_p521_key( + &mut self, + req: &request::SerializeKey, + core_keystore: &mut impl Keystore, + ) -> Result { + if req.format != KeySerialization::Raw { + debug!("Unsupported P521 public format: {:?}", req.format); + return Err(Error::FunctionFailed); + } + + let mut data = core_keystore.load_key(Secrecy::Public, Some(Kind::P521), &req.key)?; + if data.material.len() != SERIALIZED_P521_LEN + 1 { + debug!("Incorrect P521 public key length: {}", data.material.len()); + return Err(Error::FunctionFailed); + } + data.material.rotate_left(1); + data.material.resize(SERIALIZED_P521_LEN, 0).unwrap(); Ok(reply::SerializeKey { serialized_key: data.material.into(), }) @@ -2189,6 +2422,8 @@ impl> Se050Backend { Kind::Ed255 => KeyType::Ed255, Kind::X255 => KeyType::X255, Kind::P256 => KeyType::P256, + Kind::P384 => KeyType::P384, + Kind::P521 => KeyType::P521, _ => return Err(Error::FunctionFailed), }; let key_id = match ty { @@ -2203,7 +2438,6 @@ impl> Se050Backend { return Err(Error::ObjectHandleInvalid); } self.ensure_exists(mat.object_id.0, &mut [0; 128])?; - key_id_for_obj(mat.object_id.0, key_ty) } WrappedKeyType::VolatileRsa => { @@ -2598,6 +2832,8 @@ impl> Se050Backend { Mechanism::Ed255 => (Kind::Ed255, KeyType::Ed255), Mechanism::X255 => (Kind::X255, KeyType::X255), Mechanism::P256 => (Kind::P256, KeyType::P256), + Mechanism::P384 => (Kind::P384, KeyType::P384), + Mechanism::P521 => (Kind::P521, KeyType::P521), Mechanism::Rsa2048Raw | Mechanism::Rsa2048Pkcs1v15 => { return self.unsafe_inject_volatile_rsa( req, @@ -2715,6 +2951,44 @@ impl> Se050Backend { Error::FunctionFailed })?; } + Mechanism::P384 => { + // TODO: Find a way to get the public key, so that `derive` works + self.se + .run_command( + &WriteEcKey::builder() + .key_type(P1KeyType::Private) + .private_key(&req.raw_key) + .policy(POLICY) + .transient(true) + .curve(EcCurve::NistP384) + .object_id(*id) + .build(), + buf, + ) + .map_err(|_err| { + error!("Failed to inject key: {_err:?}"); + Error::FunctionFailed + })?; + } + Mechanism::P521 => { + // TODO: Find a way to get the public key, so that `derive` works + self.se + .run_command( + &WriteEcKey::builder() + .key_type(P1KeyType::Private) + .private_key(&req.raw_key) + .policy(POLICY) + .transient(true) + .curve(EcCurve::NistP521) + .object_id(*id) + .build(), + buf, + ) + .map_err(|_err| { + error!("Failed to inject key: {_err:?}"); + Error::FunctionFailed + })?; + } _ => unreachable!(), } let exported = self @@ -2860,20 +3134,50 @@ impl> Se050Backend { })?; } Mechanism::P256Prehashed | Mechanism::P256 => { - let private = - p256_cortex_m4::SecretKey::from_bytes(&req.raw_key).map_err(|_| { - debug!("Raw key is invalid"); - Error::InvalidSerializedKey + // TODO: Find a way to get the public key, so that `derive` works + self.se + .run_command( + &WriteEcKey::builder() + .key_type(P1KeyType::Private) + .private_key(&req.raw_key) + .policy(POLICY) + .curve(EcCurve::NistP256) + .object_id(*id) + .build(), + buf, + ) + .map_err(|_err| { + error!("Failed to inject key: {_err:?}"); + Error::FunctionFailed })?; - let public_key = private.public_key().to_uncompressed_sec1_bytes(); + } + Mechanism::P384Prehashed | Mechanism::P384 => { + // TODO: Find a way to get the public key, so that `derive` works + self.se + .run_command( + &WriteEcKey::builder() + .key_type(P1KeyType::Private) + .private_key(&req.raw_key) + .policy(POLICY) + .curve(EcCurve::NistP384) + .object_id(*id) + .build(), + buf, + ) + .map_err(|_err| { + error!("Failed to inject key: {_err:?}"); + Error::FunctionFailed + })?; + } + Mechanism::P521Prehashed | Mechanism::P521 => { + // TODO: Check if public key is required self.se .run_command( &WriteEcKey::builder() .key_type(P1KeyType::KeyPair) .private_key(&req.raw_key) - .public_key(&public_key) .policy(POLICY) - .curve(EcCurve::NistP256) + .curve(EcCurve::NistP521) .object_id(*id) .build(), buf, @@ -2902,6 +3206,8 @@ impl> Se050Backend { // TODO First write curve somehow Mechanism::P256 => KeyType::P256, + Mechanism::P384 => KeyType::P384, + Mechanism::P521 => KeyType::P521, Mechanism::Rsa2048Raw | Mechanism::Rsa2048Pkcs1v15 => KeyType::Rsa2048, Mechanism::Rsa3072Raw | Mechanism::Rsa3072Pkcs1v15 => KeyType::Rsa3072, Mechanism::Rsa4096Raw | Mechanism::Rsa4096Pkcs1v15 => KeyType::Rsa4096, @@ -2922,7 +3228,14 @@ impl> Se050Backend { ) -> Result { match (req.mechanism, req.format) { ( - Mechanism::Ed255 | Mechanism::X255 | Mechanism::P256 | Mechanism::P256Prehashed, + Mechanism::Ed255 + | Mechanism::X255 + | Mechanism::P256 + | Mechanism::P384 + | Mechanism::P521 + | Mechanism::P256Prehashed + | Mechanism::P384Prehashed + | Mechanism::P521Prehashed, KeySerialization::Raw, ) => {} ( @@ -2991,6 +3304,26 @@ fn generate_p256(object_id: ObjectId, transient: bool) -> WriteEcKey<'static> { .build() } +fn generate_p384(object_id: ObjectId, transient: bool) -> WriteEcKey<'static> { + WriteEcKey::builder() + .transient(transient) + .key_type(P1KeyType::KeyPair) + .policy(POLICY) + .object_id(object_id) + .curve(EcCurve::NistP384) + .build() +} + +fn generate_p521(object_id: ObjectId, transient: bool) -> WriteEcKey<'static> { + WriteEcKey::builder() + .transient(transient) + .key_type(P1KeyType::KeyPair) + .policy(POLICY) + .object_id(object_id) + .curve(EcCurve::NistP521) + .build() +} + fn generate_rsa(object_id: ObjectId, size: u16) -> WriteRsaKey<'static> { WriteRsaKey::builder() .key_type(P1KeyType::KeyPair) @@ -3008,6 +3341,10 @@ fn supported(mechanism: Mechanism) -> bool { | Mechanism::X255 | Mechanism::P256 | Mechanism::P256Prehashed + | Mechanism::P384 + | Mechanism::P384Prehashed + | Mechanism::P521 + | Mechanism::P521Prehashed | Mechanism::Rsa2048Raw | Mechanism::Rsa3072Raw | Mechanism::Rsa4096Raw diff --git a/src/core_api/ecdsa_der.rs b/src/core_api/ecdsa_der.rs new file mode 100644 index 0000000..d24f360 --- /dev/null +++ b/src/core_api/ecdsa_der.rs @@ -0,0 +1,39 @@ +use core::iter; +use der::asn1::UintRef; +use der::{Decode, Reader}; + +pub struct DerSignature<'a> { + r: UintRef<'a>, + s: UintRef<'a>, +} + +impl<'a> DerSignature<'a> { + /// Decode the `r` and `s` components of a DER-encoded ECDSA signature. + /// + /// Taken from the `ecdsa` crate to avoid bundling the entire dependency. + pub fn from_der(der_bytes: &'a [u8]) -> der::Result { + let mut reader = der::SliceReader::new(der_bytes)?; + let header = der::Header::decode(&mut reader)?; + header.tag.assert_eq(der::Tag::Sequence)?; + + let ret = reader.read_nested(header.length, |reader| { + let r = UintRef::decode(reader)?; + let s = UintRef::decode(reader)?; + Ok(DerSignature { r, s }) + })?; + + reader.finish(ret) + } + + pub fn to_bytes(&self, field_bytes_size: usize) -> impl Iterator + 'a { + // Required zero padding + let r_begin = field_bytes_size.saturating_sub(self.r.as_bytes().len()); + let s_begin = field_bytes_size.saturating_sub(self.s.as_bytes().len()); + + iter::repeat(0) + .take(r_begin) + .chain(self.r.as_bytes().iter().cloned()) + .chain(iter::repeat(0).take(s_begin)) + .chain(self.s.as_bytes().iter().cloned()) + } +} diff --git a/src/lib.rs b/src/lib.rs index 600f566..61829d1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,7 +10,9 @@ use namespacing::{Namespace, NamespaceValue}; use se05x::{ se05x::{ commands::ReadEcCurveList, - constants::{CurveInitializer, PRIME256V1_INITIALIZER, SECP521R1_INITIALIZER}, + constants::{ + CurveInitializer, PRIME256V1_INITIALIZER, SECP384R1_INITIALIZER, SECP521R1_INITIALIZER, + }, Atr, ObjectId, Se05X, }, t1::I2CForT1, @@ -38,7 +40,7 @@ const BACKEND_DIR: &Path = path!("se050-bak"); pub const GLOBAL_ATTEST_ID: ObjectId = ObjectId(hex!("F0000012")); /// The version to know wether it should be re-configured -pub const SE050_CONFIGURE_VERSION: u32 = 1; +pub const SE050_CONFIGURE_VERSION: u32 = 2; pub enum Se05xLocation { Persistent, @@ -149,7 +151,11 @@ impl> Se050Backend { } } -const REQUIRED_CURVES: &[CurveInitializer] = &[PRIME256V1_INITIALIZER, SECP521R1_INITIALIZER]; +const REQUIRED_CURVES: &[CurveInitializer] = &[ + PRIME256V1_INITIALIZER, + SECP384R1_INITIALIZER, + SECP521R1_INITIALIZER, +]; #[derive(Default, Debug)] pub struct Context { @@ -188,6 +194,14 @@ mod tests { fn backend_version() { // History of previous SE050_CONFIGURE_VERSION and the curves they used let curves_versions: &[(u32, &[_])] = &[ + ( + 2, + &[ + PRIME256V1_INITIALIZER, + SECP384R1_INITIALIZER, + SECP521R1_INITIALIZER, + ], + ), (1, &[PRIME256V1_INITIALIZER, SECP521R1_INITIALIZER]), (0, &[]), ]; diff --git a/src/namespacing.rs b/src/namespacing.rs index 0ae00ed..53881da 100644 --- a/src/namespacing.rs +++ b/src/namespacing.rs @@ -344,6 +344,8 @@ enum_number! { Rsa2048 = 0x4, Rsa3072 = 0x5, Rsa4096 = 0x6, + P384 = 0x7, + P521 = 0x8, } } @@ -353,6 +355,8 @@ impl KeyType { Self::Ed255 => Kind::Ed255, Self::X255 => Kind::X255, Self::P256 => Kind::P256, + Self::P384 => Kind::P384, + Self::P521 => Kind::P521, Self::Rsa2048 => Kind::Rsa2048, Self::Rsa3072 => Kind::Rsa3072, Self::Rsa4096 => Kind::Rsa4096, From 43cd871fde207729262e839024ab1dc8ea3f1ea1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sosth=C3=A8ne=20Gu=C3=A9don?= Date: Tue, 16 Jul 2024 14:56:59 +0200 Subject: [PATCH 2/3] Add brainpool implementations --- Cargo.toml | 2 +- src/core_api.rs | 581 ++++++++++++++++++++++++++++++++++----------- src/lib.rs | 10 +- src/namespacing.rs | 6 + 4 files changed, 457 insertions(+), 142 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index dcbcbe2..cef4c68 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -58,7 +58,7 @@ serde_test = "1.0.176" littlefs2 = { git = "https://github.com/trussed-dev/littlefs2.git", rev = "960e57d9fc0d209308c8e15dc26252bbe1ff6ba8" } apdu-dispatch = { git = "https://github.com/trussed-dev/apdu-dispatch.git", rev = "915fc237103fcecc29d0f0b73391f19abf6576de" } ctaphid-dispatch = { git = "https://github.com/trussed-dev/ctaphid-dispatch.git", rev = "57cb3317878a8593847595319aa03ef17c29ec5b" } -trussed = { git = "https://github.com/nitrokey/trussed.git", rev = "0ccdd468859ea14b43e2e95790b9712c398ae5e1" } +trussed = { git = "https://github.com/nitrokey/trussed.git", rev = "540ad725ef44f0d6d3d2da7dd6ec0bacffaeb5bf" } trussed-auth = { git = "https://github.com/trussed-dev/trussed-auth.git", tag = "v0.3.0"} trussed-manage = { git = "https://github.com/trussed-dev/trussed-staging.git", tag = "manage-v0.1.0" } trussed-rsa-alloc = { git = "https://github.com/trussed-dev/trussed-rsa-backend.git", tag = "v0.2.1" } diff --git a/src/core_api.rs b/src/core_api.rs index 28ac46c..e37c4d7 100644 --- a/src/core_api.rs +++ b/src/core_api.rs @@ -200,6 +200,11 @@ fn prepare_rsa_pkcs1v15(message: &[u8], keysize: usize) -> Result, Er const SERIALIZED_P256_LEN: usize = 64; const SERIALIZED_P384_LEN: usize = 96; const SERIALIZED_P521_LEN: usize = 128; +const SERIALIZED_BRAINPOOL_P256R1_LEN: usize = 64; +const SERIALIZED_BRAINPOOL_P384R1_LEN: usize = 96; +const SERIALIZED_BRAINPOOL_P512R1_LEN: usize = 128; + +const MAX_SERIALIZED_LEN: usize = 128; #[allow(clippy::too_many_arguments)] impl> Se050Backend { @@ -592,6 +597,60 @@ impl> Se050Backend { Ok(reply::DeriveKey { key: result }) } + KeyType::BrainpoolP256R1 => { + let material = self + .se + .run_command(&ReadObject::builder().object_id(key).build(), buf) + .map_err(|_err| { + error!("Failed to read key for derive: {_err:?}"); + Error::FunctionFailed + })?; + + let result = core_keystore.store_key( + req.attributes.persistence, + Secrecy::Public, + Kind::BrainpoolP256R1, + material.data, + )?; + + Ok(reply::DeriveKey { key: result }) + } + KeyType::BrainpoolP384R1 => { + let material = self + .se + .run_command(&ReadObject::builder().object_id(key).build(), buf) + .map_err(|_err| { + error!("Failed to read key for derive: {_err:?}"); + Error::FunctionFailed + })?; + + let result = core_keystore.store_key( + req.attributes.persistence, + Secrecy::Public, + Kind::BrainpoolP384R1, + material.data, + )?; + + Ok(reply::DeriveKey { key: result }) + } + KeyType::BrainpoolP512R1 => { + let material = self + .se + .run_command(&ReadObject::builder().object_id(key).build(), buf) + .map_err(|_err| { + error!("Failed to read key for derive: {_err:?}"); + Error::FunctionFailed + })?; + + let result = core_keystore.store_key( + req.attributes.persistence, + Secrecy::Public, + Kind::BrainpoolP512R1, + material.data, + )?; + + Ok(reply::DeriveKey { key: result }) + } KeyType::Rsa2048 | KeyType::Rsa3072 | KeyType::Rsa4096 => { self.derive_rsa_key(req, key, ty, core_keystore) } @@ -670,6 +729,9 @@ impl> Se050Backend { KeyType::P256 => Kind::P256, KeyType::P384 => Kind::P384, KeyType::P521 => Kind::P521, + KeyType::BrainpoolP256R1 => Kind::BrainpoolP256R1, + KeyType::BrainpoolP384R1 => Kind::BrainpoolP384R1, + KeyType::BrainpoolP512R1 => Kind::BrainpoolP512R1, KeyType::Rsa2048 | KeyType::Rsa3072 | KeyType::Rsa4096 => { unreachable!("Volatile rsa keys are derived in a separate function") } @@ -893,6 +955,9 @@ impl> Se050Backend { Mechanism::P256 => (Kind::P256, KeyType::P256), Mechanism::P384 => (Kind::P384, KeyType::P384), Mechanism::P521 => (Kind::P521, KeyType::P521), + Mechanism::BrainpoolP256R1 => (Kind::BrainpoolP256R1, KeyType::BrainpoolP256R1), + Mechanism::BrainpoolP384R1 => (Kind::BrainpoolP384R1, KeyType::BrainpoolP384R1), + Mechanism::BrainpoolP512R1 => (Kind::BrainpoolP512R1, KeyType::BrainpoolP512R1), Mechanism::Rsa2048Raw | Mechanism::Rsa2048Pkcs1v15 => { return self.generate_volatile_rsa_key( se050_keystore, @@ -965,6 +1030,27 @@ impl> Se050Backend { error!("Failed to generate volatile key: {_err:?}"); Error::FunctionFailed })?, + Mechanism::BrainpoolP256R1 => self + .se + .run_command(&generate_brainpool_p256r1(object_id.0, true), buf) + .map_err(|_err| { + error!("Failed to generate volatile key: {_err:?}"); + Error::FunctionFailed + })?, + Mechanism::BrainpoolP384R1 => self + .se + .run_command(&generate_brainpool_p384r1(object_id.0, true), buf) + .map_err(|_err| { + error!("Failed to generate volatile key: {_err:?}"); + Error::FunctionFailed + })?, + Mechanism::BrainpoolP512R1 => self + .se + .run_command(&generate_brainpool_p512r1(object_id.0, true), buf) + .map_err(|_err| { + error!("Failed to generate volatile key: {_err:?}"); + Error::FunctionFailed + })?, _ => unreachable!(), } let exported = self @@ -1042,6 +1128,30 @@ impl> Se050Backend { Error::FunctionFailed })?, Mechanism::P521Prehashed => return Err(Error::MechanismParamInvalid), + Mechanism::BrainpoolP256R1 => self + .se + .run_command(&generate_brainpool_p256r1(object_id.0, false), buf) + .map_err(|_err| { + error!("Failed to generate brainpool_key: {_err:?}"); + Error::FunctionFailed + })?, + Mechanism::BrainpoolP256R1Prehashed => return Err(Error::MechanismParamInvalid), + Mechanism::BrainpoolP384R1 => self + .se + .run_command(&generate_brainpool_p384r1(object_id.0, false), buf) + .map_err(|_err| { + error!("Failed to generate brainpool_key: {_err:?}"); + Error::FunctionFailed + })?, + Mechanism::BrainpoolP384R1Prehashed => return Err(Error::MechanismParamInvalid), + Mechanism::BrainpoolP512R1 => self + .se + .run_command(&generate_brainpool_p512r1(object_id.0, false), buf) + .map_err(|_err| { + error!("Failed to generate key: {_err:?}"); + Error::FunctionFailed + })?, + Mechanism::BrainpoolP512R1Prehashed => return Err(Error::MechanismParamInvalid), Mechanism::Rsa2048Raw | Mechanism::Rsa2048Pkcs1v15 => self .se .run_command(&generate_rsa(object_id.0, 2048), buf) @@ -1076,6 +1186,9 @@ impl> Se050Backend { Mechanism::P256 => KeyType::P256, Mechanism::P384 => KeyType::P384, Mechanism::P521 => KeyType::P521, + Mechanism::BrainpoolP256R1 => KeyType::BrainpoolP256R1, + Mechanism::BrainpoolP384R1 => KeyType::BrainpoolP384R1, + Mechanism::BrainpoolP512R1 => KeyType::BrainpoolP512R1, Mechanism::Rsa2048Raw | Mechanism::Rsa2048Pkcs1v15 => KeyType::Rsa2048, Mechanism::Rsa3072Raw | Mechanism::Rsa3072Pkcs1v15 => KeyType::Rsa3072, Mechanism::Rsa4096Raw | Mechanism::Rsa4096Pkcs1v15 => KeyType::Rsa4096, @@ -1102,6 +1215,9 @@ impl> Se050Backend { (Mechanism::P256, KeyType::P256) => Kind::P256, (Mechanism::P384, KeyType::P384) => Kind::P384, (Mechanism::P521, KeyType::P521) => Kind::P521, + (Mechanism::BrainpoolP256R1, KeyType::BrainpoolP256R1) => Kind::BrainpoolP256R1, + (Mechanism::BrainpoolP384R1, KeyType::BrainpoolP384R1) => Kind::BrainpoolP384R1, + (Mechanism::BrainpoolP512R1, KeyType::BrainpoolP512R1) => Kind::BrainpoolP512R1, (Mechanism::X255, KeyType::X255) => Kind::X255, _ => return Err(Error::WrongKeyKind), }; @@ -1381,21 +1497,21 @@ impl> Se050Backend { ns: NamespaceValue, ) -> Result { match req.mechanism { - Mechanism::P256 => { - debug!("TODO: Implement P256 without prehashing"); - Err(Error::FunctionNotSupported) - } - Mechanism::P256Prehashed => self.sign_ecdsa(req, se050_keystore, ns), - Mechanism::P384 => { - debug!("TODO: Implement P384 without prehashing"); - Err(Error::FunctionNotSupported) - } - Mechanism::P384Prehashed => self.sign_ecdsa(req, se050_keystore, ns), - Mechanism::P521 => { - debug!("TODO: Implement P521 without prehashing"); + Mechanism::P256 + | Mechanism::P384 + | Mechanism::P521 + | Mechanism::BrainpoolP256R1 + | Mechanism::BrainpoolP384R1 + | Mechanism::BrainpoolP512R1 => { + debug!("TODO: Implement EcDsa without prehashing"); Err(Error::FunctionNotSupported) } - Mechanism::P521Prehashed => self.sign_ecdsa(req, se050_keystore, ns), + Mechanism::P256Prehashed + | Mechanism::P384Prehashed + | Mechanism::P521Prehashed + | Mechanism::BrainpoolP256R1Prehashed + | Mechanism::BrainpoolP384R1Prehashed + | Mechanism::BrainpoolP512R1Prehashed => self.sign_ecdsa(req, se050_keystore, ns), Mechanism::Ed255 => self.sign_eddsa(req, se050_keystore, ns), Mechanism::Rsa2048Pkcs1v15 | Mechanism::Rsa3072Pkcs1v15 @@ -1549,6 +1665,15 @@ impl> Se050Backend { (Mechanism::P521Prehashed, KeyType::P521) => { (Kind::P521, EcDsaSignatureAlgo::Sha512, 66) } + (Mechanism::BrainpoolP256R1Prehashed, KeyType::BrainpoolP256R1) => { + (Kind::BrainpoolP256R1, EcDsaSignatureAlgo::Sha256, 32) + } + (Mechanism::BrainpoolP384R1Prehashed, KeyType::BrainpoolP384R1) => { + (Kind::BrainpoolP384R1, EcDsaSignatureAlgo::Sha384, 48) + } + (Mechanism::BrainpoolP512R1Prehashed, KeyType::BrainpoolP512R1) => { + (Kind::BrainpoolP512R1, EcDsaSignatureAlgo::Sha512, 64) + } _ => return Err(Error::WrongKeyKind), }; @@ -1656,8 +1781,13 @@ impl> Se050Backend { ns: NamespaceValue, ) -> Result { match req.mechanism { - Mechanism::P256 => { - debug!("Implement P256 without prehashing"); + Mechanism::P256 + | Mechanism::P384 + | Mechanism::P521 + | Mechanism::BrainpoolP256R1 + | Mechanism::BrainpoolP384R1 + | Mechanism::BrainpoolP512R1 => { + debug!("Implement EcDSA verification without prehashing"); Err(Error::FunctionNotSupported) } Mechanism::P256Prehashed => self.verify_ecdsa_prehashed( @@ -1668,10 +1798,6 @@ impl> Se050Backend { core_keystore, ns, ), - Mechanism::P384 => { - debug!("Implement P384 without prehashing"); - Err(Error::FunctionNotSupported) - } Mechanism::P384Prehashed => self.verify_ecdsa_prehashed( req, Kind::P384, @@ -1680,10 +1806,6 @@ impl> Se050Backend { core_keystore, ns, ), - Mechanism::P521 => { - debug!("Implement P521 without prehashing"); - Err(Error::FunctionNotSupported) - } Mechanism::P521Prehashed => self.verify_ecdsa_prehashed( req, Kind::P521, @@ -1692,6 +1814,30 @@ impl> Se050Backend { core_keystore, ns, ), + Mechanism::BrainpoolP256R1Prehashed => self.verify_ecdsa_prehashed( + req, + Kind::BrainpoolP256R1, + EcCurve::Brainpool256, + EcDsaSignatureAlgo::Sha256, + core_keystore, + ns, + ), + Mechanism::BrainpoolP384R1Prehashed => self.verify_ecdsa_prehashed( + req, + Kind::BrainpoolP384R1, + EcCurve::Brainpool384, + EcDsaSignatureAlgo::Sha384, + core_keystore, + ns, + ), + Mechanism::BrainpoolP512R1Prehashed => self.verify_ecdsa_prehashed( + req, + Kind::BrainpoolP512R1, + EcCurve::Brainpool512, + EcDsaSignatureAlgo::Sha512, + core_keystore, + ns, + ), Mechanism::Ed255 => { self.verify_eddsa(req, Kind::Ed255, EcCurve::IdEccEd25519, core_keystore, ns) } @@ -1933,6 +2079,9 @@ impl> Se050Backend { Mechanism::P256 => self.deserialize_p256_key(req, core_keystore), Mechanism::P384 => self.deserialize_p384_key(req, core_keystore), Mechanism::P521 => self.deserialize_p521_key(req, core_keystore), + Mechanism::BrainpoolP256R1 => self.deserialize_brainpool_p256r1_key(req, core_keystore), + Mechanism::BrainpoolP384R1 => self.deserialize_brainpool_p384r1_key(req, core_keystore), + Mechanism::BrainpoolP512R1 => self.deserialize_brainpool_p512r1_key(req, core_keystore), Mechanism::X255 => self.deserialize_x255_key(req, core_keystore), Mechanism::Ed255 => self.deserialize_ed255_key(req, core_keystore), Mechanism::Rsa2048Pkcs1v15 => { @@ -1948,62 +2097,51 @@ impl> Se050Backend { } } - fn deserialize_p256_key( + fn deserialize_ec_key( &mut self, req: &request::DeserializeKey, core_keystore: &mut impl Keystore, + kind: Kind, + expected_len: usize, ) -> Result { if req.format != KeySerialization::Raw { - debug!("Unsupported P256 public format: {:?}", req.format); + debug!("Unsupported ECC public format: {:?}", req.format); return Err(Error::FunctionFailed); } - if req.serialized_key.len() != SERIALIZED_P256_LEN { + if req.serialized_key.len() != expected_len { debug!( - "Unsupported P256 public key length: {}", + "Unsupported ECC public key length: {}", req.serialized_key.len() ); return Err(Error::MechanismParamInvalid); } - let mut material = Bytes::<{ SERIALIZED_P256_LEN + 1 }>::new(); + let mut material = Bytes::<{ MAX_SERIALIZED_LEN + 1 }>::new(); material.push(0x04).unwrap(); material.extend_from_slice(&req.serialized_key).unwrap(); let key = core_keystore.store_key( req.attributes.persistence, Secrecy::Public, - Kind::P256, + kind, &material, )?; Ok(reply::DeserializeKey { key }) } - fn deserialize_p384_key( + fn deserialize_p256_key( &mut self, req: &request::DeserializeKey, core_keystore: &mut impl Keystore, ) -> Result { - if req.format != KeySerialization::Raw { - debug!("Unsupported P384 public format: {:?}", req.format); - return Err(Error::FunctionFailed); - } + self.deserialize_ec_key(req, core_keystore, Kind::P256, SERIALIZED_P256_LEN) + } - if req.serialized_key.len() != SERIALIZED_P384_LEN { - debug!( - "Unsupported P384 public key length: {}", - req.serialized_key.len() - ); - return Err(Error::MechanismParamInvalid); - } - let mut material = Bytes::<{ SERIALIZED_P384_LEN + 1 }>::new(); - material.push(0x04).unwrap(); - material.extend_from_slice(&req.serialized_key).unwrap(); - let key = core_keystore.store_key( - req.attributes.persistence, - Secrecy::Public, - Kind::P384, - &material, - )?; - Ok(reply::DeserializeKey { key }) + fn deserialize_p384_key( + &mut self, + req: &request::DeserializeKey, + core_keystore: &mut impl Keystore, + ) -> Result { + self.deserialize_ec_key(req, core_keystore, Kind::P384, SERIALIZED_P384_LEN) } fn deserialize_p521_key( @@ -2011,28 +2149,46 @@ impl> Se050Backend { req: &request::DeserializeKey, core_keystore: &mut impl Keystore, ) -> Result { - if req.format != KeySerialization::Raw { - debug!("Unsupported P521 public format: {:?}", req.format); - return Err(Error::FunctionFailed); - } + self.deserialize_ec_key(req, core_keystore, Kind::P521, SERIALIZED_P521_LEN) + } - if req.serialized_key.len() != SERIALIZED_P521_LEN { - debug!( - "Unsupported P521 public key length: {}", - req.serialized_key.len() - ); - return Err(Error::MechanismParamInvalid); - } - let mut material = Bytes::<{ SERIALIZED_P521_LEN + 1 }>::new(); - material.push(0x04).unwrap(); - material.extend_from_slice(&req.serialized_key).unwrap(); - let key = core_keystore.store_key( - req.attributes.persistence, - Secrecy::Public, - Kind::P521, - &material, - )?; - Ok(reply::DeserializeKey { key }) + fn deserialize_brainpool_p256r1_key( + &mut self, + req: &request::DeserializeKey, + core_keystore: &mut impl Keystore, + ) -> Result { + self.deserialize_ec_key( + req, + core_keystore, + Kind::BrainpoolP256R1, + SERIALIZED_BRAINPOOL_P256R1_LEN, + ) + } + + fn deserialize_brainpool_p384r1_key( + &mut self, + req: &request::DeserializeKey, + core_keystore: &mut impl Keystore, + ) -> Result { + self.deserialize_ec_key( + req, + core_keystore, + Kind::BrainpoolP384R1, + SERIALIZED_BRAINPOOL_P384R1_LEN, + ) + } + + fn deserialize_brainpool_p512r1_key( + &mut self, + req: &request::DeserializeKey, + core_keystore: &mut impl Keystore, + ) -> Result { + self.deserialize_ec_key( + req, + core_keystore, + Kind::BrainpoolP512R1, + SERIALIZED_BRAINPOOL_P512R1_LEN, + ) } fn deserialize_x255_key( @@ -2116,6 +2272,9 @@ impl> Se050Backend { Mechanism::P256 => self.serialize_p256_key(req, core_keystore), Mechanism::P384 => self.serialize_p384_key(req, core_keystore), Mechanism::P521 => self.serialize_p521_key(req, core_keystore), + Mechanism::BrainpoolP256R1 => self.serialize_brainpool_p256r1_key(req, core_keystore), + Mechanism::BrainpoolP384R1 => self.serialize_brainpool_p384r1_key(req, core_keystore), + Mechanism::BrainpoolP512R1 => self.serialize_brainpool_p512r1_key(req, core_keystore), Mechanism::X255 => self.serialize_x255_key(req, core_keystore), Mechanism::Ed255 => self.serialize_ed255_key(req, core_keystore), Mechanism::Rsa2048Pkcs1v15 | Mechanism::Rsa2048Raw => { @@ -2131,68 +2290,86 @@ impl> Se050Backend { } } - fn serialize_p256_key( + fn serialize_ec_key( &mut self, req: &request::SerializeKey, core_keystore: &mut impl Keystore, + kind: Kind, + expected_len: usize, ) -> Result { if req.format != KeySerialization::Raw { - debug!("Unsupported P256 public format: {:?}", req.format); + debug!("Unsupported EC public format: {:?}", req.format); return Err(Error::FunctionFailed); } - let mut data = core_keystore.load_key(Secrecy::Public, Some(Kind::P256), &req.key)?; - if data.material.len() != SERIALIZED_P256_LEN + 1 { - debug!("Incorrect P256 public key length: {}", data.material.len()); + let mut data = core_keystore.load_key(Secrecy::Public, Some(kind), &req.key)?; + if data.material.len() != expected_len + 1 { + debug!("Incorrect EC public key length: {}", data.material.len()); return Err(Error::FunctionFailed); } - data.material.rotate_left(1); - data.material.resize(SERIALIZED_P256_LEN, 0).unwrap(); + data.material.copy_within(1.., 0); + data.material.truncate(expected_len); Ok(reply::SerializeKey { serialized_key: data.material.into(), }) } + + fn serialize_p256_key( + &mut self, + req: &request::SerializeKey, + core_keystore: &mut impl Keystore, + ) -> Result { + self.serialize_ec_key(req, core_keystore, Kind::P256, SERIALIZED_P256_LEN) + } fn serialize_p384_key( &mut self, req: &request::SerializeKey, core_keystore: &mut impl Keystore, ) -> Result { - if req.format != KeySerialization::Raw { - debug!("Unsupported P384 public format: {:?}", req.format); - return Err(Error::FunctionFailed); - } - - let mut data = core_keystore.load_key(Secrecy::Public, Some(Kind::P384), &req.key)?; - if data.material.len() != SERIALIZED_P384_LEN + 1 { - debug!("Incorrect P384 public key length: {}", data.material.len()); - return Err(Error::FunctionFailed); - } - data.material.rotate_left(1); - data.material.resize(SERIALIZED_P384_LEN, 0).unwrap(); - Ok(reply::SerializeKey { - serialized_key: data.material.into(), - }) + self.serialize_ec_key(req, core_keystore, Kind::P384, SERIALIZED_P384_LEN) } fn serialize_p521_key( &mut self, req: &request::SerializeKey, core_keystore: &mut impl Keystore, ) -> Result { - if req.format != KeySerialization::Raw { - debug!("Unsupported P521 public format: {:?}", req.format); - return Err(Error::FunctionFailed); - } - - let mut data = core_keystore.load_key(Secrecy::Public, Some(Kind::P521), &req.key)?; - if data.material.len() != SERIALIZED_P521_LEN + 1 { - debug!("Incorrect P521 public key length: {}", data.material.len()); - return Err(Error::FunctionFailed); - } - data.material.rotate_left(1); - data.material.resize(SERIALIZED_P521_LEN, 0).unwrap(); - Ok(reply::SerializeKey { - serialized_key: data.material.into(), - }) + self.serialize_ec_key(req, core_keystore, Kind::P521, SERIALIZED_P521_LEN) + } + fn serialize_brainpool_p256r1_key( + &mut self, + req: &request::SerializeKey, + core_keystore: &mut impl Keystore, + ) -> Result { + self.serialize_ec_key( + req, + core_keystore, + Kind::BrainpoolP256R1, + SERIALIZED_BRAINPOOL_P256R1_LEN, + ) + } + fn serialize_brainpool_p384r1_key( + &mut self, + req: &request::SerializeKey, + core_keystore: &mut impl Keystore, + ) -> Result { + self.serialize_ec_key( + req, + core_keystore, + Kind::BrainpoolP384R1, + SERIALIZED_BRAINPOOL_P384R1_LEN, + ) + } + fn serialize_brainpool_p512r1_key( + &mut self, + req: &request::SerializeKey, + core_keystore: &mut impl Keystore, + ) -> Result { + self.serialize_ec_key( + req, + core_keystore, + Kind::BrainpoolP512R1, + SERIALIZED_BRAINPOOL_P512R1_LEN, + ) } fn serialize_x255_key( &mut self, @@ -2424,6 +2601,9 @@ impl> Se050Backend { Kind::P256 => KeyType::P256, Kind::P384 => KeyType::P384, Kind::P521 => KeyType::P521, + Kind::BrainpoolP256R1 => KeyType::BrainpoolP256R1, + Kind::BrainpoolP384R1 => KeyType::BrainpoolP384R1, + Kind::BrainpoolP512R1 => KeyType::BrainpoolP512R1, _ => return Err(Error::FunctionFailed), }; let key_id = match ty { @@ -2834,6 +3014,9 @@ impl> Se050Backend { Mechanism::P256 => (Kind::P256, KeyType::P256), Mechanism::P384 => (Kind::P384, KeyType::P384), Mechanism::P521 => (Kind::P521, KeyType::P521), + Mechanism::BrainpoolP256R1 => (Kind::BrainpoolP256R1, KeyType::BrainpoolP256R1), + Mechanism::BrainpoolP384R1 => (Kind::BrainpoolP384R1, KeyType::BrainpoolP384R1), + Mechanism::BrainpoolP512R1 => (Kind::BrainpoolP512R1, KeyType::BrainpoolP512R1), Mechanism::Rsa2048Raw | Mechanism::Rsa2048Pkcs1v15 => { return self.unsafe_inject_volatile_rsa( req, @@ -2989,6 +3172,63 @@ impl> Se050Backend { Error::FunctionFailed })?; } + Mechanism::BrainpoolP256R1 => { + // TODO: Find a way to get the public key, so that `derive` works + self.se + .run_command( + &WriteEcKey::builder() + .key_type(P1KeyType::Private) + .private_key(&req.raw_key) + .policy(POLICY) + .transient(true) + .curve(EcCurve::Brainpool256) + .object_id(*id) + .build(), + buf, + ) + .map_err(|_err| { + error!("Failed to inject key: {_err:?}"); + Error::FunctionFailed + })?; + } + Mechanism::BrainpoolP384R1 => { + // TODO: Find a way to get the public key, so that `derive` works + self.se + .run_command( + &WriteEcKey::builder() + .key_type(P1KeyType::Private) + .private_key(&req.raw_key) + .policy(POLICY) + .transient(true) + .curve(EcCurve::Brainpool384) + .object_id(*id) + .build(), + buf, + ) + .map_err(|_err| { + error!("Failed to inject key: {_err:?}"); + Error::FunctionFailed + })?; + } + Mechanism::BrainpoolP512R1 => { + // TODO: Find a way to get the public key, so that `derive` works + self.se + .run_command( + &WriteEcKey::builder() + .key_type(P1KeyType::Private) + .private_key(&req.raw_key) + .policy(POLICY) + .transient(true) + .curve(EcCurve::Brainpool512) + .object_id(*id) + .build(), + buf, + ) + .map_err(|_err| { + error!("Failed to inject key: {_err:?}"); + Error::FunctionFailed + })?; + } _ => unreachable!(), } let exported = self @@ -3187,6 +3427,60 @@ impl> Se050Backend { Error::FunctionFailed })?; } + Mechanism::BrainpoolP256R1Prehashed | Mechanism::BrainpoolP256R1 => { + // TODO: Find a way to get the public key, so that `derive` works + self.se + .run_command( + &WriteEcKey::builder() + .key_type(P1KeyType::Private) + .private_key(&req.raw_key) + .policy(POLICY) + .curve(EcCurve::Brainpool256) + .object_id(*id) + .build(), + buf, + ) + .map_err(|_err| { + error!("Failed to inject key: {_err:?}"); + Error::FunctionFailed + })?; + } + Mechanism::BrainpoolP384R1Prehashed | Mechanism::BrainpoolP384R1 => { + // TODO: Find a way to get the public key, so that `derive` works + self.se + .run_command( + &WriteEcKey::builder() + .key_type(P1KeyType::Private) + .private_key(&req.raw_key) + .policy(POLICY) + .curve(EcCurve::Brainpool384) + .object_id(*id) + .build(), + buf, + ) + .map_err(|_err| { + error!("Failed to inject key: {_err:?}"); + Error::FunctionFailed + })?; + } + Mechanism::BrainpoolP512R1Prehashed | Mechanism::BrainpoolP512R1 => { + // TODO: Find a way to get the public key, so that `derive` works + self.se + .run_command( + &WriteEcKey::builder() + .key_type(P1KeyType::Private) + .private_key(&req.raw_key) + .policy(POLICY) + .curve(EcCurve::Brainpool512) + .object_id(*id) + .build(), + buf, + ) + .map_err(|_err| { + error!("Failed to inject key: {_err:?}"); + Error::FunctionFailed + })?; + } Mechanism::Rsa2048Raw | Mechanism::Rsa2048Pkcs1v15 => { self.unsafe_inject_persistent_rsa(req, id, 2048)? } @@ -3208,6 +3502,9 @@ impl> Se050Backend { Mechanism::P256 => KeyType::P256, Mechanism::P384 => KeyType::P384, Mechanism::P521 => KeyType::P521, + Mechanism::BrainpoolP256R1 => KeyType::BrainpoolP256R1, + Mechanism::BrainpoolP384R1 => KeyType::BrainpoolP384R1, + Mechanism::BrainpoolP512R1 => KeyType::BrainpoolP512R1, Mechanism::Rsa2048Raw | Mechanism::Rsa2048Pkcs1v15 => KeyType::Rsa2048, Mechanism::Rsa3072Raw | Mechanism::Rsa3072Pkcs1v15 => KeyType::Rsa3072, Mechanism::Rsa4096Raw | Mechanism::Rsa4096Pkcs1v15 => KeyType::Rsa4096, @@ -3235,7 +3532,13 @@ impl> Se050Backend { | Mechanism::P521 | Mechanism::P256Prehashed | Mechanism::P384Prehashed - | Mechanism::P521Prehashed, + | Mechanism::P521Prehashed + | Mechanism::BrainpoolP256R1 + | Mechanism::BrainpoolP384R1 + | Mechanism::BrainpoolP512R1 + | Mechanism::BrainpoolP256R1Prehashed + | Mechanism::BrainpoolP384R1Prehashed + | Mechanism::BrainpoolP512R1Prehashed, KeySerialization::Raw, ) => {} ( @@ -3274,54 +3577,46 @@ const POLICY: PolicySet<'static> = PolicySet(&[Policy { ), }]); -fn generate_ed255(object_id: ObjectId, transient: bool) -> WriteEcKey<'static> { +fn generate_ec_key(object_id: ObjectId, transient: bool, curve: EcCurve) -> WriteEcKey<'static> { WriteEcKey::builder() .transient(transient) .key_type(P1KeyType::KeyPair) .policy(POLICY) .object_id(object_id) - .curve(EcCurve::IdEccEd25519) + .curve(curve) .build() } +fn generate_ed255(object_id: ObjectId, transient: bool) -> WriteEcKey<'static> { + generate_ec_key(object_id, transient, EcCurve::IdEccEd25519) +} + fn generate_x255(object_id: ObjectId, transient: bool) -> WriteEcKey<'static> { - WriteEcKey::builder() - .transient(transient) - .key_type(P1KeyType::KeyPair) - .policy(POLICY) - .object_id(object_id) - .curve(EcCurve::IdEccMontDh25519) - .build() + generate_ec_key(object_id, transient, EcCurve::IdEccMontDh25519) } fn generate_p256(object_id: ObjectId, transient: bool) -> WriteEcKey<'static> { - WriteEcKey::builder() - .transient(transient) - .key_type(P1KeyType::KeyPair) - .policy(POLICY) - .object_id(object_id) - .curve(EcCurve::NistP256) - .build() + generate_ec_key(object_id, transient, EcCurve::NistP256) } fn generate_p384(object_id: ObjectId, transient: bool) -> WriteEcKey<'static> { - WriteEcKey::builder() - .transient(transient) - .key_type(P1KeyType::KeyPair) - .policy(POLICY) - .object_id(object_id) - .curve(EcCurve::NistP384) - .build() + generate_ec_key(object_id, transient, EcCurve::NistP384) } fn generate_p521(object_id: ObjectId, transient: bool) -> WriteEcKey<'static> { - WriteEcKey::builder() - .transient(transient) - .key_type(P1KeyType::KeyPair) - .policy(POLICY) - .object_id(object_id) - .curve(EcCurve::NistP521) - .build() + generate_ec_key(object_id, transient, EcCurve::NistP521) +} + +fn generate_brainpool_p256r1(object_id: ObjectId, transient: bool) -> WriteEcKey<'static> { + generate_ec_key(object_id, transient, EcCurve::Brainpool256) +} + +fn generate_brainpool_p384r1(object_id: ObjectId, transient: bool) -> WriteEcKey<'static> { + generate_ec_key(object_id, transient, EcCurve::Brainpool384) +} + +fn generate_brainpool_p512r1(object_id: ObjectId, transient: bool) -> WriteEcKey<'static> { + generate_ec_key(object_id, transient, EcCurve::Brainpool512) } fn generate_rsa(object_id: ObjectId, size: u16) -> WriteRsaKey<'static> { @@ -3345,6 +3640,12 @@ fn supported(mechanism: Mechanism) -> bool { | Mechanism::P384Prehashed | Mechanism::P521 | Mechanism::P521Prehashed + | Mechanism::BrainpoolP256R1 + | Mechanism::BrainpoolP256R1Prehashed + | Mechanism::BrainpoolP384R1 + | Mechanism::BrainpoolP384R1Prehashed + | Mechanism::BrainpoolP512R1 + | Mechanism::BrainpoolP512R1Prehashed | Mechanism::Rsa2048Raw | Mechanism::Rsa3072Raw | Mechanism::Rsa4096Raw diff --git a/src/lib.rs b/src/lib.rs index 61829d1..6434585 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,7 +11,9 @@ use se05x::{ se05x::{ commands::ReadEcCurveList, constants::{ - CurveInitializer, PRIME256V1_INITIALIZER, SECP384R1_INITIALIZER, SECP521R1_INITIALIZER, + CurveInitializer, BRAINPOOL_P256R1_INITIALIZER, BRAINPOOL_P384R1_INITIALIZER, + BRAINPOOL_P512R1_INITIALIZER, PRIME256V1_INITIALIZER, SECP384R1_INITIALIZER, + SECP521R1_INITIALIZER, }, Atr, ObjectId, Se05X, }, @@ -155,6 +157,9 @@ const REQUIRED_CURVES: &[CurveInitializer] = &[ PRIME256V1_INITIALIZER, SECP384R1_INITIALIZER, SECP521R1_INITIALIZER, + BRAINPOOL_P256R1_INITIALIZER, + BRAINPOOL_P384R1_INITIALIZER, + BRAINPOOL_P512R1_INITIALIZER, ]; #[derive(Default, Debug)] @@ -200,6 +205,9 @@ mod tests { PRIME256V1_INITIALIZER, SECP384R1_INITIALIZER, SECP521R1_INITIALIZER, + BRAINPOOL_P256R1_INITIALIZER, + BRAINPOOL_P384R1_INITIALIZER, + BRAINPOOL_P512R1_INITIALIZER, ], ), (1, &[PRIME256V1_INITIALIZER, SECP521R1_INITIALIZER]), diff --git a/src/namespacing.rs b/src/namespacing.rs index 53881da..b40915c 100644 --- a/src/namespacing.rs +++ b/src/namespacing.rs @@ -346,6 +346,9 @@ enum_number! { Rsa4096 = 0x6, P384 = 0x7, P521 = 0x8, + BrainpoolP256R1 = 0x9, + BrainpoolP384R1 = 0xA, + BrainpoolP512R1 = 0xB, } } @@ -357,6 +360,9 @@ impl KeyType { Self::P256 => Kind::P256, Self::P384 => Kind::P384, Self::P521 => Kind::P521, + Self::BrainpoolP256R1 => Kind::BrainpoolP256R1, + Self::BrainpoolP384R1 => Kind::BrainpoolP384R1, + Self::BrainpoolP512R1 => Kind::BrainpoolP512R1, Self::Rsa2048 => Kind::Rsa2048, Self::Rsa3072 => Kind::Rsa3072, Self::Rsa4096 => Kind::Rsa4096, From c32e0805ec96abfd89635218c19965663d70a733 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sosth=C3=A8ne=20Gu=C3=A9don?= Date: Wed, 17 Jul 2024 12:03:12 +0200 Subject: [PATCH 3/3] Feature-gate large ECC keys --- Cargo.toml | 3 ++ src/core_api.rs | 92 ++++++++++++++++++++++++++++++++++------------ src/namespacing.rs | 12 +++++- 3 files changed, 82 insertions(+), 25 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index cef4c68..47940df 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -74,3 +74,6 @@ log-info = [] log-debug = [] log-warn = [] log-error = [] + +# Support for large ECC keys (brainpool 512 and NIST P521), that do not have functional import/export +large-ecc = [] diff --git a/src/core_api.rs b/src/core_api.rs index e37c4d7..2620205 100644 --- a/src/core_api.rs +++ b/src/core_api.rs @@ -199,9 +199,11 @@ fn prepare_rsa_pkcs1v15(message: &[u8], keysize: usize) -> Result, Er const SERIALIZED_P256_LEN: usize = 64; const SERIALIZED_P384_LEN: usize = 96; +#[cfg(feature = "large-ecc")] const SERIALIZED_P521_LEN: usize = 128; const SERIALIZED_BRAINPOOL_P256R1_LEN: usize = 64; const SERIALIZED_BRAINPOOL_P384R1_LEN: usize = 96; +#[cfg(feature = "large-ecc")] const SERIALIZED_BRAINPOOL_P512R1_LEN: usize = 128; const MAX_SERIALIZED_LEN: usize = 128; @@ -579,6 +581,7 @@ impl> Se050Backend { Ok(reply::DeriveKey { key: result }) } + #[cfg(feature = "large-ecc")] KeyType::P521 => { let material = self .se @@ -633,6 +636,7 @@ impl> Se050Backend { Ok(reply::DeriveKey { key: result }) } + #[cfg(feature = "large-ecc")] KeyType::BrainpoolP512R1 => { let material = self .se @@ -728,9 +732,11 @@ impl> Se050Backend { KeyType::X255 => Kind::X255, KeyType::P256 => Kind::P256, KeyType::P384 => Kind::P384, + #[cfg(feature = "large-ecc")] KeyType::P521 => Kind::P521, KeyType::BrainpoolP256R1 => Kind::BrainpoolP256R1, KeyType::BrainpoolP384R1 => Kind::BrainpoolP384R1, + #[cfg(feature = "large-ecc")] KeyType::BrainpoolP512R1 => Kind::BrainpoolP512R1, KeyType::Rsa2048 | KeyType::Rsa3072 | KeyType::Rsa4096 => { unreachable!("Volatile rsa keys are derived in a separate function") @@ -954,9 +960,11 @@ impl> Se050Backend { Mechanism::X255 => (Kind::X255, KeyType::X255), Mechanism::P256 => (Kind::P256, KeyType::P256), Mechanism::P384 => (Kind::P384, KeyType::P384), + #[cfg(feature = "large-ecc")] Mechanism::P521 => (Kind::P521, KeyType::P521), Mechanism::BrainpoolP256R1 => (Kind::BrainpoolP256R1, KeyType::BrainpoolP256R1), Mechanism::BrainpoolP384R1 => (Kind::BrainpoolP384R1, KeyType::BrainpoolP384R1), + #[cfg(feature = "large-ecc")] Mechanism::BrainpoolP512R1 => (Kind::BrainpoolP512R1, KeyType::BrainpoolP512R1), Mechanism::Rsa2048Raw | Mechanism::Rsa2048Pkcs1v15 => { return self.generate_volatile_rsa_key( @@ -1023,6 +1031,7 @@ impl> Se050Backend { error!("Failed to generate volatile key: {_err:?}"); Error::FunctionFailed })?, + #[cfg(feature = "large-ecc")] Mechanism::P521 => self .se .run_command(&generate_p521(object_id.0, true), buf) @@ -1044,6 +1053,7 @@ impl> Se050Backend { error!("Failed to generate volatile key: {_err:?}"); Error::FunctionFailed })?, + #[cfg(feature = "large-ecc")] Mechanism::BrainpoolP512R1 => self .se .run_command(&generate_brainpool_p512r1(object_id.0, true), buf) @@ -1120,6 +1130,7 @@ impl> Se050Backend { Error::FunctionFailed })?, Mechanism::P384Prehashed => return Err(Error::MechanismParamInvalid), + #[cfg(feature = "large-ecc")] Mechanism::P521 => self .se .run_command(&generate_p521(object_id.0, false), buf) @@ -1127,6 +1138,7 @@ impl> Se050Backend { error!("Failed to generate key: {_err:?}"); Error::FunctionFailed })?, + #[cfg(feature = "large-ecc")] Mechanism::P521Prehashed => return Err(Error::MechanismParamInvalid), Mechanism::BrainpoolP256R1 => self .se @@ -1144,6 +1156,7 @@ impl> Se050Backend { Error::FunctionFailed })?, Mechanism::BrainpoolP384R1Prehashed => return Err(Error::MechanismParamInvalid), + #[cfg(feature = "large-ecc")] Mechanism::BrainpoolP512R1 => self .se .run_command(&generate_brainpool_p512r1(object_id.0, false), buf) @@ -1151,6 +1164,7 @@ impl> Se050Backend { error!("Failed to generate key: {_err:?}"); Error::FunctionFailed })?, + #[cfg(feature = "large-ecc")] Mechanism::BrainpoolP512R1Prehashed => return Err(Error::MechanismParamInvalid), Mechanism::Rsa2048Raw | Mechanism::Rsa2048Pkcs1v15 => self .se @@ -1185,9 +1199,11 @@ impl> Se050Backend { // TODO First write curve somehow Mechanism::P256 => KeyType::P256, Mechanism::P384 => KeyType::P384, + #[cfg(feature = "large-ecc")] Mechanism::P521 => KeyType::P521, Mechanism::BrainpoolP256R1 => KeyType::BrainpoolP256R1, Mechanism::BrainpoolP384R1 => KeyType::BrainpoolP384R1, + #[cfg(feature = "large-ecc")] Mechanism::BrainpoolP512R1 => KeyType::BrainpoolP512R1, Mechanism::Rsa2048Raw | Mechanism::Rsa2048Pkcs1v15 => KeyType::Rsa2048, Mechanism::Rsa3072Raw | Mechanism::Rsa3072Pkcs1v15 => KeyType::Rsa3072, @@ -1214,9 +1230,11 @@ impl> Se050Backend { let kind = match (req.mechanism, priv_parsed_ty) { (Mechanism::P256, KeyType::P256) => Kind::P256, (Mechanism::P384, KeyType::P384) => Kind::P384, + #[cfg(feature = "large-ecc")] (Mechanism::P521, KeyType::P521) => Kind::P521, (Mechanism::BrainpoolP256R1, KeyType::BrainpoolP256R1) => Kind::BrainpoolP256R1, (Mechanism::BrainpoolP384R1, KeyType::BrainpoolP384R1) => Kind::BrainpoolP384R1, + #[cfg(feature = "large-ecc")] (Mechanism::BrainpoolP512R1, KeyType::BrainpoolP512R1) => Kind::BrainpoolP512R1, (Mechanism::X255, KeyType::X255) => Kind::X255, _ => return Err(Error::WrongKeyKind), @@ -1662,6 +1680,7 @@ impl> Se050Backend { (Mechanism::P384Prehashed, KeyType::P384) => { (Kind::P384, EcDsaSignatureAlgo::Sha384, 48) } + #[cfg(feature = "large-ecc")] (Mechanism::P521Prehashed, KeyType::P521) => { (Kind::P521, EcDsaSignatureAlgo::Sha512, 66) } @@ -1671,6 +1690,7 @@ impl> Se050Backend { (Mechanism::BrainpoolP384R1Prehashed, KeyType::BrainpoolP384R1) => { (Kind::BrainpoolP384R1, EcDsaSignatureAlgo::Sha384, 48) } + #[cfg(feature = "large-ecc")] (Mechanism::BrainpoolP512R1Prehashed, KeyType::BrainpoolP512R1) => { (Kind::BrainpoolP512R1, EcDsaSignatureAlgo::Sha512, 64) } @@ -1806,6 +1826,7 @@ impl> Se050Backend { core_keystore, ns, ), + #[cfg(feature = "large-ecc")] Mechanism::P521Prehashed => self.verify_ecdsa_prehashed( req, Kind::P521, @@ -1830,6 +1851,7 @@ impl> Se050Backend { core_keystore, ns, ), + #[cfg(feature = "large-ecc")] Mechanism::BrainpoolP512R1Prehashed => self.verify_ecdsa_prehashed( req, Kind::BrainpoolP512R1, @@ -2078,9 +2100,11 @@ impl> Se050Backend { match req.mechanism { Mechanism::P256 => self.deserialize_p256_key(req, core_keystore), Mechanism::P384 => self.deserialize_p384_key(req, core_keystore), + #[cfg(feature = "large-ecc")] Mechanism::P521 => self.deserialize_p521_key(req, core_keystore), Mechanism::BrainpoolP256R1 => self.deserialize_brainpool_p256r1_key(req, core_keystore), Mechanism::BrainpoolP384R1 => self.deserialize_brainpool_p384r1_key(req, core_keystore), + #[cfg(feature = "large-ecc")] Mechanism::BrainpoolP512R1 => self.deserialize_brainpool_p512r1_key(req, core_keystore), Mechanism::X255 => self.deserialize_x255_key(req, core_keystore), Mechanism::Ed255 => self.deserialize_ed255_key(req, core_keystore), @@ -2144,6 +2168,7 @@ impl> Se050Backend { self.deserialize_ec_key(req, core_keystore, Kind::P384, SERIALIZED_P384_LEN) } + #[cfg(feature = "large-ecc")] fn deserialize_p521_key( &mut self, req: &request::DeserializeKey, @@ -2178,6 +2203,7 @@ impl> Se050Backend { ) } + #[cfg(feature = "large-ecc")] fn deserialize_brainpool_p512r1_key( &mut self, req: &request::DeserializeKey, @@ -2271,9 +2297,11 @@ impl> Se050Backend { match req.mechanism { Mechanism::P256 => self.serialize_p256_key(req, core_keystore), Mechanism::P384 => self.serialize_p384_key(req, core_keystore), + #[cfg(feature = "large-ecc")] Mechanism::P521 => self.serialize_p521_key(req, core_keystore), Mechanism::BrainpoolP256R1 => self.serialize_brainpool_p256r1_key(req, core_keystore), Mechanism::BrainpoolP384R1 => self.serialize_brainpool_p384r1_key(req, core_keystore), + #[cfg(feature = "large-ecc")] Mechanism::BrainpoolP512R1 => self.serialize_brainpool_p512r1_key(req, core_keystore), Mechanism::X255 => self.serialize_x255_key(req, core_keystore), Mechanism::Ed255 => self.serialize_ed255_key(req, core_keystore), @@ -2328,6 +2356,7 @@ impl> Se050Backend { ) -> Result { self.serialize_ec_key(req, core_keystore, Kind::P384, SERIALIZED_P384_LEN) } + #[cfg(feature = "large-ecc")] fn serialize_p521_key( &mut self, req: &request::SerializeKey, @@ -2359,6 +2388,7 @@ impl> Se050Backend { SERIALIZED_BRAINPOOL_P384R1_LEN, ) } + #[cfg(feature = "large-ecc")] fn serialize_brainpool_p512r1_key( &mut self, req: &request::SerializeKey, @@ -2600,9 +2630,11 @@ impl> Se050Backend { Kind::X255 => KeyType::X255, Kind::P256 => KeyType::P256, Kind::P384 => KeyType::P384, + #[cfg(feature = "large-ecc")] Kind::P521 => KeyType::P521, Kind::BrainpoolP256R1 => KeyType::BrainpoolP256R1, Kind::BrainpoolP384R1 => KeyType::BrainpoolP384R1, + #[cfg(feature = "large-ecc")] Kind::BrainpoolP512R1 => KeyType::BrainpoolP512R1, _ => return Err(Error::FunctionFailed), }; @@ -3013,9 +3045,11 @@ impl> Se050Backend { Mechanism::X255 => (Kind::X255, KeyType::X255), Mechanism::P256 => (Kind::P256, KeyType::P256), Mechanism::P384 => (Kind::P384, KeyType::P384), + #[cfg(feature = "large-ecc")] Mechanism::P521 => (Kind::P521, KeyType::P521), Mechanism::BrainpoolP256R1 => (Kind::BrainpoolP256R1, KeyType::BrainpoolP256R1), Mechanism::BrainpoolP384R1 => (Kind::BrainpoolP384R1, KeyType::BrainpoolP384R1), + #[cfg(feature = "large-ecc")] Mechanism::BrainpoolP512R1 => (Kind::BrainpoolP512R1, KeyType::BrainpoolP512R1), Mechanism::Rsa2048Raw | Mechanism::Rsa2048Pkcs1v15 => { return self.unsafe_inject_volatile_rsa( @@ -3153,6 +3187,7 @@ impl> Se050Backend { Error::FunctionFailed })?; } + #[cfg(feature = "large-ecc")] Mechanism::P521 => { // TODO: Find a way to get the public key, so that `derive` works self.se @@ -3210,6 +3245,7 @@ impl> Se050Backend { Error::FunctionFailed })?; } + #[cfg(feature = "large-ecc")] Mechanism::BrainpoolP512R1 => { // TODO: Find a way to get the public key, so that `derive` works self.se @@ -3409,6 +3445,7 @@ impl> Se050Backend { Error::FunctionFailed })?; } + #[cfg(feature = "large-ecc")] Mechanism::P521Prehashed | Mechanism::P521 => { // TODO: Check if public key is required self.se @@ -3463,6 +3500,7 @@ impl> Se050Backend { Error::FunctionFailed })?; } + #[cfg(feature = "large-ecc")] Mechanism::BrainpoolP512R1Prehashed | Mechanism::BrainpoolP512R1 => { // TODO: Find a way to get the public key, so that `derive` works self.se @@ -3501,9 +3539,11 @@ impl> Se050Backend { // TODO First write curve somehow Mechanism::P256 => KeyType::P256, Mechanism::P384 => KeyType::P384, + #[cfg(feature = "large-ecc")] Mechanism::P521 => KeyType::P521, Mechanism::BrainpoolP256R1 => KeyType::BrainpoolP256R1, Mechanism::BrainpoolP384R1 => KeyType::BrainpoolP384R1, + #[cfg(feature = "large-ecc")] Mechanism::BrainpoolP512R1 => KeyType::BrainpoolP512R1, Mechanism::Rsa2048Raw | Mechanism::Rsa2048Pkcs1v15 => KeyType::Rsa2048, Mechanism::Rsa3072Raw | Mechanism::Rsa3072Pkcs1v15 => KeyType::Rsa3072, @@ -3603,6 +3643,7 @@ fn generate_p384(object_id: ObjectId, transient: bool) -> WriteEcKey<'static> { generate_ec_key(object_id, transient, EcCurve::NistP384) } +#[cfg(feature = "large-ecc")] fn generate_p521(object_id: ObjectId, transient: bool) -> WriteEcKey<'static> { generate_ec_key(object_id, transient, EcCurve::NistP521) } @@ -3615,6 +3656,7 @@ fn generate_brainpool_p384r1(object_id: ObjectId, transient: bool) -> WriteEcKey generate_ec_key(object_id, transient, EcCurve::Brainpool384) } +#[cfg(feature = "large-ecc")] fn generate_brainpool_p512r1(object_id: ObjectId, transient: bool) -> WriteEcKey<'static> { generate_ec_key(object_id, transient, EcCurve::Brainpool512) } @@ -3630,29 +3672,33 @@ fn generate_rsa(object_id: ObjectId, size: u16) -> WriteRsaKey<'static> { /// Returns true on mechanisms that are handled by the S050 backend fn supported(mechanism: Mechanism) -> bool { - matches!( - mechanism, - Mechanism::Ed255 - | Mechanism::X255 - | Mechanism::P256 - | Mechanism::P256Prehashed - | Mechanism::P384 - | Mechanism::P384Prehashed - | Mechanism::P521 - | Mechanism::P521Prehashed - | Mechanism::BrainpoolP256R1 - | Mechanism::BrainpoolP256R1Prehashed - | Mechanism::BrainpoolP384R1 - | Mechanism::BrainpoolP384R1Prehashed - | Mechanism::BrainpoolP512R1 - | Mechanism::BrainpoolP512R1Prehashed - | Mechanism::Rsa2048Raw - | Mechanism::Rsa3072Raw - | Mechanism::Rsa4096Raw - | Mechanism::Rsa2048Pkcs1v15 - | Mechanism::Rsa3072Pkcs1v15 - | Mechanism::Rsa4096Pkcs1v15 - ) + let supported = [ + Mechanism::Ed255, + Mechanism::X255, + Mechanism::P256, + Mechanism::P256Prehashed, + Mechanism::P384, + Mechanism::P384Prehashed, + #[cfg(feature = "large-ecc")] + Mechanism::P521, + #[cfg(feature = "large-ecc")] + Mechanism::P521Prehashed, + Mechanism::BrainpoolP256R1, + Mechanism::BrainpoolP256R1Prehashed, + Mechanism::BrainpoolP384R1, + Mechanism::BrainpoolP384R1Prehashed, + #[cfg(feature = "large-ecc")] + Mechanism::BrainpoolP512R1, + #[cfg(feature = "large-ecc")] + Mechanism::BrainpoolP512R1Prehashed, + Mechanism::Rsa2048Raw, + Mechanism::Rsa3072Raw, + Mechanism::Rsa4096Raw, + Mechanism::Rsa2048Pkcs1v15, + Mechanism::Rsa3072Pkcs1v15, + Mechanism::Rsa4096Pkcs1v15, + ]; + supported.contains(&mechanism) } impl> Se050Backend { diff --git a/src/namespacing.rs b/src/namespacing.rs index b40915c..48c0d78 100644 --- a/src/namespacing.rs +++ b/src/namespacing.rs @@ -15,7 +15,7 @@ macro_rules! enum_number { #[repr($repr:tt)] $(#[$outer:meta])* $vis:vis enum $name:ident { - $($(#[$doc:meta])* $var:ident = $num:expr),+ + $($(#[cfg($cfg:meta)])* $(#[doc = $doc:literal])* $var:ident = $num:expr),+ $(,)* } ) => { @@ -23,7 +23,8 @@ macro_rules! enum_number { #[repr($repr)] $vis enum $name { $( - $(#[$doc])* + $(#[cfg($cfg)])* + $(#[doc = $doc])* $var = $num, )* } @@ -33,6 +34,7 @@ macro_rules! enum_number { fn try_from(val:$repr) -> ::core::result::Result { match val { $( + $(#[cfg($cfg)])* $num => Ok($name::$var), )* _ => Err(FromReprError) @@ -44,6 +46,7 @@ macro_rules! enum_number { fn from(value: $name) -> $repr { match value { $( + $(#[cfg($cfg)])* $name::$var => $num, )* } @@ -56,6 +59,7 @@ macro_rules! enum_number { pub const fn all() -> &'static [$name] { &[ $( + $(#[cfg($cfg)])* $name::$var ),* ] @@ -345,9 +349,11 @@ enum_number! { Rsa3072 = 0x5, Rsa4096 = 0x6, P384 = 0x7, + #[cfg(feature = "large-ecc")] P521 = 0x8, BrainpoolP256R1 = 0x9, BrainpoolP384R1 = 0xA, + #[cfg(feature = "large-ecc")] BrainpoolP512R1 = 0xB, } } @@ -359,9 +365,11 @@ impl KeyType { Self::X255 => Kind::X255, Self::P256 => Kind::P256, Self::P384 => Kind::P384, + #[cfg(feature = "large-ecc")] Self::P521 => Kind::P521, Self::BrainpoolP256R1 => Kind::BrainpoolP256R1, Self::BrainpoolP384R1 => Kind::BrainpoolP384R1, + #[cfg(feature = "large-ecc")] Self::BrainpoolP512R1 => Kind::BrainpoolP512R1, Self::Rsa2048 => Kind::Rsa2048, Self::Rsa3072 => Kind::Rsa3072,