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::{
17    DerTypeId, Error, UnsupportedSignatureAlgorithmContext,
18    UnsupportedSignatureAlgorithmForPublicKeyContext,
19};
20use crate::verify_cert::Budget;
21
22use pki_types::SignatureVerificationAlgorithm;
23
24#[cfg(feature = "alloc")]
25use 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)]
32pub(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")]
52impl OwnedSignedData {
53    /// Return a borrowed [`SignedData`] from the owned representation.
54    pub(crate) fn borrow(&self) -> SignedData<'_> {
55        SignedData {
56            data: untrusted::Input::from(&self.data),
57            algorithm: untrusted::Input::from(&self.algorithm),
58            signature: untrusted::Input::from(&self.signature),
59        }
60    }
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)]
67pub(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
86impl<'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    pub(crate) fn from_der(
120        der: &mut untrusted::Reader<'a>,
121        size_limit: usize,
122    ) -> Result<(untrusted::Input<'a>, Self), Error> {
123        let (data, tbs) = der.read_partial(|input| {
124            der::expect_tag_and_get_value_limited(input, der::Tag::Sequence, size_limit)
125        })?;
126        let algorithm = der::expect_tag(der, der::Tag::Sequence)?;
127        let signature = der::bit_string_with_no_unused_bits(der)?;
128
129        Ok((
130            tbs,
131            SignedData {
132                data,
133                algorithm,
134                signature,
135            },
136        ))
137    }
138
139    /// Convert the borrowed signed data to an [`OwnedSignedData`].
140    #[cfg(feature = "alloc")]
141    pub(crate) fn to_owned(&self) -> OwnedSignedData {
142        OwnedSignedData {
143            data: self.data.as_slice_less_safe().to_vec(),
144            algorithm: self.algorithm.as_slice_less_safe().to_vec(),
145            signature: self.signature.as_slice_less_safe().to_vec(),
146        }
147    }
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.
159pub(crate) fn verify_signed_data(
160    supported_algorithms: &[&dyn SignatureVerificationAlgorithm],
161    spki_value: untrusted::Input<'_>,
162    signed_data: &SignedData<'_>,
163    budget: &mut Budget,
164) -> Result<(), Error> {
165    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    let mut invalid_for_public_key = None;
187    for supported_alg in supported_algorithms
188        .iter()
189        .filter(|alg| alg.signature_alg_id().as_ref() == signed_data.algorithm.as_slice_less_safe())
190    {
191        match verify_signature(
192            *supported_alg,
193            spki_value,
194            signed_data.data,
195            signed_data.signature,
196        ) {
197            Err(Error::UnsupportedSignatureAlgorithmForPublicKeyContext(cx)) => {
198                invalid_for_public_key = Some(cx);
199                continue;
200            }
201            result => return result,
202        }
203    }
204
205    if let Some(cx) = invalid_for_public_key {
206        return Err(Error::UnsupportedSignatureAlgorithmForPublicKeyContext(cx));
207    }
208
209    Err(Error::UnsupportedSignatureAlgorithmContext(
210        UnsupportedSignatureAlgorithmContext {
211            #[cfg(feature = "alloc")]
212            signature_algorithm_id: signed_data.algorithm.as_slice_less_safe().to_vec(),
213            #[cfg(feature = "alloc")]
214            supported_algorithms: supported_algorithms
215                .iter()
216                .map(|&alg| alg.signature_alg_id())
217                .collect(),
218        },
219    ))
220}
221
222pub(crate) fn verify_signature(
223    signature_alg: &dyn SignatureVerificationAlgorithm,
224    spki_value: untrusted::Input<'_>,
225    msg: untrusted::Input<'_>,
226    signature: untrusted::Input<'_>,
227) -> Result<(), Error> {
228    let spki = der::read_all::<SubjectPublicKeyInfo<'_>>(spki_value)?;
229    if signature_alg.public_key_alg_id().as_ref() != spki.algorithm_id_value.as_slice_less_safe() {
230        return Err(Error::UnsupportedSignatureAlgorithmForPublicKeyContext(
231            UnsupportedSignatureAlgorithmForPublicKeyContext {
232                #[cfg(feature = "alloc")]
233                signature_algorithm_id: signature_alg.signature_alg_id().as_ref().to_vec(),
234                #[cfg(feature = "alloc")]
235                public_key_algorithm_id: spki.algorithm_id_value.as_slice_less_safe().to_vec(),
236            },
237        ));
238    }
239
240    signature_alg
241        .verify_signature(
242            spki.key_value.as_slice_less_safe(),
243            msg.as_slice_less_safe(),
244            signature.as_slice_less_safe(),
245        )
246        .map_err(|_| Error::InvalidSignatureForPublicKey)
247}
248
249pub(crate) struct SubjectPublicKeyInfo<'a> {
250    algorithm_id_value: untrusted::Input<'a>,
251    key_value: untrusted::Input<'a>,
252}
253
254impl<'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    fn from_der(reader: &mut untrusted::Reader<'a>) -> Result<Self, Error> {
260        let algorithm_id_value = der::expect_tag(reader, der::Tag::Sequence)?;
261        let key_value = der::bit_string_with_no_unused_bits(reader)?;
262        Ok(SubjectPublicKeyInfo {
263            algorithm_id_value,
264            key_value,
265        })
266    }
267
268    const TYPE_ID: DerTypeId = DerTypeId::SubjectPublicKeyInfo;
269}