AssociatedAlgorithmIdentifier implementation (#278)

Implement associated AlgorithmIdentifier traits for PKCS1v15 and PSS keys

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
This commit is contained in:
Dmitry Baryshkov 2023-04-05 05:12:08 +03:00 committed by GitHub
parent 70d185bb1c
commit cf90255057
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 197 additions and 15 deletions

17
Cargo.lock generated
View File

@ -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",

View File

@ -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"

View File

@ -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<D> AssociatedAlgorithmIdentifier for SigningKey<D>
where
D: Digest,
{
type Params = AnyRef<'static>;
const ALGORITHM_IDENTIFIER: AlgorithmIdentifierRef<'static> = pkcs1::ALGORITHM_ID;
}
impl<D> SignatureAlgorithmIdentifier for SigningKey<D>
where
D: Digest + oid::RsaSignatureAssociatedOid,
{
type Params = AnyRef<'static>;
const SIGNATURE_ALGORITHM_IDENTIFIER: AlgorithmIdentifierRef<'static> =
AlgorithmIdentifierRef {
oid: D::OID,
parameters: Some(AnyRef::NULL),
};
}
impl<D> From<RsaPrivateKey> for SigningKey<D>
where
D: Digest,
@ -606,6 +634,28 @@ where
}
}
impl<D> AssociatedAlgorithmIdentifier for VerifyingKey<D>
where
D: Digest,
{
type Params = AnyRef<'static>;
const ALGORITHM_IDENTIFIER: AlgorithmIdentifierRef<'static> = pkcs1::ALGORITHM_ID;
}
impl<D> SignatureAlgorithmIdentifier for VerifyingKey<D>
where
D: Digest + oid::RsaSignatureAssociatedOid,
{
type Params = AnyRef<'static>;
const SIGNATURE_ALGORITHM_IDENTIFIER: AlgorithmIdentifierRef<'static> =
AlgorithmIdentifierRef {
oid: D::OID,
parameters: Some(AnyRef::NULL),
};
}
impl<D> From<RsaPublicKey> for VerifyingKey<D>
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::*;

View File

@ -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<D>(
salt_len: Option<usize>,
) -> pkcs8::spki::Result<AlgorithmIdentifierOwned>
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<D> AssociatedAlgorithmIdentifier for SigningKey<D>
where
D: Digest,
{
type Params = AnyRef<'static>;
const ALGORITHM_IDENTIFIER: AlgorithmIdentifierRef<'static> = pkcs1::ALGORITHM_ID;
}
impl<D> DynSignatureAlgorithmIdentifier for SigningKey<D>
where
D: Digest + AssociatedOid,
{
fn signature_algorithm_identifier(&self) -> pkcs8::spki::Result<AlgorithmIdentifierOwned> {
get_pss_signature_algo_id::<D>(self.salt_len)
}
}
impl<D> From<RsaPrivateKey> for SigningKey<D>
where
D: Digest,
@ -825,6 +885,24 @@ where
}
}
impl<D> AssociatedAlgorithmIdentifier for BlindedSigningKey<D>
where
D: Digest,
{
type Params = AnyRef<'static>;
const ALGORITHM_IDENTIFIER: AlgorithmIdentifierRef<'static> = pkcs1::ALGORITHM_ID;
}
impl<D> DynSignatureAlgorithmIdentifier for BlindedSigningKey<D>
where
D: Digest + AssociatedOid,
{
fn signature_algorithm_identifier(&self) -> pkcs8::spki::Result<AlgorithmIdentifierOwned> {
get_pss_signature_algo_id::<D>(self.salt_len)
}
}
impl<D> From<RsaPrivateKey> for BlindedSigningKey<D>
where
D: Digest,
@ -958,6 +1036,15 @@ where
}
}
impl<D> AssociatedAlgorithmIdentifier for VerifyingKey<D>
where
D: Digest,
{
type Params = AnyRef<'static>;
const ALGORITHM_IDENTIFIER: AlgorithmIdentifierRef<'static> = pkcs1::ALGORITHM_ID;
}
impl<D> From<RsaPublicKey> for VerifyingKey<D>
where
D: Digest,