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