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