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 3 // found in the LICENSE file. 4 5 #include "net/cert/ct_log_verifier.h" 6 7 #include <openssl/evp.h> 8 #include <openssl/x509.h> 9 10 #include "base/logging.h" 11 #include "crypto/openssl_util.h" 12 #include "crypto/scoped_openssl_types.h" 13 #include "crypto/sha2.h" 14 #include "net/cert/signed_tree_head.h" 15 16 namespace net { 17 18 namespace { 19 20 const EVP_MD* GetEvpAlg(ct::DigitallySigned::HashAlgorithm alg) { 21 switch (alg) { 22 case ct::DigitallySigned::HASH_ALGO_MD5: 23 return EVP_md5(); 24 case ct::DigitallySigned::HASH_ALGO_SHA1: 25 return EVP_sha1(); 26 case ct::DigitallySigned::HASH_ALGO_SHA224: 27 return EVP_sha224(); 28 case ct::DigitallySigned::HASH_ALGO_SHA256: 29 return EVP_sha256(); 30 case ct::DigitallySigned::HASH_ALGO_SHA384: 31 return EVP_sha384(); 32 case ct::DigitallySigned::HASH_ALGO_SHA512: 33 return EVP_sha512(); 34 case ct::DigitallySigned::HASH_ALGO_NONE: 35 default: 36 NOTREACHED(); 37 return NULL; 38 } 39 } 40 41 } // namespace 42 43 CTLogVerifier::~CTLogVerifier() { 44 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); 45 46 if (public_key_) 47 EVP_PKEY_free(public_key_); 48 } 49 50 CTLogVerifier::CTLogVerifier() 51 : hash_algorithm_(ct::DigitallySigned::HASH_ALGO_NONE), 52 signature_algorithm_(ct::DigitallySigned::SIG_ALGO_ANONYMOUS), 53 public_key_(NULL) {} 54 55 bool CTLogVerifier::Init(const base::StringPiece& public_key, 56 const base::StringPiece& description) { 57 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); 58 59 crypto::ScopedBIO bio( 60 BIO_new_mem_buf(const_cast<char*>(public_key.data()), public_key.size())); 61 if (!bio.get()) 62 return false; 63 64 public_key_ = d2i_PUBKEY_bio(bio.get(), NULL); 65 if (!public_key_) 66 return false; 67 68 key_id_ = crypto::SHA256HashString(public_key); 69 description_ = description.as_string(); 70 71 // Right now, only RSASSA-PKCS1v15 with SHA-256 and ECDSA with SHA-256 are 72 // supported. 73 switch (EVP_PKEY_type(public_key_->type)) { 74 case EVP_PKEY_RSA: 75 hash_algorithm_ = ct::DigitallySigned::HASH_ALGO_SHA256; 76 signature_algorithm_ = ct::DigitallySigned::SIG_ALGO_RSA; 77 break; 78 case EVP_PKEY_EC: 79 hash_algorithm_ = ct::DigitallySigned::HASH_ALGO_SHA256; 80 signature_algorithm_ = ct::DigitallySigned::SIG_ALGO_ECDSA; 81 break; 82 default: 83 DVLOG(1) << "Unsupported key type: " << EVP_PKEY_type(public_key_->type); 84 return false; 85 } 86 87 // Extra sanity check: Require RSA keys of at least 2048 bits. 88 // EVP_PKEY_size returns the size in bytes. 256 = 2048-bit RSA key. 89 if (signature_algorithm_ == ct::DigitallySigned::SIG_ALGO_RSA && 90 EVP_PKEY_size(public_key_) < 256) { 91 DVLOG(1) << "Too small a public key."; 92 return false; 93 } 94 95 return true; 96 } 97 98 bool CTLogVerifier::VerifySignature(const base::StringPiece& data_to_sign, 99 const base::StringPiece& signature) { 100 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); 101 102 const EVP_MD* hash_alg = GetEvpAlg(hash_algorithm_); 103 if (hash_alg == NULL) 104 return false; 105 106 EVP_MD_CTX ctx; 107 EVP_MD_CTX_init(&ctx); 108 109 bool ok = ( 110 1 == EVP_DigestVerifyInit(&ctx, NULL, hash_alg, NULL, public_key_) && 111 1 == EVP_DigestVerifyUpdate( 112 &ctx, data_to_sign.data(), data_to_sign.size()) && 113 1 == EVP_DigestVerifyFinal( 114 &ctx, 115 reinterpret_cast<const uint8_t*>(signature.data()), 116 signature.size())); 117 118 EVP_MD_CTX_cleanup(&ctx); 119 return ok; 120 } 121 122 } // namespace net 123