webpki/
signed_data.rs

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
15use crate::der::{self, FromDer};
16use crate::error::{DerTypeId, Error};
17use crate::verify_cert::Budget;
18
19use pki_types::{AlgorithmIdentifier, SignatureVerificationAlgorithm};
20
21#[cfg(feature = "alloc")]
22use alloc::vec::Vec;
23
24/// X.509 certificates and related items that are signed are almost always
25/// encoded in the format "tbs||signatureAlgorithm||signature". This structure
26/// captures this pattern as an owned data type.
27#[cfg(feature = "alloc")]
28#[derive(Clone, Debug)]
29pub(crate) struct OwnedSignedData {
30    /// The signed data. This would be `tbsCertificate` in the case of an X.509
31    /// certificate, `tbsResponseData` in the case of an OCSP response, `tbsCertList`
32    /// in the case of a CRL, and the data nested in the `digitally-signed` construct for
33    /// TLS 1.2 signed data.
34    pub(crate) data: Vec<u8>,
35
36    /// The value of the `AlgorithmIdentifier`. This would be
37    /// `signatureAlgorithm` in the case of an X.509 certificate, OCSP
38    /// response or CRL. This would have to be synthesized in the case of TLS 1.2
39    /// signed data, since TLS does not identify algorithms by ASN.1 OIDs.
40    pub(crate) algorithm: Vec<u8>,
41
42    /// The value of the signature. This would be `signature` in an X.509
43    /// certificate, OCSP response or CRL. This would be the value of
44    /// `DigitallySigned.signature` for TLS 1.2 signed data.
45    pub(crate) signature: Vec<u8>,
46}
47
48#[cfg(feature = "alloc")]
49impl OwnedSignedData {
50    /// Return a borrowed [`SignedData`] from the owned representation.
51    pub(crate) fn borrow(&self) -> SignedData<'_> {
52        SignedData {
53            data: untrusted::Input::from(&self.data),
54            algorithm: untrusted::Input::from(&self.algorithm),
55            signature: untrusted::Input::from(&self.signature),
56        }
57    }
58}
59
60/// X.509 certificates and related items that are signed are almost always
61/// encoded in the format "tbs||signatureAlgorithm||signature". This structure
62/// captures this pattern.
63#[derive(Debug)]
64pub(crate) struct SignedData<'a> {
65    /// The signed data. This would be `tbsCertificate` in the case of an X.509
66    /// certificate, `tbsResponseData` in the case of an OCSP response, `tbsCertList`
67    /// in the case of a CRL, and the data nested in the `digitally-signed` construct for
68    /// TLS 1.2 signed data.
69    pub(crate) data: untrusted::Input<'a>,
70
71    /// The value of the `AlgorithmIdentifier`. This would be
72    /// `signatureAlgorithm` in the case of an X.509 certificate, OCSP
73    /// response or CRL. This would have to be synthesized in the case of TLS 1.2
74    /// signed data, since TLS does not identify algorithms by ASN.1 OIDs.
75    pub(crate) algorithm: untrusted::Input<'a>,
76
77    /// The value of the signature. This would be `signature` in an X.509
78    /// certificate, OCSP response or CRL. This would be the value of
79    /// `DigitallySigned.signature` for TLS 1.2 signed data.
80    pub(crate) signature: untrusted::Input<'a>,
81}
82
83impl<'a> SignedData<'a> {
84    /// Parses the concatenation of "tbs||signatureAlgorithm||signature" that
85    /// is common in the X.509 certificate and OCSP response syntaxes.
86    ///
87    /// X.509 Certificates (RFC 5280) look like this:
88    ///
89    /// ```ASN.1
90    /// Certificate (SEQUENCE) {
91    ///     tbsCertificate TBSCertificate,
92    ///     signatureAlgorithm AlgorithmIdentifier,
93    ///     signatureValue BIT STRING
94    /// }
95    /// ```
96    ///
97    /// OCSP responses (RFC 6960) look like this:
98    /// ```ASN.1
99    /// BasicOCSPResponse {
100    ///     tbsResponseData ResponseData,
101    ///     signatureAlgorithm AlgorithmIdentifier,
102    ///     signature BIT STRING,
103    ///     certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL
104    /// }
105    /// ```
106    ///
107    /// Note that this function does NOT parse the outermost `SEQUENCE` or the
108    /// `certs` value.
109    ///
110    /// The return value's first component is the contents of
111    /// `tbsCertificate`/`tbsResponseData`; the second component is a `SignedData`
112    /// structure that can be passed to `verify_signed_data`.
113    ///
114    /// The provided size_limit will enforce the largest possible outermost `SEQUENCE` this
115    /// function will read.
116    pub(crate) fn from_der(
117        der: &mut untrusted::Reader<'a>,
118        size_limit: usize,
119    ) -> Result<(untrusted::Input<'a>, Self), Error> {
120        let (data, tbs) = der.read_partial(|input| {
121            der::expect_tag_and_get_value_limited(input, der::Tag::Sequence, size_limit)
122        })?;
123        let algorithm = der::expect_tag(der, der::Tag::Sequence)?;
124        let signature = der::bit_string_with_no_unused_bits(der)?;
125
126        Ok((
127            tbs,
128            SignedData {
129                data,
130                algorithm,
131                signature,
132            },
133        ))
134    }
135
136    /// Convert the borrowed signed data to an [`OwnedSignedData`].
137    #[cfg(feature = "alloc")]
138    pub(crate) fn to_owned(&self) -> OwnedSignedData {
139        OwnedSignedData {
140            data: self.data.as_slice_less_safe().to_vec(),
141            algorithm: self.algorithm.as_slice_less_safe().to_vec(),
142            signature: self.signature.as_slice_less_safe().to_vec(),
143        }
144    }
145}
146
147/// Verify `signed_data` using the public key in the DER-encoded
148/// SubjectPublicKeyInfo `spki` using one of the algorithms in
149/// `supported_algorithms`.
150///
151/// The algorithm is chosen based on the algorithm information encoded in the
152/// algorithm identifiers in `public_key` and `signed_data.algorithm`. The
153/// ordering of the algorithms in `supported_algorithms` does not really matter,
154/// but generally more common algorithms should go first, as it is scanned
155/// linearly for matches.
156pub(crate) fn verify_signed_data(
157    supported_algorithms: &[&dyn SignatureVerificationAlgorithm],
158    spki_value: untrusted::Input<'_>,
159    signed_data: &SignedData<'_>,
160    budget: &mut Budget,
161) -> Result<(), Error> {
162    budget.consume_signature()?;
163
164    // We need to verify the signature in `signed_data` using the public key
165    // in `public_key`. In order to know which *ring* signature verification
166    // algorithm to use, we need to know the public key algorithm (ECDSA,
167    // RSA PKCS#1, etc.), the curve (if applicable), and the digest algorithm.
168    // `signed_data` identifies only the public key algorithm and the digest
169    // algorithm, and `public_key` identifies only the public key algorithm and
170    // the curve (if any). Thus, we have to combine information from both
171    // inputs to figure out which `ring::signature::VerificationAlgorithm` to
172    // use to verify the signature.
173    //
174    // This is all further complicated by the fact that we don't have any
175    // implicit knowledge about any algorithms or identifiers, since all of
176    // that information is encoded in `supported_algorithms.` In particular, we
177    // avoid hard-coding any of that information so that (link-time) dead code
178    // elimination will work effectively in eliminating code for unused
179    // algorithms.
180
181    // Parse the signature.
182    //
183    let mut found_signature_alg_match = false;
184    for supported_alg in supported_algorithms
185        .iter()
186        .filter(|alg| alg.signature_alg_id().as_ref() == signed_data.algorithm.as_slice_less_safe())
187    {
188        match verify_signature(
189            *supported_alg,
190            spki_value,
191            signed_data.data,
192            signed_data.signature,
193        ) {
194            Err(Error::UnsupportedSignatureAlgorithmForPublicKey) => {
195                found_signature_alg_match = true;
196                continue;
197            }
198            result => {
199                return result;
200            }
201        }
202    }
203
204    if found_signature_alg_match {
205        Err(Error::UnsupportedSignatureAlgorithmForPublicKey)
206    } else {
207        Err(Error::UnsupportedSignatureAlgorithm)
208    }
209}
210
211pub(crate) fn verify_signature(
212    signature_alg: &dyn SignatureVerificationAlgorithm,
213    spki_value: untrusted::Input<'_>,
214    msg: untrusted::Input<'_>,
215    signature: untrusted::Input<'_>,
216) -> Result<(), Error> {
217    let spki = der::read_all::<SubjectPublicKeyInfo<'_>>(spki_value)?;
218    if signature_alg.public_key_alg_id().as_ref() != spki.algorithm_id_value.as_slice_less_safe() {
219        return Err(Error::UnsupportedSignatureAlgorithmForPublicKey);
220    }
221
222    signature_alg
223        .verify_signature(
224            spki.key_value.as_slice_less_safe(),
225            msg.as_slice_less_safe(),
226            signature.as_slice_less_safe(),
227        )
228        .map_err(|_| Error::InvalidSignatureForPublicKey)
229}
230
231pub(crate) struct SubjectPublicKeyInfo<'a> {
232    algorithm_id_value: untrusted::Input<'a>,
233    key_value: untrusted::Input<'a>,
234}
235
236impl<'a> FromDer<'a> for SubjectPublicKeyInfo<'a> {
237    // Parse the public key into an algorithm OID, an optional curve OID, and the
238    // key value. The caller needs to check whether these match the
239    // `PublicKeyAlgorithm` for the `SignatureVerificationAlgorithm` that is matched when
240    // parsing the signature.
241    fn from_der(reader: &mut untrusted::Reader<'a>) -> Result<Self, Error> {
242        let algorithm_id_value = der::expect_tag(reader, der::Tag::Sequence)?;
243        let key_value = der::bit_string_with_no_unused_bits(reader)?;
244        Ok(SubjectPublicKeyInfo {
245            algorithm_id_value,
246            key_value,
247        })
248    }
249
250    const TYPE_ID: DerTypeId = DerTypeId::SubjectPublicKeyInfo;
251}
252
253/// Encodings of the PKIX AlgorithmIdentifier type.
254///
255/// This module contains a set of common values, and exists to keep the
256/// names of these separate from the actual algorithm implementations.
257pub mod alg_id {
258    use super::AlgorithmIdentifier;
259
260    // See src/data/README.md.
261
262    /// AlgorithmIdentifier for `id-ecPublicKey` with named curve `secp256r1`.
263    pub const ECDSA_P256: AlgorithmIdentifier =
264        AlgorithmIdentifier::from_slice(include_bytes!("data/alg-ecdsa-p256.der"));
265
266    /// AlgorithmIdentifier for `id-ecPublicKey` with named curve `secp384r1`.
267    pub const ECDSA_P384: AlgorithmIdentifier =
268        AlgorithmIdentifier::from_slice(include_bytes!("data/alg-ecdsa-p384.der"));
269
270    /// AlgorithmIdentifier for `id-ecPublicKey` with named curve `secp521r1`.
271    pub const ECDSA_P521: AlgorithmIdentifier =
272        AlgorithmIdentifier::from_slice(include_bytes!("data/alg-ecdsa-p521.der"));
273
274    /// AlgorithmIdentifier for `ecdsa-with-SHA256`.
275    pub const ECDSA_SHA256: AlgorithmIdentifier =
276        AlgorithmIdentifier::from_slice(include_bytes!("data/alg-ecdsa-sha256.der"));
277
278    /// AlgorithmIdentifier for `ecdsa-with-SHA384`.
279    pub const ECDSA_SHA384: AlgorithmIdentifier =
280        AlgorithmIdentifier::from_slice(include_bytes!("data/alg-ecdsa-sha384.der"));
281
282    /// AlgorithmIdentifier for `ecdsa-with-SHA512`.
283    pub const ECDSA_SHA512: AlgorithmIdentifier =
284        AlgorithmIdentifier::from_slice(include_bytes!("data/alg-ecdsa-sha512.der"));
285
286    /// AlgorithmIdentifier for `rsaEncryption`.
287    pub const RSA_ENCRYPTION: AlgorithmIdentifier =
288        AlgorithmIdentifier::from_slice(include_bytes!("data/alg-rsa-encryption.der"));
289
290    /// AlgorithmIdentifier for `sha256WithRSAEncryption`.
291    pub const RSA_PKCS1_SHA256: AlgorithmIdentifier =
292        AlgorithmIdentifier::from_slice(include_bytes!("data/alg-rsa-pkcs1-sha256.der"));
293
294    /// AlgorithmIdentifier for `sha384WithRSAEncryption`.
295    pub const RSA_PKCS1_SHA384: AlgorithmIdentifier =
296        AlgorithmIdentifier::from_slice(include_bytes!("data/alg-rsa-pkcs1-sha384.der"));
297
298    /// AlgorithmIdentifier for `sha512WithRSAEncryption`.
299    pub const RSA_PKCS1_SHA512: AlgorithmIdentifier =
300        AlgorithmIdentifier::from_slice(include_bytes!("data/alg-rsa-pkcs1-sha512.der"));
301
302    /// AlgorithmIdentifier for `rsassaPss` with:
303    ///
304    /// - hashAlgorithm: sha256
305    /// - maskGenAlgorithm: mgf1 with sha256
306    /// - saltLength: 32
307    pub const RSA_PSS_SHA256: AlgorithmIdentifier =
308        AlgorithmIdentifier::from_slice(include_bytes!("data/alg-rsa-pss-sha256.der"));
309
310    /// AlgorithmIdentifier for `rsassaPss` with:
311    ///
312    /// - hashAlgorithm: sha384
313    /// - maskGenAlgorithm: mgf1 with sha384
314    /// - saltLength: 48
315    pub const RSA_PSS_SHA384: AlgorithmIdentifier =
316        AlgorithmIdentifier::from_slice(include_bytes!("data/alg-rsa-pss-sha384.der"));
317
318    /// AlgorithmIdentifier for `rsassaPss` with:
319    ///
320    /// - hashAlgorithm: sha512
321    /// - maskGenAlgorithm: mgf1 with sha512
322    /// - saltLength: 64
323    pub const RSA_PSS_SHA512: AlgorithmIdentifier =
324        AlgorithmIdentifier::from_slice(include_bytes!("data/alg-rsa-pss-sha512.der"));
325
326    /// AlgorithmIdentifier for `ED25519`.
327    pub const ED25519: AlgorithmIdentifier =
328        AlgorithmIdentifier::from_slice(include_bytes!("data/alg-ed25519.der"));
329}