Coverage Report

Created: 2024-12-17 06:15

/rust/registry/src/index.crates.io-6f17d22bba15001f/rustls-webpki-0.102.8/src/x509.rs
Line
Count
Source (jump to first uncovered line)
1
// Copyright 2015 Brian Smith.
2
//
3
// Permission to use, copy, modify, and/or distribute this software for any
4
// purpose with or without fee is hereby granted, provided that the above
5
// copyright notice and this permission notice appear in all copies.
6
//
7
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
8
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
10
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
13
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14
15
use crate::der::{self, DerIterator, FromDer, CONSTRUCTED, CONTEXT_SPECIFIC};
16
use crate::error::{DerTypeId, Error};
17
use crate::subject_name::GeneralName;
18
19
pub(crate) struct Extension<'a> {
20
    pub(crate) critical: bool,
21
    pub(crate) id: untrusted::Input<'a>,
22
    pub(crate) value: untrusted::Input<'a>,
23
}
24
25
impl<'a> Extension<'a> {
26
8.18k
    pub(crate) fn unsupported(&self) -> Result<(), Error> {
27
8.18k
        match self.critical {
28
0
            true => Err(Error::UnsupportedCriticalExtension),
29
8.18k
            false => Ok(()),
30
        }
31
8.18k
    }
32
}
33
34
impl<'a> FromDer<'a> for Extension<'a> {
35
24.5k
    fn from_der(reader: &mut untrusted::Reader<'a>) -> Result<Self, Error> {
36
24.5k
        let id = der::expect_tag(reader, der::Tag::OID)?;
37
24.5k
        let critical = bool::from_der(reader)?;
38
24.5k
        let value = der::expect_tag(reader, der::Tag::OctetString)?;
39
24.5k
        Ok(Extension {
40
24.5k
            id,
41
24.5k
            critical,
42
24.5k
            value,
43
24.5k
        })
44
24.5k
    }
45
46
    const TYPE_ID: DerTypeId = DerTypeId::Extension;
47
}
48
49
16.3k
pub(crate) fn set_extension_once<T>(
50
16.3k
    destination: &mut Option<T>,
51
16.3k
    parser: impl Fn() -> Result<T, Error>,
52
16.3k
) -> Result<(), Error> {
53
16.3k
    match destination {
54
        // The extension value has already been set, indicating that we encountered it
55
        // more than once in our serialized data. That's invalid!
56
0
        Some(..) => Err(Error::ExtensionValueInvalid),
57
        None => {
58
16.3k
            *destination = Some(parser()?);
59
16.3k
            Ok(())
60
        }
61
    }
62
16.3k
}
Unexecuted instantiation: webpki::x509::set_extension_once::<rustls_pki_types::UnixTime, <webpki::crl::types::BorrowedRevokedCert>::remember_extension::{closure#0}::{closure#1}>
Unexecuted instantiation: webpki::x509::set_extension_once::<webpki::der::BitStringFlags, <webpki::crl::types::IssuingDistributionPoint>::from_der::{closure#0}::{closure#1}>
Unexecuted instantiation: webpki::x509::set_extension_once::<webpki::der::BitStringFlags, <webpki::cert::CrlDistributionPoint as webpki::der::FromDer>::from_der::{closure#0}::{closure#1}>
Unexecuted instantiation: webpki::x509::set_extension_once::<untrusted::input::Input, <webpki::crl::types::BorrowedCertRevocationList>::remember_extension::{closure#0}::{closure#1}>
Unexecuted instantiation: webpki::x509::set_extension_once::<untrusted::input::Input, <webpki::crl::types::IssuingDistributionPoint>::from_der::{closure#0}::{closure#0}>
webpki::x509::set_extension_once::<untrusted::input::Input, webpki::cert::remember_cert_extension::{closure#0}::{closure#0}>
Line
Count
Source
49
16.3k
pub(crate) fn set_extension_once<T>(
50
16.3k
    destination: &mut Option<T>,
51
16.3k
    parser: impl Fn() -> Result<T, Error>,
52
16.3k
) -> Result<(), Error> {
53
16.3k
    match destination {
54
        // The extension value has already been set, indicating that we encountered it
55
        // more than once in our serialized data. That's invalid!
56
0
        Some(..) => Err(Error::ExtensionValueInvalid),
57
        None => {
58
16.3k
            *destination = Some(parser()?);
59
16.3k
            Ok(())
60
        }
61
    }
62
16.3k
}
Unexecuted instantiation: webpki::x509::set_extension_once::<untrusted::input::Input, <webpki::cert::CrlDistributionPoint as webpki::der::FromDer>::from_der::{closure#0}::{closure#0}>
Unexecuted instantiation: webpki::x509::set_extension_once::<untrusted::input::Input, <webpki::cert::CrlDistributionPoint as webpki::der::FromDer>::from_der::{closure#0}::{closure#2}>
Unexecuted instantiation: webpki::x509::set_extension_once::<webpki::crl::types::RevocationReason, <webpki::crl::types::BorrowedRevokedCert>::remember_extension::{closure#0}::{closure#0}>
63
64
24.5k
pub(crate) fn remember_extension(
65
24.5k
    extension: &Extension<'_>,
66
24.5k
    mut handler: impl FnMut(u8) -> Result<(), Error>,
67
24.5k
) -> Result<(), Error> {
68
    // ISO arc for standard certificate and CRL extensions.
69
    // https://www.rfc-editor.org/rfc/rfc5280#appendix-A.2
70
    static ID_CE: [u8; 2] = oid![2, 5, 29];
71
72
24.5k
    if extension.id.len() != ID_CE.len() + 1
73
24.5k
        || !extension.id.as_slice_less_safe().starts_with(&ID_CE)
74
    {
75
0
        return extension.unsupported();
76
24.5k
    }
77
24.5k
78
24.5k
    // safety: we verify len is non-zero and has the correct prefix above.
79
24.5k
    let last_octet = *extension.id.as_slice_less_safe().last().unwrap();
80
24.5k
    handler(last_octet)
81
24.5k
}
Unexecuted instantiation: webpki::x509::remember_extension::<<webpki::crl::types::BorrowedCertRevocationList>::remember_extension::{closure#0}>
Unexecuted instantiation: webpki::x509::remember_extension::<<webpki::crl::types::BorrowedRevokedCert>::remember_extension::{closure#0}>
webpki::x509::remember_extension::<webpki::cert::remember_cert_extension::{closure#0}>
Line
Count
Source
64
24.5k
pub(crate) fn remember_extension(
65
24.5k
    extension: &Extension<'_>,
66
24.5k
    mut handler: impl FnMut(u8) -> Result<(), Error>,
67
24.5k
) -> Result<(), Error> {
68
    // ISO arc for standard certificate and CRL extensions.
69
    // https://www.rfc-editor.org/rfc/rfc5280#appendix-A.2
70
    static ID_CE: [u8; 2] = oid![2, 5, 29];
71
72
24.5k
    if extension.id.len() != ID_CE.len() + 1
73
24.5k
        || !extension.id.as_slice_less_safe().starts_with(&ID_CE)
74
    {
75
0
        return extension.unsupported();
76
24.5k
    }
77
24.5k
78
24.5k
    // safety: we verify len is non-zero and has the correct prefix above.
79
24.5k
    let last_octet = *extension.id.as_slice_less_safe().last().unwrap();
80
24.5k
    handler(last_octet)
81
24.5k
}
82
83
/// A certificate revocation list (CRL) distribution point name, describing a source of
84
/// CRL information for a given certificate as described in RFC 5280 section 4.2.3.13[^1].
85
///
86
/// [^1]: <https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.13>
87
pub(crate) enum DistributionPointName<'a> {
88
    /// The distribution point name is a relative distinguished name, relative to the CRL issuer.
89
    NameRelativeToCrlIssuer,
90
    /// The distribution point name is a sequence of [GeneralName] items.
91
    FullName(DerIterator<'a, GeneralName<'a>>),
92
}
93
94
impl<'a> FromDer<'a> for DistributionPointName<'a> {
95
0
    fn from_der(reader: &mut untrusted::Reader<'a>) -> Result<Self, Error> {
96
        // RFC 5280 section ยง4.2.1.13:
97
        //   When the distributionPoint field is present, it contains either a
98
        //   SEQUENCE of general names or a single value, nameRelativeToCRLIssuer
99
        const FULL_NAME_TAG: u8 = CONTEXT_SPECIFIC | CONSTRUCTED;
100
        const NAME_RELATIVE_TO_CRL_ISSUER_TAG: u8 = CONTEXT_SPECIFIC | CONSTRUCTED | 1;
101
102
0
        let (tag, value) = der::read_tag_and_get_value(reader)?;
103
0
        match tag {
104
0
            FULL_NAME_TAG => Ok(DistributionPointName::FullName(DerIterator::new(value))),
105
0
            NAME_RELATIVE_TO_CRL_ISSUER_TAG => Ok(DistributionPointName::NameRelativeToCrlIssuer),
106
0
            _ => Err(Error::BadDer),
107
        }
108
0
    }
109
110
    const TYPE_ID: DerTypeId = DerTypeId::DistributionPointName;
111
}