diff options
-rw-r--r-- | chrome/browser/extensions/install_signer.cc | 3 | ||||
-rw-r--r-- | components/crx_file.gypi | 1 | ||||
-rw-r--r-- | components/crx_file/BUILD.gn | 1 | ||||
-rw-r--r-- | components/crx_file/constants.h | 21 | ||||
-rw-r--r-- | components/crx_file/crx_file.cc | 8 | ||||
-rw-r--r-- | components/policy/core/common/cloud/cloud_policy_validator.cc | 30 | ||||
-rw-r--r-- | components/update_client/client_update_protocol_ecdsa.cc | 22 | ||||
-rw-r--r-- | components/update_client/component_unpacker.cc | 1 | ||||
-rw-r--r-- | components/variations/variations_seed_store.cc | 24 | ||||
-rw-r--r-- | crypto/ec_signature_creator_unittest.cc | 18 | ||||
-rw-r--r-- | crypto/signature_creator_unittest.cc | 28 | ||||
-rw-r--r-- | crypto/signature_verifier.h | 34 | ||||
-rw-r--r-- | crypto/signature_verifier_nss.cc | 46 | ||||
-rw-r--r-- | crypto/signature_verifier_openssl.cc | 61 | ||||
-rw-r--r-- | crypto/signature_verifier_unittest.cc | 63 | ||||
-rw-r--r-- | extensions/browser/verified_contents.cc | 10 | ||||
-rw-r--r-- | net/quic/crypto/proof_verifier_chromium.cc | 26 |
17 files changed, 109 insertions, 288 deletions
diff --git a/chrome/browser/extensions/install_signer.cc b/chrome/browser/extensions/install_signer.cc index 19c3f91..4df8e82 100644 --- a/chrome/browser/extensions/install_signer.cc +++ b/chrome/browser/extensions/install_signer.cc @@ -27,7 +27,6 @@ #include "base/values.h" #include "build/build_config.h" #include "chrome/common/chrome_switches.h" -#include "components/crx_file/constants.h" #include "crypto/random.h" #include "crypto/secure_hash.h" #include "crypto/sha2.h" @@ -261,7 +260,7 @@ bool InstallSigner::VerifySignature(const InstallSignature& signature) { crypto::SignatureVerifier verifier; if (!verifier.VerifyInit( - crx_file::kSignatureAlgorithm, sizeof(crx_file::kSignatureAlgorithm), + crypto::SignatureVerifier::RSA_PKCS1_SHA1, reinterpret_cast<const uint8_t*>(signature.signature.data()), signature.signature.size(), reinterpret_cast<const uint8_t*>(public_key.data()), diff --git a/components/crx_file.gypi b/components/crx_file.gypi index fd99563..3c81095 100644 --- a/components/crx_file.gypi +++ b/components/crx_file.gypi @@ -15,7 +15,6 @@ '..', ], 'sources': [ - 'crx_file/constants.h', 'crx_file/crx_file.cc', 'crx_file/crx_file.h', 'crx_file/id_util.cc', diff --git a/components/crx_file/BUILD.gn b/components/crx_file/BUILD.gn index ab04a23..a749439 100644 --- a/components/crx_file/BUILD.gn +++ b/components/crx_file/BUILD.gn @@ -4,7 +4,6 @@ source_set("crx_file") { sources = [ - "constants.h", "crx_file.cc", "crx_file.h", "id_util.cc", diff --git a/components/crx_file/constants.h b/components/crx_file/constants.h deleted file mode 100644 index 1cc6ede..0000000 --- a/components/crx_file/constants.h +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef COMPONENTS_CRX_FILE_CONSTANTS_H_ -#define COMPONENTS_CRX_FILE_CONSTANTS_H_ - -#include <stdint.h> - -namespace crx_file { - -// Note: this structure is an ASN.1 which encodes the algorithm used -// with its parameters. This is defined in PKCS #1 v2.1 (RFC 3447). -// It is encoding: { OID sha1WithRSAEncryption PARAMETERS NULL } -const uint8_t kSignatureAlgorithm[15] = {0x30, 0x0d, 0x06, 0x09, 0x2a, - 0x86, 0x48, 0x86, 0xf7, 0x0d, - 0x01, 0x01, 0x05, 0x05, 0x00}; - -} // namespace crx_file - -#endif // COMPONENTS_CRX_FILE_CONSTANTS_H_ diff --git a/components/crx_file/crx_file.cc b/components/crx_file/crx_file.cc index 0bb60e0..7a6240d 100644 --- a/components/crx_file/crx_file.cc +++ b/components/crx_file/crx_file.cc @@ -13,7 +13,6 @@ #include "base/numerics/safe_math.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" -#include "components/crx_file/constants.h" #include "components/crx_file/id_util.h" #include "crypto/secure_hash.h" #include "crypto/sha2.h" @@ -160,10 +159,9 @@ CrxFile::ValidateError CrxFile::ValidateSignature( return ValidateError::CRX_SIGNATURE_INVALID; crypto::SignatureVerifier verifier; - if (!verifier.VerifyInit( - crx_file::kSignatureAlgorithm, sizeof(crx_file::kSignatureAlgorithm), - &signature.front(), static_cast<int>(signature.size()), &key.front(), - static_cast<int>(key.size()))) { + if (!verifier.VerifyInit(crypto::SignatureVerifier::RSA_PKCS1_SHA1, + signature.data(), static_cast<int>(signature.size()), + key.data(), static_cast<int>(key.size()))) { // Signature verification initialization failed. This is most likely // caused by a public key in the wrong format (should encode algorithm). return ValidateError::CRX_SIGNATURE_VERIFICATION_INITIALIZATION_FAILED; diff --git a/components/policy/core/common/cloud/cloud_policy_validator.cc b/components/policy/core/common/cloud/cloud_policy_validator.cc index be2bd6f..ba1f986e 100644 --- a/components/policy/core/common/cloud/cloud_policy_validator.cc +++ b/components/policy/core/common/cloud/cloud_policy_validator.cc @@ -30,24 +30,6 @@ namespace { // Grace interval for policy-from-the-future timestamp checks. const int kTimestampGraceIntervalHours = 2; -// DER-encoded ASN.1 object identifier for the SHA1-RSA signature algorithm. -const uint8_t kSHA1SignatureAlgorithm[] = {0x30, 0x0d, 0x06, 0x09, 0x2a, - 0x86, 0x48, 0x86, 0xf7, 0x0d, - 0x01, 0x01, 0x05, 0x05, 0x00}; - -// DER-encoded ASN.1 object identifier for the SHA256-RSA signature algorithm -// (source: http://tools.ietf.org/html/rfc5754 section 3.2). -const uint8_t kSHA256SignatureAlgorithm[] = {0x30, 0x0d, 0x06, 0x09, 0x2a, - 0x86, 0x48, 0x86, 0xf7, 0x0d, - 0x01, 0x01, 0x0b, 0x05, 0x00}; - -static_assert(sizeof(kSHA256SignatureAlgorithm) == - sizeof(kSHA1SignatureAlgorithm), - "kSHA256SignatureAlgorithm must be the same size as " - "kSHA1SignatureAlgorithm"); - -const int kSignatureAlgorithmSize = sizeof(kSHA1SignatureAlgorithm); - const char kMetricPolicyKeyVerification[] = "Enterprise.PolicyKeyVerification"; enum MetricPolicyKeyVerification { @@ -526,13 +508,13 @@ bool CloudPolicyValidatorBase::VerifySignature(const std::string& data, const std::string& signature, SignatureType signature_type) { crypto::SignatureVerifier verifier; - const uint8_t* algorithm = NULL; + crypto::SignatureVerifier::SignatureAlgorithm algorithm; switch (signature_type) { case SHA1: - algorithm = kSHA1SignatureAlgorithm; + algorithm = crypto::SignatureVerifier::RSA_PKCS1_SHA1; break; case SHA256: - algorithm = kSHA256SignatureAlgorithm; + algorithm = crypto::SignatureVerifier::RSA_PKCS1_SHA256; break; default: NOTREACHED() << "Invalid signature type: " << signature_type; @@ -540,9 +522,9 @@ bool CloudPolicyValidatorBase::VerifySignature(const std::string& data, } if (!verifier.VerifyInit( - algorithm, kSignatureAlgorithmSize, - reinterpret_cast<const uint8_t*>(signature.c_str()), signature.size(), - reinterpret_cast<const uint8_t*>(key.c_str()), key.size())) { + algorithm, reinterpret_cast<const uint8_t*>(signature.c_str()), + signature.size(), reinterpret_cast<const uint8_t*>(key.c_str()), + key.size())) { DLOG(ERROR) << "Invalid verification signature/key format"; return false; } diff --git a/components/update_client/client_update_protocol_ecdsa.cc b/components/update_client/client_update_protocol_ecdsa.cc index 8479ceb..cc67b71 100644 --- a/components/update_client/client_update_protocol_ecdsa.cc +++ b/components/update_client/client_update_protocol_ecdsa.cc @@ -19,22 +19,6 @@ namespace update_client { namespace { -// This is the algorithm ID for ECDSA with SHA-256. Parameters are ABSENT. -// RFC 5758: -// ecdsa-with-SHA256 OBJECT IDENTIFIER ::= { iso(1) member-body(2) -// us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 2 } -// ... -// When the ecdsa-with-SHA224, ecdsa-with-SHA256, ecdsa-with-SHA384, or -// ecdsa-with-SHA512 algorithm identifier appears in the algorithm field -// as an AlgorithmIdentifier, the encoding MUST omit the parameters -// field. That is, the AlgorithmIdentifier SHALL be a SEQUENCE of one -// component, the OID ecdsa-with-SHA224, ecdsa-with-SHA256, ecdsa-with- -// SHA384, or ecdsa-with-SHA512. -// See also RFC 5480, Appendix A. -static const uint8_t kECDSAWithSHA256AlgorithmID[] = { - 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, -}; - std::vector<uint8_t> SHA256HashStr(const base::StringPiece& str) { std::vector<uint8_t> result(crypto::kSHA256Length); crypto::SHA256HashString(str, &result.front(), result.size()); @@ -189,9 +173,9 @@ bool ClientUpdateProtocolEcdsa::ValidateResponse( // Initialize the signature verifier. crypto::SignatureVerifier verifier; if (!verifier.VerifyInit( - kECDSAWithSHA256AlgorithmID, sizeof(kECDSAWithSHA256AlgorithmID), - &signature.front(), static_cast<int>(signature.size()), - &public_key_.front(), static_cast<int>(public_key_.size()))) { + crypto::SignatureVerifier::ECDSA_SHA256, &signature.front(), + static_cast<int>(signature.size()), &public_key_.front(), + static_cast<int>(public_key_.size()))) { DVLOG(1) << "Couldn't init SignatureVerifier."; return false; } diff --git a/components/update_client/component_unpacker.cc b/components/update_client/component_unpacker.cc index b525b4e..91c9b77 100644 --- a/components/update_client/component_unpacker.cc +++ b/components/update_client/component_unpacker.cc @@ -21,7 +21,6 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" #include "base/values.h" -#include "components/crx_file/constants.h" #include "components/crx_file/crx_file.h" #include "components/update_client/component_patcher.h" #include "components/update_client/component_patcher_operation.h" diff --git a/components/variations/variations_seed_store.cc b/components/variations/variations_seed_store.cc index 716bb05..65b1efd 100644 --- a/components/variations/variations_seed_store.cc +++ b/components/variations/variations_seed_store.cc @@ -39,22 +39,6 @@ bool SignatureVerificationEnabled() { #endif } -// This is the algorithm ID for ECDSA with SHA-256. Parameters are ABSENT. -// RFC 5758: -// ecdsa-with-SHA256 OBJECT IDENTIFIER ::= { iso(1) member-body(2) -// us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 2 } -// ... -// When the ecdsa-with-SHA224, ecdsa-with-SHA256, ecdsa-with-SHA384, or -// ecdsa-with-SHA512 algorithm identifier appears in the algorithm field -// as an AlgorithmIdentifier, the encoding MUST omit the parameters -// field. That is, the AlgorithmIdentifier SHALL be a SEQUENCE of one -// component, the OID ecdsa-with-SHA224, ecdsa-with-SHA256, ecdsa-with- -// SHA384, or ecdsa-with-SHA512. -// See also RFC 5480, Appendix A. -const uint8_t kECDSAWithSHA256AlgorithmID[] = { - 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, -}; - // The ECDSA public key of the variations server for verifying variations seed // signatures. const uint8_t kPublicKey[] = { @@ -341,10 +325,10 @@ VariationsSeedStore::VerifySeedSignature( return VARIATIONS_SEED_SIGNATURE_DECODE_FAILED; crypto::SignatureVerifier verifier; - if (!verifier.VerifyInit( - kECDSAWithSHA256AlgorithmID, sizeof(kECDSAWithSHA256AlgorithmID), - reinterpret_cast<const uint8_t*>(signature.data()), signature.size(), - kPublicKey, arraysize(kPublicKey))) { + if (!verifier.VerifyInit(crypto::SignatureVerifier::ECDSA_SHA256, + reinterpret_cast<const uint8_t*>(signature.data()), + signature.size(), kPublicKey, + arraysize(kPublicKey))) { return VARIATIONS_SEED_SIGNATURE_INVALID_SIGNATURE; } diff --git a/crypto/ec_signature_creator_unittest.cc b/crypto/ec_signature_creator_unittest.cc index 36c850a..5aa27f2 100644 --- a/crypto/ec_signature_creator_unittest.cc +++ b/crypto/ec_signature_creator_unittest.cc @@ -47,25 +47,9 @@ TEST(ECSignatureCreatorTest, BasicTest) { std::vector<uint8_t> public_key_info; ASSERT_TRUE(key_original->ExportPublicKey(&public_key_info)); - // This is the algorithm ID for ECDSA with SHA-256. Parameters are ABSENT. - // RFC 5758: - // ecdsa-with-SHA256 OBJECT IDENTIFIER ::= { iso(1) member-body(2) - // us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 2 } - // ... - // When the ecdsa-with-SHA224, ecdsa-with-SHA256, ecdsa-with-SHA384, or - // ecdsa-with-SHA512 algorithm identifier appears in the algorithm field - // as an AlgorithmIdentifier, the encoding MUST omit the parameters - // field. That is, the AlgorithmIdentifier SHALL be a SEQUENCE of one - // component, the OID ecdsa-with-SHA224, ecdsa-with-SHA256, ecdsa-with- - // SHA384, or ecdsa-with-SHA512. - // See also RFC 5480, Appendix A. - const uint8_t kECDSAWithSHA256AlgorithmID[] = { - 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, - }; crypto::SignatureVerifier verifier; ASSERT_TRUE(verifier.VerifyInit( - kECDSAWithSHA256AlgorithmID, sizeof(kECDSAWithSHA256AlgorithmID), - &signature[0], signature.size(), + crypto::SignatureVerifier::ECDSA_SHA256, &signature[0], signature.size(), &public_key_info.front(), public_key_info.size())); verifier.VerifyUpdate(reinterpret_cast<const uint8_t*>(data.c_str()), diff --git a/crypto/signature_creator_unittest.cc b/crypto/signature_creator_unittest.cc index af1a042..fff065e5 100644 --- a/crypto/signature_creator_unittest.cc +++ b/crypto/signature_creator_unittest.cc @@ -14,19 +14,6 @@ #include "crypto/signature_verifier.h" #include "testing/gtest/include/gtest/gtest.h" -namespace { - -// This is the algorithm ID for SHA-1 with RSA encryption. -const uint8_t kSHA1WithRSAAlgorithmID[] = {0x30, 0x0d, 0x06, 0x09, 0x2a, - 0x86, 0x48, 0x86, 0xf7, 0x0d, - 0x01, 0x01, 0x05, 0x05, 0x00}; - -// This is the algorithm ID for SHA-1 with RSA encryption. -const uint8_t kSHA256WithRSAAlgorithmID[] = {0x30, 0x0d, 0x06, 0x09, 0x2a, - 0x86, 0x48, 0x86, 0xf7, 0x0d, - 0x01, 0x01, 0x0B, 0x05, 0x00}; -} - TEST(SignatureCreatorTest, BasicTest) { // Do a verify round trip. scoped_ptr<crypto::RSAPrivateKey> key_original( @@ -56,9 +43,8 @@ TEST(SignatureCreatorTest, BasicTest) { crypto::SignatureVerifier verifier; ASSERT_TRUE(verifier.VerifyInit( - kSHA1WithRSAAlgorithmID, sizeof(kSHA1WithRSAAlgorithmID), - &signature.front(), signature.size(), - &public_key_info.front(), public_key_info.size())); + crypto::SignatureVerifier::RSA_PKCS1_SHA1, &signature.front(), + signature.size(), &public_key_info.front(), public_key_info.size())); verifier.VerifyUpdate(reinterpret_cast<const uint8_t*>(data.c_str()), data.size()); @@ -91,9 +77,8 @@ TEST(SignatureCreatorTest, SignDigestTest) { // Verify the input data. crypto::SignatureVerifier verifier; ASSERT_TRUE(verifier.VerifyInit( - kSHA1WithRSAAlgorithmID, sizeof(kSHA1WithRSAAlgorithmID), - &signature.front(), signature.size(), - &public_key_info.front(), public_key_info.size())); + crypto::SignatureVerifier::RSA_PKCS1_SHA1, &signature.front(), + signature.size(), &public_key_info.front(), public_key_info.size())); verifier.VerifyUpdate(reinterpret_cast<const uint8_t*>(data.c_str()), data.size()); @@ -127,9 +112,8 @@ TEST(SignatureCreatorTest, SignSHA256DigestTest) { // Verify the input data. crypto::SignatureVerifier verifier; ASSERT_TRUE(verifier.VerifyInit( - kSHA256WithRSAAlgorithmID, sizeof(kSHA256WithRSAAlgorithmID), - &signature.front(), signature.size(), - &public_key_info.front(), public_key_info.size())); + crypto::SignatureVerifier::RSA_PKCS1_SHA256, &signature.front(), + signature.size(), &public_key_info.front(), public_key_info.size())); verifier.VerifyUpdate(reinterpret_cast<const uint8_t*>(data.c_str()), data.size()); diff --git a/crypto/signature_verifier.h b/crypto/signature_verifier.h index b26a0df..5b7369f 100644 --- a/crypto/signature_verifier.h +++ b/crypto/signature_verifier.h @@ -33,6 +33,13 @@ class CRYPTO_EXPORT SignatureVerifier { SHA256, }; + // The set of supported signature algorithms. Extend as required. + enum SignatureAlgorithm { + RSA_PKCS1_SHA1, + RSA_PKCS1_SHA256, + ECDSA_SHA256, + }; + SignatureVerifier(); ~SignatureVerifier(); @@ -42,16 +49,7 @@ class CRYPTO_EXPORT SignatureVerifier { // by one or more VerifyUpdate calls and a VerifyFinal call. // NOTE: for RSA-PSS signatures, use VerifyInitRSAPSS instead. // - // The signature algorithm is specified as a DER encoded ASN.1 - // AlgorithmIdentifier structure: - // AlgorithmIdentifier ::= SEQUENCE { - // algorithm OBJECT IDENTIFIER, - // parameters ANY DEFINED BY algorithm OPTIONAL } - // - // The signature is encoded according to the signature algorithm, but it - // must not be further encoded in an ASN.1 BIT STRING. - // Note: An RSA signature is actually a big integer. It must be in - // big-endian byte order. + // The signature is encoded according to the signature algorithm. // // The public key is specified as a DER encoded ASN.1 SubjectPublicKeyInfo // structure, which contains not only the public key but also its type @@ -59,8 +57,7 @@ class CRYPTO_EXPORT SignatureVerifier { // SubjectPublicKeyInfo ::= SEQUENCE { // algorithm AlgorithmIdentifier, // subjectPublicKey BIT STRING } - bool VerifyInit(const uint8_t* signature_algorithm, - int signature_algorithm_len, + bool VerifyInit(SignatureAlgorithm signature_algorithm, const uint8_t* signature, int signature_len, const uint8_t* public_key_info, @@ -98,19 +95,10 @@ class CRYPTO_EXPORT SignatureVerifier { // error occurred. bool VerifyFinal(); - // Note: we can provide a one-shot interface if there is interest: - // bool Verify(const uint8_t* data, - // int data_len, - // const uint8_t* signature_algorithm, - // int signature_algorithm_len, - // const uint8_t* signature, - // int signature_len, - // const uint8_t* public_key_info, - // int public_key_info_len); - private: #if defined(USE_OPENSSL) - bool CommonInit(const EVP_MD* digest, + bool CommonInit(int pkey_type, + const EVP_MD* digest, const uint8_t* signature, int signature_len, const uint8_t* public_key_info, diff --git a/crypto/signature_verifier_nss.cc b/crypto/signature_verifier_nss.cc index e6cd3e0..edbd3f6 100644 --- a/crypto/signature_verifier_nss.cc +++ b/crypto/signature_verifier_nss.cc @@ -30,6 +30,18 @@ HASH_HashType ToNSSHashType(SignatureVerifier::HashAlgorithm hash_alg) { return HASH_AlgNULL; } +SECOidTag ToNSSSignatureType(SignatureVerifier::SignatureAlgorithm sig_alg) { + switch (sig_alg) { + case SignatureVerifier::RSA_PKCS1_SHA1: + return SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION; + case SignatureVerifier::RSA_PKCS1_SHA256: + return SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION; + case SignatureVerifier::ECDSA_SHA256: + return SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE; + } + return SEC_OID_UNKNOWN; +} + SECStatus VerifyRSAPSS_End(SECKEYPublicKey* public_key, HASHContext* hash_context, HASH_HashType mask_hash_alg, @@ -74,8 +86,7 @@ SignatureVerifier::~SignatureVerifier() { Reset(); } -bool SignatureVerifier::VerifyInit(const uint8_t* signature_algorithm, - int signature_algorithm_len, +bool SignatureVerifier::VerifyInit(SignatureAlgorithm signature_algorithm, const uint8_t* signature, int signature_len, const uint8_t* public_key_info, @@ -90,37 +101,13 @@ bool SignatureVerifier::VerifyInit(const uint8_t* signature_algorithm, if (!public_key) return false; - PLArenaPool* arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if (!arena) { - SECKEY_DestroyPublicKey(public_key); - return false; - } - - SECItem sig_alg_der; - sig_alg_der.type = siBuffer; - sig_alg_der.data = const_cast<uint8_t*>(signature_algorithm); - sig_alg_der.len = signature_algorithm_len; - SECAlgorithmID sig_alg_id; - SECStatus rv; - rv = SEC_QuickDERDecodeItem(arena, &sig_alg_id, - SEC_ASN1_GET(SECOID_AlgorithmIDTemplate), - &sig_alg_der); - if (rv != SECSuccess) { - SECKEY_DestroyPublicKey(public_key); - PORT_FreeArena(arena, PR_TRUE); - return false; - } - SECItem sig; sig.type = siBuffer; sig.data = const_cast<uint8_t*>(signature); sig.len = signature_len; - SECOidTag hash_alg_tag; - vfy_context_ = VFY_CreateContextWithAlgorithmID(public_key, &sig, - &sig_alg_id, &hash_alg_tag, - NULL); + vfy_context_ = VFY_CreateContext( + public_key, &sig, ToNSSSignatureType(signature_algorithm), nullptr); SECKEY_DestroyPublicKey(public_key); // Done with public_key. - PORT_FreeArena(arena, PR_TRUE); // Done with sig_alg_id. if (!vfy_context_) { // A corrupted RSA signature could be detected without the data, so // VFY_CreateContextWithAlgorithmID may fail with SEC_ERROR_BAD_SIGNATURE @@ -128,8 +115,7 @@ bool SignatureVerifier::VerifyInit(const uint8_t* signature_algorithm, return false; } - rv = VFY_Begin(vfy_context_); - if (rv != SECSuccess) { + if (VFY_Begin(vfy_context_) != SECSuccess) { NOTREACHED(); return false; } diff --git a/crypto/signature_verifier_openssl.cc b/crypto/signature_verifier_openssl.cc index 2e64a58..495abd2 100644 --- a/crypto/signature_verifier_openssl.cc +++ b/crypto/signature_verifier_openssl.cc @@ -5,8 +5,8 @@ #include "crypto/signature_verifier.h" #include <openssl/bytestring.h> +#include <openssl/digest.h> #include <openssl/evp.h> -#include <openssl/x509.h> #include <stdint.h> #include <vector> @@ -44,33 +44,32 @@ SignatureVerifier::~SignatureVerifier() { Reset(); } -bool SignatureVerifier::VerifyInit(const uint8_t* signature_algorithm, - int signature_algorithm_len, +bool SignatureVerifier::VerifyInit(SignatureAlgorithm signature_algorithm, const uint8_t* signature, int signature_len, const uint8_t* public_key_info, int public_key_info_len) { - OpenSSLErrStackTracer err_tracer(FROM_HERE); - ScopedOpenSSL<X509_ALGOR, X509_ALGOR_free> algorithm( - d2i_X509_ALGOR(NULL, &signature_algorithm, signature_algorithm_len)); - if (!algorithm.get()) - return false; - int nid = OBJ_obj2nid(algorithm.get()->algorithm); - const EVP_MD* digest; - if (nid == NID_ecdsa_with_SHA1) { - digest = EVP_sha1(); - } else if (nid == NID_ecdsa_with_SHA256) { - digest = EVP_sha256(); - } else { - // This works for PKCS #1 v1.5 RSA signatures, but not for ECDSA - // signatures. - digest = EVP_get_digestbyobj(algorithm.get()->algorithm); + int pkey_type = EVP_PKEY_NONE; + const EVP_MD* digest = nullptr; + switch (signature_algorithm) { + case RSA_PKCS1_SHA1: + pkey_type = EVP_PKEY_RSA; + digest = EVP_sha1(); + break; + case RSA_PKCS1_SHA256: + pkey_type = EVP_PKEY_RSA; + digest = EVP_sha256(); + break; + case ECDSA_SHA256: + pkey_type = EVP_PKEY_EC; + digest = EVP_sha256(); + break; } - if (!digest) - return false; + DCHECK_NE(EVP_PKEY_NONE, pkey_type); + DCHECK(digest); - return CommonInit(digest, signature, signature_len, public_key_info, - public_key_info_len, NULL); + return CommonInit(pkey_type, digest, signature, signature_len, + public_key_info, public_key_info_len, nullptr); } bool SignatureVerifier::VerifyInitRSAPSS(HashAlgorithm hash_alg, @@ -88,8 +87,8 @@ bool SignatureVerifier::VerifyInitRSAPSS(HashAlgorithm hash_alg, } EVP_PKEY_CTX* pkey_ctx; - if (!CommonInit(digest, signature, signature_len, public_key_info, - public_key_info_len, &pkey_ctx)) { + if (!CommonInit(EVP_PKEY_RSA, digest, signature, signature_len, + public_key_info, public_key_info_len, &pkey_ctx)) { return false; } @@ -101,11 +100,8 @@ bool SignatureVerifier::VerifyInitRSAPSS(HashAlgorithm hash_alg, if (!mgf_digest) { return false; } - rv = EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, mgf_digest); - if (rv != 1) - return false; - rv = EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx, salt_len); - return rv == 1; + return EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, mgf_digest) && + EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx, salt_len); } void SignatureVerifier::VerifyUpdate(const uint8_t* data_part, @@ -127,7 +123,8 @@ bool SignatureVerifier::VerifyFinal() { return rv == 1; } -bool SignatureVerifier::CommonInit(const EVP_MD* digest, +bool SignatureVerifier::CommonInit(int pkey_type, + const EVP_MD* digest, const uint8_t* signature, int signature_len, const uint8_t* public_key_info, @@ -143,8 +140,10 @@ bool SignatureVerifier::CommonInit(const EVP_MD* digest, CBS cbs; CBS_init(&cbs, public_key_info, public_key_info_len); ScopedEVP_PKEY public_key(EVP_parse_public_key(&cbs)); - if (!public_key || CBS_len(&cbs) != 0) + if (!public_key || CBS_len(&cbs) != 0 || + EVP_PKEY_id(public_key.get()) != pkey_type) { return false; + } verify_context_->ctx.reset(EVP_MD_CTX_create()); int rv = EVP_DigestVerifyInit(verify_context_->ctx.get(), pkey_ctx, diff --git a/crypto/signature_verifier_unittest.cc b/crypto/signature_verifier_unittest.cc index adcc885..d71ea82 100644 --- a/crypto/signature_verifier_unittest.cc +++ b/crypto/signature_verifier_unittest.cc @@ -14,9 +14,9 @@ TEST(SignatureVerifierTest, BasicTest) { // The input data in this test comes from real certificates. // - // tbs_certificate ("to-be-signed certificate", the part of a certificate - // that is signed), signature_algorithm, and algorithm come from the - // certificate of bugs.webkit.org. + // tbs_certificate ("to-be-signed certificate", the part of a certificate that + // is signed), signature, and algorithm come from the certificate of + // bugs.webkit.org. // // public_key_info comes from the certificate of the issuer, Go Daddy Secure // Certification Authority. @@ -116,19 +116,6 @@ TEST(SignatureVerifierTest, BasicTest) { 0x74, 0x2e, 0x6f, 0x72, 0x67, 0x82, 0x0a, 0x77, 0x65, 0x62, 0x6b, 0x69, 0x74, 0x2e, 0x6f, 0x72, 0x67}; - // The signature algorithm is specified as the following ASN.1 structure: - // AlgorithmIdentifier ::= SEQUENCE { - // algorithm OBJECT IDENTIFIER, - // parameters ANY DEFINED BY algorithm OPTIONAL } - // - const uint8_t signature_algorithm[15] = { - 0x30, 0x0d, // a SEQUENCE of length 13 (0xd) - 0x06, 0x09, // an OBJECT IDENTIFIER of length 9 - // 1.2.840.113549.1.1.5 - sha1WithRSAEncryption - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, - 0x00, // a NULL of length 0 - }; - // RSA signature, a big integer in the big-endian byte order. const uint8_t signature[256] = { 0x1e, 0x6a, 0xe7, 0xe0, 0x4f, 0xe7, 0x4d, 0xd0, 0x69, 0x7c, 0xf8, 0x8f, @@ -202,12 +189,11 @@ TEST(SignatureVerifierTest, BasicTest) { crypto::SignatureVerifier verifier; bool ok; - // Test 1: feed all of the data to the verifier at once (a single + // Test 1: feed all of the data to the verifier at once (a single // VerifyUpdate call). - ok = verifier.VerifyInit(signature_algorithm, - sizeof(signature_algorithm), - signature, sizeof(signature), - public_key_info, sizeof(public_key_info)); + ok = verifier.VerifyInit(crypto::SignatureVerifier::RSA_PKCS1_SHA1, signature, + sizeof(signature), public_key_info, + sizeof(public_key_info)); EXPECT_TRUE(ok); verifier.VerifyUpdate(tbs_certificate, sizeof(tbs_certificate)); ok = verifier.VerifyFinal(); @@ -215,12 +201,11 @@ TEST(SignatureVerifierTest, BasicTest) { // Test 2: feed the data to the verifier in three parts (three VerifyUpdate // calls). - ok = verifier.VerifyInit(signature_algorithm, - sizeof(signature_algorithm), - signature, sizeof(signature), - public_key_info, sizeof(public_key_info)); + ok = verifier.VerifyInit(crypto::SignatureVerifier::RSA_PKCS1_SHA1, signature, + sizeof(signature), public_key_info, + sizeof(public_key_info)); EXPECT_TRUE(ok); - verifier.VerifyUpdate(tbs_certificate, 256); + verifier.VerifyUpdate(tbs_certificate, 256); verifier.VerifyUpdate(tbs_certificate + 256, 256); verifier.VerifyUpdate(tbs_certificate + 512, sizeof(tbs_certificate) - 512); ok = verifier.VerifyFinal(); @@ -230,10 +215,9 @@ TEST(SignatureVerifierTest, BasicTest) { uint8_t bad_tbs_certificate[sizeof(tbs_certificate)]; memcpy(bad_tbs_certificate, tbs_certificate, sizeof(tbs_certificate)); bad_tbs_certificate[10] += 1; // Corrupt one byte of the data. - ok = verifier.VerifyInit(signature_algorithm, - sizeof(signature_algorithm), - signature, sizeof(signature), - public_key_info, sizeof(public_key_info)); + ok = verifier.VerifyInit(crypto::SignatureVerifier::RSA_PKCS1_SHA1, signature, + sizeof(signature), public_key_info, + sizeof(public_key_info)); EXPECT_TRUE(ok); verifier.VerifyUpdate(bad_tbs_certificate, sizeof(bad_tbs_certificate)); ok = verifier.VerifyFinal(); @@ -243,8 +227,7 @@ TEST(SignatureVerifierTest, BasicTest) { uint8_t bad_signature[sizeof(signature)]; memcpy(bad_signature, signature, sizeof(signature)); bad_signature[10] += 1; // Corrupt one byte of the signature. - ok = verifier.VerifyInit(signature_algorithm, - sizeof(signature_algorithm), + ok = verifier.VerifyInit(crypto::SignatureVerifier::RSA_PKCS1_SHA1, bad_signature, sizeof(bad_signature), public_key_info, sizeof(public_key_info)); @@ -260,20 +243,18 @@ TEST(SignatureVerifierTest, BasicTest) { uint8_t bad_public_key_info[sizeof(public_key_info)]; memcpy(bad_public_key_info, public_key_info, sizeof(public_key_info)); bad_public_key_info[0] += 1; // Corrupt part of the SPKI syntax. - ok = verifier.VerifyInit(signature_algorithm, - sizeof(signature_algorithm), - signature, sizeof(signature), - bad_public_key_info, sizeof(bad_public_key_info)); + ok = verifier.VerifyInit(crypto::SignatureVerifier::RSA_PKCS1_SHA1, signature, + sizeof(signature), bad_public_key_info, + sizeof(bad_public_key_info)); EXPECT_FALSE(ok); // Test 6: import a key with extra data. uint8_t long_public_key_info[sizeof(public_key_info) + 5]; memset(long_public_key_info, 0, sizeof(long_public_key_info)); memcpy(long_public_key_info, public_key_info, sizeof(public_key_info)); - ok = verifier.VerifyInit(signature_algorithm, - sizeof(signature_algorithm), - signature, sizeof(signature), - long_public_key_info, sizeof(long_public_key_info)); + ok = verifier.VerifyInit(crypto::SignatureVerifier::RSA_PKCS1_SHA1, signature, + sizeof(signature), long_public_key_info, + sizeof(long_public_key_info)); EXPECT_FALSE(ok); } @@ -1022,7 +1003,7 @@ static bool EncodeRSAPublicKey(const std::vector<uint8_t>& modulus_n, // algorithm AlgorithmIdentifier, // subjectPublicKey BIT STRING } // - // The signature algorithm is specified as the following ASN.1 structure: + // The algorithm is specified as the following ASN.1 structure: // AlgorithmIdentifier ::= SEQUENCE { // algorithm OBJECT IDENTIFIER, // parameters ANY DEFINED BY algorithm OPTIONAL } diff --git a/extensions/browser/verified_contents.cc b/extensions/browser/verified_contents.cc index 28ed16a..fc2471d 100644 --- a/extensions/browser/verified_contents.cc +++ b/extensions/browser/verified_contents.cc @@ -21,14 +21,6 @@ using base::Value; namespace { -// Note: this structure is an ASN.1 which encodes the algorithm used with its -// parameters. The signature algorithm is "RSA256" aka "RSASSA-PKCS-v1_5 using -// SHA-256 hash algorithm". This is defined in PKCS #1 (RFC 3447). -// It is encoding: { OID sha256WithRSAEncryption PARAMETERS NULL } -const uint8_t kSignatureAlgorithm[15] = {0x30, 0x0d, 0x06, 0x09, 0x2a, - 0x86, 0x48, 0x86, 0xf7, 0x0d, - 0x01, 0x01, 0x0b, 0x05, 0x00}; - const char kBlockSizeKey[] = "block_size"; const char kContentHashesKey[] = "content_hashes"; const char kDescriptionKey[] = "description"; @@ -308,7 +300,7 @@ bool VerifiedContents::VerifySignature(const std::string& protected_value, const std::string& signature_bytes) { crypto::SignatureVerifier signature_verifier; if (!signature_verifier.VerifyInit( - kSignatureAlgorithm, sizeof(kSignatureAlgorithm), + crypto::SignatureVerifier::RSA_PKCS1_SHA256, reinterpret_cast<const uint8_t*>(signature_bytes.data()), signature_bytes.size(), public_key_, public_key_size_)) { VLOG(1) << "Could not verify signature - VerifyInit failure"; diff --git a/net/quic/crypto/proof_verifier_chromium.cc b/net/quic/crypto/proof_verifier_chromium.cc index 2331a6db..6823550 100644 --- a/net/quic/crypto/proof_verifier_chromium.cc +++ b/net/quic/crypto/proof_verifier_chromium.cc @@ -371,27 +371,11 @@ bool ProofVerifierChromium::Job::VerifySignature(const string& signed_data, return false; } } else if (type == X509Certificate::kPublicKeyTypeECDSA) { - // This is the algorithm ID for ECDSA with SHA-256. Parameters are ABSENT. - // RFC 5758: - // ecdsa-with-SHA256 OBJECT IDENTIFIER ::= { iso(1) member-body(2) - // us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 2 } - // ... - // When the ecdsa-with-SHA224, ecdsa-with-SHA256, ecdsa-with-SHA384, or - // ecdsa-with-SHA512 algorithm identifier appears in the algorithm field - // as an AlgorithmIdentifier, the encoding MUST omit the parameters - // field. That is, the AlgorithmIdentifier SHALL be a SEQUENCE of one - // component, the OID ecdsa-with-SHA224, ecdsa-with-SHA256, ecdsa-with- - // SHA384, or ecdsa-with-SHA512. - // See also RFC 5480, Appendix A. - static const uint8_t kECDSAWithSHA256AlgorithmID[] = { - 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, - }; - - if (!verifier.VerifyInit( - kECDSAWithSHA256AlgorithmID, sizeof(kECDSAWithSHA256AlgorithmID), - reinterpret_cast<const uint8_t*>(signature.data()), - signature.size(), reinterpret_cast<const uint8_t*>(spki.data()), - spki.size())) { + if (!verifier.VerifyInit(crypto::SignatureVerifier::ECDSA_SHA256, + reinterpret_cast<const uint8_t*>(signature.data()), + signature.size(), + reinterpret_cast<const uint8_t*>(spki.data()), + spki.size())) { DLOG(WARNING) << "VerifyInit failed"; return false; } |