/src/boringssl/pki/verify_signed_data.cc
Line | Count | Source |
1 | | // Copyright 2015 The Chromium Authors |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | | // you may not use this file except in compliance with the License. |
5 | | // You may obtain a copy of the License at |
6 | | // |
7 | | // https://www.apache.org/licenses/LICENSE-2.0 |
8 | | // |
9 | | // Unless required by applicable law or agreed to in writing, software |
10 | | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | | // See the License for the specific language governing permissions and |
13 | | // limitations under the License. |
14 | | |
15 | | #include "verify_signed_data.h" |
16 | | |
17 | | #include <iterator> |
18 | | |
19 | | #include <openssl/bytestring.h> |
20 | | #include <openssl/digest.h> |
21 | | #include <openssl/err.h> |
22 | | #include <openssl/evp.h> |
23 | | #include <openssl/pki/signature_verify_cache.h> |
24 | | #include <openssl/rsa.h> |
25 | | #include <openssl/sha2.h> |
26 | | |
27 | | #include "cert_errors.h" |
28 | | #include "input.h" |
29 | | #include "parse_values.h" |
30 | | #include "parser.h" |
31 | | #include "signature_algorithm.h" |
32 | | |
33 | | BSSL_NAMESPACE_BEGIN |
34 | | |
35 | | namespace { |
36 | | |
37 | | bool SHA256UpdateWithLengthPrefixedData(SHA256_CTX *s_ctx, const uint8_t *data, |
38 | 0 | uint64_t length) { |
39 | 0 | return (SHA256_Update(s_ctx, reinterpret_cast<uint8_t *>(&length), |
40 | 0 | sizeof(length)) && |
41 | 0 | SHA256_Update(s_ctx, data, length)); |
42 | 0 | } |
43 | | |
44 | | // Increase to make incompatible changes in the computation of the |
45 | | // cache key. |
46 | | constexpr uint32_t VerifyCacheKeyVersion = 1; |
47 | | |
48 | | std::string SignatureVerifyCacheKey(std::string_view algorithm_name, |
49 | | der::Input signed_data, |
50 | | der::Input signature_value_bytes, |
51 | 0 | EVP_PKEY *public_key) { |
52 | 0 | SHA256_CTX s_ctx; |
53 | 0 | bssl::ScopedCBB public_key_cbb; |
54 | 0 | uint8_t digest[SHA256_DIGEST_LENGTH]; |
55 | 0 | uint32_t version = VerifyCacheKeyVersion; |
56 | 0 | if (CBB_init(public_key_cbb.get(), 128) && |
57 | 0 | EVP_marshal_public_key(public_key_cbb.get(), public_key) && |
58 | 0 | SHA256_Init(&s_ctx) && |
59 | 0 | SHA256_Update(&s_ctx, reinterpret_cast<uint8_t *>(&version), |
60 | 0 | sizeof(version)) && |
61 | 0 | SHA256UpdateWithLengthPrefixedData( |
62 | 0 | &s_ctx, reinterpret_cast<const uint8_t *>(algorithm_name.data()), |
63 | 0 | algorithm_name.length()) && |
64 | 0 | SHA256UpdateWithLengthPrefixedData(&s_ctx, CBB_data(public_key_cbb.get()), |
65 | 0 | CBB_len(public_key_cbb.get())) && |
66 | 0 | SHA256UpdateWithLengthPrefixedData(&s_ctx, signature_value_bytes.data(), |
67 | 0 | signature_value_bytes.size()) && |
68 | 0 | SHA256UpdateWithLengthPrefixedData(&s_ctx, signed_data.data(), |
69 | 0 | signed_data.size()) && |
70 | 0 | SHA256_Final(digest, &s_ctx)) { |
71 | 0 | return std::string(reinterpret_cast<char *>(digest), sizeof(digest)); |
72 | 0 | } |
73 | 0 | return std::string(); |
74 | 0 | } |
75 | | |
76 | | // Place an instance of this class on the call stack to automatically clear |
77 | | // the OpenSSL error stack on function exit. |
78 | | // TODO(crbug.com/boringssl/38): Remove this when the library is more robust to |
79 | | // leaving things in the error queue. |
80 | | class OpenSSLErrStackTracer { |
81 | | public: |
82 | 0 | ~OpenSSLErrStackTracer() { ERR_clear_error(); } |
83 | | }; |
84 | | |
85 | | } // namespace |
86 | | |
87 | | // Parses an RSA, EC, or ML-DSA public key from SPKI to an EVP_PKEY. Returns |
88 | | // true on success. |
89 | | // |
90 | | // This function only recognizes the "pk-rsa" (rsaEncryption) flavor of RSA |
91 | | // public key from RFC 5912. |
92 | | // |
93 | | // pk-rsa PUBLIC-KEY ::= { |
94 | | // IDENTIFIER rsaEncryption |
95 | | // KEY RSAPublicKey |
96 | | // PARAMS TYPE NULL ARE absent |
97 | | // -- Private key format not in this module -- |
98 | | // CERT-KEY-USAGE {digitalSignature, nonRepudiation, |
99 | | // keyEncipherment, dataEncipherment, keyCertSign, cRLSign} |
100 | | // } |
101 | | // |
102 | | // COMPATIBILITY NOTE: RFC 5912 and RFC 3279 are in disagreement on the value |
103 | | // of parameters for rsaEncryption. Whereas RFC 5912 says they must be absent, |
104 | | // RFC 3279 says they must be NULL: |
105 | | // |
106 | | // The rsaEncryption OID is intended to be used in the algorithm field |
107 | | // of a value of type AlgorithmIdentifier. The parameters field MUST |
108 | | // have ASN.1 type NULL for this algorithm identifier. |
109 | | // |
110 | | // Following RFC 3279 in this case. |
111 | | // |
112 | | // In the case of parsing EC keys, RFC 5912 describes all the ECDSA |
113 | | // signature algorithms as requiring a public key of type "pk-ec": |
114 | | // |
115 | | // pk-ec PUBLIC-KEY ::= { |
116 | | // IDENTIFIER id-ecPublicKey |
117 | | // KEY ECPoint |
118 | | // PARAMS TYPE ECParameters ARE required |
119 | | // -- Private key format not in this module -- |
120 | | // CERT-KEY-USAGE { digitalSignature, nonRepudiation, keyAgreement, |
121 | | // keyCertSign, cRLSign } |
122 | | // } |
123 | | // |
124 | | // Moreover RFC 5912 stipulates what curves are allowed. The ECParameters |
125 | | // MUST NOT use an implicitCurve or specificCurve for PKIX: |
126 | | // |
127 | | // ECParameters ::= CHOICE { |
128 | | // namedCurve CURVE.&id({NamedCurve}) |
129 | | // -- implicitCurve NULL |
130 | | // -- implicitCurve MUST NOT be used in PKIX |
131 | | // -- specifiedCurve SpecifiedCurve |
132 | | // -- specifiedCurve MUST NOT be used in PKIX |
133 | | // -- Details for specifiedCurve can be found in [X9.62] |
134 | | // -- Any future additions to this CHOICE should be coordinated |
135 | | // -- with ANSI X.9. |
136 | | // } |
137 | | // -- If you need to be able to decode ANSI X.9 parameter structures, |
138 | | // -- uncomment the implicitCurve and specifiedCurve above, and also |
139 | | // -- uncomment the following: |
140 | | // --(WITH COMPONENTS {namedCurve PRESENT}) |
141 | | // |
142 | | // The namedCurves are extensible. The ones described by RFC 5912 are: |
143 | | // |
144 | | // NamedCurve CURVE ::= { |
145 | | // { ID secp192r1 } | { ID sect163k1 } | { ID sect163r2 } | |
146 | | // { ID secp224r1 } | { ID sect233k1 } | { ID sect233r1 } | |
147 | | // { ID secp256r1 } | { ID sect283k1 } | { ID sect283r1 } | |
148 | | // { ID secp384r1 } | { ID sect409k1 } | { ID sect409r1 } | |
149 | | // { ID secp521r1 } | { ID sect571k1 } | { ID sect571r1 }, |
150 | | // ... -- Extensible |
151 | | // } |
152 | | bool ParsePublicKey(der::Input public_key_spki, |
153 | 0 | bssl::UniquePtr<EVP_PKEY> *public_key) { |
154 | | // Parse the SPKI to an EVP_PKEY. |
155 | 0 | OpenSSLErrStackTracer err_tracer; |
156 | 0 | const EVP_PKEY_ALG *const algs[] = { |
157 | 0 | EVP_pkey_rsa(), |
158 | 0 | EVP_pkey_ec_p256(), |
159 | 0 | EVP_pkey_ec_p384(), |
160 | | // TODO(davidben): Remove P-521 from here, or let callers configure this. |
161 | | // We don't advertise it in TLS. |
162 | 0 | EVP_pkey_ec_p521(), |
163 | 0 | EVP_pkey_ml_dsa_44(), |
164 | 0 | EVP_pkey_ml_dsa_65(), |
165 | 0 | EVP_pkey_ml_dsa_87(), |
166 | 0 | }; |
167 | 0 | public_key->reset(EVP_PKEY_from_subject_public_key_info( |
168 | 0 | public_key_spki.data(), public_key_spki.size(), algs, std::size(algs))); |
169 | 0 | return *public_key != nullptr; |
170 | 0 | } |
171 | | |
172 | | bool VerifySignedData(SignatureAlgorithm algorithm, der::Input signed_data, |
173 | | const der::BitString &signature_value, |
174 | 0 | EVP_PKEY *public_key, SignatureVerifyCache *cache) { |
175 | 0 | int expected_pkey_id = 1; |
176 | 0 | const EVP_MD *digest = nullptr; |
177 | 0 | bool is_rsa_pss = false; |
178 | 0 | std::string_view cache_algorithm_name; |
179 | 0 | switch (algorithm) { |
180 | 0 | case SignatureAlgorithm::kRsaPkcs1Sha1: |
181 | 0 | expected_pkey_id = EVP_PKEY_RSA; |
182 | 0 | digest = EVP_sha1(); |
183 | 0 | cache_algorithm_name = "RsaPkcs1Sha1"; |
184 | 0 | break; |
185 | 0 | case SignatureAlgorithm::kRsaPkcs1Sha256: |
186 | 0 | expected_pkey_id = EVP_PKEY_RSA; |
187 | 0 | digest = EVP_sha256(); |
188 | 0 | cache_algorithm_name = "RsaPkcs1Sha256"; |
189 | 0 | break; |
190 | 0 | case SignatureAlgorithm::kRsaPkcs1Sha384: |
191 | 0 | expected_pkey_id = EVP_PKEY_RSA; |
192 | 0 | digest = EVP_sha384(); |
193 | 0 | cache_algorithm_name = "RsaPkcs1Sha384"; |
194 | 0 | break; |
195 | 0 | case SignatureAlgorithm::kRsaPkcs1Sha512: |
196 | 0 | expected_pkey_id = EVP_PKEY_RSA; |
197 | 0 | digest = EVP_sha512(); |
198 | 0 | cache_algorithm_name = "RsaPkcs1Sha512"; |
199 | 0 | break; |
200 | | |
201 | 0 | case SignatureAlgorithm::kEcdsaSha1: |
202 | 0 | expected_pkey_id = EVP_PKEY_EC; |
203 | 0 | digest = EVP_sha1(); |
204 | 0 | cache_algorithm_name = "EcdsaSha1"; |
205 | 0 | break; |
206 | 0 | case SignatureAlgorithm::kEcdsaSha256: |
207 | 0 | expected_pkey_id = EVP_PKEY_EC; |
208 | 0 | digest = EVP_sha256(); |
209 | 0 | cache_algorithm_name = "EcdsaSha256"; |
210 | 0 | break; |
211 | 0 | case SignatureAlgorithm::kEcdsaSha384: |
212 | 0 | expected_pkey_id = EVP_PKEY_EC; |
213 | 0 | digest = EVP_sha384(); |
214 | 0 | cache_algorithm_name = "EcdsaSha384"; |
215 | 0 | break; |
216 | 0 | case SignatureAlgorithm::kEcdsaSha512: |
217 | 0 | expected_pkey_id = EVP_PKEY_EC; |
218 | 0 | digest = EVP_sha512(); |
219 | 0 | cache_algorithm_name = "EcdsaSha512"; |
220 | 0 | break; |
221 | | |
222 | 0 | case SignatureAlgorithm::kRsaPssSha256: |
223 | 0 | expected_pkey_id = EVP_PKEY_RSA; |
224 | 0 | digest = EVP_sha256(); |
225 | 0 | cache_algorithm_name = "RsaPssSha256"; |
226 | 0 | is_rsa_pss = true; |
227 | 0 | break; |
228 | 0 | case SignatureAlgorithm::kRsaPssSha384: |
229 | 0 | expected_pkey_id = EVP_PKEY_RSA; |
230 | 0 | digest = EVP_sha384(); |
231 | 0 | cache_algorithm_name = "RsaPssSha384"; |
232 | 0 | is_rsa_pss = true; |
233 | 0 | break; |
234 | 0 | case SignatureAlgorithm::kRsaPssSha512: |
235 | 0 | expected_pkey_id = EVP_PKEY_RSA; |
236 | 0 | digest = EVP_sha512(); |
237 | 0 | cache_algorithm_name = "RsaPssSha512"; |
238 | 0 | is_rsa_pss = true; |
239 | 0 | break; |
240 | | |
241 | 0 | case SignatureAlgorithm::kMtcProofDraftDavidben08: |
242 | | // This function can't verify MTC proofs. |
243 | 0 | return false; |
244 | | |
245 | 0 | case SignatureAlgorithm::kMldsa44: |
246 | 0 | expected_pkey_id = EVP_PKEY_ML_DSA_44; |
247 | 0 | cache_algorithm_name = "Mldsa44"; |
248 | 0 | break; |
249 | 0 | case SignatureAlgorithm::kMldsa65: |
250 | 0 | expected_pkey_id = EVP_PKEY_ML_DSA_65; |
251 | 0 | cache_algorithm_name = "Mldsa65"; |
252 | 0 | break; |
253 | 0 | case SignatureAlgorithm::kMldsa87: |
254 | 0 | expected_pkey_id = EVP_PKEY_ML_DSA_87; |
255 | 0 | cache_algorithm_name = "Mldsa87"; |
256 | 0 | break; |
257 | 0 | } |
258 | | |
259 | 0 | if (expected_pkey_id != EVP_PKEY_id(public_key)) { |
260 | 0 | return false; |
261 | 0 | } |
262 | | |
263 | | // For the supported algorithms the signature value must be a whole |
264 | | // number of bytes. |
265 | 0 | if (signature_value.unused_bits() != 0) { |
266 | 0 | return false; |
267 | 0 | } |
268 | 0 | der::Input signature_value_bytes = signature_value.bytes(); |
269 | |
|
270 | 0 | std::string cache_key; |
271 | 0 | if (cache) { |
272 | 0 | cache_key = SignatureVerifyCacheKey(cache_algorithm_name, signed_data, |
273 | 0 | signature_value_bytes, public_key); |
274 | 0 | if (!cache_key.empty()) { |
275 | 0 | switch (cache->Check(cache_key)) { |
276 | 0 | case SignatureVerifyCache::Value::kValid: |
277 | 0 | return true; |
278 | 0 | case SignatureVerifyCache::Value::kInvalid: |
279 | 0 | return false; |
280 | 0 | case SignatureVerifyCache::Value::kUnknown: |
281 | 0 | break; |
282 | 0 | } |
283 | 0 | } |
284 | 0 | } |
285 | | |
286 | 0 | OpenSSLErrStackTracer err_tracer; |
287 | |
|
288 | 0 | bssl::ScopedEVP_MD_CTX ctx; |
289 | 0 | EVP_PKEY_CTX *pctx = nullptr; // Owned by `ctx`. |
290 | |
|
291 | 0 | if (!EVP_DigestVerifyInit(ctx.get(), &pctx, digest, nullptr, public_key)) { |
292 | 0 | return false; |
293 | 0 | } |
294 | | |
295 | 0 | if (is_rsa_pss) { |
296 | | // All supported RSASSA-PSS algorithms match signing and MGF-1 digest. They |
297 | | // also use the digest length as the salt length, which is specified with -1 |
298 | | // in OpenSSL's API. |
299 | 0 | if (!EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) || |
300 | 0 | !EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, RSA_PSS_SALTLEN_DIGEST)) { |
301 | 0 | return false; |
302 | 0 | } |
303 | 0 | } |
304 | | |
305 | 0 | bool ret = 1 == EVP_DigestVerify(ctx.get(), signature_value_bytes.data(), |
306 | 0 | signature_value_bytes.size(), |
307 | 0 | signed_data.data(), signed_data.size()); |
308 | 0 | if (!cache_key.empty()) { |
309 | 0 | cache->Store(cache_key, ret ? SignatureVerifyCache::Value::kValid |
310 | 0 | : SignatureVerifyCache::Value::kInvalid); |
311 | 0 | } |
312 | |
|
313 | 0 | return ret; |
314 | 0 | } |
315 | | |
316 | | bool VerifySignedData(SignatureAlgorithm algorithm, der::Input signed_data, |
317 | | const der::BitString &signature_value, |
318 | 0 | der::Input public_key_spki, SignatureVerifyCache *cache) { |
319 | 0 | bssl::UniquePtr<EVP_PKEY> public_key; |
320 | 0 | if (!ParsePublicKey(public_key_spki, &public_key)) { |
321 | 0 | return false; |
322 | 0 | } |
323 | 0 | return VerifySignedData(algorithm, signed_data, signature_value, |
324 | 0 | public_key.get(), cache); |
325 | 0 | } |
326 | | |
327 | | BSSL_NAMESPACE_END |