Skip to main content
This is unreleased documentation for the main (development) branch of crypto-glue.

crypto_glue/x509/
mod.rs

1use crate::{
2    ecdsa_p256::{EcdsaP256PublicKey, EcdsaP256Signature, EcdsaP256VerifyingKey},
3    ecdsa_p384::{EcdsaP384PublicKey, EcdsaP384Signature, EcdsaP384VerifyingKey},
4    rsa::{RS256PublicKey, RS256Signature, RS256VerifyingKey},
5    s256::{Sha256, Sha256Output},
6    traits::{Digest, EncodeDer, OwnedToRef, Verifier},
7};
8use tracing::error;
9
10pub use self::chain::{X509Store, X509VerificationError};
11pub use self::display::X509Display;
12pub use self::serialise::{pkeyb64, x509b64};
13pub use const_oid::db as oiddb;
14pub use const_oid::{AssociatedOid, ObjectIdentifier};
15pub use der::asn1::{BitString, GeneralizedTime, Ia5String, OctetString};
16pub use x509_cert::builder::RequestBuilder as CertificateRequestBuilder;
17pub use x509_cert::builder::{Builder, CertificateBuilder, Profile};
18pub use x509_cert::certificate::{Certificate, Version};
19pub use x509_cert::ext::pkix::name::{DistributionPointName, GeneralName, OtherName};
20pub use x509_cert::ext::pkix::{
21    crl::dp::DistributionPoint, crl::CrlDistributionPoints, AccessDescription,
22    AuthorityInfoAccessSyntax, AuthorityKeyIdentifier, BasicConstraints, ExtendedKeyUsage,
23    KeyUsage, KeyUsages, SubjectAltName, SubjectKeyIdentifier,
24};
25pub use x509_cert::name::Name;
26pub use x509_cert::request::CertReq as CertificateRequest;
27pub use x509_cert::serial_number::SerialNumber;
28pub use x509_cert::spki::{
29    AlgorithmIdentifier, SignatureBitStringEncoding, SubjectPublicKeyInfoOwned,
30};
31pub use x509_cert::time::{Time, Validity};
32
33mod chain;
34mod display;
35mod serialise;
36
37pub fn uuid_to_serial(serial_uuid: uuid::Uuid) -> SerialNumber {
38    let mut serial_bytes: [u8; 17] = [0; 17];
39    // The first byte must be a value else if the leading byte is a null then
40    // der is unhappy.
41    serial_bytes[0] = 0x01;
42    let update_bytes = &mut serial_bytes[1..];
43    update_bytes.copy_from_slice(serial_uuid.as_bytes());
44
45    #[allow(clippy::expect_used)]
46    SerialNumber::new(&serial_bytes).expect("Failed to create serial number from uuid")
47}
48
49pub fn x509_digest_public_key_sha256(certificate: &Certificate) -> Option<Sha256Output> {
50    let public_key_bytes = certificate
51        .tbs_certificate
52        .subject_public_key_info
53        .subject_public_key
54        .as_bytes()?;
55
56    let mut hasher = Sha256::new();
57    hasher.update(public_key_bytes);
58    Some(hasher.finalize())
59}
60
61pub fn x509_digest_cert_sha256(certificate: &Certificate) -> Result<Sha256Output, der::Error> {
62    let mut hasher = Sha256::new();
63    hasher.update(certificate.to_der()?);
64    Ok(hasher.finalize())
65}
66
67pub fn x509_verify_signature(
68    data: &[u8],
69    signature: &[u8],
70    certificate: &Certificate,
71) -> Result<(), X509VerificationError> {
72    let subject_public_key_info = certificate
73        .tbs_certificate
74        .subject_public_key_info
75        .owned_to_ref();
76
77    match subject_public_key_info.algorithm.oids() {
78        Ok((oiddb::rfc5912::ID_EC_PUBLIC_KEY, Some(oiddb::rfc5912::SECP_256_R_1))) => {
79            let signature = EcdsaP256Signature::from_der(signature)
80                .map_err(|_err| X509VerificationError::DerSignatureInvalid)?;
81
82            let verifier = EcdsaP256PublicKey::try_from(subject_public_key_info)
83                .map(EcdsaP256VerifyingKey::from)
84                .map_err(|_err| X509VerificationError::VerifyingKeyFromSpki)?;
85
86            verifier
87                .verify(data, &signature)
88                .map_err(|_err| X509VerificationError::SignatureVerificationFailed)?;
89        }
90        Ok((oiddb::rfc5912::ID_EC_PUBLIC_KEY, Some(oiddb::rfc5912::SECP_384_R_1))) => {
91            let signature = EcdsaP384Signature::from_der(signature)
92                .map_err(|_err| X509VerificationError::DerSignatureInvalid)?;
93
94            let verifier = EcdsaP384PublicKey::try_from(subject_public_key_info)
95                .map(EcdsaP384VerifyingKey::from)
96                .map_err(|_err| X509VerificationError::VerifyingKeyFromSpki)?;
97
98            verifier
99                .verify(data, &signature)
100                .map_err(|_err| X509VerificationError::SignatureVerificationFailed)?;
101        }
102        Ok((oiddb::rfc5912::SHA_256_WITH_RSA_ENCRYPTION, None)) => {
103            let signature = RS256Signature::try_from(signature)
104                .map_err(|_err| X509VerificationError::DerSignatureInvalid)?;
105
106            let verifier = RS256PublicKey::try_from(subject_public_key_info)
107                .map(RS256VerifyingKey::new)
108                .map_err(|_err| X509VerificationError::VerifyingKeyFromSpki)?;
109
110            verifier
111                .verify(data, &signature)
112                .map_err(|_err| X509VerificationError::SignatureVerificationFailed)?;
113        }
114        algo_oids => {
115            error!(?algo_oids);
116            return Err(X509VerificationError::SignatureAlgorithmNotImplemented);
117        }
118    }
119
120    Ok(())
121}