forked from sanyaade-mobiledev/chromium.src
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Create a new ECSignatureCreator class for signing content using EC cr…
…ypto. Review URL: http://codereview.chromium.org/9240029 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@118964 0039d316-1c4b-4281-b951-d872f2087c98
- Loading branch information
rch@chromium.org
committed
Jan 25, 2012
1 parent
40f96f2
commit e4c1847
Showing
6 changed files
with
271 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters