/rust/registry/src/index.crates.io-1949cf8c6b5b557f/rustls-webpki-0.104.0-alpha.2/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, Hash)] |
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 | } |
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 | 11.3k | pub(crate) fn from_der( |
120 | 11.3k | der: &mut untrusted::Reader<'a>, |
121 | 11.3k | size_limit: usize, |
122 | 11.3k | ) -> Result<(untrusted::Input<'a>, Self), Error> { |
123 | 11.3k | let (data, tbs) = der.read_partial(|input| { |
124 | 11.3k | der::expect_tag_and_get_value_limited(input, der::Tag::Sequence, size_limit) |
125 | 11.3k | })?; |
126 | 11.2k | let algorithm = der::expect_tag(der, der::Tag::Sequence)?; |
127 | 11.1k | let signature = der::bit_string_with_no_unused_bits(der)?; |
128 | | |
129 | 11.1k | Ok(( |
130 | 11.1k | tbs, |
131 | 11.1k | SignedData { |
132 | 11.1k | data, |
133 | 11.1k | algorithm, |
134 | 11.1k | signature, |
135 | 11.1k | }, |
136 | 11.1k | )) |
137 | 11.3k | } |
138 | | |
139 | | /// Verify `signed_data` using the public key in the DER-encoded |
140 | | /// SubjectPublicKeyInfo `spki` using one of the algorithms in |
141 | | /// `supported_algorithms`. |
142 | | /// |
143 | | /// The algorithm is chosen based on the algorithm information encoded in the |
144 | | /// algorithm identifiers in `public_key` and `signed_data.algorithm`. The |
145 | | /// ordering of the algorithms in `supported_algorithms` does not really matter, |
146 | | /// but generally more common algorithms should go first, as it is scanned |
147 | | /// linearly for matches. |
148 | 762 | pub(crate) fn verify( |
149 | 762 | &self, |
150 | 762 | supported_algorithms: &[&dyn SignatureVerificationAlgorithm], |
151 | 762 | spki_value: untrusted::Input<'_>, |
152 | 762 | budget: &mut Budget, |
153 | 762 | ) -> Result<(), Error> { |
154 | 762 | budget.consume_signature()?; |
155 | | |
156 | | // We need to verify the signature in `signed_data` using the public key |
157 | | // in `public_key`. In order to know which *ring* signature verification |
158 | | // algorithm to use, we need to know the public key algorithm (ECDSA, |
159 | | // RSA PKCS#1, etc.), the curve (if applicable), and the digest algorithm. |
160 | | // `signed_data` identifies only the public key algorithm and the digest |
161 | | // algorithm, and `public_key` identifies only the public key algorithm and |
162 | | // the curve (if any). Thus, we have to combine information from both |
163 | | // inputs to figure out which `ring::signature::VerificationAlgorithm` to |
164 | | // use to verify the signature. |
165 | | // |
166 | | // This is all further complicated by the fact that we don't have any |
167 | | // implicit knowledge about any algorithms or identifiers, since all of |
168 | | // that information is encoded in `supported_algorithms.` In particular, we |
169 | | // avoid hard-coding any of that information so that (link-time) dead code |
170 | | // elimination will work effectively in eliminating code for unused |
171 | | // algorithms. |
172 | | |
173 | | // Parse the signature. |
174 | | // |
175 | 762 | let mut invalid_for_public_key = None; |
176 | 762 | for supported_alg in supported_algorithms |
177 | 762 | .iter() |
178 | 762 | .filter(|alg| alg.signature_alg_id().as_ref() == self.algorithm.as_slice_less_safe()) |
179 | | { |
180 | 754 | match verify_signature(*supported_alg, spki_value, self.data, self.signature) { |
181 | 0 | Err(Error::UnsupportedSignatureAlgorithmForPublicKey(cx)) => { |
182 | 0 | invalid_for_public_key = Some(cx); |
183 | 0 | continue; |
184 | | } |
185 | 754 | result => return result, |
186 | | } |
187 | | } |
188 | | |
189 | 8 | if let Some(cx) = invalid_for_public_key { |
190 | 0 | return Err(Error::UnsupportedSignatureAlgorithmForPublicKey(cx)); |
191 | 8 | } |
192 | | |
193 | | Err(Error::UnsupportedSignatureAlgorithm( |
194 | | UnsupportedSignatureAlgorithmContext { |
195 | | #[cfg(feature = "alloc")] |
196 | 8 | signature_algorithm_id: self.algorithm.as_slice_less_safe().to_vec(), |
197 | | #[cfg(feature = "alloc")] |
198 | 8 | supported_algorithms: supported_algorithms |
199 | 8 | .iter() |
200 | 8 | .map(|&alg| alg.signature_alg_id()) |
201 | 8 | .collect(), |
202 | | }, |
203 | | )) |
204 | 762 | } |
205 | | |
206 | | /// Convert the borrowed signed data to an [`OwnedSignedData`]. |
207 | | #[cfg(feature = "alloc")] |
208 | 0 | pub(crate) fn to_owned(&self) -> OwnedSignedData { |
209 | 0 | OwnedSignedData { |
210 | 0 | data: self.data.as_slice_less_safe().to_vec(), |
211 | 0 | algorithm: self.algorithm.as_slice_less_safe().to_vec(), |
212 | 0 | signature: self.signature.as_slice_less_safe().to_vec(), |
213 | 0 | } |
214 | 0 | } |
215 | | } |
216 | | |
217 | | impl core::hash::Hash for SignedData<'_> { |
218 | 0 | fn hash<H: core::hash::Hasher>(&self, state: &mut H) { |
219 | 0 | let Self { |
220 | 0 | data, |
221 | 0 | algorithm, |
222 | 0 | signature, |
223 | 0 | } = self; |
224 | 0 | data.as_slice_less_safe().hash(state); |
225 | 0 | algorithm.as_slice_less_safe().hash(state); |
226 | 0 | signature.as_slice_less_safe().hash(state); |
227 | 0 | } Unexecuted instantiation: <webpki::signed_data::SignedData as core::hash::Hash>::hash::<rustls::core_hash_polyfill::DynHasher> Unexecuted instantiation: <webpki::signed_data::SignedData as core::hash::Hash>::hash::<_> |
228 | | } |
229 | | |
230 | 1.14k | pub(crate) fn verify_signature( |
231 | 1.14k | signature_alg: &dyn SignatureVerificationAlgorithm, |
232 | 1.14k | spki_value: untrusted::Input<'_>, |
233 | 1.14k | msg: untrusted::Input<'_>, |
234 | 1.14k | signature: untrusted::Input<'_>, |
235 | 1.14k | ) -> Result<(), Error> { |
236 | 1.14k | let spki = der::read_all::<SubjectPublicKeyInfo<'_>>(spki_value)?; |
237 | 1.14k | if signature_alg.public_key_alg_id().as_ref() != spki.algorithm_id_value.as_slice_less_safe() { |
238 | 11 | return Err(Error::UnsupportedSignatureAlgorithmForPublicKey( |
239 | 11 | UnsupportedSignatureAlgorithmForPublicKeyContext { |
240 | 11 | #[cfg(feature = "alloc")] |
241 | 11 | signature_algorithm_id: signature_alg.signature_alg_id().as_ref().to_vec(), |
242 | 11 | #[cfg(feature = "alloc")] |
243 | 11 | public_key_algorithm_id: spki.algorithm_id_value.as_slice_less_safe().to_vec(), |
244 | 11 | }, |
245 | 11 | )); |
246 | 1.13k | } |
247 | | |
248 | 1.13k | signature_alg |
249 | 1.13k | .verify_signature( |
250 | 1.13k | spki.key_value.as_slice_less_safe(), |
251 | 1.13k | msg.as_slice_less_safe(), |
252 | 1.13k | signature.as_slice_less_safe(), |
253 | | ) |
254 | 1.13k | .map_err(|_| Error::InvalidSignatureForPublicKey) |
255 | 1.14k | } |
256 | | |
257 | | pub(crate) struct SubjectPublicKeyInfo<'a> { |
258 | | algorithm_id_value: untrusted::Input<'a>, |
259 | | key_value: untrusted::Input<'a>, |
260 | | } |
261 | | |
262 | | impl<'a> FromDer<'a> for SubjectPublicKeyInfo<'a> { |
263 | | // Parse the public key into an algorithm OID, an optional curve OID, and the |
264 | | // key value. The caller needs to check whether these match the |
265 | | // `PublicKeyAlgorithm` for the `SignatureVerificationAlgorithm` that is matched when |
266 | | // parsing the signature. |
267 | 1.14k | fn from_der(reader: &mut untrusted::Reader<'a>) -> Result<Self, Error> { |
268 | 1.14k | let algorithm_id_value = der::expect_tag(reader, der::Tag::Sequence)?; |
269 | 1.14k | let key_value = der::bit_string_with_no_unused_bits(reader)?; |
270 | 1.14k | Ok(SubjectPublicKeyInfo { |
271 | 1.14k | algorithm_id_value, |
272 | 1.14k | key_value, |
273 | 1.14k | }) |
274 | 1.14k | } |
275 | | |
276 | | const TYPE_ID: DerTypeId = DerTypeId::SubjectPublicKeyInfo; |
277 | | } |