1f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 2f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// found in the LICENSE file. 4f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 5f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "net/cert/ct_log_verifier.h" 6f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 7f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include <cryptohi.h> 8f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include <keyhi.h> 9f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include <nss.h> 10f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include <pk11pub.h> 11f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include <secitem.h> 12f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include <secoid.h> 13f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 14f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/logging.h" 15f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "crypto/nss_util.h" 16f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "crypto/sha2.h" 17cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "net/cert/signed_tree_head.h" 18f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 19f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)namespace net { 20f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 21f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)namespace { 22f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 23f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)SECOidTag GetNSSSigAlg(ct::DigitallySigned::SignatureAlgorithm alg) { 24f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) switch (alg) { 25f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) case ct::DigitallySigned::SIG_ALGO_RSA: 26f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return SEC_OID_PKCS1_RSA_ENCRYPTION; 27f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) case ct::DigitallySigned::SIG_ALGO_DSA: 28f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return SEC_OID_ANSIX9_DSA_SIGNATURE; 29f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) case ct::DigitallySigned::SIG_ALGO_ECDSA: 30f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return SEC_OID_ANSIX962_EC_PUBLIC_KEY; 31f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) case ct::DigitallySigned::SIG_ALGO_ANONYMOUS: 32f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) default: 33f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) NOTREACHED(); 34f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return SEC_OID_UNKNOWN; 35f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 36f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 37f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 38f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)SECOidTag GetNSSHashAlg(ct::DigitallySigned::HashAlgorithm alg) { 39f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) switch (alg) { 40f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) case ct::DigitallySigned::HASH_ALGO_MD5: 41f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return SEC_OID_MD5; 42f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) case ct::DigitallySigned::HASH_ALGO_SHA1: 43f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return SEC_OID_SHA1; 44f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) case ct::DigitallySigned::HASH_ALGO_SHA224: 45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return SEC_OID_SHA224; 46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) case ct::DigitallySigned::HASH_ALGO_SHA256: 47f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return SEC_OID_SHA256; 48f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) case ct::DigitallySigned::HASH_ALGO_SHA384: 49f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return SEC_OID_SHA384; 50f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) case ct::DigitallySigned::HASH_ALGO_SHA512: 51f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return SEC_OID_SHA512; 52f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) case ct::DigitallySigned::HASH_ALGO_NONE: 53f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) default: 54f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) NOTREACHED(); 55f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return SEC_OID_UNKNOWN; 56f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 57f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 58f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 59f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} // namespace 60f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 61f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)CTLogVerifier::~CTLogVerifier() { 62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (public_key_) 63f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) SECKEY_DestroyPublicKey(public_key_); 64f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 65f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)CTLogVerifier::CTLogVerifier() 67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) : hash_algorithm_(ct::DigitallySigned::HASH_ALGO_NONE), 68f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) signature_algorithm_(ct::DigitallySigned::SIG_ALGO_ANONYMOUS), 69f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) public_key_(NULL) {} 70f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 71f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool CTLogVerifier::Init(const base::StringPiece& public_key, 72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const base::StringPiece& description) { 73f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) SECItem key_data; 74f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 75f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) crypto::EnsureNSSInit(); 76f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 77f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) key_data.data = reinterpret_cast<unsigned char*>( 78f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const_cast<char*>(public_key.data())); 79f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) key_data.len = public_key.size(); 80f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 81f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) CERTSubjectPublicKeyInfo* public_key_info = 82f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) SECKEY_DecodeDERSubjectPublicKeyInfo(&key_data); 83f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!public_key_info) { 84f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DVLOG(1) << "Failed decoding public key."; 85f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return false; 86f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 87f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 88f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) public_key_ = SECKEY_ExtractPublicKey(public_key_info); 89f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) SECKEY_DestroySubjectPublicKeyInfo(public_key_info); 90f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 91f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!public_key_) { 92f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DVLOG(1) << "Failed extracting public key."; 93f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return false; 94f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 95f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 96f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) key_id_ = crypto::SHA256HashString(public_key); 97f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) description_ = description.as_string(); 98f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 99f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Right now, only RSASSA-PKCS1v15 with SHA-256 and ECDSA with SHA-256 are 100f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // supported. 101f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) switch (SECKEY_GetPublicKeyType(public_key_)) { 102f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) case rsaKey: 103f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) hash_algorithm_ = ct::DigitallySigned::HASH_ALGO_SHA256; 104f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) signature_algorithm_ = ct::DigitallySigned::SIG_ALGO_RSA; 105f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) break; 106f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) case ecKey: 107f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) hash_algorithm_ = ct::DigitallySigned::HASH_ALGO_SHA256; 108f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) signature_algorithm_ = ct::DigitallySigned::SIG_ALGO_ECDSA; 109f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) break; 110f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) default: 111f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DVLOG(1) << "Unsupported key type: " 112f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) << SECKEY_GetPublicKeyType(public_key_); 113f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return false; 114f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 115f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 116f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Extra sanity check: Require RSA keys of at least 2048 bits. 117f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (signature_algorithm_ == ct::DigitallySigned::SIG_ALGO_RSA && 118f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) SECKEY_PublicKeyStrengthInBits(public_key_) < 2048) { 119f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DVLOG(1) << "Too small a public key."; 120f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return false; 121f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 122f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 123f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return true; 124f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 125f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 126f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool CTLogVerifier::VerifySignature(const base::StringPiece& data_to_sign, 127f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const base::StringPiece& signature) { 128f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) SECItem sig_data; 129f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) sig_data.data = reinterpret_cast<unsigned char*>(const_cast<char*>( 130f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) signature.data())); 131f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) sig_data.len = signature.size(); 132f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 133f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) SECStatus rv = VFY_VerifyDataDirect( 134f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) reinterpret_cast<const unsigned char*>(data_to_sign.data()), 135f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) data_to_sign.size(), public_key_, &sig_data, 136f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) GetNSSSigAlg(signature_algorithm_), GetNSSHashAlg(hash_algorithm_), 137f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) NULL, NULL); 138f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DVLOG(1) << "Signature verification result: " << (rv == SECSuccess); 139f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return rv == SECSuccess; 140f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 141f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 142f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} // namespace net 143