summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrch@chromium.org <rch@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-01-25 00:56:43 +0000
committerrch@chromium.org <rch@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-01-25 00:56:43 +0000
commite4c1847a71fa607fe7fb5df24106db1966608062 (patch)
tree07752406002540e8ca35ee202e3c15acd24ea7cd
parent40f96f2ddddda80dd9df007b0b5033b8e0b6ecdf (diff)
downloadchromium_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.gyp14
-rw-r--r--crypto/ec_signature_creator.h52
-rw-r--r--crypto/ec_signature_creator_nss.cc99
-rw-r--r--crypto/ec_signature_creator_openssl.cc33
-rw-r--r--crypto/ec_signature_creator_unittest.cc72
-rw-r--r--crypto/signature_verifier.h26
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
};