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}