Skip to content

Commit

Permalink
Add support for secp256k1
Browse files Browse the repository at this point in the history
  • Loading branch information
sosthene-nitrokey committed Oct 22, 2024
1 parent cac4bd1 commit d059690
Show file tree
Hide file tree
Showing 4 changed files with 165 additions and 10 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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 = "540ad725ef44f0d6d3d2da7dd6ec0bacffaeb5bf" }
trussed = { git = "https://github.com/trussed-dev/trussed.git", rev = "cc9d367ffa76668e9419ad8a0c04a92903936efb" }
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" }
Expand Down
152 changes: 146 additions & 6 deletions src/core_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ const SERIALIZED_P521_LEN: usize = 132;
const SERIALIZED_BRAINPOOL_P256R1_LEN: usize = 64;
const SERIALIZED_BRAINPOOL_P384R1_LEN: usize = 96;
const SERIALIZED_BRAINPOOL_P512R1_LEN: usize = 128;
const SERIALIZED_SECP256K1_LEN: usize = 64;

const MAX_SERIALIZED_LEN: usize = 132;

Expand Down Expand Up @@ -453,7 +454,12 @@ impl<Twi: I2CForT1, D: DelayUs<u32>> Se050Backend<Twi, D> {
obj: ObjectId,
) -> Result<(), Error> {
let buf = &mut [0; 128];
let material = se050_keystore.load_key(Secrecy::Secret, Some(kind), &key)?;
debug_now!("Reimporting");
let material = se050_keystore
.load_key(Secrecy::Secret, Some(kind), &key)
.inspect_err(|_err| {
error_now!("Failed reimport: {_err:?}");
})?;
let parsed: VolatileKeyMaterialRef = trussed::cbor_deserialize(&material.material)
.map_err(|_err| {
error!("Failed to parsed volatile key data: {_err:?}");
Expand Down Expand Up @@ -483,6 +489,7 @@ impl<Twi: I2CForT1, D: DelayUs<u32>> Se050Backend<Twi, D> {
Kind::BrainpoolP256R1 => (EcCurve::Brainpool256, Some([0; 32].as_slice())),
Kind::BrainpoolP384R1 => (EcCurve::Brainpool384, Some([0; 48].as_slice())),
Kind::BrainpoolP512R1 => (EcCurve::Brainpool512, Some([0; 64].as_slice())),
Kind::Secp256k1 => (EcCurve::Secp256k1, Some([0; 32].as_slice())),
_ => unreachable!(),
};
let key_type = if parsed.is_only_private {
Expand Down Expand Up @@ -566,6 +573,7 @@ impl<Twi: I2CForT1, D: DelayUs<u32>> Se050Backend<Twi, D> {
ty: KeyType,
) -> Result<reply::DeriveKey, Error> {
let buf = &mut [0; 1024];
debug_now!("Deriving key for ty: {ty:?}");
match ty {
KeyType::Ed255 => {
let material = self
Expand Down Expand Up @@ -711,6 +719,28 @@ impl<Twi: I2CForT1, D: DelayUs<u32>> Se050Backend<Twi, D> {

Ok(reply::DeriveKey { key: result })
}
KeyType::Secp256k1 => {
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
})?;

debug_now!("Read public key");

let result = core_keystore.store_key(
req.attributes.persistence,
Secrecy::Public,
Kind::Secp256k1,
material.data,
)?;

debug_now!("Stored public key");

Ok(reply::DeriveKey { key: result })
}
KeyType::Rsa2048 | KeyType::Rsa3072 | KeyType::Rsa4096 => {
self.derive_rsa_key(req, key, ty, core_keystore)
}
Expand Down Expand Up @@ -802,6 +832,7 @@ impl<Twi: I2CForT1, D: DelayUs<u32>> Se050Backend<Twi, D> {
KeyType::BrainpoolP256R1 => Kind::BrainpoolP256R1,
KeyType::BrainpoolP384R1 => Kind::BrainpoolP384R1,
KeyType::BrainpoolP512R1 => Kind::BrainpoolP512R1,
KeyType::Secp256k1 => Kind::Secp256k1,
KeyType::Rsa2048 | KeyType::Rsa3072 | KeyType::Rsa4096 => {
unreachable!("Volatile rsa keys are derived in a separate function")
}
Expand Down Expand Up @@ -1027,6 +1058,7 @@ impl<Twi: I2CForT1, D: DelayUs<u32>> Se050Backend<Twi, D> {
Mechanism::BrainpoolP256R1 => (Kind::BrainpoolP256R1, KeyType::BrainpoolP256R1),
Mechanism::BrainpoolP384R1 => (Kind::BrainpoolP384R1, KeyType::BrainpoolP384R1),
Mechanism::BrainpoolP512R1 => (Kind::BrainpoolP512R1, KeyType::BrainpoolP512R1),
Mechanism::Secp256k1 => (Kind::Secp256k1, KeyType::Secp256k1),
Mechanism::Rsa2048Raw | Mechanism::Rsa2048Pkcs1v15 => {
return self.generate_volatile_rsa_key(
se050_keystore,
Expand Down Expand Up @@ -1120,8 +1152,16 @@ impl<Twi: I2CForT1, D: DelayUs<u32>> Se050Backend<Twi, D> {
error!("Failed to generate volatile key: {_err:?}");
Error::FunctionFailed
})?,
Mechanism::Secp256k1 => self
.se
.run_command(&generate_secp256k1(object_id.0, true), buf)
.map_err(|_err| {
error!("Failed to generate volatile key: {_err:?}");
Error::FunctionFailed
})?,
_ => unreachable!(),
}
debug_now!("Generated key for mechanism: {:?}", req.mechanism);
let exported = self
.se
.run_command(&ExportObject::builder().object_id(object_id.0).build(), buf)
Expand Down Expand Up @@ -1221,6 +1261,14 @@ impl<Twi: I2CForT1, D: DelayUs<u32>> Se050Backend<Twi, D> {
Error::FunctionFailed
})?,
Mechanism::BrainpoolP512R1Prehashed => return Err(Error::MechanismParamInvalid),
Mechanism::Secp256k1 => self
.se
.run_command(&generate_secp256k1(object_id.0, false), buf)
.map_err(|_err| {
error!("Failed to generate key: {_err:?}");
Error::FunctionFailed
})?,
Mechanism::Secp256k1Prehashed => return Err(Error::MechanismParamInvalid),
Mechanism::Rsa2048Raw | Mechanism::Rsa2048Pkcs1v15 => self
.se
.run_command(&generate_rsa(object_id.0, 2048), buf)
Expand Down Expand Up @@ -1258,6 +1306,7 @@ impl<Twi: I2CForT1, D: DelayUs<u32>> Se050Backend<Twi, D> {
Mechanism::BrainpoolP256R1 => KeyType::BrainpoolP256R1,
Mechanism::BrainpoolP384R1 => KeyType::BrainpoolP384R1,
Mechanism::BrainpoolP512R1 => KeyType::BrainpoolP512R1,
Mechanism::Secp256k1 => KeyType::Secp256k1,
Mechanism::Rsa2048Raw | Mechanism::Rsa2048Pkcs1v15 => KeyType::Rsa2048,
Mechanism::Rsa3072Raw | Mechanism::Rsa3072Pkcs1v15 => KeyType::Rsa3072,
Mechanism::Rsa4096Raw | Mechanism::Rsa4096Pkcs1v15 => KeyType::Rsa4096,
Expand Down Expand Up @@ -1287,6 +1336,7 @@ impl<Twi: I2CForT1, D: DelayUs<u32>> Se050Backend<Twi, D> {
(Mechanism::BrainpoolP256R1, KeyType::BrainpoolP256R1) => Kind::BrainpoolP256R1,
(Mechanism::BrainpoolP384R1, KeyType::BrainpoolP384R1) => Kind::BrainpoolP384R1,
(Mechanism::BrainpoolP512R1, KeyType::BrainpoolP512R1) => Kind::BrainpoolP512R1,
(Mechanism::Secp256k1, KeyType::Secp256k1) => Kind::Secp256k1,
(Mechanism::X255, KeyType::X255) => Kind::X255,
_ => return Err(Error::WrongKeyKind),
};
Expand Down Expand Up @@ -1574,7 +1624,8 @@ impl<Twi: I2CForT1, D: DelayUs<u32>> Se050Backend<Twi, D> {
| Mechanism::P521
| Mechanism::BrainpoolP256R1
| Mechanism::BrainpoolP384R1
| Mechanism::BrainpoolP512R1 => {
| Mechanism::BrainpoolP512R1
| Mechanism::Secp256k1 => {
debug!("TODO: Implement EcDsa without prehashing");
Err(Error::FunctionNotSupported)
}
Expand All @@ -1583,7 +1634,8 @@ impl<Twi: I2CForT1, D: DelayUs<u32>> Se050Backend<Twi, D> {
| Mechanism::P521Prehashed
| Mechanism::BrainpoolP256R1Prehashed
| Mechanism::BrainpoolP384R1Prehashed
| Mechanism::BrainpoolP512R1Prehashed => self.sign_ecdsa(req, se050_keystore, ns),
| Mechanism::BrainpoolP512R1Prehashed
| Mechanism::Secp256k1Prehashed => self.sign_ecdsa(req, se050_keystore, ns),
Mechanism::Ed255 => self.sign_eddsa(req, se050_keystore, ns),
Mechanism::Rsa2048Pkcs1v15
| Mechanism::Rsa3072Pkcs1v15
Expand Down Expand Up @@ -1746,6 +1798,9 @@ impl<Twi: I2CForT1, D: DelayUs<u32>> Se050Backend<Twi, D> {
(Mechanism::BrainpoolP512R1Prehashed, KeyType::BrainpoolP512R1) => {
(Kind::BrainpoolP512R1, EcDsaSignatureAlgo::Sha512, 64)
}
(Mechanism::Secp256k1Prehashed, KeyType::Secp256k1) => {
(Kind::Secp256k1, EcDsaSignatureAlgo::Sha256, 64)
}
_ => return Err(Error::WrongKeyKind),
};

Expand Down Expand Up @@ -1774,7 +1829,7 @@ impl<Twi: I2CForT1, D: DelayUs<u32>> Se050Backend<Twi, D> {
buf,
)
.map_err(|_err| {
error!("Failed to perform agree: {_err:?}");
error!("Failed to perform ecdsa signature: {_err:?}");
Error::FunctionFailed
})?;

Expand Down Expand Up @@ -1841,7 +1896,7 @@ impl<Twi: I2CForT1, D: DelayUs<u32>> Se050Backend<Twi, D> {
buf,
)
.map_err(|_err| {
error!("Failed to perform agree: {_err:?}");
error!("Failed to perform Eddsa signature: {_err:?}");
Error::FunctionFailed
})?;

Expand Down Expand Up @@ -1875,7 +1930,8 @@ impl<Twi: I2CForT1, D: DelayUs<u32>> Se050Backend<Twi, D> {
| Mechanism::P521
| Mechanism::BrainpoolP256R1
| Mechanism::BrainpoolP384R1
| Mechanism::BrainpoolP512R1 => {
| Mechanism::BrainpoolP512R1
| Mechanism::Secp256k1 => {
debug!("Implement EcDSA verification without prehashing");
Err(Error::FunctionNotSupported)
}
Expand Down Expand Up @@ -1927,6 +1983,14 @@ impl<Twi: I2CForT1, D: DelayUs<u32>> Se050Backend<Twi, D> {
core_keystore,
ns,
),
Mechanism::Secp256k1Prehashed => self.verify_ecdsa_prehashed(
req,
Kind::Secp256k1,
EcCurve::Secp256k1,
EcDsaSignatureAlgo::Sha256,
core_keystore,
ns,
),
Mechanism::Ed255 => {
self.verify_eddsa(req, Kind::Ed255, EcCurve::IdEccEd25519, core_keystore, ns)
}
Expand Down Expand Up @@ -2168,6 +2232,7 @@ impl<Twi: I2CForT1, D: DelayUs<u32>> Se050Backend<Twi, D> {
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::Secp256k1 => self.deserialize_secp256k1_key(req, core_keystore),
Mechanism::X255 => self.deserialize_x255_key(req, core_keystore),
Mechanism::Ed255 => self.deserialize_ed255_key(req, core_keystore),
Mechanism::Rsa2048Pkcs1v15 => {
Expand Down Expand Up @@ -2277,6 +2342,19 @@ impl<Twi: I2CForT1, D: DelayUs<u32>> Se050Backend<Twi, D> {
)
}

fn deserialize_secp256k1_key(
&mut self,
req: &request::DeserializeKey,
core_keystore: &mut impl Keystore,
) -> Result<reply::DeserializeKey, Error> {
self.deserialize_ec_key(
req,
core_keystore,
Kind::Secp256k1,
SERIALIZED_SECP256K1_LEN,
)
}

fn deserialize_x255_key(
&mut self,
req: &request::DeserializeKey,
Expand Down Expand Up @@ -2361,6 +2439,7 @@ impl<Twi: I2CForT1, D: DelayUs<u32>> Se050Backend<Twi, D> {
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::Secp256k1 => self.serialize_secp256k1_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 => {
Expand Down Expand Up @@ -2457,6 +2536,18 @@ impl<Twi: I2CForT1, D: DelayUs<u32>> Se050Backend<Twi, D> {
SERIALIZED_BRAINPOOL_P512R1_LEN,
)
}
fn serialize_secp256k1_key(
&mut self,
req: &request::SerializeKey,
core_keystore: &mut impl Keystore,
) -> Result<reply::SerializeKey, Error> {
self.serialize_ec_key(
req,
core_keystore,
Kind::Secp256k1,
SERIALIZED_SECP256K1_LEN,
)
}
fn serialize_x255_key(
&mut self,
req: &request::SerializeKey,
Expand Down Expand Up @@ -2715,6 +2806,7 @@ impl<Twi: I2CForT1, D: DelayUs<u32>> Se050Backend<Twi, D> {
Kind::BrainpoolP256R1 => KeyType::BrainpoolP256R1,
Kind::BrainpoolP384R1 => KeyType::BrainpoolP384R1,
Kind::BrainpoolP512R1 => KeyType::BrainpoolP512R1,
Kind::Secp256k1 => KeyType::Secp256k1,
_ => return Err(Error::FunctionFailed),
};
let key_id = match ty {
Expand Down Expand Up @@ -3127,6 +3219,7 @@ impl<Twi: I2CForT1, D: DelayUs<u32>> Se050Backend<Twi, D> {
Mechanism::BrainpoolP256R1 => (Kind::BrainpoolP256R1, KeyType::BrainpoolP256R1),
Mechanism::BrainpoolP384R1 => (Kind::BrainpoolP384R1, KeyType::BrainpoolP384R1),
Mechanism::BrainpoolP512R1 => (Kind::BrainpoolP512R1, KeyType::BrainpoolP512R1),
Mechanism::Secp256k1 => (Kind::Secp256k1, KeyType::Secp256k1),
Mechanism::Rsa2048Raw | Mechanism::Rsa2048Pkcs1v15 => {
return self.unsafe_inject_volatile_rsa(
req,
Expand Down Expand Up @@ -3348,6 +3441,26 @@ impl<Twi: I2CForT1, D: DelayUs<u32>> Se050Backend<Twi, D> {
Error::FunctionFailed
})?;
}
Mechanism::Secp256k1 => {
// TODO: Find a way to get the public key, so that `derive` works
key_type = P1KeyType::Private;
self.se
.run_command(
&WriteEcKey::builder()
.key_type(key_type)
.private_key(&req.raw_key)
.policy(POLICY)
.transient(true)
.curve(EcCurve::Secp256k1)
.object_id(*id)
.build(),
buf,
)
.map_err(|_err| {
error!("Failed to inject key: {_err:?}");
Error::FunctionFailed
})?;
}
_ => unreachable!(),
};
let exported = self
Expand Down Expand Up @@ -3601,6 +3714,24 @@ impl<Twi: I2CForT1, D: DelayUs<u32>> Se050Backend<Twi, D> {
Error::FunctionFailed
})?;
}
Mechanism::Secp256k1Prehashed | Mechanism::Secp256k1 => {
// 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::Secp256k1)
.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)?
}
Expand All @@ -3625,6 +3756,7 @@ impl<Twi: I2CForT1, D: DelayUs<u32>> Se050Backend<Twi, D> {
Mechanism::BrainpoolP256R1 => KeyType::BrainpoolP256R1,
Mechanism::BrainpoolP384R1 => KeyType::BrainpoolP384R1,
Mechanism::BrainpoolP512R1 => KeyType::BrainpoolP512R1,
Mechanism::Secp256k1 => KeyType::Secp256k1,
Mechanism::Rsa2048Raw | Mechanism::Rsa2048Pkcs1v15 => KeyType::Rsa2048,
Mechanism::Rsa3072Raw | Mechanism::Rsa3072Pkcs1v15 => KeyType::Rsa3072,
Mechanism::Rsa4096Raw | Mechanism::Rsa4096Pkcs1v15 => KeyType::Rsa4096,
Expand Down Expand Up @@ -3653,6 +3785,8 @@ impl<Twi: I2CForT1, D: DelayUs<u32>> Se050Backend<Twi, D> {
| Mechanism::P256Prehashed
| Mechanism::P384Prehashed
| Mechanism::P521Prehashed
| Mechanism::Secp256k1
| Mechanism::Secp256k1Prehashed
| Mechanism::BrainpoolP256R1
| Mechanism::BrainpoolP384R1
| Mechanism::BrainpoolP512R1
Expand Down Expand Up @@ -3739,6 +3873,10 @@ fn generate_brainpool_p512r1(object_id: ObjectId, transient: bool) -> WriteEcKey
generate_ec_key(object_id, transient, EcCurve::Brainpool512)
}

fn generate_secp256k1(object_id: ObjectId, transient: bool) -> WriteEcKey<'static> {
generate_ec_key(object_id, transient, EcCurve::Secp256k1)
}

fn generate_rsa(object_id: ObjectId, size: u16) -> WriteRsaKey<'static> {
WriteRsaKey::builder()
.key_type(P1KeyType::KeyPair)
Expand All @@ -3765,6 +3903,8 @@ fn supported(mechanism: Mechanism) -> bool {
Mechanism::BrainpoolP384R1Prehashed,
Mechanism::BrainpoolP512R1,
Mechanism::BrainpoolP512R1Prehashed,
Mechanism::Secp256k1,
Mechanism::Secp256k1Prehashed,
Mechanism::Rsa2048Raw,
Mechanism::Rsa3072Raw,
Mechanism::Rsa4096Raw,
Expand Down
Loading

0 comments on commit d059690

Please sign in to comment.