diff --git a/sw/device/silicon_creator/lib/ownership/datatypes.h b/sw/device/silicon_creator/lib/ownership/datatypes.h index d849f39ee97e43..88c745d6f2ff0b 100644 --- a/sw/device/silicon_creator/lib/ownership/datatypes.h +++ b/sw/device/silicon_creator/lib/ownership/datatypes.h @@ -17,6 +17,11 @@ extern "C" { #endif // __cplusplus +typedef struct hybrid_key { + ecdsa_p256_public_key_t ecdsa; + sigverify_spx_key_t spx; +} hybrid_key_t; + /** * An owner_key can be either a ECDSA P256 or SPX+ key. The type of the key * material will be determined by a separate field on the owner block @@ -24,6 +29,10 @@ extern "C" { typedef union owner_key { /** ECDSA P256 public key */ ecdsa_p256_public_key_t ecdsa; + /** SPHINCS+ public key */ + sigverify_spx_key_t spx; + /** Hybrid ECDSA & SPHINCS+ public key */ + hybrid_key_t hybrid; /** Enough space to hold an ECDSA key and a SPX+ key for hybrid schemes */ uint32_t raw[16 + 8]; } owner_key_t; @@ -55,10 +64,24 @@ typedef enum ownership_key_alg { kOwnershipKeyAlgRsa = 0x33415352, /** Key algorithm ECDSA P-256: `P256` */ kOwnershipKeyAlgEcdsaP256 = 0x36353250, - /** Key algorithm SPX+: `SPX+` */ - kOwnershipKeyAlgSpx = 0x2b585053, - /** Key algorithm SPX+q20: `Sq20` */ - kOwnershipKeyAlgSpxq20 = 0x30327153, + /** Key algorithm SPX+ Pure: `S+Pu` */ + kOwnershipKeyAlgSpxPure = 0x75502b53, + /** Key algorithm SPX+ Prehashed SHA256: `S+S2` */ + kOwnershipKeyAlgSpxPrehash = 0x32532b53, + /** Key algorithm Hybrid P256 & SPX+ Pure: `H+Pu` */ + kOwnershipKeyAlgHybridSpxPure = 0x75502b48, + /** Key algorithm Hybrid P256 & SPX+ Prehashed SHA256: `H+S2` */ + kOwnershipKeyAlgHybridSpxPrehash = 0x32532b48, + + // Tentative identifiers for SPHINCS+ q20 variants (not yet supported): + // Key algorithm SPX+ Pure: `SqPu` + kOwnershipKeyAlgSq20Pure = 0x75507153, + // Key algorithm SPX+ Prehashed SHA256: `SqS2` + kOwnershipKeyAlgSq20Prehash = 0x32537153, + // Key algorithm Hybrid P256 & SPX+ Pure: `HqPu` + kOwnershipKeyAlgHybridSq20Pure = 0x75507148, + // Key algorithm Hybrid P256 & SPX+ Prehashed SHA256: `HqS2` + kOwnershipKeyAlgHybridSq20Prehash = 0x32537148, } ownership_key_alg_t; typedef enum ownership_update_mode { @@ -224,6 +247,7 @@ typedef struct owner_application_key { sigverify_rsa_key_t rsa; sigverify_spx_key_t spx; ecdsa_p256_public_key_t ecdsa; + hybrid_key_t hybrid; } data; } owner_application_key_t; @@ -242,6 +266,8 @@ enum { offsetof(owner_application_key_t, data) + sizeof(sigverify_spx_key_t), kTlvLenApplicationKeyEcdsa = offsetof(owner_application_key_t, data) + sizeof(ecdsa_p256_public_key_t), + kTlvLenApplicationKeyHybrid = + offsetof(owner_application_key_t, data) + sizeof(hybrid_key_t), }; // clang-format off diff --git a/sw/host/opentitanlib/src/ownership/misc.rs b/sw/host/opentitanlib/src/ownership/misc.rs index e4b9f936df635c..a29bbcff819bcc 100644 --- a/sw/host/opentitanlib/src/ownership/misc.rs +++ b/sw/host/opentitanlib/src/ownership/misc.rs @@ -31,8 +31,10 @@ with_unknown! { Unknown = 0, Rsa = u32::from_le_bytes(*b"RSA3"), EcdsaP256 = u32::from_le_bytes(*b"P256"), - Spx = u32::from_le_bytes(*b"SPX+"), - Spxq20 = u32::from_le_bytes(*b"Sq20"), + SpxPure = u32::from_le_bytes(*b"S+Pu"), + SpxPrehash = u32::from_le_bytes(*b"S+S2"), + HybridSpxPure = u32::from_le_bytes(*b"H+Pu"), + HybridSpxPrehash = u32::from_le_bytes(*b"H+S2"), } } @@ -130,6 +132,31 @@ impl TlvHeader { } } +#[derive(Debug, Serialize, Deserialize)] +pub struct HybridRawPublicKey { + #[serde(deserialize_with = "string_or_struct")] + pub ecdsa: EcdsaRawPublicKey, + #[serde(deserialize_with = "string_or_struct")] + pub spx: SpxRawPublicKey, +} + +impl HybridRawPublicKey { + const SIZE: usize = EcdsaRawPublicKey::SIZE + SpxRawPublicKey::SIZE; + + pub fn read(src: &mut impl Read) -> Result { + Ok(Self { + ecdsa: EcdsaRawPublicKey::read(src)?, + spx: SpxRawPublicKey::read(src)?, + }) + } + + pub fn write(&self, dest: &mut impl Write) -> Result<()> { + self.ecdsa.write(dest)?; + self.spx.write(dest)?; + Ok(()) + } +} + /// Low-level key material (ie: bit representation). #[derive(Debug, Serialize, Deserialize)] #[allow(clippy::len_without_is_empty)] @@ -142,6 +169,8 @@ pub enum KeyMaterial { Rsa(#[serde(deserialize_with = "string_or_struct")] RsaRawPublicKey), #[serde(alias = "spx")] Spx(#[serde(deserialize_with = "string_or_struct")] SpxRawPublicKey), + #[serde(alias = "hybrid")] + Hybrid(HybridRawPublicKey), } impl Default for KeyMaterial { @@ -156,6 +185,7 @@ impl KeyMaterial { KeyMaterial::Ecdsa(_) => EcdsaRawPublicKey::SIZE, KeyMaterial::Rsa(_) => RsaRawPublicKey::SIZE, KeyMaterial::Spx(_) => SpxRawPublicKey::SIZE, + KeyMaterial::Hybrid(_) => HybridRawPublicKey::SIZE, KeyMaterial::Unknown(u) => u.len(), } } @@ -164,7 +194,8 @@ impl KeyMaterial { match self { KeyMaterial::Ecdsa(_) => OwnershipKeyAlg::EcdsaP256, KeyMaterial::Rsa(_) => OwnershipKeyAlg::Rsa, - KeyMaterial::Spx(_) => OwnershipKeyAlg::Spx, + KeyMaterial::Spx(_) => OwnershipKeyAlg::SpxPure, + KeyMaterial::Hybrid(_) => OwnershipKeyAlg::HybridSpxPure, KeyMaterial::Unknown(_) => OwnershipKeyAlg::Unknown, } } @@ -173,9 +204,12 @@ impl KeyMaterial { let result = match kind { OwnershipKeyAlg::Rsa => KeyMaterial::Rsa(RsaRawPublicKey::read(src)?), OwnershipKeyAlg::EcdsaP256 => KeyMaterial::Ecdsa(EcdsaRawPublicKey::read(src)?), - OwnershipKeyAlg::Spx | OwnershipKeyAlg::Spxq20 => { + OwnershipKeyAlg::SpxPure | OwnershipKeyAlg::SpxPrehash => { KeyMaterial::Spx(SpxRawPublicKey::read(src)?) } + OwnershipKeyAlg::HybridSpxPure | OwnershipKeyAlg::HybridSpxPrehash => { + KeyMaterial::Hybrid(HybridRawPublicKey::read(src)?) + } _ => { return Err( Error::InvalidPublicKey(anyhow!("Unknown key algorithm {}", kind)).into(), @@ -208,6 +242,7 @@ impl KeyMaterial { KeyMaterial::Ecdsa(k) => k.write(dest)?, KeyMaterial::Rsa(k) => k.write(dest)?, KeyMaterial::Spx(k) => k.write(dest)?, + KeyMaterial::Hybrid(k) => k.write(dest)?, _ => { return Err(Error::InvalidPublicKey(anyhow!("Unknown key type")).into()); }