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