Coverage Report

Created: 2025-12-31 06:11

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/rustls-webpki-0.103.8/src/signed_data.rs
Line
Count
Source
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, FromDer};
16
use crate::error::{
17
    DerTypeId, Error, UnsupportedSignatureAlgorithmContext,
18
    UnsupportedSignatureAlgorithmForPublicKeyContext,
19
};
20
use crate::verify_cert::Budget;
21
22
use pki_types::SignatureVerificationAlgorithm;
23
24
#[cfg(feature = "alloc")]
25
use alloc::vec::Vec;
26
27
/// X.509 certificates and related items that are signed are almost always
28
/// encoded in the format "tbs||signatureAlgorithm||signature". This structure
29
/// captures this pattern as an owned data type.
30
#[cfg(feature = "alloc")]
31
#[derive(Clone, Debug)]
32
pub(crate) struct OwnedSignedData {
33
    /// The signed data. This would be `tbsCertificate` in the case of an X.509
34
    /// certificate, `tbsResponseData` in the case of an OCSP response, `tbsCertList`
35
    /// in the case of a CRL, and the data nested in the `digitally-signed` construct for
36
    /// TLS 1.2 signed data.
37
    pub(crate) data: Vec<u8>,
38
39
    /// The value of the `AlgorithmIdentifier`. This would be
40
    /// `signatureAlgorithm` in the case of an X.509 certificate, OCSP
41
    /// response or CRL. This would have to be synthesized in the case of TLS 1.2
42
    /// signed data, since TLS does not identify algorithms by ASN.1 OIDs.
43
    pub(crate) algorithm: Vec<u8>,
44
45
    /// The value of the signature. This would be `signature` in an X.509
46
    /// certificate, OCSP response or CRL. This would be the value of
47
    /// `DigitallySigned.signature` for TLS 1.2 signed data.
48
    pub(crate) signature: Vec<u8>,
49
}
50
51
#[cfg(feature = "alloc")]
52
impl OwnedSignedData {
53
    /// Return a borrowed [`SignedData`] from the owned representation.
54
0
    pub(crate) fn borrow(&self) -> SignedData<'_> {
55
0
        SignedData {
56
0
            data: untrusted::Input::from(&self.data),
57
0
            algorithm: untrusted::Input::from(&self.algorithm),
58
0
            signature: untrusted::Input::from(&self.signature),
59
0
        }
60
0
    }
Unexecuted instantiation: <webpki::signed_data::OwnedSignedData>::borrow
Unexecuted instantiation: <webpki::signed_data::OwnedSignedData>::borrow
61
}
62
63
/// X.509 certificates and related items that are signed are almost always
64
/// encoded in the format "tbs||signatureAlgorithm||signature". This structure
65
/// captures this pattern.
66
#[derive(Debug)]
67
pub(crate) struct SignedData<'a> {
68
    /// The signed data. This would be `tbsCertificate` in the case of an X.509
69
    /// certificate, `tbsResponseData` in the case of an OCSP response, `tbsCertList`
70
    /// in the case of a CRL, and the data nested in the `digitally-signed` construct for
71
    /// TLS 1.2 signed data.
72
    pub(crate) data: untrusted::Input<'a>,
73
74
    /// The value of the `AlgorithmIdentifier`. This would be
75
    /// `signatureAlgorithm` in the case of an X.509 certificate, OCSP
76
    /// response or CRL. This would have to be synthesized in the case of TLS 1.2
77
    /// signed data, since TLS does not identify algorithms by ASN.1 OIDs.
78
    pub(crate) algorithm: untrusted::Input<'a>,
79
80
    /// The value of the signature. This would be `signature` in an X.509
81
    /// certificate, OCSP response or CRL. This would be the value of
82
    /// `DigitallySigned.signature` for TLS 1.2 signed data.
83
    pub(crate) signature: untrusted::Input<'a>,
84
}
85
86
impl<'a> SignedData<'a> {
87
    /// Parses the concatenation of "tbs||signatureAlgorithm||signature" that
88
    /// is common in the X.509 certificate and OCSP response syntaxes.
89
    ///
90
    /// X.509 Certificates (RFC 5280) look like this:
91
    ///
92
    /// ```ASN.1
93
    /// Certificate (SEQUENCE) {
94
    ///     tbsCertificate TBSCertificate,
95
    ///     signatureAlgorithm AlgorithmIdentifier,
96
    ///     signatureValue BIT STRING
97
    /// }
98
    /// ```
99
    ///
100
    /// OCSP responses (RFC 6960) look like this:
101
    /// ```ASN.1
102
    /// BasicOCSPResponse {
103
    ///     tbsResponseData ResponseData,
104
    ///     signatureAlgorithm AlgorithmIdentifier,
105
    ///     signature BIT STRING,
106
    ///     certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL
107
    /// }
108
    /// ```
109
    ///
110
    /// Note that this function does NOT parse the outermost `SEQUENCE` or the
111
    /// `certs` value.
112
    ///
113
    /// The return value's first component is the contents of
114
    /// `tbsCertificate`/`tbsResponseData`; the second component is a `SignedData`
115
    /// structure that can be passed to `verify_signed_data`.
116
    ///
117
    /// The provided size_limit will enforce the largest possible outermost `SEQUENCE` this
118
    /// function will read.
119
0
    pub(crate) fn from_der(
120
0
        der: &mut untrusted::Reader<'a>,
121
0
        size_limit: usize,
122
0
    ) -> Result<(untrusted::Input<'a>, Self), Error> {
123
0
        let (data, tbs) = der.read_partial(|input| {
124
0
            der::expect_tag_and_get_value_limited(input, der::Tag::Sequence, size_limit)
125
0
        })?;
Unexecuted instantiation: <webpki::signed_data::SignedData>::from_der::{closure#0}
Unexecuted instantiation: <webpki::signed_data::SignedData>::from_der::{closure#0}
126
0
        let algorithm = der::expect_tag(der, der::Tag::Sequence)?;
127
0
        let signature = der::bit_string_with_no_unused_bits(der)?;
128
129
0
        Ok((
130
0
            tbs,
131
0
            SignedData {
132
0
                data,
133
0
                algorithm,
134
0
                signature,
135
0
            },
136
0
        ))
137
0
    }
Unexecuted instantiation: <webpki::signed_data::SignedData>::from_der
Unexecuted instantiation: <webpki::signed_data::SignedData>::from_der
138
139
    /// Convert the borrowed signed data to an [`OwnedSignedData`].
140
    #[cfg(feature = "alloc")]
141
0
    pub(crate) fn to_owned(&self) -> OwnedSignedData {
142
0
        OwnedSignedData {
143
0
            data: self.data.as_slice_less_safe().to_vec(),
144
0
            algorithm: self.algorithm.as_slice_less_safe().to_vec(),
145
0
            signature: self.signature.as_slice_less_safe().to_vec(),
146
0
        }
147
0
    }
Unexecuted instantiation: <webpki::signed_data::SignedData>::to_owned
Unexecuted instantiation: <webpki::signed_data::SignedData>::to_owned
148
}
149
150
/// Verify `signed_data` using the public key in the DER-encoded
151
/// SubjectPublicKeyInfo `spki` using one of the algorithms in
152
/// `supported_algorithms`.
153
///
154
/// The algorithm is chosen based on the algorithm information encoded in the
155
/// algorithm identifiers in `public_key` and `signed_data.algorithm`. The
156
/// ordering of the algorithms in `supported_algorithms` does not really matter,
157
/// but generally more common algorithms should go first, as it is scanned
158
/// linearly for matches.
159
0
pub(crate) fn verify_signed_data(
160
0
    supported_algorithms: &[&dyn SignatureVerificationAlgorithm],
161
0
    spki_value: untrusted::Input<'_>,
162
0
    signed_data: &SignedData<'_>,
163
0
    budget: &mut Budget,
164
0
) -> Result<(), Error> {
165
0
    budget.consume_signature()?;
166
167
    // We need to verify the signature in `signed_data` using the public key
168
    // in `public_key`. In order to know which *ring* signature verification
169
    // algorithm to use, we need to know the public key algorithm (ECDSA,
170
    // RSA PKCS#1, etc.), the curve (if applicable), and the digest algorithm.
171
    // `signed_data` identifies only the public key algorithm and the digest
172
    // algorithm, and `public_key` identifies only the public key algorithm and
173
    // the curve (if any). Thus, we have to combine information from both
174
    // inputs to figure out which `ring::signature::VerificationAlgorithm` to
175
    // use to verify the signature.
176
    //
177
    // This is all further complicated by the fact that we don't have any
178
    // implicit knowledge about any algorithms or identifiers, since all of
179
    // that information is encoded in `supported_algorithms.` In particular, we
180
    // avoid hard-coding any of that information so that (link-time) dead code
181
    // elimination will work effectively in eliminating code for unused
182
    // algorithms.
183
184
    // Parse the signature.
185
    //
186
0
    let mut invalid_for_public_key = None;
187
0
    for supported_alg in supported_algorithms
188
0
        .iter()
189
0
        .filter(|alg| alg.signature_alg_id().as_ref() == signed_data.algorithm.as_slice_less_safe())
Unexecuted instantiation: webpki::signed_data::verify_signed_data::{closure#0}
Unexecuted instantiation: webpki::signed_data::verify_signed_data::{closure#0}
190
    {
191
0
        match verify_signature(
192
0
            *supported_alg,
193
0
            spki_value,
194
0
            signed_data.data,
195
0
            signed_data.signature,
196
        ) {
197
0
            Err(Error::UnsupportedSignatureAlgorithmForPublicKeyContext(cx)) => {
198
0
                invalid_for_public_key = Some(cx);
199
0
                continue;
200
            }
201
0
            result => return result,
202
        }
203
    }
204
205
0
    if let Some(cx) = invalid_for_public_key {
206
0
        return Err(Error::UnsupportedSignatureAlgorithmForPublicKeyContext(cx));
207
0
    }
208
209
    Err(Error::UnsupportedSignatureAlgorithmContext(
210
        UnsupportedSignatureAlgorithmContext {
211
            #[cfg(feature = "alloc")]
212
0
            signature_algorithm_id: signed_data.algorithm.as_slice_less_safe().to_vec(),
213
            #[cfg(feature = "alloc")]
214
0
            supported_algorithms: supported_algorithms
215
0
                .iter()
216
0
                .map(|&alg| alg.signature_alg_id())
Unexecuted instantiation: webpki::signed_data::verify_signed_data::{closure#1}
Unexecuted instantiation: webpki::signed_data::verify_signed_data::{closure#1}
217
0
                .collect(),
218
        },
219
    ))
220
0
}
Unexecuted instantiation: webpki::signed_data::verify_signed_data
Unexecuted instantiation: webpki::signed_data::verify_signed_data
221
222
0
pub(crate) fn verify_signature(
223
0
    signature_alg: &dyn SignatureVerificationAlgorithm,
224
0
    spki_value: untrusted::Input<'_>,
225
0
    msg: untrusted::Input<'_>,
226
0
    signature: untrusted::Input<'_>,
227
0
) -> Result<(), Error> {
228
0
    let spki = der::read_all::<SubjectPublicKeyInfo<'_>>(spki_value)?;
229
0
    if signature_alg.public_key_alg_id().as_ref() != spki.algorithm_id_value.as_slice_less_safe() {
230
0
        return Err(Error::UnsupportedSignatureAlgorithmForPublicKeyContext(
231
0
            UnsupportedSignatureAlgorithmForPublicKeyContext {
232
0
                #[cfg(feature = "alloc")]
233
0
                signature_algorithm_id: signature_alg.signature_alg_id().as_ref().to_vec(),
234
0
                #[cfg(feature = "alloc")]
235
0
                public_key_algorithm_id: spki.algorithm_id_value.as_slice_less_safe().to_vec(),
236
0
            },
237
0
        ));
238
0
    }
239
240
0
    signature_alg
241
0
        .verify_signature(
242
0
            spki.key_value.as_slice_less_safe(),
243
0
            msg.as_slice_less_safe(),
244
0
            signature.as_slice_less_safe(),
245
        )
246
0
        .map_err(|_| Error::InvalidSignatureForPublicKey)
247
0
}
Unexecuted instantiation: webpki::signed_data::verify_signature
Unexecuted instantiation: webpki::signed_data::verify_signature
248
249
pub(crate) struct SubjectPublicKeyInfo<'a> {
250
    algorithm_id_value: untrusted::Input<'a>,
251
    key_value: untrusted::Input<'a>,
252
}
253
254
impl<'a> FromDer<'a> for SubjectPublicKeyInfo<'a> {
255
    // Parse the public key into an algorithm OID, an optional curve OID, and the
256
    // key value. The caller needs to check whether these match the
257
    // `PublicKeyAlgorithm` for the `SignatureVerificationAlgorithm` that is matched when
258
    // parsing the signature.
259
0
    fn from_der(reader: &mut untrusted::Reader<'a>) -> Result<Self, Error> {
260
0
        let algorithm_id_value = der::expect_tag(reader, der::Tag::Sequence)?;
261
0
        let key_value = der::bit_string_with_no_unused_bits(reader)?;
262
0
        Ok(SubjectPublicKeyInfo {
263
0
            algorithm_id_value,
264
0
            key_value,
265
0
        })
266
0
    }
Unexecuted instantiation: <webpki::signed_data::SubjectPublicKeyInfo as webpki::der::FromDer>::from_der
Unexecuted instantiation: <webpki::signed_data::SubjectPublicKeyInfo as webpki::der::FromDer>::from_der
267
268
    const TYPE_ID: DerTypeId = DerTypeId::SubjectPublicKeyInfo;
269
}