/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 | | } |