diff --git a/Cargo.lock b/Cargo.lock index 33f6853d..7f92bb31 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -101,9 +101,9 @@ dependencies = [ [[package]] name = "der" -version = "0.7.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc302fd9b18d66834a6f092d10ea85489c0ca8ad6b7304092135fab171d853cd" +checksum = "19c5cb402c5c958281c7c0702edea7b780d03b86b606497ca3a10fcd3fc393ac" dependencies = [ "const-oid", "pem-rfc7468", @@ -268,9 +268,9 @@ dependencies = [ [[package]] name = "pkcs1" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "178ba28ece1961eafdff1991bd1744c29564cbab5d803f3ccb4a4895a6c550a7" +checksum = "575fd6eebed721a2929faa1ee1383a49788378083bbbd7f299af75dd84195cee" dependencies = [ "der", "pkcs8", @@ -295,9 +295,9 @@ dependencies = [ [[package]] name = "pkcs8" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d2820d87d2b008616e5c27212dd9e0e694fb4c6b522de06094106813328cb49" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" dependencies = [ "der", "pkcs5", @@ -374,6 +374,7 @@ version = "0.9.0-pre.0" dependencies = [ "base64ct", "byteorder", + "const-oid", "digest", "hex-literal", "num-bigint-dig", @@ -501,9 +502,9 @@ checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" [[package]] name = "spki" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0445c905640145c7ea8c1993555957f65e7c46d0535b91ba501bc9bfc85522f" +checksum = "37a5be806ab6f127c3da44b7378837ebf01dadca8510a0e572460216b228bd0e" dependencies = [ "base64ct", "der", diff --git a/Cargo.toml b/Cargo.toml index e8a05d9e..51fefdf5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,15 +19,19 @@ num-integer = { version = "0.1.39", default-features = false } num-iter = { version = "0.1.37", default-features = false } rand_core = { version = "0.6.4", default-features = false } byteorder = { version = "1.3.1", default-features = false } +const-oid = { version = "0.9", default-features = false } subtle = { version = "2.1.1", default-features = false } digest = { version = "0.10.5", default-features = false, features = ["alloc", "oid"] } -pkcs1 = { version = "0.7.1", default-features = false, features = ["alloc", "pkcs8"] } -pkcs8 = { version = "0.10", default-features = false, features = ["alloc"] } -serde = { version = "1.0.103", optional = true, default-features = false, features = ["derive"] } -sha2 = { version = "0.10.6", optional = true, default-features = false, features = ["oid"] } +pkcs1 = { version = "0.7.2", default-features = false, features = ["alloc", "pkcs8"] } +pkcs8 = { version = "0.10.2", default-features = false, features = ["alloc"] } signature = { version = "2", default-features = false , features = ["digest", "rand_core"] } zeroize = { version = "1", features = ["alloc"] } +# optional dependencies +serde = { version = "1.0.103", optional = true, default-features = false, features = ["derive"] } +sha1 = { version = "0.10.5", optional = true, default-features = false, features = ["oid"] } +sha2 = { version = "0.10.6", optional = true, default-features = false, features = ["oid"] } + [dev-dependencies] base64ct = { version = "1", features = ["alloc"] } hex-literal = "0.3.3" diff --git a/src/pkcs1v15.rs b/src/pkcs1v15.rs index 5d9bac41..30d29df2 100644 --- a/src/pkcs1v15.rs +++ b/src/pkcs1v15.rs @@ -11,7 +11,13 @@ use alloc::vec::Vec; use core::fmt::{Debug, Display, Formatter, LowerHex, UpperHex}; use core::marker::PhantomData; use digest::Digest; -use pkcs8::{AssociatedOid, Document, EncodePrivateKey, EncodePublicKey, SecretDocument}; +use pkcs8::{ + spki::{ + der::AnyRef, AlgorithmIdentifierRef, AssociatedAlgorithmIdentifier, + SignatureAlgorithmIdentifier, + }, + AssociatedOid, Document, EncodePrivateKey, EncodePublicKey, SecretDocument, +}; use rand_core::CryptoRngCore; use signature::{ hazmat::{PrehashSigner, PrehashVerifier}, @@ -436,6 +442,28 @@ where } } +impl AssociatedAlgorithmIdentifier for SigningKey +where + D: Digest, +{ + type Params = AnyRef<'static>; + + const ALGORITHM_IDENTIFIER: AlgorithmIdentifierRef<'static> = pkcs1::ALGORITHM_ID; +} + +impl SignatureAlgorithmIdentifier for SigningKey +where + D: Digest + oid::RsaSignatureAssociatedOid, +{ + type Params = AnyRef<'static>; + + const SIGNATURE_ALGORITHM_IDENTIFIER: AlgorithmIdentifierRef<'static> = + AlgorithmIdentifierRef { + oid: D::OID, + parameters: Some(AnyRef::NULL), + }; +} + impl From for SigningKey where D: Digest, @@ -606,6 +634,28 @@ where } } +impl AssociatedAlgorithmIdentifier for VerifyingKey +where + D: Digest, +{ + type Params = AnyRef<'static>; + + const ALGORITHM_IDENTIFIER: AlgorithmIdentifierRef<'static> = pkcs1::ALGORITHM_ID; +} + +impl SignatureAlgorithmIdentifier for VerifyingKey +where + D: Digest + oid::RsaSignatureAssociatedOid, +{ + type Params = AnyRef<'static>; + + const SIGNATURE_ALGORITHM_IDENTIFIER: AlgorithmIdentifierRef<'static> = + AlgorithmIdentifierRef { + oid: D::OID, + parameters: Some(AnyRef::NULL), + }; +} + impl From for VerifyingKey where D: Digest, @@ -774,6 +824,46 @@ impl EncryptingKeypair for DecryptingKey { } } +mod oid { + use const_oid::ObjectIdentifier; + + /// A trait which associates an RSA-specific OID with a type. + pub(crate) trait RsaSignatureAssociatedOid { + /// The OID associated with this type. + const OID: ObjectIdentifier; + } + + #[cfg(feature = "sha1")] + impl RsaSignatureAssociatedOid for sha1::Sha1 { + const OID: ObjectIdentifier = + const_oid::ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.5"); + } + + #[cfg(feature = "sha2")] + impl RsaSignatureAssociatedOid for sha2::Sha224 { + const OID: ObjectIdentifier = + const_oid::ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.14"); + } + + #[cfg(feature = "sha2")] + impl RsaSignatureAssociatedOid for sha2::Sha256 { + const OID: ObjectIdentifier = + const_oid::ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.11"); + } + + #[cfg(feature = "sha2")] + impl RsaSignatureAssociatedOid for sha2::Sha384 { + const OID: ObjectIdentifier = + const_oid::ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.12"); + } + + #[cfg(feature = "sha2")] + impl RsaSignatureAssociatedOid for sha2::Sha512 { + const OID: ObjectIdentifier = + const_oid::ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.13"); + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/src/pss.rs b/src/pss.rs index 5111a4a3..5042eda5 100644 --- a/src/pss.rs +++ b/src/pss.rs @@ -12,10 +12,19 @@ use alloc::boxed::Box; use alloc::vec::Vec; use core::fmt::{self, Debug, Display, Formatter, LowerHex, UpperHex}; - use core::marker::PhantomData; + +use const_oid::{AssociatedOid, ObjectIdentifier}; use digest::{Digest, DynDigest, FixedOutputReset}; -use pkcs8::{Document, EncodePrivateKey, EncodePublicKey, SecretDocument}; +use pkcs1::RsaPssParams; +use pkcs8::{ + spki::{ + der::{Any, AnyRef}, + AlgorithmIdentifier, AlgorithmIdentifierOwned, AlgorithmIdentifierRef, + AssociatedAlgorithmIdentifier, DynSignatureAlgorithmIdentifier, + }, + Document, EncodePrivateKey, EncodePublicKey, SecretDocument, +}; use rand_core::CryptoRngCore; use signature::{ hazmat::{PrehashVerifier, RandomizedPrehashSigner}, @@ -689,6 +698,57 @@ where } } +fn get_pss_signature_algo_id( + salt_len: Option, +) -> pkcs8::spki::Result +where + D: Digest + AssociatedOid, +{ + const ID_MGF_1: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.8"); + const ID_RSASSA_PSS: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.10"); + + let salt_len = salt_len.map_or(RsaPssParams::SALT_LEN_DEFAULT, |l| l as u8); + + let pss_params = RsaPssParams { + hash: AlgorithmIdentifierRef { + oid: D::OID, + parameters: None, + }, + mask_gen: AlgorithmIdentifier { + oid: ID_MGF_1, + parameters: Some(AlgorithmIdentifierRef { + oid: D::OID, + parameters: None, + }), + }, + salt_len, + trailer_field: Default::default(), + }; + + Ok(AlgorithmIdentifierOwned { + oid: ID_RSASSA_PSS, + parameters: Some(Any::encode_from(&pss_params)?), + }) +} + +impl AssociatedAlgorithmIdentifier for SigningKey +where + D: Digest, +{ + type Params = AnyRef<'static>; + + const ALGORITHM_IDENTIFIER: AlgorithmIdentifierRef<'static> = pkcs1::ALGORITHM_ID; +} + +impl DynSignatureAlgorithmIdentifier for SigningKey +where + D: Digest + AssociatedOid, +{ + fn signature_algorithm_identifier(&self) -> pkcs8::spki::Result { + get_pss_signature_algo_id::(self.salt_len) + } +} + impl From for SigningKey where D: Digest, @@ -825,6 +885,24 @@ where } } +impl AssociatedAlgorithmIdentifier for BlindedSigningKey +where + D: Digest, +{ + type Params = AnyRef<'static>; + + const ALGORITHM_IDENTIFIER: AlgorithmIdentifierRef<'static> = pkcs1::ALGORITHM_ID; +} + +impl DynSignatureAlgorithmIdentifier for BlindedSigningKey +where + D: Digest + AssociatedOid, +{ + fn signature_algorithm_identifier(&self) -> pkcs8::spki::Result { + get_pss_signature_algo_id::(self.salt_len) + } +} + impl From for BlindedSigningKey where D: Digest, @@ -958,6 +1036,15 @@ where } } +impl AssociatedAlgorithmIdentifier for VerifyingKey +where + D: Digest, +{ + type Params = AnyRef<'static>; + + const ALGORITHM_IDENTIFIER: AlgorithmIdentifierRef<'static> = pkcs1::ALGORITHM_ID; +} + impl From for VerifyingKey where D: Digest,