| Index: net/cert/ct_log_verifier.cc
|
| diff --git a/net/cert/ct_log_verifier.cc b/net/cert/ct_log_verifier.cc
|
| index 05f1b0490570cd7e38e9d38e1e6aa5a572338a2e..45adabe4862c8e4cf661250e11ee0c1f69cd4fcb 100644
|
| --- a/net/cert/ct_log_verifier.cc
|
| +++ b/net/cert/ct_log_verifier.cc
|
| @@ -5,8 +5,13 @@
|
| #include "net/cert/ct_log_verifier.h"
|
|
|
| #include <string.h>
|
| +#include <openssl/bytestring.h>
|
| +#include <openssl/evp.h>
|
|
|
| #include "base/logging.h"
|
| +#include "crypto/openssl_util.h"
|
| +#include "crypto/scoped_openssl_types.h"
|
| +#include "crypto/sha2.h"
|
| #include "net/cert/ct_log_verifier_util.h"
|
| #include "net/cert/ct_serialization.h"
|
| #include "net/cert/merkle_consistency_proof.h"
|
| @@ -26,6 +31,27 @@ bool IsPowerOfTwo(uint64_t n) {
|
| return n != 0 && (n & (n - 1)) == 0;
|
| }
|
|
|
| +const EVP_MD* GetEvpAlg(ct::DigitallySigned::HashAlgorithm alg) {
|
| + switch (alg) {
|
| + case ct::DigitallySigned::HASH_ALGO_MD5:
|
| + return EVP_md5();
|
| + case ct::DigitallySigned::HASH_ALGO_SHA1:
|
| + return EVP_sha1();
|
| + case ct::DigitallySigned::HASH_ALGO_SHA224:
|
| + return EVP_sha224();
|
| + case ct::DigitallySigned::HASH_ALGO_SHA256:
|
| + return EVP_sha256();
|
| + case ct::DigitallySigned::HASH_ALGO_SHA384:
|
| + return EVP_sha384();
|
| + case ct::DigitallySigned::HASH_ALGO_SHA512:
|
| + return EVP_sha512();
|
| + case ct::DigitallySigned::HASH_ALGO_NONE:
|
| + default:
|
| + NOTREACHED();
|
| + return NULL;
|
| + }
|
| +}
|
| +
|
| } // namespace
|
|
|
| // static
|
| @@ -212,4 +238,73 @@ bool CTLogVerifier::VerifyConsistencyProof(
|
| return fr == old_tree_hash && sr == new_tree_hash && sn == 0;
|
| }
|
|
|
| +CTLogVerifier::~CTLogVerifier() {
|
| + crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
|
| +
|
| + if (public_key_)
|
| + EVP_PKEY_free(public_key_);
|
| +}
|
| +
|
| +bool CTLogVerifier::Init(const base::StringPiece& public_key) {
|
| + crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
|
| +
|
| + CBS cbs;
|
| + CBS_init(&cbs, reinterpret_cast<const uint8_t*>(public_key.data()),
|
| + public_key.size());
|
| + public_key_ = EVP_parse_public_key(&cbs);
|
| + if (!public_key_ || CBS_len(&cbs) != 0)
|
| + return false;
|
| +
|
| + key_id_ = crypto::SHA256HashString(public_key);
|
| +
|
| + // Right now, only RSASSA-PKCS1v15 with SHA-256 and ECDSA with SHA-256 are
|
| + // supported.
|
| + switch (EVP_PKEY_type(public_key_->type)) {
|
| + case EVP_PKEY_RSA:
|
| + hash_algorithm_ = ct::DigitallySigned::HASH_ALGO_SHA256;
|
| + signature_algorithm_ = ct::DigitallySigned::SIG_ALGO_RSA;
|
| + break;
|
| + case EVP_PKEY_EC:
|
| + hash_algorithm_ = ct::DigitallySigned::HASH_ALGO_SHA256;
|
| + signature_algorithm_ = ct::DigitallySigned::SIG_ALGO_ECDSA;
|
| + break;
|
| + default:
|
| + DVLOG(1) << "Unsupported key type: " << EVP_PKEY_type(public_key_->type);
|
| + return false;
|
| + }
|
| +
|
| + // Extra sanity check: Require RSA keys of at least 2048 bits.
|
| + // EVP_PKEY_size returns the size in bytes. 256 = 2048-bit RSA key.
|
| + if (signature_algorithm_ == ct::DigitallySigned::SIG_ALGO_RSA &&
|
| + EVP_PKEY_size(public_key_) < 256) {
|
| + DVLOG(1) << "Too small a public key.";
|
| + return false;
|
| + }
|
| +
|
| + return true;
|
| +}
|
| +
|
| +bool CTLogVerifier::VerifySignature(const base::StringPiece& data_to_sign,
|
| + const base::StringPiece& signature) const {
|
| + crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
|
| +
|
| + const EVP_MD* hash_alg = GetEvpAlg(hash_algorithm_);
|
| + if (hash_alg == NULL)
|
| + return false;
|
| +
|
| + EVP_MD_CTX ctx;
|
| + EVP_MD_CTX_init(&ctx);
|
| +
|
| + bool ok =
|
| + (1 == EVP_DigestVerifyInit(&ctx, NULL, hash_alg, NULL, public_key_) &&
|
| + 1 == EVP_DigestVerifyUpdate(&ctx, data_to_sign.data(),
|
| + data_to_sign.size()) &&
|
| + 1 == EVP_DigestVerifyFinal(
|
| + &ctx, reinterpret_cast<const uint8_t*>(signature.data()),
|
| + signature.size()));
|
| +
|
| + EVP_MD_CTX_cleanup(&ctx);
|
| + return ok;
|
| +}
|
| +
|
| } // namespace net
|
|
|