Skip to content

Commit

Permalink
spki.rs completed
Browse files Browse the repository at this point in the history
Signed-off-by: Richard Zak <richard@profian.com>
  • Loading branch information
rjzak committed Sep 28, 2022
1 parent de94371 commit 892efa0
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 35 deletions.
3 changes: 2 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

72 changes: 38 additions & 34 deletions src/crypto/spki.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
// SPDX-FileCopyrightText: 2022 Profian Inc. <opensource@profian.com>
// SPDX-License-Identifier: AGPL-3.0-only

use anyhow::{anyhow, bail, Result};
use const_oid::ObjectIdentifier;
use der::{asn1::AnyRef, Sequence};
use ring::signature::VerificationAlgorithm as VerAlg;
use ring::signature::*;
use rsa::pkcs1::DecodeRsaPublicKey;
use spki::{AlgorithmIdentifier, SubjectPublicKeyInfo};

use const_oid::db::rfc5912::{
ECDSA_WITH_SHA_256, ECDSA_WITH_SHA_384, ID_EC_PUBLIC_KEY as ECPK, ID_MGF_1, ID_RSASSA_PSS,
ECDSA_WITH_SHA_256, ECDSA_WITH_SHA_384, ID_EC_PUBLIC_KEY as ECPK, ID_RSASSA_PSS,
ID_SHA_256 as SHA256, ID_SHA_384 as SHA384, ID_SHA_512 as SHA512, RSA_ENCRYPTION as RSA,
SECP_256_R_1 as P256, SECP_384_R_1 as P384,
};

use anyhow::{anyhow, Result};

const ES256: (ObjectIdentifier, Option<AnyRef<'static>>) = (ECDSA_WITH_SHA_256, None);
const ES384: (ObjectIdentifier, Option<AnyRef<'static>>) = (ECDSA_WITH_SHA_384, None);

Expand Down Expand Up @@ -46,44 +44,50 @@ pub trait SubjectPublicKeyInfoExt {

impl<'a> SubjectPublicKeyInfoExt for SubjectPublicKeyInfo<'a> {
fn verify(&self, body: &[u8], algo: AlgorithmIdentifier<'_>, sign: &[u8]) -> Result<()> {
let alg: &'static dyn VerAlg = match (self.algorithm.oids()?, (algo.oid, algo.parameters)) {
((ECPK, Some(P256)), ES256) => &ECDSA_P256_SHA256_ASN1,
((ECPK, Some(P384)), ES384) => &ECDSA_P384_SHA384_ASN1,
match (self.algorithm.oids()?, (algo.oid, algo.parameters)) {
((ECPK, Some(P256)), ES256) => {
use p256::ecdsa::signature::Verifier;
let vkey = p256::ecdsa::VerifyingKey::from_sec1_bytes(self.subject_public_key)?;
let sig = p256::ecdsa::Signature::from_der(sign)?;
return Ok(vkey.verify(&body, &sig)?);
}
((ECPK, Some(P384)), ES384) => {
use p384::ecdsa::signature::Verifier;
let vkey = p384::ecdsa::VerifyingKey::from_sec1_bytes(self.subject_public_key)?;
let sig = p384::ecdsa::Signature::from_der(sign)?;
return Ok(vkey.verify(&body, &sig).unwrap());
}
((RSA, None), (ID_RSASSA_PSS, Some(p))) => {
use signature::{Signature, Verifier};
// Decompose the RSA PSS parameters.
let RsaSsaPssParams {
hash_algorithm: hash,
hash_algorithm: _hash,
mask_algorithm: mask,
salt_length: salt,
trailer_field: tfld,
salt_length: _salt,
trailer_field: _tfld,
} = p.decode_into()?;

// Validate the sanity of the mask algorithm.
let algo = match (mask.oid, mask.parameters) {
(ID_MGF_1, Some(p)) => {
let p = p.decode_into::<AlgorithmIdentifier<'_>>()?;
match (p.oids()?, salt, tfld) {
((SHA256, None), 32, 1) => Ok(SHA256),
((SHA384, None), 48, 1) => Ok(SHA384),
((SHA512, None), 64, 1) => Ok(SHA512),
_ => Err(anyhow!("unsupported")),
}
}
_ => Err(anyhow!("unsupported")),
}?;
let pkey = rsa::RsaPublicKey::from_pkcs1_der(self.subject_public_key)?;
let s = rsa::pss::Signature::from_bytes(sign)?;

// Prepare for validation.
match (hash.oids()?, algo) {
((SHA256, None), SHA256) => &RSA_PSS_2048_8192_SHA256,
((SHA384, None), SHA384) => &RSA_PSS_2048_8192_SHA384,
((SHA512, None), SHA512) => &RSA_PSS_2048_8192_SHA512,
_ => return Err(anyhow!("unsupported")),
let p2 = mask.parameters.ok_or(anyhow!("bad RSA parameters"))?;
match p2.decode_into::<AlgorithmIdentifier<'_>>()?.oid {
SHA256 => {
let vkey = rsa::pss::VerifyingKey::<sha2::Sha256>::new(pkey);
return Ok(vkey.verify(body, &s)?);
}
SHA384 => {
let vkey = rsa::pss::VerifyingKey::<sha2::Sha384>::new(pkey);
return Ok(vkey.verify(body, &s)?);
}
SHA512 => {
let vkey = rsa::pss::VerifyingKey::<sha2::Sha512>::new(pkey);
return Ok(vkey.verify(body, &s)?);
}
_ => bail!("unsupported"),
}
}
_ => return Err(anyhow!("unsupported")),
};

let upk = UnparsedPublicKey::new(alg, self.subject_public_key);
Ok(upk.verify(body, sign)?)
}
}
}

0 comments on commit 892efa0

Please sign in to comment.