diff options
author | rch@chromium.org <rch@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-01-25 00:56:43 +0000 |
---|---|---|
committer | rch@chromium.org <rch@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-01-25 00:56:43 +0000 |
commit | e4c1847a71fa607fe7fb5df24106db1966608062 (patch) | |
tree | 07752406002540e8ca35ee202e3c15acd24ea7cd | |
parent | 40f96f2ddddda80dd9df007b0b5033b8e0b6ecdf (diff) | |
download | chromium_src-e4c1847a71fa607fe7fb5df24106db1966608062.zip chromium_src-e4c1847a71fa607fe7fb5df24106db1966608062.tar.gz chromium_src-e4c1847a71fa607fe7fb5df24106db1966608062.tar.bz2 |
Create a new ECSignatureCreator class for signing content using EC crypto.
Review URL: http://codereview.chromium.org/9240029
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@118964 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | crypto/crypto.gyp | 14 | ||||
-rw-r--r-- | crypto/ec_signature_creator.h | 52 | ||||
-rw-r--r-- | crypto/ec_signature_creator_nss.cc | 99 | ||||
-rw-r--r-- | crypto/ec_signature_creator_openssl.cc | 33 | ||||
-rw-r--r-- | crypto/ec_signature_creator_unittest.cc | 72 | ||||
-rw-r--r-- | crypto/signature_verifier.h | 26 |
6 files changed, 271 insertions, 25 deletions
diff --git a/crypto/crypto.gyp b/crypto/crypto.gyp index 2b76403..32065f4 100644 --- a/crypto/crypto.gyp +++ b/crypto/crypto.gyp @@ -1,4 +1,4 @@ -# Copyright (c) 2011 The Chromium Authors. All rights reserved. +# Copyright (c) 2012 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. @@ -39,6 +39,8 @@ 'sources/': [ ['exclude', '_nss\.cc$'], ['include', 'ec_private_key_nss\.cc$'], + ['include', 'ec_signature_creator_nss\.cc$'], + ['include', 'signature_verifier_nss\.cc$'], ], 'sources!': [ 'openpgp_symmetric_encryption.cc', @@ -50,6 +52,8 @@ ], 'sources/': [ ['exclude', 'ec_private_key_nss\.cc$'], + ['exclude', 'ec_signature_creator_nss\.cc$'], + ['exclude', 'signature_verifier_nss\.cc$'], ], }], [ 'os_bsd==1', { @@ -91,6 +95,7 @@ # OpenSSL file set is complete. 'sources!': [ 'ec_private_key_nss.cc', + 'ec_signature_creator_nss.cc', 'encryptor_nss.cc', 'hmac_nss.cc', 'nss_util.cc', @@ -112,6 +117,7 @@ }, { 'sources!': [ 'ec_private_key_openssl.cc', + 'ec_signature_creator_openssl.cc', 'encryptor_openssl.cc', 'hmac_openssl.cc', 'openssl_util.cc', @@ -134,6 +140,9 @@ 'ec_private_key.h', 'ec_private_key_nss.cc', 'ec_private_key_openssl.cc', + 'ec_signature_creator.h', + 'ec_signature_creator_nss.cc', + 'ec_signature_creator_openssl.cc', 'encryptor.cc', 'encryptor.h', 'encryptor_mac.cc', @@ -180,10 +189,8 @@ 'signature_creator_openssl.cc', 'signature_creator_win.cc', 'signature_verifier.h', - 'signature_verifier_mac.cc', 'signature_verifier_nss.cc', 'signature_verifier_openssl.cc', - 'signature_verifier_win.cc', 'symmetric_key.h', 'symmetric_key_mac.cc', 'symmetric_key_nss.cc', @@ -207,6 +214,7 @@ # Tests. 'ec_private_key_unittest.cc', + 'ec_signature_creator_unittest.cc', 'encryptor_unittest.cc', 'hmac_unittest.cc', 'nss_util_unittest.cc', diff --git a/crypto/ec_signature_creator.h b/crypto/ec_signature_creator.h new file mode 100644 index 0000000..8858eb5 --- /dev/null +++ b/crypto/ec_signature_creator.h @@ -0,0 +1,52 @@ +// Copyright (c) 2012 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 CRYPTO_EC_SIGNATURE_CREATOR_H_ +#define CRYPTO_EC_SIGNATURE_CREATOR_H_ +#pragma once + +#include <vector> + +#include "base/basictypes.h" +#include "crypto/crypto_export.h" + +namespace crypto { + +class ECPrivateKey; + +// Signs data using a bare private key (as opposed to a full certificate). +// We need this class because SignatureCreator is hardcoded to use +// RSAPrivateKey. +class CRYPTO_EXPORT ECSignatureCreator { + public: + ~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 + // pass in the hash algorithm identifier. + static ECSignatureCreator* Create(ECPrivateKey* key); + + // Signs |data_len| bytes from |data| and writes the results into + // |signature| as a DER encoded ECDSA-Sig-Value from RFC 3279. + // + // ECDSA-Sig-Value ::= SEQUENCE { + // r INTEGER, + // s INTEGER } + bool Sign(const uint8* data, + int data_len, + std::vector<uint8>* signature); + + private: + // Private constructor. Use the Create() method instead. + explicit ECSignatureCreator(ECPrivateKey* key); + + ECPrivateKey* key_; + + DISALLOW_COPY_AND_ASSIGN(ECSignatureCreator); +}; + +} // namespace crypto + +#endif // CRYPTO_EC_SIGNATURE_CREATOR_H_ diff --git a/crypto/ec_signature_creator_nss.cc b/crypto/ec_signature_creator_nss.cc new file mode 100644 index 0000000..147535b --- /dev/null +++ b/crypto/ec_signature_creator_nss.cc @@ -0,0 +1,99 @@ +// Copyright (c) 2012 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. + +#include "crypto/ec_signature_creator.h" + +#include <cryptohi.h> +#include <pk11pub.h> +#include <secerr.h> +#include <sechash.h> + +#include "base/logging.h" +#include "crypto/ec_private_key.h" +#include "crypto/nss_util.h" +#include "crypto/scoped_nss_types.h" + +namespace crypto { + +namespace { + +SECStatus SignData(PLArenaPool* arena, + SECItem* result, + SECItem* input, + SECKEYPrivateKey* key, + HASH_HashType hash_type) { + if (key->keyType != ecKey) { + DLOG(FATAL) << "Should be using an EC key."; + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + + // Hash the input. + std::vector<uint8> hash_data(HASH_ResultLen(hash_type)); + SECStatus rv = HASH_HashBuf( + hash_type, &hash_data[0], input->data, input->len); + if (rv != SECSuccess) + return rv; + SECItem hash = {siBuffer, &hash_data[0], hash_data.size()}; + + // Compute signature of hash. + int signature_len = PK11_SignatureLen(key); + std::vector<uint8> signature_data(signature_len); + SECItem sig = {siBuffer, &signature_data[0], signature_len}; + rv = PK11_Sign(key, &sig, &hash); + if (rv != SECSuccess) + return rv; + + // DER encode the signature. + return DSAU_EncodeDerSigWithLen(result, &sig, sig.len); +} + +} // namespace + +// static +ECSignatureCreator* ECSignatureCreator::Create(ECPrivateKey* key) { + return new ECSignatureCreator(key); +} + +ECSignatureCreator::ECSignatureCreator(ECPrivateKey* key) + : key_(key) { + EnsureNSSInit(); +} + +ECSignatureCreator::~ECSignatureCreator() { } + +bool ECSignatureCreator::Sign(const uint8* data, + int data_len, + std::vector<uint8>* signature) { + // Data to be signed + SECItem secret; + secret.type = siBuffer; + secret.len = data_len; + secret.data = const_cast<unsigned char*>(data); + + // |arena| is used to encode the cert. + crypto::ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE)); + CHECK(arena.get() != NULL); + + // Allocate space to contain the signed data. + SECItem* result = SECITEM_AllocItem(arena.get(), NULL, 0); + if (!result) { + DLOG(ERROR) << "Unable to allocate space for signed data."; + return false; + } + + // Sign the secret data and save it to |result|. + SECStatus rv = + SignData(arena.get(), result, &secret, key_->key(), HASH_AlgSHA1); + if (rv != SECSuccess) { + DLOG(ERROR) << "DerSignData: " << PORT_GetError(); + return false; + } + + // Copy the signed data into the output vector. + signature->assign(result->data, result->data + result->len); + return true; +} + +} // namespace crypto diff --git a/crypto/ec_signature_creator_openssl.cc b/crypto/ec_signature_creator_openssl.cc new file mode 100644 index 0000000..9e75ca2 --- /dev/null +++ b/crypto/ec_signature_creator_openssl.cc @@ -0,0 +1,33 @@ +// Copyright (c) 2012 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. + +#include "crypto/ec_signature_creator.h" + +#include "base/logging.h" + +namespace crypto { + +// static +ECSignatureCreator* ECSignatureCreator::Create(ECPrivateKey* key) { + NOTIMPLEMENTED(); + return NULL; +} + +ECSignatureCreator::ECSignatureCreator(ECPrivateKey* key, + HASH_HashType hash_type) + : key_(key), + hash_type_(hash_type) { + NOTIMPLEMENTED(); +} + +ECSignatureCreator::~ECSignatureCreator() { } + +bool ECSignatureCreator::Sign(const uint8* data, + int data_len, + std::vector<uint8>* signature) { + NOTIMPLEMENTED(); + return false; +} + +} // namespace crypto diff --git a/crypto/ec_signature_creator_unittest.cc b/crypto/ec_signature_creator_unittest.cc new file mode 100644 index 0000000..def8a63 --- /dev/null +++ b/crypto/ec_signature_creator_unittest.cc @@ -0,0 +1,72 @@ +// Copyright (c) 2012 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. + +#include "crypto/ec_signature_creator.h" + +#include <string> +#include <vector> + +#include "base/memory/scoped_ptr.h" +#include "crypto/ec_private_key.h" +#include "crypto/signature_verifier.h" +#include "testing/gtest/include/gtest/gtest.h" + +#if defined(USE_OPENSSL) +// Once ECSignatureCreator is implemented for OpenSSL, remove this #if block. +// TODO(rch): When that happens, also add some exported keys from each to +// test interop between NSS and OpenSSL. +TEST(ECSignatureCreatorTest, OpenSSLStub) { + scoped_ptr<crypto::ECSignatureCreator> signer( + crypto::ECSignatureCreator::Create(NULL)); + ASSERT_FALSE(signer.get()); +} +#else +TEST(ECSignatureCreatorTest, BasicTest) { + // Do a verify round trip. + scoped_ptr<crypto::ECPrivateKey> key_original( + crypto::ECPrivateKey::Create()); + ASSERT_TRUE(key_original.get()); + + std::vector<uint8> key_info; + ASSERT_TRUE(key_original->ExportEncryptedPrivateKey("", 1000, &key_info)); + std::vector<uint8> pubkey_info; + ASSERT_TRUE(key_original->ExportPublicKey(&pubkey_info)); + + scoped_ptr<crypto::ECPrivateKey> key( + crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo("", key_info, + pubkey_info)); + ASSERT_TRUE(key.get()); + ASSERT_TRUE(key->key() != NULL); + + scoped_ptr<crypto::ECSignatureCreator> signer( + crypto::ECSignatureCreator::Create(key.get())); + ASSERT_TRUE(signer.get()); + + std::string data("Hello, World!"); + std::vector<uint8> signature; + ASSERT_TRUE(signer->Sign(reinterpret_cast<const uint8*>(data.c_str()), + data.size(), + &signature)); + + std::vector<uint8> 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, + 0x05, 0x00 + }; + crypto::SignatureVerifier verifier; + ASSERT_TRUE(verifier.VerifyInit( + kECDSAWithSHA1AlgorithmID, sizeof(kECDSAWithSHA1AlgorithmID), + &signature.front(), signature.size(), + &public_key_info.front(), public_key_info.size())); + + verifier.VerifyUpdate(reinterpret_cast<const uint8*>(data.c_str()), + data.size()); + ASSERT_TRUE(verifier.VerifyFinal()); +} +#endif // !defined(USE_OPENSSL) diff --git a/crypto/signature_verifier.h b/crypto/signature_verifier.h index 3faa572..ad23188 100644 --- a/crypto/signature_verifier.h +++ b/crypto/signature_verifier.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 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. @@ -8,19 +8,13 @@ #include "build/build_config.h" -#if defined(USE_NSS) -#include <cryptoht.h> -#elif defined(OS_MACOSX) -#include <Security/cssm.h> -#endif - #include <vector> #include "base/basictypes.h" #include "crypto/crypto_export.h" -#if defined(OS_WIN) -#include "crypto/scoped_capi_types.h" +#if !defined(USE_OPENSSL) +typedef struct VFYContextStr VFYContext; #endif namespace crypto { @@ -87,20 +81,8 @@ class CRYPTO_EXPORT SignatureVerifier { #if defined(USE_OPENSSL) struct VerifyContext; VerifyContext* verify_context_; -#elif defined(USE_NSS) +#else VFYContext* vfy_context_; -#elif defined(OS_MACOSX) - std::vector<uint8> public_key_info_; - - CSSM_CC_HANDLE sig_handle_; - - CSSM_KEY public_key_; -#elif defined(OS_WIN) - ScopedHCRYPTPROV provider_; - - ScopedHCRYPTHASH hash_object_; - - ScopedHCRYPTKEY public_key_; #endif }; |