summaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorrsleevi@chromium.org <rsleevi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-07-10 04:39:38 +0000
committerrsleevi@chromium.org <rsleevi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-07-10 04:39:38 +0000
commitcd9b75b1194ef656668b4d848c99d24d5968eb3a (patch)
tree2f0ee7adcb172a43aa6f635538daf57e52e48e6d /crypto
parent253a24133db77bda145e3599e2d7582e4f8c7409 (diff)
downloadchromium_src-cd9b75b1194ef656668b4d848c99d24d5968eb3a.zip
chromium_src-cd9b75b1194ef656668b4d848c99d24d5968eb3a.tar.gz
chromium_src-cd9b75b1194ef656668b4d848c99d24d5968eb3a.tar.bz2
Eliminate ScopedOpenSSL in favour of scoped_ptr<> specializations.
Match the NSS, CryptoAPI (Win) and Security (OS X) approaches by declaring the scoped types as specializations of our existing scoped classes. Like NSS, this requires an intermediate helper type, because our scoped_ptr<> doesn't accept deleter functions as template arguments (though they are valid in C++11's unique_ptr<>). A few base cryptographic (non-certificate) types are used in scoped_openssl_types.h, while the remainder are left for implementations to specialize as needed. In an ideal world, this would be scoped_ptr<FOO, FOO_free>, but that will require unique_ptr<> support. BUG=388904 Review URL: https://codereview.chromium.org/361193003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@282257 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'crypto')
-rw-r--r--crypto/ec_private_key_openssl.cc46
-rw-r--r--crypto/ec_signature_creator_openssl.cc11
-rw-r--r--crypto/openssl_bio_string_unittest.cc10
-rw-r--r--crypto/openssl_util.h30
-rw-r--r--crypto/rsa_private_key_openssl.cc11
-rw-r--r--crypto/scoped_openssl_types.h49
-rw-r--r--crypto/signature_verifier_openssl.cc11
7 files changed, 98 insertions, 70 deletions
diff --git a/crypto/ec_private_key_openssl.cc b/crypto/ec_private_key_openssl.cc
index b7b6b48..beda29f 100644
--- a/crypto/ec_private_key_openssl.cc
+++ b/crypto/ec_private_key_openssl.cc
@@ -12,6 +12,7 @@
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "crypto/openssl_util.h"
+#include "crypto/scoped_openssl_types.h"
namespace crypto {
@@ -24,6 +25,10 @@ namespace {
// style guide, hence the unusual parameter placement / types.
typedef int (*ExportBioFunction)(BIO* bio, const void* key);
+typedef ScopedOpenSSL<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_free>::Type
+ ScopedPKCS8_PRIV_KEY_INFO;
+typedef ScopedOpenSSL<X509_SIG, X509_SIG_free>::Type ScopedX509_SIG;
+
// Helper to export |key| into |output| via the specified ExportBioFunction.
bool ExportKeyWithBio(const void* key,
ExportBioFunction export_fn,
@@ -31,7 +36,7 @@ bool ExportKeyWithBio(const void* key,
if (!key)
return false;
- ScopedOpenSSL<BIO, BIO_free_all> bio(BIO_new(BIO_s_mem()));
+ ScopedBIO bio(BIO_new(BIO_s_mem()));
if (!bio.get())
return false;
@@ -87,8 +92,7 @@ bool ECPrivateKey::IsSupported() { return true; }
ECPrivateKey* ECPrivateKey::Create() {
OpenSSLErrStackTracer err_tracer(FROM_HERE);
- ScopedOpenSSL<EC_KEY, EC_KEY_free> ec_key(
- EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
+ ScopedEC_KEY ec_key(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
if (!ec_key.get() || !EC_KEY_generate_key(ec_key.get()))
return NULL;
@@ -118,21 +122,17 @@ ECPrivateKey* ECPrivateKey::CreateFromEncryptedPrivateKeyInfo(
const_cast<uint8*>(&encrypted_private_key_info[0]));
int private_key_data_len =
static_cast<int>(encrypted_private_key_info.size());
- ScopedOpenSSL<BIO, BIO_free_all> bio(
- BIO_new_mem_buf(private_key_data, private_key_data_len));
+ ScopedBIO bio(BIO_new_mem_buf(private_key_data, private_key_data_len));
if (!bio.get())
return NULL;
// Convert it, then decrypt it into a PKCS#8 object.
- ScopedOpenSSL<X509_SIG, X509_SIG_free> p8_encrypted(
- d2i_PKCS8_bio(bio.get(), NULL));
+ ScopedX509_SIG p8_encrypted(d2i_PKCS8_bio(bio.get(), NULL));
if (!p8_encrypted.get())
return NULL;
- ScopedOpenSSL<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_free> p8_decrypted(
- PKCS8_decrypt(p8_encrypted.get(),
- password.c_str(),
- static_cast<int>(password.size())));
+ ScopedPKCS8_PRIV_KEY_INFO p8_decrypted(PKCS8_decrypt(
+ p8_encrypted.get(), password.c_str(), static_cast<int>(password.size())));
if (!p8_decrypted.get() && password.empty()) {
// Hack for reading keys generated by ec_private_key_nss. Passing NULL
// causes OpenSSL to use an empty password instead of "\0\0".
@@ -156,8 +156,7 @@ bool ECPrivateKey::ExportEncryptedPrivateKey(
std::vector<uint8>* output) {
OpenSSLErrStackTracer err_tracer(FROM_HERE);
// Convert into a PKCS#8 object.
- ScopedOpenSSL<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_free> pkcs8(
- EVP_PKEY2PKCS8(key_));
+ ScopedPKCS8_PRIV_KEY_INFO pkcs8(EVP_PKEY2PKCS8(key_));
if (!pkcs8.get())
return false;
@@ -165,15 +164,14 @@ bool ECPrivateKey::ExportEncryptedPrivateKey(
// NOTE: NSS uses SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC
// so use NID_pbe_WithSHA1And3_Key_TripleDES_CBC which should be the OpenSSL
// equivalent.
- ScopedOpenSSL<X509_SIG, X509_SIG_free> encrypted(
- PKCS8_encrypt(NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
- NULL,
- password.c_str(),
- static_cast<int>(password.size()),
- NULL,
- 0,
- iterations,
- pkcs8.get()));
+ ScopedX509_SIG encrypted(PKCS8_encrypt(NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
+ NULL,
+ password.c_str(),
+ static_cast<int>(password.size()),
+ NULL,
+ 0,
+ iterations,
+ pkcs8.get()));
if (!encrypted.get())
return false;
@@ -211,7 +209,7 @@ bool ECPrivateKey::ExportRawPublicKey(std::string* output) {
bool ECPrivateKey::ExportValue(std::vector<uint8>* output) {
OpenSSLErrStackTracer err_tracer(FROM_HERE);
- ScopedOpenSSL<EC_KEY, EC_KEY_free> ec_key(EVP_PKEY_get1_EC_KEY(key_));
+ ScopedEC_KEY ec_key(EVP_PKEY_get1_EC_KEY(key_));
return ExportKey(ec_key.get(),
reinterpret_cast<ExportDataFunction>(i2d_ECPrivateKey),
output);
@@ -219,7 +217,7 @@ bool ECPrivateKey::ExportValue(std::vector<uint8>* output) {
bool ECPrivateKey::ExportECParams(std::vector<uint8>* output) {
OpenSSLErrStackTracer err_tracer(FROM_HERE);
- ScopedOpenSSL<EC_KEY, EC_KEY_free> ec_key(EVP_PKEY_get1_EC_KEY(key_));
+ ScopedEC_KEY ec_key(EVP_PKEY_get1_EC_KEY(key_));
return ExportKey(ec_key.get(),
reinterpret_cast<ExportDataFunction>(i2d_ECParameters),
output);
diff --git a/crypto/ec_signature_creator_openssl.cc b/crypto/ec_signature_creator_openssl.cc
index 7f0a873..adff2c9 100644
--- a/crypto/ec_signature_creator_openssl.cc
+++ b/crypto/ec_signature_creator_openssl.cc
@@ -13,9 +13,16 @@
#include "base/logging.h"
#include "crypto/ec_private_key.h"
#include "crypto/openssl_util.h"
+#include "crypto/scoped_openssl_types.h"
namespace crypto {
+namespace {
+
+typedef ScopedOpenSSL<ECDSA_SIG, ECDSA_SIG_free>::Type ScopedECDSA_SIG;
+
+} // namespace
+
ECSignatureCreatorImpl::ECSignatureCreatorImpl(ECPrivateKey* key)
: key_(key), signature_len_(0) {
EnsureOpenSSLInit();
@@ -27,7 +34,7 @@ bool ECSignatureCreatorImpl::Sign(const uint8* data,
int data_len,
std::vector<uint8>* signature) {
OpenSSLErrStackTracer err_tracer(FROM_HERE);
- ScopedOpenSSL<EVP_MD_CTX, EVP_MD_CTX_destroy> ctx(EVP_MD_CTX_create());
+ ScopedEVP_MD_CTX ctx(EVP_MD_CTX_create());
size_t sig_len = 0;
if (!ctx.get() ||
!EVP_DigestSignInit(ctx.get(), NULL, EVP_sha256(), NULL, key_->key()) ||
@@ -52,7 +59,7 @@ bool ECSignatureCreatorImpl::DecodeSignature(const std::vector<uint8>& der_sig,
OpenSSLErrStackTracer err_tracer(FROM_HERE);
// Create ECDSA_SIG object from DER-encoded data.
const unsigned char* der_data = &der_sig.front();
- ScopedOpenSSL<ECDSA_SIG, ECDSA_SIG_free> ecdsa_sig(
+ ScopedECDSA_SIG ecdsa_sig(
d2i_ECDSA_SIG(NULL, &der_data, static_cast<long>(der_sig.size())));
if (!ecdsa_sig.get())
return false;
diff --git a/crypto/openssl_bio_string_unittest.cc b/crypto/openssl_bio_string_unittest.cc
index 39d3a9a..2467215 100644
--- a/crypto/openssl_bio_string_unittest.cc
+++ b/crypto/openssl_bio_string_unittest.cc
@@ -6,16 +6,18 @@
#include <openssl/bio.h>
-#include "crypto/openssl_util.h"
+#include "crypto/scoped_openssl_types.h"
#include "testing/gtest/include/gtest/gtest.h"
+namespace crypto {
+
TEST(OpenSSLBIOString, TestWrite) {
std::string s;
const std::string expected1("a one\nb 2\n");
const std::string expected2("c d e f");
const std::string expected3("g h i");
{
- crypto::ScopedOpenSSL<BIO, BIO_free_all> bio(crypto::BIO_new_string(&s));
+ ScopedBIO bio(BIO_new_string(&s));
ASSERT_TRUE(bio.get());
EXPECT_EQ(static_cast<int>(expected1.size()),
@@ -48,7 +50,7 @@ TEST(OpenSSLBIOString, TestReset) {
const std::string expected1("a b c\n");
const std::string expected2("d e f g\n");
{
- crypto::ScopedOpenSSL<BIO, BIO_free_all> bio(crypto::BIO_new_string(&s));
+ ScopedBIO bio(BIO_new_string(&s));
ASSERT_TRUE(bio.get());
EXPECT_EQ(static_cast<int>(expected1.size()),
@@ -64,3 +66,5 @@ TEST(OpenSSLBIOString, TestReset) {
}
EXPECT_EQ(expected2, s);
}
+
+} // namespace crypto
diff --git a/crypto/openssl_util.h b/crypto/openssl_util.h
index bf83e47..2743883 100644
--- a/crypto/openssl_util.h
+++ b/crypto/openssl_util.h
@@ -11,36 +11,6 @@
namespace crypto {
-// A helper class that takes care of destroying OpenSSL objects when they go out
-// of scope.
-template <typename T, void (*destructor)(T*)>
-class ScopedOpenSSL {
- public:
- ScopedOpenSSL() : ptr_(NULL) { }
- explicit ScopedOpenSSL(T* ptr) : ptr_(ptr) { }
- ~ScopedOpenSSL() {
- reset(NULL);
- }
-
- T* get() const { return ptr_; }
- T* release() {
- T* ptr = ptr_;
- ptr_ = NULL;
- return ptr;
- }
- void reset(T* ptr) {
- if (ptr != ptr_) {
- if (ptr_) (*destructor)(ptr_);
- ptr_ = ptr;
- }
- }
-
- private:
- T* ptr_;
-
- DISALLOW_COPY_AND_ASSIGN(ScopedOpenSSL);
-};
-
// Provides a buffer of at least MIN_SIZE bytes, for use when calling OpenSSL's
// SHA256, HMAC, etc functions, adapting the buffer sizing rules to meet those
// of the our base wrapper APIs.
diff --git a/crypto/rsa_private_key_openssl.cc b/crypto/rsa_private_key_openssl.cc
index f191e39..bd00a73 100644
--- a/crypto/rsa_private_key_openssl.cc
+++ b/crypto/rsa_private_key_openssl.cc
@@ -11,6 +11,7 @@
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "crypto/openssl_util.h"
+#include "crypto/scoped_openssl_types.h"
namespace crypto {
@@ -29,7 +30,7 @@ bool ExportKey(EVP_PKEY* key,
return false;
OpenSSLErrStackTracer err_tracer(FROM_HERE);
- ScopedOpenSSL<BIO, BIO_free_all> bio(BIO_new(BIO_s_mem()));
+ ScopedBIO bio(BIO_new(BIO_s_mem()));
int res = export_fn(bio.get(), key);
if (!res)
@@ -50,8 +51,8 @@ bool ExportKey(EVP_PKEY* key,
RSAPrivateKey* RSAPrivateKey::Create(uint16 num_bits) {
OpenSSLErrStackTracer err_tracer(FROM_HERE);
- ScopedOpenSSL<RSA, RSA_free> rsa_key(RSA_new());
- ScopedOpenSSL<BIGNUM, BN_free> bn(BN_new());
+ ScopedRSA rsa_key(RSA_new());
+ ScopedBIGNUM bn(BN_new());
if (!rsa_key.get() || !bn.get() || !BN_set_word(bn.get(), 65537L))
return NULL;
@@ -75,14 +76,14 @@ RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfo(
OpenSSLErrStackTracer err_tracer(FROM_HERE);
// BIO_new_mem_buf is not const aware, but it does not modify the buffer.
char* data = reinterpret_cast<char*>(const_cast<uint8*>(&input[0]));
- ScopedOpenSSL<BIO, BIO_free_all> bio(BIO_new_mem_buf(data, input.size()));
+ ScopedBIO bio(BIO_new_mem_buf(data, input.size()));
if (!bio.get())
return NULL;
// Importing is a little more involved than exporting, as we must first
// PKCS#8 decode the input, and then import the EVP_PKEY from Private Key
// Info structure returned.
- ScopedOpenSSL<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_free> p8inf(
+ ScopedOpenSSL<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_free>::Type p8inf(
d2i_PKCS8_PRIV_KEY_INFO_bio(bio.get(), NULL));
if (!p8inf.get())
return NULL;
diff --git a/crypto/scoped_openssl_types.h b/crypto/scoped_openssl_types.h
new file mode 100644
index 0000000..a949233
--- /dev/null
+++ b/crypto/scoped_openssl_types.h
@@ -0,0 +1,49 @@
+// Copyright 2014 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_SCOPED_OPENSSL_TYPES_H_
+#define CRYPTO_SCOPED_OPENSSL_TYPES_H_
+
+#include <openssl/bn.h>
+#include <openssl/dsa.h>
+#include <openssl/ec.h>
+#include <openssl/ecdsa.h>
+#include <openssl/evp.h>
+#include <openssl/rsa.h>
+
+#include "base/memory/scoped_ptr.h"
+
+namespace crypto {
+
+// Simplistic helper that wraps a call to a deleter function. In a C++11 world,
+// this would be std::function<>. An alternative would be to re-use
+// base::internal::RunnableAdapter<>, but that's far too heavy weight.
+template <typename Type, void (*Destroyer)(Type*)>
+struct OpenSSLDestroyer {
+ void operator()(Type* ptr) const { Destroyer(ptr); }
+};
+
+template <typename PointerType, void (*Destroyer)(PointerType*)>
+struct ScopedOpenSSL {
+ typedef scoped_ptr<PointerType, OpenSSLDestroyer<PointerType, Destroyer> >
+ Type;
+};
+
+// Several typedefs are provided for crypto-specific primitives, for
+// short-hand and prevalence. Note that OpenSSL types related to X.509 are
+// intentionally not included, as crypto/ does not generally deal with
+// certificates or PKI.
+typedef ScopedOpenSSL<BIGNUM, BN_free>::Type ScopedBIGNUM;
+typedef ScopedOpenSSL<EC_KEY, EC_KEY_free>::Type ScopedEC_KEY;
+typedef ScopedOpenSSL<BIO, BIO_free_all>::Type ScopedBIO;
+typedef ScopedOpenSSL<DSA, DSA_free>::Type ScopedDSA;
+typedef ScopedOpenSSL<ECDSA_SIG, ECDSA_SIG_free>::Type ScopedECDSA_SIG;
+typedef ScopedOpenSSL<EC_KEY, EC_KEY_free>::Type ScopedEC_KEY;
+typedef ScopedOpenSSL<EVP_MD_CTX, EVP_MD_CTX_destroy>::Type ScopedEVP_MD_CTX;
+typedef ScopedOpenSSL<EVP_PKEY, EVP_PKEY_free>::Type ScopedEVP_PKEY;
+typedef ScopedOpenSSL<RSA, RSA_free>::Type ScopedRSA;
+
+} // namespace crypto
+
+#endif // CRYPTO_SCOPED_OPENSSL_TYPES_H_
diff --git a/crypto/signature_verifier_openssl.cc b/crypto/signature_verifier_openssl.cc
index a85f00b..155a2cf3 100644
--- a/crypto/signature_verifier_openssl.cc
+++ b/crypto/signature_verifier_openssl.cc
@@ -13,6 +13,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/stl_util.h"
#include "crypto/openssl_util.h"
+#include "crypto/scoped_openssl_types.h"
namespace crypto {
@@ -31,7 +32,7 @@ const EVP_MD* ToOpenSSLDigest(SignatureVerifier::HashAlgorithm hash_alg) {
} // namespace
struct SignatureVerifier::VerifyContext {
- ScopedOpenSSL<EVP_MD_CTX, EVP_MD_CTX_destroy> ctx;
+ ScopedEVP_MD_CTX ctx;
};
SignatureVerifier::SignatureVerifier()
@@ -49,7 +50,7 @@ bool SignatureVerifier::VerifyInit(const uint8* signature_algorithm,
const uint8* public_key_info,
int public_key_info_len) {
OpenSSLErrStackTracer err_tracer(FROM_HERE);
- ScopedOpenSSL<X509_ALGOR, X509_ALGOR_free> algorithm(
+ ScopedOpenSSL<X509_ALGOR, X509_ALGOR_free>::Type algorithm(
d2i_X509_ALGOR(NULL, &signature_algorithm, signature_algorithm_len));
if (!algorithm.get())
return false;
@@ -135,13 +136,11 @@ bool SignatureVerifier::CommonInit(const EVP_MD* digest,
// BIO_new_mem_buf is not const aware, but it does not modify the buffer.
char* data = reinterpret_cast<char*>(const_cast<uint8*>(public_key_info));
- ScopedOpenSSL<BIO, BIO_free_all> bio(BIO_new_mem_buf(data,
- public_key_info_len));
+ ScopedBIO bio(BIO_new_mem_buf(data, public_key_info_len));
if (!bio.get())
return false;
- ScopedOpenSSL<EVP_PKEY, EVP_PKEY_free> public_key(
- d2i_PUBKEY_bio(bio.get(), NULL));
+ ScopedEVP_PKEY public_key(d2i_PUBKEY_bio(bio.get(), NULL));
if (!public_key.get())
return false;