| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/ct_log_verifier.h" | 5 #include "net/cert/ct_log_verifier.h" |
| 6 | 6 |
| 7 #include <string.h> | 7 #include <string.h> |
| 8 #include <openssl/bytestring.h> |
| 9 #include <openssl/evp.h> |
| 8 | 10 |
| 9 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "crypto/openssl_util.h" |
| 13 #include "crypto/scoped_openssl_types.h" |
| 14 #include "crypto/sha2.h" |
| 10 #include "net/cert/ct_log_verifier_util.h" | 15 #include "net/cert/ct_log_verifier_util.h" |
| 11 #include "net/cert/ct_serialization.h" | 16 #include "net/cert/ct_serialization.h" |
| 12 #include "net/cert/merkle_consistency_proof.h" | 17 #include "net/cert/merkle_consistency_proof.h" |
| 13 #include "net/cert/signed_tree_head.h" | 18 #include "net/cert/signed_tree_head.h" |
| 14 | 19 |
| 15 namespace net { | 20 namespace net { |
| 16 | 21 |
| 17 namespace { | 22 namespace { |
| 18 | 23 |
| 19 // The SHA-256 hash of the empty string. | 24 // The SHA-256 hash of the empty string. |
| 20 const unsigned char kSHA256EmptyStringHash[ct::kSthRootHashLength] = { | 25 const unsigned char kSHA256EmptyStringHash[ct::kSthRootHashLength] = { |
| 21 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, | 26 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, |
| 22 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, | 27 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, |
| 23 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55}; | 28 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55}; |
| 24 | 29 |
| 25 bool IsPowerOfTwo(uint64_t n) { | 30 bool IsPowerOfTwo(uint64_t n) { |
| 26 return n != 0 && (n & (n - 1)) == 0; | 31 return n != 0 && (n & (n - 1)) == 0; |
| 27 } | 32 } |
| 28 | 33 |
| 34 const EVP_MD* GetEvpAlg(ct::DigitallySigned::HashAlgorithm alg) { |
| 35 switch (alg) { |
| 36 case ct::DigitallySigned::HASH_ALGO_MD5: |
| 37 return EVP_md5(); |
| 38 case ct::DigitallySigned::HASH_ALGO_SHA1: |
| 39 return EVP_sha1(); |
| 40 case ct::DigitallySigned::HASH_ALGO_SHA224: |
| 41 return EVP_sha224(); |
| 42 case ct::DigitallySigned::HASH_ALGO_SHA256: |
| 43 return EVP_sha256(); |
| 44 case ct::DigitallySigned::HASH_ALGO_SHA384: |
| 45 return EVP_sha384(); |
| 46 case ct::DigitallySigned::HASH_ALGO_SHA512: |
| 47 return EVP_sha512(); |
| 48 case ct::DigitallySigned::HASH_ALGO_NONE: |
| 49 default: |
| 50 NOTREACHED(); |
| 51 return NULL; |
| 52 } |
| 53 } |
| 54 |
| 29 } // namespace | 55 } // namespace |
| 30 | 56 |
| 31 // static | 57 // static |
| 32 scoped_refptr<const CTLogVerifier> CTLogVerifier::Create( | 58 scoped_refptr<const CTLogVerifier> CTLogVerifier::Create( |
| 33 const base::StringPiece& public_key, | 59 const base::StringPiece& public_key, |
| 34 const base::StringPiece& description, | 60 const base::StringPiece& description, |
| 35 const base::StringPiece& url) { | 61 const base::StringPiece& url) { |
| 36 GURL log_url(url.as_string()); | 62 GURL log_url(url.as_string()); |
| 37 if (!log_url.is_valid()) | 63 if (!log_url.is_valid()) |
| 38 return nullptr; | 64 return nullptr; |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 205 sn >>= 1; | 231 sn >>= 1; |
| 206 } | 232 } |
| 207 | 233 |
| 208 // 6. After completing iterating through the "consistency_path" array as | 234 // 6. After completing iterating through the "consistency_path" array as |
| 209 // described above, verify that the "fr" calculated is equal to the | 235 // described above, verify that the "fr" calculated is equal to the |
| 210 // "first_hash" supplied, that the "sr" calculated is equal to the | 236 // "first_hash" supplied, that the "sr" calculated is equal to the |
| 211 // "second_hash" supplied and that "sn" is 0. | 237 // "second_hash" supplied and that "sn" is 0. |
| 212 return fr == old_tree_hash && sr == new_tree_hash && sn == 0; | 238 return fr == old_tree_hash && sr == new_tree_hash && sn == 0; |
| 213 } | 239 } |
| 214 | 240 |
| 241 CTLogVerifier::~CTLogVerifier() { |
| 242 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); |
| 243 |
| 244 if (public_key_) |
| 245 EVP_PKEY_free(public_key_); |
| 246 } |
| 247 |
| 248 bool CTLogVerifier::Init(const base::StringPiece& public_key) { |
| 249 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); |
| 250 |
| 251 CBS cbs; |
| 252 CBS_init(&cbs, reinterpret_cast<const uint8_t*>(public_key.data()), |
| 253 public_key.size()); |
| 254 public_key_ = EVP_parse_public_key(&cbs); |
| 255 if (!public_key_ || CBS_len(&cbs) != 0) |
| 256 return false; |
| 257 |
| 258 key_id_ = crypto::SHA256HashString(public_key); |
| 259 |
| 260 // Right now, only RSASSA-PKCS1v15 with SHA-256 and ECDSA with SHA-256 are |
| 261 // supported. |
| 262 switch (EVP_PKEY_type(public_key_->type)) { |
| 263 case EVP_PKEY_RSA: |
| 264 hash_algorithm_ = ct::DigitallySigned::HASH_ALGO_SHA256; |
| 265 signature_algorithm_ = ct::DigitallySigned::SIG_ALGO_RSA; |
| 266 break; |
| 267 case EVP_PKEY_EC: |
| 268 hash_algorithm_ = ct::DigitallySigned::HASH_ALGO_SHA256; |
| 269 signature_algorithm_ = ct::DigitallySigned::SIG_ALGO_ECDSA; |
| 270 break; |
| 271 default: |
| 272 DVLOG(1) << "Unsupported key type: " << EVP_PKEY_type(public_key_->type); |
| 273 return false; |
| 274 } |
| 275 |
| 276 // Extra sanity check: Require RSA keys of at least 2048 bits. |
| 277 // EVP_PKEY_size returns the size in bytes. 256 = 2048-bit RSA key. |
| 278 if (signature_algorithm_ == ct::DigitallySigned::SIG_ALGO_RSA && |
| 279 EVP_PKEY_size(public_key_) < 256) { |
| 280 DVLOG(1) << "Too small a public key."; |
| 281 return false; |
| 282 } |
| 283 |
| 284 return true; |
| 285 } |
| 286 |
| 287 bool CTLogVerifier::VerifySignature(const base::StringPiece& data_to_sign, |
| 288 const base::StringPiece& signature) const { |
| 289 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); |
| 290 |
| 291 const EVP_MD* hash_alg = GetEvpAlg(hash_algorithm_); |
| 292 if (hash_alg == NULL) |
| 293 return false; |
| 294 |
| 295 EVP_MD_CTX ctx; |
| 296 EVP_MD_CTX_init(&ctx); |
| 297 |
| 298 bool ok = |
| 299 (1 == EVP_DigestVerifyInit(&ctx, NULL, hash_alg, NULL, public_key_) && |
| 300 1 == EVP_DigestVerifyUpdate(&ctx, data_to_sign.data(), |
| 301 data_to_sign.size()) && |
| 302 1 == EVP_DigestVerifyFinal( |
| 303 &ctx, reinterpret_cast<const uint8_t*>(signature.data()), |
| 304 signature.size())); |
| 305 |
| 306 EVP_MD_CTX_cleanup(&ctx); |
| 307 return ok; |
| 308 } |
| 309 |
| 215 } // namespace net | 310 } // namespace net |
| OLD | NEW |