From 7c3090a02e256e1fc42d37123195caa134cb487b Mon Sep 17 00:00:00 2001 From: "agl@chromium.org" Date: Wed, 19 Sep 2012 15:11:33 +0000 Subject: crypto: add DecodeSignature and use SHA-256 with ECDSA. This changes ECSignatureCreator to use the hash function that SPDY expects (SHA-256). There are no other users of ECSignatureCreator in the tree so I'm going to defer making these choices parameters until there's a benefit to be had. It also adds DecodeSignature to convert from ASN.1 signatures to the `raw' form that SPDY needs. BUG=none Review URL: https://chromiumcodereview.appspot.com/10910226 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@157551 0039d316-1c4b-4281-b951-d872f2087c98 --- crypto/ec_signature_creator.h | 11 ++++++++++- crypto/ec_signature_creator_impl.h | 4 ++++ crypto/ec_signature_creator_nss.cc | 26 +++++++++++++++++++++++--- crypto/ec_signature_creator_openssl.cc | 6 ++++++ crypto/ec_signature_creator_unittest.cc | 14 +++++++------- 5 files changed, 50 insertions(+), 11 deletions(-) (limited to 'crypto') diff --git a/crypto/ec_signature_creator.h b/crypto/ec_signature_creator.h index b557daa..16e64f5 100644 --- a/crypto/ec_signature_creator.h +++ b/crypto/ec_signature_creator.h @@ -5,6 +5,7 @@ #ifndef CRYPTO_EC_SIGNATURE_CREATOR_H_ #define CRYPTO_EC_SIGNATURE_CREATOR_H_ +#include #include #include "base/basictypes.h" @@ -31,7 +32,7 @@ class CRYPTO_EXPORT ECSignatureCreator { // Create an instance. The caller must ensure that the provided PrivateKey // instance outlives the created ECSignatureCreator. - // TODO(rch): This is currently hard coded to use SHA1. Ideally, we should + // TODO(rch): This is currently hard coded to use SHA256. Ideally, we should // pass in the hash algorithm identifier. static ECSignatureCreator* Create(ECPrivateKey* key); @@ -50,6 +51,14 @@ class CRYPTO_EXPORT ECSignatureCreator { virtual bool Sign(const uint8* data, int data_len, std::vector* signature) = 0; + + // DecodeSignature converts from a DER encoded ECDSA-Sig-Value (as produced + // by Sign) to a `raw' ECDSA signature which consists of a pair of + // big-endian, zero-padded, 256-bit integers, r and s. On success it returns + // true and puts the raw signature into |out_raw_sig|. + // (Only P-256 signatures are supported.) + virtual bool DecodeSignature(const std::vector& signature, + std::vector* out_raw_sig) = 0; }; } // namespace crypto diff --git a/crypto/ec_signature_creator_impl.h b/crypto/ec_signature_creator_impl.h index f8baf86..8ef67cd 100644 --- a/crypto/ec_signature_creator_impl.h +++ b/crypto/ec_signature_creator_impl.h @@ -19,8 +19,12 @@ class ECSignatureCreatorImpl : public ECSignatureCreator { int data_len, std::vector* signature) OVERRIDE; + virtual bool DecodeSignature(const std::vector& der_sig, + std::vector* out_raw_sig) OVERRIDE; + private: ECPrivateKey* key_; + size_t signature_len_; DISALLOW_COPY_AND_ASSIGN(ECSignatureCreatorImpl); }; diff --git a/crypto/ec_signature_creator_nss.cc b/crypto/ec_signature_creator_nss.cc index a85b1e9..3e3626f 100644 --- a/crypto/ec_signature_creator_nss.cc +++ b/crypto/ec_signature_creator_nss.cc @@ -24,7 +24,8 @@ namespace { SECStatus SignData(SECItem* result, SECItem* input, SECKEYPrivateKey* key, - HASH_HashType hash_type) { + HASH_HashType hash_type, + size_t* out_signature_len) { if (key->keyType != ecKey) { DLOG(FATAL) << "Should be using an EC key."; PORT_SetError(SEC_ERROR_INVALID_ARGS); @@ -49,6 +50,8 @@ SECStatus SignData(SECItem* result, if (rv != SECSuccess) return rv; + *out_signature_len = sig.len; + // DER encode the signature. return DSAU_EncodeDerSigWithLen(result, &sig, sig.len); } @@ -56,7 +59,8 @@ SECStatus SignData(SECItem* result, } // namespace ECSignatureCreatorImpl::ECSignatureCreatorImpl(ECPrivateKey* key) - : key_(key) { + : key_(key), + signature_len_(0) { EnsureNSSInit(); } @@ -79,7 +83,7 @@ bool ECSignatureCreatorImpl::Sign(const uint8* data, // Sign the secret data and save it to |result|. SECStatus rv = - SignData(&result, &secret, key_->key(), HASH_AlgSHA1); + SignData(&result, &secret, key_->key(), HASH_AlgSHA256, &signature_len_); if (rv != SECSuccess) { DLOG(ERROR) << "DerSignData: " << PORT_GetError(); return false; @@ -91,4 +95,20 @@ bool ECSignatureCreatorImpl::Sign(const uint8* data, return true; } +bool ECSignatureCreatorImpl::DecodeSignature( + const std::vector& der_sig, + std::vector* out_raw_sig) { + SECItem der_sig_item; + der_sig_item.type = siBuffer; + der_sig_item.len = der_sig.size(); + der_sig_item.data = const_cast(&der_sig[0]); + + SECItem* raw_sig = DSAU_DecodeDerSigToLen(&der_sig_item, signature_len_); + if (!raw_sig) + return false; + out_raw_sig->assign(raw_sig->data, raw_sig->data + raw_sig->len); + SECITEM_FreeItem(raw_sig, PR_TRUE /* free SECItem structure itself. */); + return true; +} + } // namespace crypto diff --git a/crypto/ec_signature_creator_openssl.cc b/crypto/ec_signature_creator_openssl.cc index ae443c4..8854f5e 100644 --- a/crypto/ec_signature_creator_openssl.cc +++ b/crypto/ec_signature_creator_openssl.cc @@ -22,4 +22,10 @@ bool ECSignatureCreatorImpl::Sign(const uint8* data, return false; } +bool ECSignatureCreatorImpl::DecodeSignature(const std::vector& der_sig, + std::vector* out_raw_sig) { + NOTIMPLEMENTED(); + return false; +} + } // namespace crypto diff --git a/crypto/ec_signature_creator_unittest.cc b/crypto/ec_signature_creator_unittest.cc index 407b278..df73bec 100644 --- a/crypto/ec_signature_creator_unittest.cc +++ b/crypto/ec_signature_creator_unittest.cc @@ -53,17 +53,17 @@ TEST(ECSignatureCreatorTest, BasicTest) { std::vector public_key_info; ASSERT_TRUE(key_original->ExportPublicKey(&public_key_info)); - // This is the algorithm ID for SHA-1 with EC encryption. - const uint8 kECDSAWithSHA1AlgorithmID[] = { - 0x30, 0x0b, - 0x06, 0x07, - 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x01, + // This is the algorithm ID for SHA-256 with EC encryption. + const uint8 kECDSAWithSHA256AlgorithmID[] = { + 0x30, 0x0c, + 0x06, 0x08, + 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x05, 0x00 }; crypto::SignatureVerifier verifier; ASSERT_TRUE(verifier.VerifyInit( - kECDSAWithSHA1AlgorithmID, sizeof(kECDSAWithSHA1AlgorithmID), - &signature.front(), signature.size(), + kECDSAWithSHA256AlgorithmID, sizeof(kECDSAWithSHA256AlgorithmID), + &signature[0], signature.size(), &public_key_info.front(), public_key_info.size())); verifier.VerifyUpdate(reinterpret_cast(data.c_str()), -- cgit v1.1