x509_parser/
verify.rs

1use crate::prelude::*;
2use crate::signature_algorithm::RsaSsaPssParams;
3use asn1_rs::{Any, BitString};
4use oid_registry::{
5    OID_EC_P256, OID_NIST_EC_P384, OID_NIST_HASH_SHA256, OID_NIST_HASH_SHA384,
6    OID_NIST_HASH_SHA512, OID_PKCS1_RSASSAPSS, OID_PKCS1_SHA1WITHRSA, OID_PKCS1_SHA256WITHRSA,
7    OID_PKCS1_SHA384WITHRSA, OID_PKCS1_SHA512WITHRSA, OID_SHA1_WITH_RSA, OID_SIG_ECDSA_WITH_SHA256,
8    OID_SIG_ECDSA_WITH_SHA384, OID_SIG_ED25519,
9};
10use std::convert::TryFrom;
11
12// Since the `signature` object is similar in ring and in aws-lc-rs, we just use simple logic
13// to determine which one to use.
14// If both verify and verify-aws features are enabled, aws will be used.
15#[cfg(feature = "verify-aws")]
16use aws_lc_rs::signature;
17#[cfg(all(feature = "verify", not(feature = "verify-aws")))]
18use ring::signature;
19
20/// Verify the cryptographic signature of the raw data (can be a certificate, a CRL or a CSR).
21///
22/// `public_key` is the public key of the **signer**.
23///
24/// Not all algorithms are supported, this function is limited to what `aws_lc_rs` or `ring` supports.
25pub fn verify_signature(
26    public_key: &SubjectPublicKeyInfo,
27    signature_algorithm: &AlgorithmIdentifier,
28    signature_value: &BitString,
29    raw_data: &[u8],
30) -> Result<(), X509Error> {
31    let AlgorithmIdentifier {
32        algorithm: signature_algorithm,
33        parameters: signature_algorithm_parameters,
34    } = &signature_algorithm;
35
36    // identify verification algorithm
37    let verification_alg: &dyn signature::VerificationAlgorithm = if *signature_algorithm
38        == OID_PKCS1_SHA1WITHRSA
39        || *signature_algorithm == OID_SHA1_WITH_RSA
40    {
41        &signature::RSA_PKCS1_1024_8192_SHA1_FOR_LEGACY_USE_ONLY
42    } else if *signature_algorithm == OID_PKCS1_SHA256WITHRSA {
43        &signature::RSA_PKCS1_2048_8192_SHA256
44    } else if *signature_algorithm == OID_PKCS1_SHA384WITHRSA {
45        &signature::RSA_PKCS1_2048_8192_SHA384
46    } else if *signature_algorithm == OID_PKCS1_SHA512WITHRSA {
47        &signature::RSA_PKCS1_2048_8192_SHA512
48    } else if *signature_algorithm == OID_PKCS1_RSASSAPSS {
49        get_rsa_pss_verification_algo(signature_algorithm_parameters)
50            .ok_or(X509Error::SignatureUnsupportedAlgorithm)?
51    } else if *signature_algorithm == OID_SIG_ECDSA_WITH_SHA256 {
52        get_ec_curve_sha(&public_key.algorithm, 256)
53            .ok_or(X509Error::SignatureUnsupportedAlgorithm)?
54    } else if *signature_algorithm == OID_SIG_ECDSA_WITH_SHA384 {
55        get_ec_curve_sha(&public_key.algorithm, 384)
56            .ok_or(X509Error::SignatureUnsupportedAlgorithm)?
57    } else if *signature_algorithm == OID_SIG_ED25519 {
58        &signature::ED25519
59    } else {
60        return Err(X509Error::SignatureUnsupportedAlgorithm);
61    };
62    // get public key
63    let key =
64        signature::UnparsedPublicKey::new(verification_alg, &public_key.subject_public_key.data);
65    // verify signature
66    key.verify(raw_data, &signature_value.data)
67        .or(Err(X509Error::SignatureVerificationError))
68}
69
70/// Find the verification algorithm for the given EC curve and SHA digest size
71///
72/// Not all algorithms are supported, we are limited to what `aws_lc_rs`  or `ring`supports.
73fn get_ec_curve_sha(
74    pubkey_alg: &AlgorithmIdentifier,
75    sha_len: usize,
76) -> Option<&'static dyn signature::VerificationAlgorithm> {
77    let curve_oid = pubkey_alg.parameters.as_ref()?.as_oid().ok()?;
78    // let curve_oid = pubkey_alg.parameters.as_ref()?.as_oid().ok()?;
79    if curve_oid == OID_EC_P256 {
80        match sha_len {
81            256 => Some(&signature::ECDSA_P256_SHA256_ASN1),
82            384 => Some(&signature::ECDSA_P256_SHA384_ASN1),
83            _ => None,
84        }
85    } else if curve_oid == OID_NIST_EC_P384 {
86        match sha_len {
87            256 => Some(&signature::ECDSA_P384_SHA256_ASN1),
88            384 => Some(&signature::ECDSA_P384_SHA384_ASN1),
89            _ => None,
90        }
91    } else {
92        None
93    }
94}
95
96/// Find the verification algorithm for the given RSA-PSS parameters
97///
98/// Not all algorithms are supported, we are limited to what `aws_lc_rs` or `ring` supports.
99/// Notably, the SHA-1 hash algorithm is not supported.
100fn get_rsa_pss_verification_algo(
101    params: &Option<Any>,
102) -> Option<&'static dyn signature::VerificationAlgorithm> {
103    let params = params.as_ref()?;
104    let params = RsaSsaPssParams::try_from(params).ok()?;
105    let hash_algo = params.hash_algorithm_oid();
106
107    if *hash_algo == OID_NIST_HASH_SHA256 {
108        Some(&signature::RSA_PSS_2048_8192_SHA256)
109    } else if *hash_algo == OID_NIST_HASH_SHA384 {
110        Some(&signature::RSA_PSS_2048_8192_SHA384)
111    } else if *hash_algo == OID_NIST_HASH_SHA512 {
112        Some(&signature::RSA_PSS_2048_8192_SHA512)
113    } else {
114        None
115    }
116}