OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/cert/internal/verify_signed_data.h" | 5 #include "net/cert/internal/verify_signed_data.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 | 8 |
9 // TODO(eroman): There is no intention to implement this for non-OpenSSL. Remove | 9 // TODO(eroman): There is no intention to implement this for non-OpenSSL. Remove |
10 // this branch once the migration is complete. This could have been done as a | 10 // this branch once the migration is complete. This could have been done as a |
11 // conditional file (_openssl.cc) in the build file instead, but that is likely | 11 // conditional file (_openssl.cc) in the build file instead, but that is likely |
12 // not worth the effort at this point. | 12 // not worth the effort at this point. |
13 | 13 |
14 #if !defined(USE_OPENSSL) | 14 #if !defined(USE_OPENSSL) |
15 | 15 |
16 namespace net { | 16 namespace net { |
17 | 17 |
18 bool VerifySignedData(const SignatureAlgorithm& signature_algorithm, | 18 bool VerifySignedData(const SignatureAlgorithm& signature_algorithm, |
19 const der::Input& signed_data, | 19 const der::Input& signed_data, |
20 const der::Input& signature_value_bit_string, | 20 const der::Input& signature_value_bit_string, |
21 const der::Input& public_key) { | 21 const der::Input& public_key, |
| 22 const VerificationPolicy* policy) { |
22 NOTIMPLEMENTED(); | 23 NOTIMPLEMENTED(); |
23 return false; | 24 return false; |
24 } | 25 } |
25 | 26 |
26 } // namespace net | 27 } // namespace net |
27 | 28 |
28 #else | 29 #else |
29 | 30 |
30 #include <openssl/digest.h> | 31 #include <openssl/digest.h> |
31 #include <openssl/ec.h> | 32 #include <openssl/ec.h> |
32 #include <openssl/ec_key.h> | 33 #include <openssl/ec_key.h> |
33 #include <openssl/evp.h> | 34 #include <openssl/evp.h> |
34 #include <openssl/rsa.h> | 35 #include <openssl/rsa.h> |
35 #include <openssl/x509.h> | 36 #include <openssl/x509.h> |
36 | 37 |
37 #include "base/compiler_specific.h" | 38 #include "base/compiler_specific.h" |
38 #include "crypto/openssl_util.h" | 39 #include "crypto/openssl_util.h" |
39 #include "crypto/scoped_openssl_types.h" | 40 #include "crypto/scoped_openssl_types.h" |
40 #include "net/cert/internal/signature_algorithm.h" | 41 #include "net/cert/internal/signature_algorithm.h" |
| 42 #include "net/cert/internal/verification_policy.h" |
41 #include "net/der/input.h" | 43 #include "net/der/input.h" |
42 #include "net/der/parser.h" | 44 #include "net/der/parser.h" |
43 | 45 |
44 namespace net { | 46 namespace net { |
45 | 47 |
46 namespace { | 48 namespace { |
47 | 49 |
48 // Converts a DigestAlgorithm to an equivalent EVP_MD*. | 50 // Converts a DigestAlgorithm to an equivalent EVP_MD*. |
49 WARN_UNUSED_RESULT bool GetDigest(DigestAlgorithm digest, const EVP_MD** out) { | 51 WARN_UNUSED_RESULT bool GetDigest(DigestAlgorithm digest, |
| 52 const VerificationPolicy* policy, |
| 53 const EVP_MD** out) { |
50 *out = nullptr; | 54 *out = nullptr; |
51 | 55 |
| 56 if (!policy->IsAcceptableDigestAlgorithm(digest)) |
| 57 return false; |
| 58 |
52 switch (digest) { | 59 switch (digest) { |
53 case DigestAlgorithm::Sha1: | 60 case DigestAlgorithm::Sha1: |
54 *out = EVP_sha1(); | 61 *out = EVP_sha1(); |
55 break; | 62 break; |
56 case DigestAlgorithm::Sha256: | 63 case DigestAlgorithm::Sha256: |
57 *out = EVP_sha256(); | 64 *out = EVP_sha256(); |
58 break; | 65 break; |
59 case DigestAlgorithm::Sha384: | 66 case DigestAlgorithm::Sha384: |
60 *out = EVP_sha384(); | 67 *out = EVP_sha384(); |
61 break; | 68 break; |
62 case DigestAlgorithm::Sha512: | 69 case DigestAlgorithm::Sha512: |
63 *out = EVP_sha512(); | 70 *out = EVP_sha512(); |
64 break; | 71 break; |
65 } | 72 } |
66 | 73 |
67 return *out != nullptr; | 74 return *out != nullptr; |
68 } | 75 } |
69 | 76 |
70 // Sets the RSASSA-PSS parameters on |pctx|. Returns true on success. | 77 // Sets the RSASSA-PSS parameters on |pctx|. Returns true on success. |
71 WARN_UNUSED_RESULT bool ApplyRsaPssOptions(const RsaPssParameters* params, | 78 WARN_UNUSED_RESULT bool ApplyRsaPssOptions(const RsaPssParameters* params, |
72 EVP_PKEY_CTX* pctx) { | 79 EVP_PKEY_CTX* pctx, |
| 80 const VerificationPolicy* policy) { |
73 // BoringSSL takes a signed int for the salt length, and interprets | 81 // BoringSSL takes a signed int for the salt length, and interprets |
74 // negative values in a special manner. Make sure not to silently underflow. | 82 // negative values in a special manner. Make sure not to silently underflow. |
75 base::CheckedNumeric<int> salt_length_bytes_int(params->salt_length()); | 83 base::CheckedNumeric<int> salt_length_bytes_int(params->salt_length()); |
76 if (!salt_length_bytes_int.IsValid()) | 84 if (!salt_length_bytes_int.IsValid()) |
77 return false; | 85 return false; |
78 | 86 |
79 const EVP_MD* mgf1_hash; | 87 const EVP_MD* mgf1_hash; |
80 if (!GetDigest(params->mgf1_hash(), &mgf1_hash)) | 88 if (!GetDigest(params->mgf1_hash(), policy, &mgf1_hash)) |
81 return false; | 89 return false; |
82 | 90 |
83 return EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) && | 91 return EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) && |
84 EVP_PKEY_CTX_set_rsa_mgf1_md(pctx, mgf1_hash) && | 92 EVP_PKEY_CTX_set_rsa_mgf1_md(pctx, mgf1_hash) && |
85 EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, | 93 EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, |
86 salt_length_bytes_int.ValueOrDie()); | 94 salt_length_bytes_int.ValueOrDie()); |
87 } | 95 } |
88 | 96 |
89 // TODO(eroman): This function is not strict enough. It accepts BER, other RSA | 97 // TODO(eroman): This function is not strict enough. It accepts BER, other RSA |
90 // OIDs, and does not check id-rsaEncryption parameters. | 98 // OIDs, and does not check id-rsaEncryption parameters. |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
153 // COMPATIBILITY NOTE: RFC 5912 and RFC 3279 are in disagreement on the value | 161 // COMPATIBILITY NOTE: RFC 5912 and RFC 3279 are in disagreement on the value |
154 // of parameters for rsaEncryption. Whereas RFC 5912 says they must be absent, | 162 // of parameters for rsaEncryption. Whereas RFC 5912 says they must be absent, |
155 // RFC 3279 says they must be NULL: | 163 // RFC 3279 says they must be NULL: |
156 // | 164 // |
157 // The rsaEncryption OID is intended to be used in the algorithm field | 165 // The rsaEncryption OID is intended to be used in the algorithm field |
158 // of a value of type AlgorithmIdentifier. The parameters field MUST | 166 // of a value of type AlgorithmIdentifier. The parameters field MUST |
159 // have ASN.1 type NULL for this algorithm identifier. | 167 // have ASN.1 type NULL for this algorithm identifier. |
160 // | 168 // |
161 // Following RFC 3279 in this case. | 169 // Following RFC 3279 in this case. |
162 WARN_UNUSED_RESULT bool ParseRsaKeyFromSpki(const der::Input& public_key_spki, | 170 WARN_UNUSED_RESULT bool ParseRsaKeyFromSpki(const der::Input& public_key_spki, |
163 crypto::ScopedEVP_PKEY* pkey) { | 171 crypto::ScopedEVP_PKEY* pkey, |
164 return ImportPkeyFromSpki(public_key_spki, EVP_PKEY_RSA, pkey); | 172 const VerificationPolicy* policy) { |
| 173 if (!ImportPkeyFromSpki(public_key_spki, EVP_PKEY_RSA, pkey)) |
| 174 return false; |
| 175 |
| 176 // Extract the modulus length from the key. |
| 177 crypto::ScopedRSA rsa(EVP_PKEY_get1_RSA(pkey->get())); |
| 178 if (!rsa.get()) |
| 179 return false; |
| 180 unsigned int modulus_length_bits = BN_num_bits(rsa.get()->n); |
| 181 |
| 182 return policy->IsAcceptableModulusLengthForRsa(modulus_length_bits); |
165 } | 183 } |
166 | 184 |
167 // Does signature verification using either RSA or ECDSA. | 185 // Does signature verification using either RSA or ECDSA. |
168 // | 186 // |
169 // Note that the |signature_value| input is expected to be a byte string (and | 187 // Note that the |signature_value| input is expected to be a byte string (and |
170 // not a DER-encoded BIT STRING) | 188 // not a DER-encoded BIT STRING) |
171 WARN_UNUSED_RESULT bool DoVerify(const SignatureAlgorithm& algorithm, | 189 WARN_UNUSED_RESULT bool DoVerify(const SignatureAlgorithm& algorithm, |
172 const der::Input& signed_data, | 190 const der::Input& signed_data, |
173 const der::Input& signature_value, | 191 const der::Input& signature_value, |
174 EVP_PKEY* public_key) { | 192 EVP_PKEY* public_key, |
| 193 const VerificationPolicy* policy) { |
175 DCHECK(algorithm.algorithm() == SignatureAlgorithmId::RsaPkcs1 || | 194 DCHECK(algorithm.algorithm() == SignatureAlgorithmId::RsaPkcs1 || |
176 algorithm.algorithm() == SignatureAlgorithmId::RsaPss || | 195 algorithm.algorithm() == SignatureAlgorithmId::RsaPss || |
177 algorithm.algorithm() == SignatureAlgorithmId::Ecdsa); | 196 algorithm.algorithm() == SignatureAlgorithmId::Ecdsa); |
178 | 197 |
179 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); | 198 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); |
180 | 199 |
181 crypto::ScopedEVP_MD_CTX ctx(EVP_MD_CTX_create()); | 200 crypto::ScopedEVP_MD_CTX ctx(EVP_MD_CTX_create()); |
182 EVP_PKEY_CTX* pctx = nullptr; // Owned by |ctx|. | 201 EVP_PKEY_CTX* pctx = nullptr; // Owned by |ctx|. |
183 | 202 |
184 const EVP_MD* digest; | 203 const EVP_MD* digest; |
185 if (!GetDigest(algorithm.digest(), &digest)) | 204 if (!GetDigest(algorithm.digest(), policy, &digest)) |
186 return false; | 205 return false; |
187 | 206 |
188 if (!EVP_DigestVerifyInit(ctx.get(), &pctx, digest, nullptr, public_key)) | 207 if (!EVP_DigestVerifyInit(ctx.get(), &pctx, digest, nullptr, public_key)) |
189 return false; | 208 return false; |
190 | 209 |
191 // Set the RSASSA-PSS specific options. | 210 // Set the RSASSA-PSS specific options. |
192 if (algorithm.algorithm() == SignatureAlgorithmId::RsaPss && | 211 if (algorithm.algorithm() == SignatureAlgorithmId::RsaPss && |
193 !ApplyRsaPssOptions(algorithm.ParamsForRsaPss(), pctx)) { | 212 !ApplyRsaPssOptions(algorithm.ParamsForRsaPss(), pctx, policy)) { |
194 return false; | 213 return false; |
195 } | 214 } |
196 | 215 |
197 if (!EVP_DigestVerifyUpdate(ctx.get(), signed_data.UnsafeData(), | 216 if (!EVP_DigestVerifyUpdate(ctx.get(), signed_data.UnsafeData(), |
198 signed_data.Length())) { | 217 signed_data.Length())) { |
199 return false; | 218 return false; |
200 } | 219 } |
201 | 220 |
202 return 1 == EVP_DigestVerifyFinal(ctx.get(), signature_value.UnsafeData(), | 221 return 1 == EVP_DigestVerifyFinal(ctx.get(), signature_value.UnsafeData(), |
203 signature_value.Length()); | 222 signature_value.Length()); |
204 } | 223 } |
205 | 224 |
206 // Returns true if the given curve is allowed for ECDSA. The input is a | |
207 // BoringSSL NID. | |
208 // | |
209 // TODO(eroman): Extract policy decisions such as allowed curves, hashes, RSA | |
210 // modulus size, to somewhere more central. | |
211 WARN_UNUSED_RESULT bool IsAllowedCurveName(int curve_nid) { | |
212 switch (curve_nid) { | |
213 case NID_X9_62_prime256v1: | |
214 case NID_secp384r1: | |
215 case NID_secp521r1: | |
216 return true; | |
217 } | |
218 return false; | |
219 } | |
220 | |
221 // Parses an EC public key from SPKI to an EVP_PKEY. | 225 // Parses an EC public key from SPKI to an EVP_PKEY. |
222 // | 226 // |
223 // Returns true on success. | 227 // Returns true on success. |
224 // | 228 // |
225 // RFC 5912 describes all the ECDSA signature algorithms as requiring a public | 229 // RFC 5912 describes all the ECDSA signature algorithms as requiring a public |
226 // key of type "pk-ec": | 230 // key of type "pk-ec": |
227 // | 231 // |
228 // pk-ec PUBLIC-KEY ::= { | 232 // pk-ec PUBLIC-KEY ::= { |
229 // IDENTIFIER id-ecPublicKey | 233 // IDENTIFIER id-ecPublicKey |
230 // KEY ECPoint | 234 // KEY ECPoint |
(...skipping 25 matching lines...) Expand all Loading... |
256 // | 260 // |
257 // NamedCurve CURVE ::= { | 261 // NamedCurve CURVE ::= { |
258 // { ID secp192r1 } | { ID sect163k1 } | { ID sect163r2 } | | 262 // { ID secp192r1 } | { ID sect163k1 } | { ID sect163r2 } | |
259 // { ID secp224r1 } | { ID sect233k1 } | { ID sect233r1 } | | 263 // { ID secp224r1 } | { ID sect233k1 } | { ID sect233r1 } | |
260 // { ID secp256r1 } | { ID sect283k1 } | { ID sect283r1 } | | 264 // { ID secp256r1 } | { ID sect283k1 } | { ID sect283r1 } | |
261 // { ID secp384r1 } | { ID sect409k1 } | { ID sect409r1 } | | 265 // { ID secp384r1 } | { ID sect409k1 } | { ID sect409r1 } | |
262 // { ID secp521r1 } | { ID sect571k1 } | { ID sect571r1 }, | 266 // { ID secp521r1 } | { ID sect571k1 } | { ID sect571r1 }, |
263 // ... -- Extensible | 267 // ... -- Extensible |
264 // } | 268 // } |
265 WARN_UNUSED_RESULT bool ParseEcKeyFromSpki(const der::Input& public_key_spki, | 269 WARN_UNUSED_RESULT bool ParseEcKeyFromSpki(const der::Input& public_key_spki, |
266 crypto::ScopedEVP_PKEY* pkey) { | 270 crypto::ScopedEVP_PKEY* pkey, |
| 271 const VerificationPolicy* policy) { |
267 if (!ImportPkeyFromSpki(public_key_spki, EVP_PKEY_EC, pkey)) | 272 if (!ImportPkeyFromSpki(public_key_spki, EVP_PKEY_EC, pkey)) |
268 return false; | 273 return false; |
269 | 274 |
270 // Enforce policy on allowed curves in case ImportPkeyFromSpki() were to | 275 // Extract the curve name. |
271 // recognize and allow use of a weak curve. | |
272 crypto::ScopedEC_KEY ec(EVP_PKEY_get1_EC_KEY(pkey->get())); | 276 crypto::ScopedEC_KEY ec(EVP_PKEY_get1_EC_KEY(pkey->get())); |
273 if (!ec.get()) | 277 if (!ec.get()) |
274 return false; // Unexpected. | 278 return false; // Unexpected. |
| 279 int curve_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec.get())); |
275 | 280 |
276 int curve_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec.get())); | 281 return policy->IsAcceptableCurveForEcdsa(curve_nid); |
277 return IsAllowedCurveName(curve_nid); | |
278 } | 282 } |
279 | 283 |
280 } // namespace | 284 } // namespace |
281 | 285 |
282 bool VerifySignedData(const SignatureAlgorithm& signature_algorithm, | 286 bool VerifySignedData(const SignatureAlgorithm& signature_algorithm, |
283 const der::Input& signed_data, | 287 const der::Input& signed_data, |
284 const der::Input& signature_value_bit_string, | 288 const der::Input& signature_value_bit_string, |
285 const der::Input& public_key_spki) { | 289 const der::Input& public_key_spki, |
| 290 const VerificationPolicy* policy) { |
| 291 // Optimization: Check the digest before parsing the SPKI. This isn't |
| 292 // strictly necessary as it will also get checked by GetDigest(). |
| 293 if (!policy->IsAcceptableDigestAlgorithm(signature_algorithm.digest())) |
| 294 return false; |
| 295 |
286 crypto::ScopedEVP_PKEY public_key; | 296 crypto::ScopedEVP_PKEY public_key; |
287 | 297 |
288 // Parse the SPKI to an EVP_PKEY appropriate for the signature algorithm. | 298 // Parse the SPKI to an EVP_PKEY appropriate for the signature algorithm. |
289 switch (signature_algorithm.algorithm()) { | 299 switch (signature_algorithm.algorithm()) { |
290 case SignatureAlgorithmId::RsaPkcs1: | 300 case SignatureAlgorithmId::RsaPkcs1: |
291 case SignatureAlgorithmId::RsaPss: | 301 case SignatureAlgorithmId::RsaPss: |
292 if (!ParseRsaKeyFromSpki(public_key_spki, &public_key)) | 302 if (!ParseRsaKeyFromSpki(public_key_spki, &public_key, policy)) |
293 return false; | 303 return false; |
294 break; | 304 break; |
295 case SignatureAlgorithmId::Ecdsa: | 305 case SignatureAlgorithmId::Ecdsa: |
296 if (!ParseEcKeyFromSpki(public_key_spki, &public_key)) | 306 if (!ParseEcKeyFromSpki(public_key_spki, &public_key, policy)) |
297 return false; | 307 return false; |
298 break; | 308 break; |
299 } | 309 } |
300 | 310 |
301 // Extract the bytes of the signature_value. Assume that the BIT STRING has | 311 // Extract the bytes of the signature_value. Assume that the BIT STRING has |
302 // no unused bits (in other words, is a multiple of 8 bits), since that is the | 312 // no unused bits (in other words, is a multiple of 8 bits), since that is the |
303 // case for all of the currently supported algorithms. | 313 // case for all of the currently supported algorithms. |
304 der::Input signature_value; | 314 der::Input signature_value; |
305 der::Parser parser(signature_value_bit_string); | 315 der::Parser parser(signature_value_bit_string); |
306 if (!parser.ReadBitStringNoUnusedBits(&signature_value)) | 316 if (!parser.ReadBitStringNoUnusedBits(&signature_value)) |
307 return false; | 317 return false; |
308 // By definition signature_value_bit_string must be a single BIT STRING. | 318 // By definition signature_value_bit_string must be a single BIT STRING. |
309 if (parser.HasMore()) | 319 if (parser.HasMore()) |
310 return false; | 320 return false; |
311 | 321 |
312 return DoVerify(signature_algorithm, signed_data, signature_value, | 322 return DoVerify(signature_algorithm, signed_data, signature_value, |
313 public_key.get()); | 323 public_key.get(), policy); |
314 } | 324 } |
315 | 325 |
316 } // namespace net | 326 } // namespace net |
317 | 327 |
318 #endif | 328 #endif |
OLD | NEW |