Commit 0cf460ec authored by dougsteed's avatar dougsteed Committed by Commit bot

Generalize crypto::SignatureCreator to allow choice of hash function, so as to...

Generalize crypto::SignatureCreator to allow choice of hash function, so as to support SHA256 (not just SHA1).

BUG=412531

R=rsleevi@chromium.org,davidben@chromium.org

TBR=pfeldman@chromium.org

Review URL: https://codereview.chromium.org/560583002

Cr-Commit-Position: refs/heads/master@{#295747}
parent 4da78f3f
...@@ -262,8 +262,9 @@ std::string AndroidRSASign(crypto::RSAPrivateKey* key, ...@@ -262,8 +262,9 @@ std::string AndroidRSASign(crypto::RSAPrivateKey* key,
const std::string& body) { const std::string& body) {
std::vector<uint8> digest(body.begin(), body.end()); std::vector<uint8> digest(body.begin(), body.end());
std::vector<uint8> result; std::vector<uint8> result;
if (!crypto::SignatureCreator::Sign(key, vector_as_array(&digest), if (!crypto::SignatureCreator::Sign(key, crypto::SignatureCreator::SHA1,
digest.size(), &result)) { vector_as_array(&digest), digest.size(),
&result)) {
return std::string(); return std::string();
} }
return std::string(result.begin(), result.end()); return std::string(result.begin(), result.end());
......
...@@ -211,7 +211,8 @@ bool ExtensionCreator::SignZip(const base::FilePath& zip_path, ...@@ -211,7 +211,8 @@ bool ExtensionCreator::SignZip(const base::FilePath& zip_path,
crypto::RSAPrivateKey* private_key, crypto::RSAPrivateKey* private_key,
std::vector<uint8>* signature) { std::vector<uint8>* signature) {
scoped_ptr<crypto::SignatureCreator> signature_creator( scoped_ptr<crypto::SignatureCreator> signature_creator(
crypto::SignatureCreator::Create(private_key)); crypto::SignatureCreator::Create(private_key,
crypto::SignatureCreator::SHA1));
base::ScopedFILE zip_handle(base::OpenFile(zip_path, "rb")); base::ScopedFILE zip_handle(base::OpenFile(zip_path, "rb"));
size_t buffer_size = 1 << 16; size_t buffer_size = 1 << 16;
scoped_ptr<uint8[]> buffer(new uint8[buffer_size]); scoped_ptr<uint8[]> buffer(new uint8[buffer_size]);
......
...@@ -32,7 +32,8 @@ std::string AssembleAndSignPolicy(scoped_ptr<em::PolicyData> policy, ...@@ -32,7 +32,8 @@ std::string AssembleAndSignPolicy(scoped_ptr<em::PolicyData> policy,
// Generate the signature. // Generate the signature.
scoped_ptr<crypto::SignatureCreator> signature_creator( scoped_ptr<crypto::SignatureCreator> signature_creator(
crypto::SignatureCreator::Create(private_key)); crypto::SignatureCreator::Create(private_key,
crypto::SignatureCreator::SHA1));
signature_creator->Update( signature_creator->Update(
reinterpret_cast<const uint8*>(policy_response.policy_data().c_str()), reinterpret_cast<const uint8*>(policy_response.policy_data().c_str()),
policy_response.policy_data().size()); policy_response.policy_data().size());
......
...@@ -295,7 +295,8 @@ void PolicyBuilder::SignData(const std::string& data, ...@@ -295,7 +295,8 @@ void PolicyBuilder::SignData(const std::string& data,
crypto::RSAPrivateKey* key, crypto::RSAPrivateKey* key,
std::string* signature) { std::string* signature) {
scoped_ptr<crypto::SignatureCreator> signature_creator( scoped_ptr<crypto::SignatureCreator> signature_creator(
crypto::SignatureCreator::Create(key)); crypto::SignatureCreator::Create(key,
crypto::SignatureCreator::SHA1));
signature_creator->Update(reinterpret_cast<const uint8*>(data.c_str()), signature_creator->Update(reinterpret_cast<const uint8*>(data.c_str()),
data.size()); data.size());
std::vector<uint8> signature_bytes; std::vector<uint8> signature_bytes;
......
...@@ -24,18 +24,27 @@ namespace crypto { ...@@ -24,18 +24,27 @@ namespace crypto {
class RSAPrivateKey; class RSAPrivateKey;
// Signs data using a bare private key (as opposed to a full certificate). // Signs data using a bare private key (as opposed to a full certificate).
// Currently can only sign data using SHA-1 with RSA encryption. // Currently can only sign data using SHA-1 or SHA-256 with RSA PKCS#1v1.5.
class CRYPTO_EXPORT SignatureCreator { class CRYPTO_EXPORT SignatureCreator {
public: public:
// The set of supported hash functions. Extend as required.
enum HashAlgorithm {
SHA1,
SHA256,
};
~SignatureCreator(); ~SignatureCreator();
// Create an instance. The caller must ensure that the provided PrivateKey // Create an instance. The caller must ensure that the provided PrivateKey
// instance outlives the created SignatureCreator. // instance outlives the created SignatureCreator. Uses the HashAlgorithm
static SignatureCreator* Create(RSAPrivateKey* key); // specified.
static SignatureCreator* Create(RSAPrivateKey* key, HashAlgorithm hash_alg);
// Signs the precomputed SHA-1 digest |data| using private |key| as // Signs the precomputed |hash_alg| digest |data| using private |key| as
// specified in PKCS #1 v1.5. // specified in PKCS #1 v1.5.
static bool Sign(RSAPrivateKey* key, static bool Sign(RSAPrivateKey* key,
HashAlgorithm hash_alg,
const uint8* data, const uint8* data,
int data_len, int data_len,
std::vector<uint8>* signature); std::vector<uint8>* signature);
......
...@@ -15,6 +15,30 @@ ...@@ -15,6 +15,30 @@
namespace crypto { namespace crypto {
namespace {
SECOidTag ToNSSSigOid(SignatureCreator::HashAlgorithm hash_alg) {
switch (hash_alg) {
case SignatureCreator::SHA1:
return SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
case SignatureCreator::SHA256:
return SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION;
}
return SEC_OID_UNKNOWN;
}
SECOidTag ToNSSHashOid(SignatureCreator::HashAlgorithm hash_alg) {
switch (hash_alg) {
case SignatureCreator::SHA1:
return SEC_OID_SHA1;
case SignatureCreator::SHA256:
return SEC_OID_SHA256;
}
return SEC_OID_UNKNOWN;
}
} // namespace
SignatureCreator::~SignatureCreator() { SignatureCreator::~SignatureCreator() {
if (sign_context_) { if (sign_context_) {
SGN_DestroyContext(sign_context_, PR_TRUE); SGN_DestroyContext(sign_context_, PR_TRUE);
...@@ -23,12 +47,12 @@ SignatureCreator::~SignatureCreator() { ...@@ -23,12 +47,12 @@ SignatureCreator::~SignatureCreator() {
} }
// static // static
SignatureCreator* SignatureCreator::Create(RSAPrivateKey* key) { SignatureCreator* SignatureCreator::Create(RSAPrivateKey* key,
HashAlgorithm hash_alg) {
scoped_ptr<SignatureCreator> result(new SignatureCreator); scoped_ptr<SignatureCreator> result(new SignatureCreator);
result->key_ = key; result->key_ = key;
result->sign_context_ = SGN_NewContext(SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION, result->sign_context_ = SGN_NewContext(ToNSSSigOid(hash_alg), key->key());
key->key());
if (!result->sign_context_) { if (!result->sign_context_) {
NOTREACHED(); NOTREACHED();
return NULL; return NULL;
...@@ -45,6 +69,7 @@ SignatureCreator* SignatureCreator::Create(RSAPrivateKey* key) { ...@@ -45,6 +69,7 @@ SignatureCreator* SignatureCreator::Create(RSAPrivateKey* key) {
// static // static
bool SignatureCreator::Sign(RSAPrivateKey* key, bool SignatureCreator::Sign(RSAPrivateKey* key,
HashAlgorithm hash_alg,
const uint8* data, const uint8* data,
int data_len, int data_len,
std::vector<uint8>* signature) { std::vector<uint8>* signature) {
...@@ -54,7 +79,7 @@ bool SignatureCreator::Sign(RSAPrivateKey* key, ...@@ -54,7 +79,7 @@ bool SignatureCreator::Sign(RSAPrivateKey* key,
data_item.len = data_len; data_item.len = data_len;
SECItem signature_item; SECItem signature_item;
SECStatus rv = SGN_Digest(key->key(), SEC_OID_SHA1, &signature_item, SECStatus rv = SGN_Digest(key->key(), ToNSSHashOid(hash_alg), &signature_item,
&data_item); &data_item);
if (rv != SECSuccess) { if (rv != SECSuccess) {
NOTREACHED(); NOTREACHED();
......
...@@ -16,18 +16,49 @@ ...@@ -16,18 +16,49 @@
namespace crypto { namespace crypto {
namespace {
const EVP_MD* ToOpenSSLDigest(SignatureCreator::HashAlgorithm hash_alg) {
switch (hash_alg) {
case SignatureCreator::SHA1:
return EVP_sha1();
case SignatureCreator::SHA256:
return EVP_sha256();
}
return NULL;
}
int ToOpenSSLDigestType(SignatureCreator::HashAlgorithm hash_alg) {
switch (hash_alg) {
case SignatureCreator::SHA1:
return NID_sha1;
case SignatureCreator::SHA256:
return NID_sha256;
}
return NID_undef;
}
} // namespace
// static // static
SignatureCreator* SignatureCreator::Create(RSAPrivateKey* key) { SignatureCreator* SignatureCreator::Create(RSAPrivateKey* key,
HashAlgorithm hash_alg) {
OpenSSLErrStackTracer err_tracer(FROM_HERE); OpenSSLErrStackTracer err_tracer(FROM_HERE);
scoped_ptr<SignatureCreator> result(new SignatureCreator); scoped_ptr<SignatureCreator> result(new SignatureCreator);
result->key_ = key; result->key_ = key;
if (!EVP_SignInit_ex(result->sign_context_, EVP_sha1(), NULL)) const EVP_MD* const digest = ToOpenSSLDigest(hash_alg);
DCHECK(digest);
if (!digest) {
return NULL;
}
if (!EVP_SignInit_ex(result->sign_context_, digest, NULL))
return NULL; return NULL;
return result.release(); return result.release();
} }
// static // static
bool SignatureCreator::Sign(RSAPrivateKey* key, bool SignatureCreator::Sign(RSAPrivateKey* key,
HashAlgorithm hash_alg,
const uint8* data, const uint8* data,
int data_len, int data_len,
std::vector<uint8>* signature) { std::vector<uint8>* signature) {
...@@ -37,8 +68,8 @@ bool SignatureCreator::Sign(RSAPrivateKey* key, ...@@ -37,8 +68,8 @@ bool SignatureCreator::Sign(RSAPrivateKey* key,
signature->resize(RSA_size(rsa_key.get())); signature->resize(RSA_size(rsa_key.get()));
unsigned int len = 0; unsigned int len = 0;
bool success = RSA_sign(NID_sha1, data, data_len, vector_as_array(signature), bool success = RSA_sign(ToOpenSSLDigestType(hash_alg), data, data_len,
&len, rsa_key.get()); vector_as_array(signature), &len, rsa_key.get());
if (!success) { if (!success) {
signature->clear(); signature->clear();
return false; return false;
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
#include "base/sha1.h" #include "base/sha1.h"
#include "crypto/rsa_private_key.h" #include "crypto/rsa_private_key.h"
#include "crypto/sha2.h"
#include "crypto/signature_creator.h" #include "crypto/signature_creator.h"
#include "crypto/signature_verifier.h" #include "crypto/signature_verifier.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
...@@ -19,6 +20,12 @@ const uint8 kSHA1WithRSAAlgorithmID[] = { ...@@ -19,6 +20,12 @@ const uint8 kSHA1WithRSAAlgorithmID[] = {
0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00
}; };
// This is the algorithm ID for SHA-1 with RSA encryption.
const uint8 kSHA256WithRSAAlgorithmID[] = {
0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
0xf7, 0x0d, 0x01, 0x01, 0x0B, 0x05, 0x00
};
} }
TEST(SignatureCreatorTest, BasicTest) { TEST(SignatureCreatorTest, BasicTest) {
...@@ -34,7 +41,8 @@ TEST(SignatureCreatorTest, BasicTest) { ...@@ -34,7 +41,8 @@ TEST(SignatureCreatorTest, BasicTest) {
ASSERT_TRUE(key.get()); ASSERT_TRUE(key.get());
scoped_ptr<crypto::SignatureCreator> signer( scoped_ptr<crypto::SignatureCreator> signer(
crypto::SignatureCreator::Create(key.get())); crypto::SignatureCreator::Create(key.get(),
crypto::SignatureCreator::SHA1));
ASSERT_TRUE(signer.get()); ASSERT_TRUE(signer.get());
std::string data("Hello, World!"); std::string data("Hello, World!");
...@@ -76,6 +84,7 @@ TEST(SignatureCreatorTest, SignDigestTest) { ...@@ -76,6 +84,7 @@ TEST(SignatureCreatorTest, SignDigestTest) {
std::vector<uint8> signature; std::vector<uint8> signature;
ASSERT_TRUE(crypto::SignatureCreator::Sign( ASSERT_TRUE(crypto::SignatureCreator::Sign(
key.get(), key.get(),
crypto::SignatureCreator::SHA1,
reinterpret_cast<const uint8*>(sha1.c_str()), reinterpret_cast<const uint8*>(sha1.c_str()),
sha1.size(), sha1.size(),
&signature)); &signature));
...@@ -94,3 +103,41 @@ TEST(SignatureCreatorTest, SignDigestTest) { ...@@ -94,3 +103,41 @@ TEST(SignatureCreatorTest, SignDigestTest) {
data.size()); data.size());
ASSERT_TRUE(verifier.VerifyFinal()); ASSERT_TRUE(verifier.VerifyFinal());
} }
TEST(SignatureCreatorTest, SignSHA256DigestTest) {
// Do a verify round trip.
scoped_ptr<crypto::RSAPrivateKey> key_original(
crypto::RSAPrivateKey::Create(1024));
ASSERT_TRUE(key_original.get());
std::vector<uint8> key_info;
key_original->ExportPrivateKey(&key_info);
scoped_ptr<crypto::RSAPrivateKey> key(
crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(key_info));
ASSERT_TRUE(key.get());
std::string data("Hello, World!");
std::string sha256 = crypto::SHA256HashString(data);
// Sign sha256 of the input data.
std::vector<uint8> signature;
ASSERT_TRUE(crypto::SignatureCreator::Sign(
key.get(),
crypto::SignatureCreator::HashAlgorithm::SHA256,
reinterpret_cast<const uint8*>(sha256.c_str()),
sha256.size(),
&signature));
std::vector<uint8> public_key_info;
ASSERT_TRUE(key_original->ExportPublicKey(&public_key_info));
// 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()));
verifier.VerifyUpdate(reinterpret_cast<const uint8*>(data.c_str()),
data.size());
ASSERT_TRUE(verifier.VerifyFinal());
}
...@@ -78,7 +78,8 @@ std::string RsaKeyPair::GetPublicKey() const { ...@@ -78,7 +78,8 @@ std::string RsaKeyPair::GetPublicKey() const {
std::string RsaKeyPair::SignMessage(const std::string& message) const { std::string RsaKeyPair::SignMessage(const std::string& message) const {
scoped_ptr<crypto::SignatureCreator> signature_creator( scoped_ptr<crypto::SignatureCreator> signature_creator(
crypto::SignatureCreator::Create(key_.get())); crypto::SignatureCreator::Create(key_.get(),
crypto::SignatureCreator::SHA1));
signature_creator->Update(reinterpret_cast<const uint8*>(message.c_str()), signature_creator->Update(reinterpret_cast<const uint8*>(message.c_str()),
message.length()); message.length());
std::vector<uint8> signature_buf; std::vector<uint8> signature_buf;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment