diff options
author | Zeno Albisser <zeno.albisser@theqtcompany.com> | 2014-12-05 15:04:29 +0100 |
---|---|---|
committer | Andras Becsi <andras.becsi@theqtcompany.com> | 2014-12-09 10:49:28 +0100 |
commit | af6588f8d723931a298c995fa97259bb7f7deb55 (patch) | |
tree | 060ca707847ba1735f01af2372e0d5e494dc0366 /chromium/crypto | |
parent | 2fff84d821cc7b1c785f6404e0f8091333283e74 (diff) | |
download | qtwebengine-chromium-af6588f8d723931a298c995fa97259bb7f7deb55.tar.gz |
BASELINE: Update chromium to 40.0.2214.28 and ninja to 1.5.3.
Change-Id: I759465284fd64d59ad120219cbe257f7402c4181
Reviewed-by: Andras Becsi <andras.becsi@theqtcompany.com>
Diffstat (limited to 'chromium/crypto')
59 files changed, 1397 insertions, 764 deletions
diff --git a/chromium/crypto/BUILD.gn b/chromium/crypto/BUILD.gn index 307842084cb..d3d318de50f 100644 --- a/chromium/crypto/BUILD.gn +++ b/chromium/crypto/BUILD.gn @@ -49,6 +49,8 @@ component("crypto") { "nss_util.cc", "nss_util.h", "nss_util_internal.h", + "openssl_bio_string.cc", + "openssl_bio_string.h", "openssl_util.cc", "openssl_util.h", "p224.cc", @@ -131,6 +133,7 @@ component("crypto") { "hmac_nss.cc", "nss_util.cc", "nss_util.h", + "nss_util_internal.h", "rsa_private_key_nss.cc", "secure_hash_default.cc", "signature_creator_nss.cc", @@ -150,6 +153,8 @@ component("crypto") { "ec_signature_creator_openssl.cc", "encryptor_openssl.cc", "hmac_openssl.cc", + "openssl_bio_string.cc", + "openssl_bio_string.h", "openssl_util.cc", "openssl_util.h", "rsa_private_key_openssl.cc", @@ -204,6 +209,7 @@ test("crypto_unittests") { "hkdf_unittest.cc", "hmac_unittest.cc", "nss_util_unittest.cc", + "openssl_bio_string_unittest.cc", "p224_unittest.cc", "p224_spake_unittest.cc", "random_unittest.cc", @@ -224,11 +230,14 @@ test("crypto_unittests") { if (use_openssl) { sources -= [ "nss_util_unittest.cc" ] + } else { + sources -= [ "openssl_bio_string_unittest.cc" ] } deps = [ ":crypto", ":platform", + ":test_support", "//base", "//base/test:run_all_unittests", "//base/test:test_support", @@ -237,12 +246,44 @@ test("crypto_unittests") { ] } +source_set("test_support") { + sources = [ + "scoped_test_nss_db.cc", + "scoped_test_nss_db.h", + "scoped_test_nss_chromeos_user.cc", + "scoped_test_nss_chromeos_user.h", + "scoped_test_system_nss_key_slot.cc", + "scoped_test_system_nss_key_slot.h", + ] + deps = [ + ":crypto", + ":platform", + "//base", + ] + + if (!use_nss_certs) { + sources -= [ + "scoped_test_nss_db.cc", + "scoped_test_nss_db.h", + ] + } + + if (!is_chromeos) { + sources -= [ + "scoped_test_nss_chromeos_user.cc", + "scoped_test_nss_chromeos_user.h", + "scoped_test_system_nss_key_slot.cc", + "scoped_test_system_nss_key_slot.h", + ] + } +} + # This is a meta-target that forwards to NSS's SSL library or OpenSSL, # according to the state of the crypto flags. A target just wanting to depend # on the current SSL library should just depend on this. group("platform") { if (use_openssl) { - deps = [ "//third_party/openssl" ] + deps = [ "//third_party/boringssl" ] } else { deps = [ "//net/third_party/nss/ssl:libssl" ] if (is_linux) { @@ -251,11 +292,11 @@ group("platform") { # # We always need our SSL header search path to come before the system one # so our versions are used. The libssl target will add the search path we - # want, but according to GN's ordering rules, direct_dependent_configs' - # search path will get applied before ones inherited from our - # dependencies. Therefore, we need to explicitly list our custom libssl's - # config here before the system one. - direct_dependent_configs = [ + # want, but according to GN's ordering rules, public_configs' search path + # will get applied before ones inherited from our dependencies. + # Therefore, we need to explicitly list our custom libssl's config here + # before the system one. + public_configs = [ "//net/third_party/nss/ssl:ssl_config", "//third_party/nss:system_nss_no_ssl_config", ] diff --git a/chromium/crypto/OWNERS b/chromium/crypto/OWNERS index 6f5cc98b802..bde32a088b4 100644 --- a/chromium/crypto/OWNERS +++ b/chromium/crypto/OWNERS @@ -1,4 +1,5 @@ agl@chromium.org +davidben@chromium.org rsleevi@chromium.org rvargas@chromium.org wtc@chromium.org diff --git a/chromium/crypto/PRESUBMIT.py b/chromium/crypto/PRESUBMIT.py index ce3988e50c6..a2a5af9ae7a 100644 --- a/chromium/crypto/PRESUBMIT.py +++ b/chromium/crypto/PRESUBMIT.py @@ -11,7 +11,7 @@ for more details on the presubmit API built into gcl. def GetPreferredTryMasters(project, change): # Changes in crypto often need a corresponding OpenSSL edit. return { - 'tryserver.chromium': { + 'tryserver.chromium.linux': { 'linux_redux': set(['defaulttests']), } } diff --git a/chromium/crypto/capi_util.h b/chromium/crypto/capi_util.h index 09a44e7634c..9d43293e231 100644 --- a/chromium/crypto/capi_util.h +++ b/chromium/crypto/capi_util.h @@ -6,9 +6,9 @@ #define CRYPTO_CAPI_UTIL_H_ #include <windows.h> -#include <wincrypt.h> #include "crypto/crypto_export.h" +#include "crypto/wincrypt_shim.h" namespace crypto { diff --git a/chromium/crypto/crypto.gyp b/chromium/crypto/crypto.gyp index 0c472ffc2eb..6d60f480fed 100644 --- a/chromium/crypto/crypto.gyp +++ b/chromium/crypto/crypto.gyp @@ -21,9 +21,6 @@ 'defines': [ 'CRYPTO_IMPLEMENTATION', ], - 'msvs_disabled_warnings': [ - 4018, - ], 'conditions': [ [ 'os_posix == 1 and OS != "mac" and OS != "ios" and OS != "android"', { 'dependencies': [ @@ -95,12 +92,14 @@ ], }], [ 'OS == "win"', { - # TODO(jschuh): crbug.com/167187 fix size_t to int truncations. - 'msvs_disabled_warnings': [4267, ], + 'msvs_disabled_warnings': [ + 4267, # TODO(jschuh): crbug.com/167187 fix size_t to int truncations. + 4018, + ], }], [ 'use_openssl==1', { 'dependencies': [ - '../third_party/openssl/openssl.gyp:openssl', + '../third_party/boringssl/boringssl.gyp:boringssl', ], # TODO(joth): Use a glob to match exclude patterns once the # OpenSSL file set is complete. @@ -111,6 +110,7 @@ 'hmac_nss.cc', 'nss_util.cc', 'nss_util.h', + 'nss_util_internal.h', 'rsa_private_key_nss.cc', 'secure_hash_default.cc', 'signature_creator_nss.cc', @@ -174,6 +174,7 @@ ], 'dependencies': [ 'crypto', + 'crypto_test_support', '../base/base.gyp:base', '../base/base.gyp:run_all_unittests', '../base/base.gyp:test_support_base', @@ -209,7 +210,7 @@ }], [ 'use_openssl==1', { 'dependencies': [ - '../third_party/openssl/openssl.gyp:openssl', + '../third_party/boringssl/boringssl.gyp:boringssl', ], 'sources!': [ 'nss_util_unittest.cc', @@ -254,5 +255,47 @@ }, ], }], + ['use_nss==1', { + 'targets': [ + { + 'target_name': 'crypto_test_support', + 'type': 'static_library', + 'dependencies': [ + '../base/base.gyp:base', + 'crypto', + ], + 'sources': [ + 'scoped_test_nss_db.cc', + 'scoped_test_nss_db.h', + 'scoped_test_nss_chromeos_user.cc', + 'scoped_test_nss_chromeos_user.h', + 'scoped_test_system_nss_key_slot.cc', + 'scoped_test_system_nss_key_slot.h', + ], + 'conditions': [ + ['use_nss==0', { + 'sources!': [ + 'scoped_test_nss_db.cc', + 'scoped_test_nss_db.h', + ], + }], + [ 'chromeos==0', { + 'sources!': [ + 'scoped_test_nss_chromeos_user.cc', + 'scoped_test_nss_chromeos_user.h', + 'scoped_test_system_nss_key_slot.cc', + 'scoped_test_system_nss_key_slot.h', + ], + }], + ], + } + ]}, { # use_nss==0 + 'targets': [ + { + 'target_name': 'crypto_test_support', + 'type': 'none', + 'sources': [], + } + ]}], ], } diff --git a/chromium/crypto/crypto.gypi b/chromium/crypto/crypto.gypi index de65e198ebb..82b5da5dbc8 100644 --- a/chromium/crypto/crypto.gypi +++ b/chromium/crypto/crypto.gypi @@ -20,6 +20,7 @@ 'third_party/nss/chromium-prtypes.h', 'third_party/nss/chromium-sha256.h', 'third_party/nss/sha512.cc', + 'wincrypt_shim.h', ], }, 'hmac_win64_related_sources': [ '<@(hmac_win64_related_sources)' ], diff --git a/chromium/crypto/crypto_nacl.gyp b/chromium/crypto/crypto_nacl.gyp index 6ec5e830ced..44516109196 100644 --- a/chromium/crypto/crypto_nacl.gyp +++ b/chromium/crypto/crypto_nacl.gyp @@ -22,7 +22,7 @@ 'build_pnacl_newlib': 1, }, 'dependencies': [ - '../third_party/openssl/openssl_nacl.gyp:openssl_nacl', + '../third_party/boringssl/boringssl_nacl.gyp:boringssl_nacl', '../native_client/tools.gyp:prep_toolchain', '../native_client_sdk/native_client_sdk_untrusted.gyp:nacl_io_untrusted', ], diff --git a/chromium/crypto/ec_private_key.h b/chromium/crypto/ec_private_key.h index 28701635d50..9fd8ffdfb62 100644 --- a/chromium/crypto/ec_private_key.h +++ b/chromium/crypto/ec_private_key.h @@ -86,6 +86,9 @@ class CRYPTO_EXPORT ECPrivateKey { bool sensitive, SECKEYPrivateKey** key, SECKEYPublicKey** public_key); + + // Returns a copy of the object. + ECPrivateKey* Copy() const; #endif #if defined(USE_OPENSSL) @@ -107,6 +110,9 @@ class CRYPTO_EXPORT ECPrivateKey { // Exports the public key to an X.509 SubjectPublicKeyInfo block. bool ExportPublicKey(std::vector<uint8>* output); + // Exports the public key as an EC point in the uncompressed point format. + bool ExportRawPublicKey(std::string* output); + // Exports private key data for testing. The format of data stored into output // doesn't matter other than that it is consistent for the same key. bool ExportValue(std::vector<uint8>* output); diff --git a/chromium/crypto/ec_private_key_nss.cc b/chromium/crypto/ec_private_key_nss.cc index 1d3bf889204..2daa0c0f4a3 100644 --- a/chromium/crypto/ec_private_key_nss.cc +++ b/chromium/crypto/ec_private_key_nss.cc @@ -159,6 +159,13 @@ bool ECPrivateKey::ImportFromEncryptedPrivateKeyInfo( return false; } + if (SECKEY_GetPublicKeyType(*public_key) != ecKey) { + DLOG(ERROR) << "The public key is not an EC key"; + SECKEY_DestroyPublicKey(*public_key); + *public_key = NULL; + return false; + } + SECItem encoded_epki = { siBuffer, const_cast<unsigned char*>(encrypted_private_key_info), @@ -208,6 +215,21 @@ bool ECPrivateKey::ImportFromEncryptedPrivateKeyInfo( return true; } +ECPrivateKey* ECPrivateKey::Copy() const { + scoped_ptr<ECPrivateKey> copy(new ECPrivateKey); + if (key_) { + copy->key_ = SECKEY_CopyPrivateKey(key_); + if (!copy->key_) + return NULL; + } + if (public_key_) { + copy->public_key_ = SECKEY_CopyPublicKey(public_key_); + if (!copy->public_key_) + return NULL; + } + return copy.release(); +} + bool ECPrivateKey::ExportEncryptedPrivateKey( const std::string& password, int iterations, @@ -223,12 +245,12 @@ bool ECPrivateKey::ExportEncryptedPrivateKey( }; SECKEYEncryptedPrivateKeyInfo* encrypted = PK11_ExportEncryptedPrivKeyInfo( - NULL, // Slot, optional. + NULL, // Slot, optional. SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC, &password_item, key_, iterations, - NULL); // wincx. + NULL); // wincx. if (!encrypted) { DLOG(ERROR) << "PK11_ExportEncryptedPrivKeyInfo: " << PORT_GetError(); @@ -264,6 +286,23 @@ bool ECPrivateKey::ExportPublicKey(std::vector<uint8>* output) { return true; } +bool ECPrivateKey::ExportRawPublicKey(std::string* output) { + // public_key_->u.ec.publicValue is an ANSI X9.62 public key which, for + // a P-256 key, is 0x04 (meaning uncompressed) followed by the x and y field + // elements as 32-byte, big-endian numbers. + static const unsigned int kExpectedKeyLength = 65; + + CHECK_EQ(ecKey, SECKEY_GetPublicKeyType(public_key_)); + const unsigned char* const data = public_key_->u.ec.publicValue.data; + const unsigned int len = public_key_->u.ec.publicValue.len; + if (len != kExpectedKeyLength || data[0] != 0x04) + return false; + + output->assign(reinterpret_cast<const char*>(data + 1), + kExpectedKeyLength - 1); + return true; +} + bool ECPrivateKey::ExportValue(std::vector<uint8>* output) { return ReadAttribute(key_, CKA_VALUE, output); } @@ -301,7 +340,7 @@ ECPrivateKey* ECPrivateKey::CreateWithParams(PK11SlotInfo* slot, }; ec_parameters.data[0] = SEC_ASN1_OBJECT_ID; - ec_parameters.data[1] = oid_data->oid.len; + ec_parameters.data[1] = static_cast<unsigned char>(oid_data->oid.len); memcpy(ec_parameters.data + 2, oid_data->oid.data, oid_data->oid.len); result->key_ = PK11_GenerateKeyPair(slot, @@ -315,6 +354,7 @@ ECPrivateKey* ECPrivateKey::CreateWithParams(PK11SlotInfo* slot, DLOG(ERROR) << "PK11_GenerateKeyPair: " << PORT_GetError(); return NULL; } + CHECK_EQ(ecKey, SECKEY_GetPublicKeyType(result->public_key_)); return result.release(); } @@ -354,8 +394,10 @@ ECPrivateKey* ECPrivateKey::CreateFromEncryptedPrivateKeyInfoWithParams( SECKEY_DestroySubjectPublicKeyInfo(decoded_spki); - if (success) + if (success) { + CHECK_EQ(ecKey, SECKEY_GetPublicKeyType(result->public_key_)); return result.release(); + } return NULL; } diff --git a/chromium/crypto/ec_private_key_openssl.cc b/chromium/crypto/ec_private_key_openssl.cc index 8504ab50c35..2d44759d8b0 100644 --- a/chromium/crypto/ec_private_key_openssl.cc +++ b/chromium/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; @@ -97,6 +101,7 @@ ECPrivateKey* ECPrivateKey::Create() { if (!result->key_ || !EVP_PKEY_set1_EC_KEY(result->key_, ec_key.get())) return NULL; + CHECK_EQ(EVP_PKEY_EC, EVP_PKEY_type(result->key_->type)); return result.release(); } @@ -112,38 +117,37 @@ ECPrivateKey* ECPrivateKey::CreateFromEncryptedPrivateKeyInfo( return NULL; OpenSSLErrStackTracer err_tracer(FROM_HERE); - // Write the encrypted private key into a memory BIO. - char* private_key_data = reinterpret_cast<char*>( - 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)); - 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)); - if (!p8_encrypted.get()) + const uint8_t* data = &encrypted_private_key_info[0]; + const uint8_t* ptr = data; + ScopedX509_SIG p8_encrypted( + d2i_X509_SIG(NULL, &ptr, encrypted_private_key_info.size())); + if (!p8_encrypted || ptr != data + encrypted_private_key_info.size()) 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()))); - 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". - p8_decrypted.reset(PKCS8_decrypt(p8_encrypted.get(), NULL, 0)); + ScopedPKCS8_PRIV_KEY_INFO p8_decrypted; + if (password.empty()) { + // Hack for reading keys generated by an older version of the OpenSSL + // code. OpenSSL used to use "\0\0" rather than the empty string because it + // would treat the password as an ASCII string to be converted to UCS-2 + // while NSS used a byte string. + p8_decrypted.reset(PKCS8_decrypt_pbe( + p8_encrypted.get(), reinterpret_cast<const uint8_t*>("\0\0"), 2)); + } + if (!p8_decrypted) { + p8_decrypted.reset(PKCS8_decrypt_pbe( + p8_encrypted.get(), + reinterpret_cast<const uint8_t*>(password.data()), + password.size())); } - if (!p8_decrypted.get()) + + if (!p8_decrypted) return NULL; // Create a new EVP_PKEY for it. scoped_ptr<ECPrivateKey> result(new ECPrivateKey); result->key_ = EVP_PKCS82PKEY(p8_decrypted.get()); - if (!result->key_) + if (!result->key_ || EVP_PKEY_type(result->key_->type) != EVP_PKEY_EC) return NULL; return result.release(); @@ -155,8 +159,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; @@ -164,15 +167,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_pbe( + NID_pbe_WithSHA1And3_Key_TripleDES_CBC, + reinterpret_cast<const uint8_t*>(password.data()), + password.size(), + NULL, + 0, + iterations, + pkcs8.get())); if (!encrypted.get()) return false; @@ -188,9 +190,29 @@ bool ECPrivateKey::ExportPublicKey(std::vector<uint8>* output) { key_, reinterpret_cast<ExportBioFunction>(i2d_PUBKEY_bio), output); } +bool ECPrivateKey::ExportRawPublicKey(std::string* output) { + // i2d_PublicKey will produce an ANSI X9.62 public key which, for a P-256 + // key, is 0x04 (meaning uncompressed) followed by the x and y field + // elements as 32-byte, big-endian numbers. + static const int kExpectedKeyLength = 65; + + int len = i2d_PublicKey(key_, NULL); + if (len != kExpectedKeyLength) + return false; + + uint8 buf[kExpectedKeyLength]; + uint8* derp = buf; + len = i2d_PublicKey(key_, &derp); + if (len != kExpectedKeyLength) + return false; + + output->assign(reinterpret_cast<char*>(buf + 1), kExpectedKeyLength - 1); + return true; +} + 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); @@ -198,7 +220,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/chromium/crypto/ec_private_key_unittest.cc b/chromium/crypto/ec_private_key_unittest.cc index 8f653f15e58..6993a20b08f 100644 --- a/chromium/crypto/ec_private_key_unittest.cc +++ b/chromium/crypto/ec_private_key_unittest.cc @@ -6,6 +6,7 @@ #include <vector> +#include "base/macros.h" #include "base/memory/scoped_ptr.h" #include "testing/gtest/include/gtest/gtest.h" @@ -16,10 +17,8 @@ TEST(ECPrivateKeyUnitTest, InitRandomTest) { const std::string password1; const std::string password2 = "test"; - scoped_ptr<crypto::ECPrivateKey> keypair1( - crypto::ECPrivateKey::Create()); - scoped_ptr<crypto::ECPrivateKey> keypair2( - crypto::ECPrivateKey::Create()); + scoped_ptr<crypto::ECPrivateKey> keypair1(crypto::ECPrivateKey::Create()); + scoped_ptr<crypto::ECPrivateKey> keypair2(crypto::ECPrivateKey::Create()); ASSERT_TRUE(keypair1.get()); ASSERT_TRUE(keypair2.get()); @@ -36,12 +35,14 @@ TEST(ECPrivateKeyUnitTest, InitRandomTest) { std::vector<uint8> privkey2; std::vector<uint8> pubkey1; std::vector<uint8> pubkey2; - ASSERT_TRUE(keypair1->ExportEncryptedPrivateKey( - password1, 1, &privkey1)); - ASSERT_TRUE(keypair2->ExportEncryptedPrivateKey( - password2, 1, &privkey2)); + std::string raw_pubkey1; + std::string raw_pubkey2; + ASSERT_TRUE(keypair1->ExportEncryptedPrivateKey(password1, 1, &privkey1)); + ASSERT_TRUE(keypair2->ExportEncryptedPrivateKey(password2, 1, &privkey2)); EXPECT_TRUE(keypair1->ExportPublicKey(&pubkey1)); EXPECT_TRUE(keypair2->ExportPublicKey(&pubkey2)); + EXPECT_TRUE(keypair1->ExportRawPublicKey(&raw_pubkey1)); + EXPECT_TRUE(keypair2->ExportRawPublicKey(&raw_pubkey2)); scoped_ptr<crypto::ECPrivateKey> keypair3( crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo( @@ -68,13 +69,52 @@ TEST(ECPrivateKeyUnitTest, InitRandomTest) { std::vector<uint8> pubkey3; std::vector<uint8> pubkey4; + std::string raw_pubkey3; + std::string raw_pubkey4; EXPECT_TRUE(keypair3->ExportPublicKey(&pubkey3)); EXPECT_TRUE(keypair4->ExportPublicKey(&pubkey4)); + EXPECT_TRUE(keypair3->ExportRawPublicKey(&raw_pubkey3)); + EXPECT_TRUE(keypair4->ExportRawPublicKey(&raw_pubkey4)); EXPECT_EQ(pubkey1, pubkey3); EXPECT_EQ(pubkey2, pubkey4); + EXPECT_EQ(raw_pubkey1, raw_pubkey3); + EXPECT_EQ(raw_pubkey2, raw_pubkey4); } +#if !defined(USE_OPENSSL) +TEST(ECPrivateKeyUnitTest, Copy) { + scoped_ptr<crypto::ECPrivateKey> keypair1(crypto::ECPrivateKey::Create()); + scoped_ptr<crypto::ECPrivateKey> keypair2(keypair1->Copy()); + ASSERT_TRUE(keypair1.get()); + ASSERT_TRUE(keypair2.get()); + + std::vector<uint8> key1value; + std::vector<uint8> key2value; + EXPECT_TRUE(keypair1->ExportValue(&key1value)); + EXPECT_TRUE(keypair2->ExportValue(&key2value)); + EXPECT_EQ(key1value, key2value); + + std::vector<uint8> key1params; + std::vector<uint8> key2params; + EXPECT_TRUE(keypair1->ExportECParams(&key1params)); + EXPECT_TRUE(keypair2->ExportECParams(&key2params)); + EXPECT_EQ(key1params, key2params); + + std::vector<uint8> pubkey1; + std::vector<uint8> pubkey2; + EXPECT_TRUE(keypair1->ExportPublicKey(&pubkey1)); + EXPECT_TRUE(keypair2->ExportPublicKey(&pubkey2)); + EXPECT_EQ(pubkey1, pubkey2); + + std::string raw_pubkey1; + std::string raw_pubkey2; + EXPECT_TRUE(keypair1->ExportRawPublicKey(&raw_pubkey1)); + EXPECT_TRUE(keypair2->ExportRawPublicKey(&raw_pubkey2)); + EXPECT_EQ(raw_pubkey1, raw_pubkey2); +} +#endif // !defined(USE_OPENSSL) + TEST(ECPrivateKeyUnitTest, BadPasswordTest) { const std::string password1; const std::string password2 = "test"; @@ -113,7 +153,6 @@ TEST(ECPrivateKeyUnitTest, LoadNSSKeyTest) { 0x58, 0x82, 0x14, 0xfb, 0x47, 0x85, 0x3c, 0xc3, 0xdf, 0xdd, 0xcc, 0x79, 0x9f, 0x41, 0x83, 0x72, 0xf2, 0x0a, 0xe9, 0xe1, 0x2c, 0x12, 0xb0, 0xb0, 0x0a, 0xb2, 0x1d, 0xca, 0x15, 0xb2, 0xca}; - unsigned int nss_key_len = 187; static const unsigned char nss_pub_key[] = { 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, @@ -123,22 +162,62 @@ TEST(ECPrivateKeyUnitTest, LoadNSSKeyTest) { 0xd7, 0x5c, 0x5d, 0xc5, 0x53, 0x6e, 0xe5, 0xa9, 0x33, 0xd5, 0xcc, 0xab, 0x53, 0x78, 0xdd, 0xd6, 0x12, 0x3a, 0x5e, 0xeb, 0xbf, 0xdf, 0x16, 0xd3, 0x2c, 0x3b, 0xe8, 0xdb, 0x19, 0xfc, 0x5e}; - unsigned int nss_pub_key_len = 91; scoped_ptr<crypto::ECPrivateKey> keypair_nss( crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo( "", - std::vector<uint8>(nss_key, nss_key + nss_key_len), - std::vector<uint8>(nss_pub_key, nss_pub_key + nss_pub_key_len))); + std::vector<uint8>(nss_key, nss_key + arraysize(nss_key)), + std::vector<uint8>(nss_pub_key, + nss_pub_key + arraysize(nss_pub_key)))); EXPECT_TRUE(keypair_nss.get()); } -// The plan is to migrate to OpenSSL everywhere, so making NSS implementation be -// able to load the OpenSSL generated keys isn't that important. -#if defined(USE_OPENSSL) +// Although the plan is to transition from OpenSSL to NSS, ensure NSS can import +// OpenSSL's format so that it is possible to rollback. TEST(ECPrivateKeyUnitTest, LoadOpenSSLKeyTest) { static const unsigned char openssl_key[] = { + 0x30, 0x81, 0xb0, 0x30, 0x1b, 0x06, 0x0a, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x0c, 0x01, 0x03, 0x30, 0x0d, 0x04, 0x08, 0xb2, 0xfe, 0x68, + 0xc2, 0xea, 0x0f, 0x10, 0x9c, 0x02, 0x01, 0x01, 0x04, 0x81, 0x90, 0xe2, + 0xf6, 0x1c, 0xca, 0xad, 0x64, 0x30, 0xbf, 0x88, 0x04, 0x35, 0xe5, 0x0f, + 0x11, 0x49, 0x06, 0x01, 0x14, 0x33, 0x80, 0xa2, 0x78, 0x44, 0x5b, 0xaa, + 0x0d, 0xd7, 0x00, 0x36, 0x9d, 0x91, 0x97, 0x37, 0x20, 0x7b, 0x27, 0xc1, + 0xa0, 0xa2, 0x73, 0x06, 0x15, 0xdf, 0xc8, 0x13, 0x9b, 0xc9, 0x8c, 0x9c, + 0xce, 0x00, 0xd0, 0xc8, 0x42, 0xc1, 0xda, 0x2b, 0x07, 0x2b, 0x12, 0xa3, + 0xce, 0x10, 0x39, 0x7a, 0xf1, 0x55, 0x69, 0x8d, 0xa5, 0xc4, 0x2a, 0x00, + 0x0d, 0x94, 0xc6, 0xde, 0x6a, 0x3d, 0xb7, 0xe5, 0x6d, 0x59, 0x3e, 0x09, + 0xb5, 0xe3, 0x3e, 0xfc, 0x50, 0x56, 0xe9, 0x50, 0x42, 0x7c, 0xe7, 0xf0, + 0x19, 0xbd, 0x31, 0xa7, 0x85, 0x47, 0xb3, 0xe9, 0xb3, 0x50, 0x3c, 0xc9, + 0x32, 0x37, 0x1a, 0x93, 0x78, 0x48, 0x78, 0x82, 0xde, 0xad, 0x5c, 0xf2, + 0xcf, 0xf2, 0xbb, 0x2c, 0x44, 0x05, 0x7f, 0x4a, 0xf9, 0xb1, 0x2b, 0xdd, + 0x49, 0xf6, 0x7e, 0xd0, 0x42, 0xaa, 0x14, 0x3c, 0x24, 0x77, 0xb4}; + static const unsigned char openssl_pub_key[] = { + 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, + 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, + 0x42, 0x00, 0x04, 0xb9, 0xda, 0x0d, 0x71, 0x60, 0xb3, 0x63, 0x28, 0x22, + 0x67, 0xe7, 0xe0, 0xa3, 0xf8, 0x00, 0x8e, 0x4c, 0x89, 0xed, 0x31, 0x34, + 0xf6, 0xdb, 0xc4, 0xfe, 0x0b, 0x5d, 0xe1, 0x11, 0x39, 0x49, 0xa6, 0x50, + 0xa8, 0xe3, 0x4a, 0xc0, 0x40, 0x88, 0xb8, 0x38, 0x3f, 0x56, 0xfb, 0x33, + 0x8d, 0xd4, 0x64, 0x91, 0xd6, 0x15, 0x77, 0x42, 0x27, 0xc5, 0xaa, 0x44, + 0xff, 0xab, 0x4d, 0xb5, 0x7e, 0x25, 0x3d}; + + scoped_ptr<crypto::ECPrivateKey> keypair_openssl( + crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo( + "", + std::vector<uint8>(openssl_key, openssl_key + arraysize(openssl_key)), + std::vector<uint8>(openssl_pub_key, + openssl_pub_key + arraysize(openssl_pub_key)))); + + EXPECT_TRUE(keypair_openssl.get()); +} + +// The Android code writes out Channel IDs differently from the NSS +// implementation; the empty password is converted to "\0\0". The OpenSSL port +// should support either. +#if defined(USE_OPENSSL) +TEST(ECPrivateKeyUnitTest, LoadOldOpenSSLKeyTest) { + static const unsigned char openssl_key[] = { 0x30, 0x82, 0x01, 0xa1, 0x30, 0x1b, 0x06, 0x0a, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x01, 0x03, 0x30, 0x0d, 0x04, 0x08, 0x86, 0xaa, 0xd7, 0xdf, 0x3b, 0x91, 0x97, 0x60, 0x02, 0x01, 0x01, 0x04, 0x82, 0x01, @@ -175,7 +254,6 @@ TEST(ECPrivateKeyUnitTest, LoadOpenSSLKeyTest) { 0xc2, 0xc1, 0x55, 0x22, 0x42, 0x2f, 0x13, 0x7d, 0x93, 0x27, 0xc8, 0x11, 0x35, 0xc5, 0xe3, 0xc5, 0xaa, 0x15, 0x3c, 0xac, 0x30, 0xbc, 0x45, 0x16, 0xed}; - unsigned int openssl_key_len = 421; static const unsigned char openssl_pub_key[] = { 0x30, 0x82, 0x01, 0x4b, 0x30, 0x82, 0x01, 0x03, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x30, 0x81, 0xf7, 0x02, 0x01, 0x01, 0x30, @@ -205,14 +283,13 @@ TEST(ECPrivateKeyUnitTest, LoadOpenSSLKeyTest) { 0x88, 0x38, 0xc0, 0xdb, 0xba, 0xf6, 0x99, 0xd8, 0xa5, 0x3b, 0x83, 0xe9, 0xe3, 0xd5, 0x61, 0x99, 0x73, 0x42, 0xc6, 0x6c, 0xe8, 0x0a, 0x95, 0x40, 0x41, 0x3b, 0x0d, 0x10, 0xa7, 0x4a, 0x93, 0xdb, 0x5a, 0xe7, 0xec}; - unsigned int openssl_pub_key_len = 335; scoped_ptr<crypto::ECPrivateKey> keypair_openssl( crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo( "", - std::vector<uint8>(openssl_key, openssl_key + openssl_key_len), + std::vector<uint8>(openssl_key, openssl_key + arraysize(openssl_key)), std::vector<uint8>(openssl_pub_key, - openssl_pub_key + openssl_pub_key_len))); + openssl_pub_key + arraysize(openssl_pub_key)))); EXPECT_TRUE(keypair_openssl.get()); } diff --git a/chromium/crypto/ec_signature_creator_impl.h b/chromium/crypto/ec_signature_creator_impl.h index 8ef67cd7f3d..f2ef9d65795 100644 --- a/chromium/crypto/ec_signature_creator_impl.h +++ b/chromium/crypto/ec_signature_creator_impl.h @@ -17,10 +17,10 @@ class ECSignatureCreatorImpl : public ECSignatureCreator { virtual bool Sign(const uint8* data, int data_len, - std::vector<uint8>* signature) OVERRIDE; + std::vector<uint8>* signature) override; virtual bool DecodeSignature(const std::vector<uint8>& der_sig, - std::vector<uint8>* out_raw_sig) OVERRIDE; + std::vector<uint8>* out_raw_sig) override; private: ECPrivateKey* key_; diff --git a/chromium/crypto/ec_signature_creator_openssl.cc b/chromium/crypto/ec_signature_creator_openssl.cc index 7f0a873f993..91e8a6a8d33 100644 --- a/chromium/crypto/ec_signature_creator_openssl.cc +++ b/chromium/crypto/ec_signature_creator_openssl.cc @@ -13,6 +13,7 @@ #include "base/logging.h" #include "crypto/ec_private_key.h" #include "crypto/openssl_util.h" +#include "crypto/scoped_openssl_types.h" namespace crypto { @@ -27,7 +28,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 +53,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/chromium/crypto/encryptor_openssl.cc b/chromium/crypto/encryptor_openssl.cc index 0bf96b79df2..0504adbcb9f 100644 --- a/chromium/crypto/encryptor_openssl.cc +++ b/chromium/crypto/encryptor_openssl.cc @@ -19,7 +19,6 @@ namespace { const EVP_CIPHER* GetCipherForKey(SymmetricKey* key) { switch (key->key().length()) { case 16: return EVP_aes_128_cbc(); - case 24: return EVP_aes_192_cbc(); case 32: return EVP_aes_256_cbc(); default: return NULL; } @@ -100,8 +99,8 @@ bool Encryptor::Crypt(bool do_encrypt, DCHECK(cipher); // Already handled in Init(); const std::string& key = key_->key(); - DCHECK_EQ(EVP_CIPHER_iv_length(cipher), static_cast<int>(iv_.length())); - DCHECK_EQ(EVP_CIPHER_key_length(cipher), static_cast<int>(key.length())); + DCHECK_EQ(EVP_CIPHER_iv_length(cipher), iv_.length()); + DCHECK_EQ(EVP_CIPHER_key_length(cipher), key.length()); ScopedCipherCTX ctx; if (!EVP_CipherInit_ex(ctx.get(), cipher, NULL, diff --git a/chromium/crypto/encryptor_unittest.cc b/chromium/crypto/encryptor_unittest.cc index 2a21a8e13db..1a99783679f 100644 --- a/chromium/crypto/encryptor_unittest.cc +++ b/chromium/crypto/encryptor_unittest.cc @@ -456,48 +456,21 @@ TEST(EncryptorTest, EncryptAES128CBCRegression) { EXPECT_EQ(plaintext, decrypted); } -// Expected output derived from the NSS implementation. -TEST(EncryptorTest, EncryptAES192CBCRegression) { - std::string key = "192bitsIsTwentyFourByte!"; - std::string iv = "Sweet Sixteen IV"; - std::string plaintext = "Small text"; - std::string expected_ciphertext_hex = "78DE5D7C2714FC5C61346C5416F6C89A"; - - scoped_ptr<crypto::SymmetricKey> sym_key(crypto::SymmetricKey::Import( - crypto::SymmetricKey::AES, key)); - ASSERT_TRUE(sym_key.get()); - - crypto::Encryptor encryptor; - // The IV must be exactly as long a the cipher block size. - EXPECT_EQ(16U, iv.size()); - EXPECT_TRUE(encryptor.Init(sym_key.get(), crypto::Encryptor::CBC, iv)); - - std::string ciphertext; - EXPECT_TRUE(encryptor.Encrypt(plaintext, &ciphertext)); - EXPECT_EQ(expected_ciphertext_hex, base::HexEncode(ciphertext.data(), - ciphertext.size())); - - std::string decrypted; - EXPECT_TRUE(encryptor.Decrypt(ciphertext, &decrypted)); - EXPECT_EQ(plaintext, decrypted); -} - -// Not all platforms allow import/generation of symmetric keys with an -// unsupported size. -#if !defined(USE_NSS) && !defined(OS_WIN) && !defined(OS_MACOSX) +// Symmetric keys with an unsupported size should be rejected. Whether they are +// rejected by SymmetricKey::Import or Encryptor::Init depends on the platform. TEST(EncryptorTest, UnsupportedKeySize) { std::string key = "7 = bad"; std::string iv = "Sweet Sixteen IV"; scoped_ptr<crypto::SymmetricKey> sym_key(crypto::SymmetricKey::Import( crypto::SymmetricKey::AES, key)); - ASSERT_TRUE(sym_key.get()); + if (!sym_key.get()) + return; crypto::Encryptor encryptor; - // The IV must be exactly as long a the cipher block size. + // The IV must be exactly as long as the cipher block size. EXPECT_EQ(16U, iv.size()); EXPECT_FALSE(encryptor.Init(sym_key.get(), crypto::Encryptor::CBC, iv)); } -#endif // unsupported platforms. TEST(EncryptorTest, UnsupportedIV) { std::string key = "128=SixteenBytes"; diff --git a/chromium/crypto/hkdf.cc b/chromium/crypto/hkdf.cc index 1cd8468977e..82aae24679e 100644 --- a/chromium/crypto/hkdf.cc +++ b/chromium/crypto/hkdf.cc @@ -5,6 +5,7 @@ #include "crypto/hkdf.h" #include "base/logging.h" +#include "base/memory/scoped_ptr.h" #include "crypto/hmac.h" namespace crypto { @@ -15,7 +16,8 @@ HKDF::HKDF(const base::StringPiece& secret, const base::StringPiece& salt, const base::StringPiece& info, size_t key_bytes_to_generate, - size_t iv_bytes_to_generate) { + size_t iv_bytes_to_generate, + size_t subkey_secret_bytes_to_generate) { // https://tools.ietf.org/html/rfc5869#section-2.2 base::StringPiece actual_salt = salt; char zeros[kSHA256HashLength]; @@ -40,8 +42,9 @@ HKDF::HKDF(const base::StringPiece& secret, // https://tools.ietf.org/html/rfc5869#section-2.3 // Perform the Expand phase to turn the pseudorandom key // and info into the output keying material. - const size_t material_length = - 2*key_bytes_to_generate + 2*iv_bytes_to_generate; + const size_t material_length = 2 * key_bytes_to_generate + + 2 * iv_bytes_to_generate + + subkey_secret_bytes_to_generate; const size_t n = (material_length + kSHA256HashLength-1) / kSHA256HashLength; DCHECK_LT(n, 256u); @@ -90,6 +93,11 @@ HKDF::HKDF(const base::StringPiece& secret, j += iv_bytes_to_generate; server_write_iv_ = base::StringPiece(reinterpret_cast<char*>(&output_[j]), iv_bytes_to_generate); + j += iv_bytes_to_generate; + } + if (subkey_secret_bytes_to_generate) { + subkey_secret_ = base::StringPiece(reinterpret_cast<char*>(&output_[j]), + subkey_secret_bytes_to_generate); } } diff --git a/chromium/crypto/hkdf.h b/chromium/crypto/hkdf.h index 1d7a87673a1..e91bccf5b4f 100644 --- a/chromium/crypto/hkdf.h +++ b/chromium/crypto/hkdf.h @@ -8,9 +8,7 @@ #include <vector> #include "base/basictypes.h" -#include "base/memory/scoped_ptr.h" #include "base/strings/string_piece.h" -#include "build/build_config.h" #include "crypto/crypto_export.h" namespace crypto { @@ -20,7 +18,7 @@ namespace crypto { // See https://tools.ietf.org/html/rfc5869 for details. class CRYPTO_EXPORT HKDF { public: - // |secret|: The input shared secret (or, from RFC 5869, the IKM). + // |secret|: the input shared secret (or, from RFC 5869, the IKM). // |salt|: an (optional) public salt / non-secret random value. While // optional, callers are strongly recommended to provide a salt. There is no // added security value in making this larger than the SHA-256 block size of @@ -28,13 +26,18 @@ class CRYPTO_EXPORT HKDF { // |info|: an (optional) label to distinguish different uses of HKDF. It is // optional context and application specific information (can be a zero-length // string). - // |key_bytes_to_generate|: the number of bytes of key material to generate. - // |iv_bytes_to_generate|: the number of bytes of IV to generate. + // |key_bytes_to_generate|: the number of bytes of key material to generate + // for both client and server. + // |iv_bytes_to_generate|: the number of bytes of IV to generate for both + // client and server. + // |subkey_secret_bytes_to_generate|: the number of bytes of subkey secret to + // generate, shared between client and server. HKDF(const base::StringPiece& secret, const base::StringPiece& salt, const base::StringPiece& info, size_t key_bytes_to_generate, - size_t iv_bytes_to_generate); + size_t iv_bytes_to_generate, + size_t subkey_secret_bytes_to_generate); ~HKDF(); base::StringPiece client_write_key() const { @@ -49,6 +52,9 @@ class CRYPTO_EXPORT HKDF { base::StringPiece server_write_iv() const { return server_write_iv_; } + base::StringPiece subkey_secret() const { + return subkey_secret_; + } private: std::vector<uint8> output_; @@ -57,6 +63,7 @@ class CRYPTO_EXPORT HKDF { base::StringPiece server_write_key_; base::StringPiece client_write_iv_; base::StringPiece server_write_iv_; + base::StringPiece subkey_secret_; }; } // namespace crypto diff --git a/chromium/crypto/hkdf_unittest.cc b/chromium/crypto/hkdf_unittest.cc index dc369d1b94f..bcb19c5c10d 100644 --- a/chromium/crypto/hkdf_unittest.cc +++ b/chromium/crypto/hkdf_unittest.cc @@ -82,7 +82,7 @@ TEST(HKDFTest, HKDF) { // We set the key_length to the length of the expected output and then take // the result from the first key, which is the client write key. - HKDF hkdf(key, salt, info, expected.size(), 0); + HKDF hkdf(key, salt, info, expected.size(), 0, 0); ASSERT_EQ(expected.size(), hkdf.client_write_key().size()); EXPECT_EQ(0, memcmp(expected.data(), hkdf.client_write_key().data(), diff --git a/chromium/crypto/hmac_openssl.cc b/chromium/crypto/hmac_openssl.cc index 46bfbaefbef..92eea19d780 100644 --- a/chromium/crypto/hmac_openssl.cc +++ b/chromium/crypto/hmac_openssl.cc @@ -54,7 +54,7 @@ bool HMAC::Sign(const base::StringPiece& data, DCHECK(!plat_->key.empty()); // Init must be called before Sign. ScopedOpenSSLSafeSizeBuffer<EVP_MAX_MD_SIZE> result(digest, digest_length); - return ::HMAC(hash_alg_ == SHA1 ? EVP_sha1() : EVP_sha256(), + return !!::HMAC(hash_alg_ == SHA1 ? EVP_sha1() : EVP_sha256(), &plat_->key[0], plat_->key.size(), reinterpret_cast<const unsigned char*>(data.data()), data.size(), diff --git a/chromium/crypto/hmac_unittest.cc b/chromium/crypto/hmac_unittest.cc index 174c32382fa..91eccd68e23 100644 --- a/chromium/crypto/hmac_unittest.cc +++ b/chromium/crypto/hmac_unittest.cc @@ -142,7 +142,7 @@ TEST(HMACTest, RFC2202TestCases) { "\xBB\xFF\x1A\x91" } }; - for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) { + for (size_t i = 0; i < arraysize(cases); ++i) { crypto::HMAC hmac(crypto::HMAC::SHA1); ASSERT_TRUE(hmac.Init(reinterpret_cast<const unsigned char*>(cases[i].key), cases[i].key_len)); @@ -239,7 +239,7 @@ TEST(HMACTest, HMACObjectReuse) { ASSERT_TRUE( hmac.Init(reinterpret_cast<const unsigned char*>(kSimpleKey), kSimpleKeyLength)); - for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kSimpleHmacCases); ++i) { + for (size_t i = 0; i < arraysize(kSimpleHmacCases); ++i) { std::string data_string(kSimpleHmacCases[i].data, kSimpleHmacCases[i].data_len); unsigned char digest[kSHA1DigestSize]; @@ -254,7 +254,7 @@ TEST(HMACTest, Verify) { hmac.Init(reinterpret_cast<const unsigned char*>(kSimpleKey), kSimpleKeyLength)); const char empty_digest[kSHA1DigestSize] = { 0 }; - for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kSimpleHmacCases); ++i) { + for (size_t i = 0; i < arraysize(kSimpleHmacCases); ++i) { // Expected results EXPECT_TRUE(hmac.Verify( base::StringPiece(kSimpleHmacCases[i].data, diff --git a/chromium/crypto/hmac_win.cc b/chromium/crypto/hmac_win.cc index ba7d8275035..99b3a60d57e 100644 --- a/chromium/crypto/hmac_win.cc +++ b/chromium/crypto/hmac_win.cc @@ -5,7 +5,6 @@ #include "crypto/hmac.h" #include <windows.h> -#include <wincrypt.h> #include <algorithm> #include <vector> @@ -14,6 +13,7 @@ #include "crypto/scoped_capi_types.h" #include "crypto/third_party/nss/chromium-blapi.h" #include "crypto/third_party/nss/chromium-sha256.h" +#include "crypto/wincrypt_shim.h" namespace crypto { diff --git a/chromium/crypto/mock_apple_keychain.h b/chromium/crypto/mock_apple_keychain.h index efbb438aa6a..d9573162ee6 100644 --- a/chromium/crypto/mock_apple_keychain.h +++ b/chromium/crypto/mock_apple_keychain.h @@ -40,9 +40,9 @@ class CRYPTO_EXPORT MockAppleKeychain : public AppleKeychain { const char* accountName, UInt32* passwordLength, void** passwordData, - SecKeychainItemRef* itemRef) const OVERRIDE; + SecKeychainItemRef* itemRef) const override; virtual OSStatus ItemFreeContent(SecKeychainAttributeList* attrList, - void* data) const OVERRIDE; + void* data) const override; virtual OSStatus AddGenericPassword( SecKeychainRef keychain, UInt32 serviceNameLength, @@ -51,7 +51,7 @@ class CRYPTO_EXPORT MockAppleKeychain : public AppleKeychain { const char* accountName, UInt32 passwordLength, const void* passwordData, - SecKeychainItemRef* itemRef) const OVERRIDE; + SecKeychainItemRef* itemRef) const override; #if !defined(OS_IOS) virtual OSStatus ItemCopyAttributesAndData( @@ -60,23 +60,23 @@ class CRYPTO_EXPORT MockAppleKeychain : public AppleKeychain { SecItemClass* itemClass, SecKeychainAttributeList** attrList, UInt32* length, - void** outData) const OVERRIDE; + void** outData) const override; // Pass "fail_me" as the data to get errSecAuthFailed. virtual OSStatus ItemModifyAttributesAndData( SecKeychainItemRef itemRef, const SecKeychainAttributeList* attrList, UInt32 length, - const void* data) const OVERRIDE; + const void* data) const override; virtual OSStatus ItemFreeAttributesAndData(SecKeychainAttributeList* attrList, - void* data) const OVERRIDE; - virtual OSStatus ItemDelete(SecKeychainItemRef itemRef) const OVERRIDE; + void* data) const override; + virtual OSStatus ItemDelete(SecKeychainItemRef itemRef) const override; virtual OSStatus SearchCreateFromAttributes( CFTypeRef keychainOrArray, SecItemClass itemClass, const SecKeychainAttributeList* attrList, - SecKeychainSearchRef* searchRef) const OVERRIDE; + SecKeychainSearchRef* searchRef) const override; virtual OSStatus SearchCopyNext(SecKeychainSearchRef searchRef, - SecKeychainItemRef* itemRef) const OVERRIDE; + SecKeychainItemRef* itemRef) const override; // Pass "some.domain.com" as the serverName to get errSecDuplicateItem. virtual OSStatus AddInternetPassword( SecKeychainRef keychain, @@ -91,8 +91,8 @@ class CRYPTO_EXPORT MockAppleKeychain : public AppleKeychain { SecAuthenticationType authenticationType, UInt32 passwordLength, const void* passwordData, - SecKeychainItemRef* itemRef) const OVERRIDE; - virtual void Free(CFTypeRef ref) const OVERRIDE; + SecKeychainItemRef* itemRef) const override; + virtual void Free(CFTypeRef ref) const override; // Return the counts of objects returned by Create/Copy functions but never // Free'd as they should have been. @@ -140,7 +140,6 @@ class CRYPTO_EXPORT MockAppleKeychain : public AppleKeychain { int password_data_count() const { return password_data_count_; } private: - // Type used for the keys in the std::map(s) and MockAppleKeychain items. typedef uintptr_t MockKeychainItemType; diff --git a/chromium/crypto/nss_util.cc b/chromium/crypto/nss_util.cc index 5958ad972da..8f9865a3c6c 100644 --- a/chromium/crypto/nss_util.cc +++ b/chromium/crypto/nss_util.cc @@ -27,8 +27,8 @@ #include "base/debug/alias.h" #include "base/debug/stack_trace.h" #include "base/environment.h" -#include "base/file_util.h" #include "base/files/file_path.h" +#include "base/files/file_util.h" #include "base/lazy_instance.h" #include "base/logging.h" #include "base/memory/scoped_ptr.h" @@ -57,7 +57,7 @@ namespace crypto { namespace { #if defined(OS_CHROMEOS) -const char kNSSDatabaseName[] = "Real NSS database"; +const char kUserNSSDatabaseName[] = "UserNSSDB"; // Constants for loading the Chrome OS TPM-backed PKCS #11 library. const char kChapsModuleName[] = "Chaps"; @@ -81,6 +81,7 @@ std::string GetNSSErrorMessage() { } #if defined(USE_NSS) +#if !defined(OS_CHROMEOS) base::FilePath GetDefaultConfigDirectory() { base::FilePath dir; PathService::Get(base::DIR_HOME, &dir); @@ -96,6 +97,7 @@ base::FilePath GetDefaultConfigDirectory() { DVLOG(2) << "DefaultConfigDirectory: " << dir.value(); return dir; } +#endif // !defined(IS_CHROMEOS) // On non-Chrome OS platforms, return the default config directory. On Chrome OS // test images, return a read-only directory with fake root CA certs (which are @@ -196,12 +198,6 @@ class NSPRInitSingleton { base::LazyInstance<NSPRInitSingleton>::Leaky g_nspr_singleton = LAZY_INSTANCE_INITIALIZER; -// This is a LazyInstance so that it will be deleted automatically when the -// unittest exits. NSSInitSingleton is a LeakySingleton, so it would not be -// deleted if it were a regular member. -base::LazyInstance<base::ScopedTempDir> g_test_nss_db_dir = - LAZY_INSTANCE_INITIALIZER; - // Force a crash with error info on NSS_NoDB_Init failure. void CrashOnNSSInitFailure() { int nss_error = PR_GetError(); @@ -216,11 +212,11 @@ void CrashOnNSSInitFailure() { #if defined(OS_CHROMEOS) class ChromeOSUserData { public: - ChromeOSUserData(ScopedPK11Slot public_slot, bool is_primary_user) + explicit ChromeOSUserData(ScopedPK11Slot public_slot) : public_slot_(public_slot.Pass()), - is_primary_user_(is_primary_user) {} + private_slot_initialization_started_(false) {} ~ChromeOSUserData() { - if (public_slot_ && !is_primary_user_) { + if (public_slot_) { SECStatus status = SECMOD_CloseUserDB(public_slot_.get()); if (status != SECSuccess) PLOG(ERROR) << "SECMOD_CloseUserDB failed: " << PORT_GetError(); @@ -254,10 +250,19 @@ class ChromeOSUserData { } } + bool private_slot_initialization_started() const { + return private_slot_initialization_started_; + } + + void set_private_slot_initialization_started() { + private_slot_initialization_started_ = true; + } + private: ScopedPK11Slot public_slot_; ScopedPK11Slot private_slot_; - bool is_primary_user_; + + bool private_slot_initialization_started_; typedef std::vector<base::Callback<void(ScopedPK11Slot)> > SlotReadyCallbackList; @@ -271,30 +276,13 @@ class NSSInitSingleton { // Used with PostTaskAndReply to pass handles to worker thread and back. struct TPMModuleAndSlot { explicit TPMModuleAndSlot(SECMODModule* init_chaps_module) - : chaps_module(init_chaps_module), tpm_slot(NULL) {} + : chaps_module(init_chaps_module) {} SECMODModule* chaps_module; - PK11SlotInfo* tpm_slot; + crypto::ScopedPK11Slot tpm_slot; }; - void OpenPersistentNSSDB() { - DCHECK(thread_checker_.CalledOnValidThread()); - - if (!chromeos_user_logged_in_) { - // GetDefaultConfigDirectory causes us to do blocking IO on UI thread. - // Temporarily allow it until we fix http://crbug.com/70119 - base::ThreadRestrictions::ScopedAllowIO allow_io; - chromeos_user_logged_in_ = true; - - // This creates another DB slot in NSS that is read/write, unlike - // the fake root CA cert DB and the "default" crypto key - // provider, which are still read-only (because we initialized - // NSS before we had a cryptohome mounted). - software_slot_ = OpenUserDB(GetDefaultConfigDirectory(), - kNSSDatabaseName); - } - } - - PK11SlotInfo* OpenPersistentNSSDBForPath(const base::FilePath& path) { + ScopedPK11Slot OpenPersistentNSSDBForPath(const std::string& db_name, + const base::FilePath& path) { DCHECK(thread_checker_.CalledOnValidThread()); // NSS is allowed to do IO on the current thread since dispatching // to a dedicated thread would still have the affect of blocking @@ -304,9 +292,9 @@ class NSSInitSingleton { base::FilePath nssdb_path = path.AppendASCII(".pki").AppendASCII("nssdb"); if (!base::CreateDirectory(nssdb_path)) { LOG(ERROR) << "Failed to create " << nssdb_path.value() << " directory."; - return NULL; + return ScopedPK11Slot(); } - return OpenUserDB(nssdb_path, kNSSDatabaseName); + return OpenSoftwareNSSDB(nssdb_path, db_name); } void EnableTPMTokenForNSS() { @@ -323,8 +311,9 @@ class NSSInitSingleton { return tpm_token_enabled_for_nss_; } - void InitializeTPMToken(int token_slot_id, - const base::Callback<void(bool)>& callback) { + void InitializeTPMTokenAndSystemSlot( + int system_slot_id, + const base::Callback<void(bool)>& callback) { DCHECK(thread_checker_.CalledOnValidThread()); // Should not be called while there is already an initialization in // progress. @@ -352,9 +341,9 @@ class NSSInitSingleton { if (base::WorkerPool::PostTaskAndReply( FROM_HERE, base::Bind(&NSSInitSingleton::InitializeTPMTokenOnWorkerThread, - token_slot_id, + system_slot_id, tpm_args_ptr), - base::Bind(&NSSInitSingleton::OnInitializedTPMToken, + base::Bind(&NSSInitSingleton::OnInitializedTPMTokenAndSystemSlot, base::Unretained(this), // NSSInitSingleton is leaky callback, base::Passed(&tpm_args)), @@ -389,34 +378,38 @@ class NSSInitSingleton { } } - void OnInitializedTPMToken(const base::Callback<void(bool)>& callback, - scoped_ptr<TPMModuleAndSlot> tpm_args) { + void OnInitializedTPMTokenAndSystemSlot( + const base::Callback<void(bool)>& callback, + scoped_ptr<TPMModuleAndSlot> tpm_args) { DCHECK(thread_checker_.CalledOnValidThread()); DVLOG(2) << "Loaded chaps: " << !!tpm_args->chaps_module << ", got tpm slot: " << !!tpm_args->tpm_slot; chaps_module_ = tpm_args->chaps_module; - tpm_slot_ = tpm_args->tpm_slot; - if (!chaps_module_ && test_slot_) { + tpm_slot_ = tpm_args->tpm_slot.Pass(); + if (!chaps_module_ && test_system_slot_) { // chromeos_unittests try to test the TPM initialization process. If we // have a test DB open, pretend that it is the TPM slot. - tpm_slot_ = PK11_ReferenceSlot(test_slot_); + tpm_slot_.reset(PK11_ReferenceSlot(test_system_slot_.get())); } initializing_tpm_token_ = false; - if (tpm_slot_) { - TPMReadyCallbackList callback_list; - callback_list.swap(tpm_ready_callback_list_); - for (TPMReadyCallbackList::iterator i = callback_list.begin(); - i != callback_list.end(); - ++i) { - (*i).Run(); - } - } + if (tpm_slot_) + RunAndClearTPMReadyCallbackList(); callback.Run(!!tpm_slot_); } + void RunAndClearTPMReadyCallbackList() { + TPMReadyCallbackList callback_list; + callback_list.swap(tpm_ready_callback_list_); + for (TPMReadyCallbackList::iterator i = callback_list.begin(); + i != callback_list.end(); + ++i) { + i->Run(); + } + } + bool IsTPMTokenReady(const base::Closure& callback) { if (!callback.is_null()) { // Cannot DCHECK in the general case yet, but since the callback is @@ -429,7 +422,7 @@ class NSSInitSingleton { << base::debug::StackTrace().ToString(); } - if (tpm_slot_ != NULL) + if (tpm_slot_) return true; if (!callback.is_null()) @@ -441,8 +434,9 @@ class NSSInitSingleton { // Note that CK_SLOT_ID is an unsigned long, but cryptohome gives us the slot // id as an int. This should be safe since this is only used with chaps, which // we also control. - static PK11SlotInfo* GetTPMSlotForIdOnWorkerThread(SECMODModule* chaps_module, - CK_SLOT_ID slot_id) { + static crypto::ScopedPK11Slot GetTPMSlotForIdOnWorkerThread( + SECMODModule* chaps_module, + CK_SLOT_ID slot_id) { DCHECK(chaps_module); DVLOG(3) << "Poking chaps module."; @@ -453,37 +447,49 @@ class NSSInitSingleton { PK11SlotInfo* slot = SECMOD_LookupSlot(chaps_module->moduleID, slot_id); if (!slot) LOG(ERROR) << "TPM slot " << slot_id << " not found."; - return slot; + return crypto::ScopedPK11Slot(slot); } - bool InitializeNSSForChromeOSUser( - const std::string& email, - const std::string& username_hash, - bool is_primary_user, - const base::FilePath& path) { + bool InitializeNSSForChromeOSUser(const std::string& username_hash, + const base::FilePath& path) { DCHECK(thread_checker_.CalledOnValidThread()); if (chromeos_user_map_.find(username_hash) != chromeos_user_map_.end()) { // This user already exists in our mapping. DVLOG(2) << username_hash << " already initialized."; return false; } - ScopedPK11Slot public_slot; - if (is_primary_user) { - DVLOG(2) << "Primary user, using GetPublicNSSKeySlot()"; - public_slot.reset(GetPublicNSSKeySlot()); - } else { - DVLOG(2) << "Opening NSS DB " << path.value(); - public_slot.reset(OpenPersistentNSSDBForPath(path)); - } + + DVLOG(2) << "Opening NSS DB " << path.value(); + std::string db_name = base::StringPrintf( + "%s %s", kUserNSSDatabaseName, username_hash.c_str()); + ScopedPK11Slot public_slot(OpenPersistentNSSDBForPath(db_name, path)); chromeos_user_map_[username_hash] = - new ChromeOSUserData(public_slot.Pass(), is_primary_user); + new ChromeOSUserData(public_slot.Pass()); return true; } + bool ShouldInitializeTPMForChromeOSUser(const std::string& username_hash) { + DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(chromeos_user_map_.find(username_hash) != chromeos_user_map_.end()); + + return !chromeos_user_map_[username_hash] + ->private_slot_initialization_started(); + } + + void WillInitializeTPMForChromeOSUser(const std::string& username_hash) { + DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(chromeos_user_map_.find(username_hash) != chromeos_user_map_.end()); + + chromeos_user_map_[username_hash] + ->set_private_slot_initialization_started(); + } + void InitializeTPMForChromeOSUser(const std::string& username_hash, CK_SLOT_ID slot_id) { DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(chromeos_user_map_.find(username_hash) != chromeos_user_map_.end()); + DCHECK(chromeos_user_map_[username_hash]-> + private_slot_initialization_started()); if (!chaps_module_) return; @@ -511,7 +517,7 @@ class NSSInitSingleton { DVLOG(2) << "Got tpm slot for " << username_hash << " " << !!tpm_args->tpm_slot; chromeos_user_map_[username_hash]->SetPrivateSlot( - ScopedPK11Slot(tpm_args->tpm_slot)); + tpm_args->tpm_slot.Pass()); } void InitializePrivateSoftwareSlotForChromeOSUser( @@ -519,6 +525,9 @@ class NSSInitSingleton { DCHECK(thread_checker_.CalledOnValidThread()); VLOG(1) << "using software private slot for " << username_hash; DCHECK(chromeos_user_map_.find(username_hash) != chromeos_user_map_.end()); + DCHECK(chromeos_user_map_[username_hash]-> + private_slot_initialization_started()); + chromeos_user_map_[username_hash]->SetPrivateSlot( chromeos_user_map_[username_hash]->GetPublicSlot()); } @@ -532,11 +541,6 @@ class NSSInitSingleton { return ScopedPK11Slot(); } - if (test_slot_) { - DVLOG(2) << "returning test_slot_ for " << username_hash; - return ScopedPK11Slot(PK11_ReferenceSlot(test_slot_)); - } - if (chromeos_user_map_.find(username_hash) == chromeos_user_map_.end()) { LOG(ERROR) << username_hash << " not initialized."; return ScopedPK11Slot(); @@ -560,97 +564,69 @@ class NSSInitSingleton { DCHECK(chromeos_user_map_.find(username_hash) != chromeos_user_map_.end()); - if (test_slot_) { - DVLOG(2) << "returning test_slot_ for " << username_hash; - return ScopedPK11Slot(PK11_ReferenceSlot(test_slot_)); - } - return chromeos_user_map_[username_hash]->GetPrivateSlot(callback); } - void CloseTestChromeOSUser(const std::string& username_hash) { + void CloseChromeOSUserForTesting(const std::string& username_hash) { DCHECK(thread_checker_.CalledOnValidThread()); ChromeOSUserMap::iterator i = chromeos_user_map_.find(username_hash); DCHECK(i != chromeos_user_map_.end()); delete i->second; chromeos_user_map_.erase(i); } -#endif // defined(OS_CHROMEOS) - - - bool OpenTestNSSDB() { - DCHECK(thread_checker_.CalledOnValidThread()); - // NSS is allowed to do IO on the current thread since dispatching - // to a dedicated thread would still have the affect of blocking - // the current thread, due to NSS's internal locking requirements - base::ThreadRestrictions::ScopedAllowIO allow_io; - - if (test_slot_) - return true; - if (!g_test_nss_db_dir.Get().CreateUniqueTempDir()) - return false; - test_slot_ = OpenUserDB(g_test_nss_db_dir.Get().path(), kTestTPMTokenName); - return !!test_slot_; - } - void CloseTestNSSDB() { - DCHECK(thread_checker_.CalledOnValidThread()); - // NSS is allowed to do IO on the current thread since dispatching - // to a dedicated thread would still have the affect of blocking - // the current thread, due to NSS's internal locking requirements - base::ThreadRestrictions::ScopedAllowIO allow_io; - - if (!test_slot_) - return; - SECStatus status = SECMOD_CloseUserDB(test_slot_); - if (status != SECSuccess) - PLOG(ERROR) << "SECMOD_CloseUserDB failed: " << PORT_GetError(); - PK11_FreeSlot(test_slot_); - test_slot_ = NULL; - ignore_result(g_test_nss_db_dir.Get().Delete()); + void SetSystemKeySlotForTesting(ScopedPK11Slot slot) { + // Ensure that a previous value of test_system_slot_ is not overwritten. + // Unsetting, i.e. setting a NULL, however is allowed. + DCHECK(!slot || !test_system_slot_); + test_system_slot_ = slot.Pass(); + if (test_system_slot_) { + tpm_slot_.reset(PK11_ReferenceSlot(test_system_slot_.get())); + RunAndClearTPMReadyCallbackList(); + } else { + tpm_slot_.reset(); + } } +#endif // defined(OS_CHROMEOS) - PK11SlotInfo* GetPublicNSSKeySlot() { +#if !defined(OS_CHROMEOS) + PK11SlotInfo* GetPersistentNSSKeySlot() { // TODO(mattm): Change to DCHECK when callers have been fixed. if (!thread_checker_.CalledOnValidThread()) { DVLOG(1) << "Called on wrong thread.\n" << base::debug::StackTrace().ToString(); } - if (test_slot_) - return PK11_ReferenceSlot(test_slot_); - if (software_slot_) - return PK11_ReferenceSlot(software_slot_); return PK11_GetInternalKeySlot(); } +#endif - PK11SlotInfo* GetPrivateNSSKeySlot() { - // TODO(mattm): Change to DCHECK when callers have been fixed. - if (!thread_checker_.CalledOnValidThread()) { - DVLOG(1) << "Called on wrong thread.\n" - << base::debug::StackTrace().ToString(); - } +#if defined(OS_CHROMEOS) + void GetSystemNSSKeySlotCallback( + const base::Callback<void(ScopedPK11Slot)>& callback) { + callback.Run(ScopedPK11Slot(PK11_ReferenceSlot(tpm_slot_.get()))); + } - if (test_slot_) - return PK11_ReferenceSlot(test_slot_); + ScopedPK11Slot GetSystemNSSKeySlot( + const base::Callback<void(ScopedPK11Slot)>& callback) { + DCHECK(thread_checker_.CalledOnValidThread()); + // TODO(mattm): chromeos::TPMTokenloader always calls + // InitializeTPMTokenAndSystemSlot with slot 0. If the system slot is + // disabled, tpm_slot_ will be the first user's slot instead. Can that be + // detected and return NULL instead? -#if defined(OS_CHROMEOS) - if (tpm_token_enabled_for_nss_) { - if (IsTPMTokenReady(base::Closure())) { - return PK11_ReferenceSlot(tpm_slot_); - } else { - // If we were supposed to get the hardware token, but were - // unable to, return NULL rather than fall back to sofware. - return NULL; - } + base::Closure wrapped_callback; + if (!callback.is_null()) { + wrapped_callback = + base::Bind(&NSSInitSingleton::GetSystemNSSKeySlotCallback, + base::Unretained(this) /* singleton is leaky */, + callback); } -#endif - // If we weren't supposed to enable the TPM for NSS, then return - // the software slot. - if (software_slot_) - return PK11_ReferenceSlot(software_slot_); - return PK11_GetInternalKeySlot(); + if (IsTPMTokenReady(wrapped_callback)) + return ScopedPK11Slot(PK11_ReferenceSlot(tpm_slot_.get())); + return ScopedPK11Slot(); } +#endif #if defined(USE_NSS) base::Lock* write_lock() { @@ -671,11 +647,7 @@ class NSSInitSingleton { : tpm_token_enabled_for_nss_(false), initializing_tpm_token_(false), chaps_module_(NULL), - software_slot_(NULL), - test_slot_(NULL), - tpm_slot_(NULL), - root_(NULL), - chromeos_user_logged_in_(false) { + root_(NULL) { base::TimeTicks start_time = base::TimeTicks::Now(); // It's safe to construct on any thread, since LazyInstance will prevent any @@ -776,12 +748,12 @@ class NSSInitSingleton { 0, NSS_USE_ALG_IN_CERT_SIGNATURE); // The UMA bit is conditionally set for this histogram in - // chrome/common/startup_metric_utils.cc . - HISTOGRAM_CUSTOM_TIMES("Startup.SlowStartupNSSInit", - base::TimeTicks::Now() - start_time, - base::TimeDelta::FromMilliseconds(10), - base::TimeDelta::FromHours(1), - 50); + // components/startup_metric_utils.cc . + LOCAL_HISTOGRAM_CUSTOM_TIMES("Startup.SlowStartupNSSInit", + base::TimeTicks::Now() - start_time, + base::TimeDelta::FromMilliseconds(10), + base::TimeDelta::FromHours(1), + 50); } // NOTE(willchan): We don't actually execute this code since we leak NSS to @@ -791,16 +763,7 @@ class NSSInitSingleton { #if defined(OS_CHROMEOS) STLDeleteValues(&chromeos_user_map_); #endif - if (tpm_slot_) { - PK11_FreeSlot(tpm_slot_); - tpm_slot_ = NULL; - } - if (software_slot_) { - SECMOD_CloseUserDB(software_slot_); - PK11_FreeSlot(software_slot_); - software_slot_ = NULL; - } - CloseTestNSSDB(); + tpm_slot_.reset(); if (root_) { SECMOD_UnloadUserModule(root_); SECMOD_DestroyModule(root_); @@ -862,23 +825,6 @@ class NSSInitSingleton { } #endif - static PK11SlotInfo* OpenUserDB(const base::FilePath& path, - const char* description) { - const std::string modspec = - base::StringPrintf("configDir='sql:%s' tokenDescription='%s'", - path.value().c_str(), description); - PK11SlotInfo* db_slot = SECMOD_OpenUserDB(modspec.c_str()); - if (db_slot) { - if (PK11_NeedUserInit(db_slot)) - PK11_InitPin(db_slot, NULL, NULL); - } - else { - LOG(ERROR) << "Error opening persistent database (" << modspec - << "): " << GetNSSErrorMessage(); - } - return db_slot; - } - static void DisableAESNIIfNeeded() { if (NSS_VersionCheck("3.15") && !NSS_VersionCheck("3.15.4")) { // Some versions of NSS have a bug that causes AVX instructions to be @@ -902,14 +848,12 @@ class NSSInitSingleton { typedef std::vector<base::Closure> TPMReadyCallbackList; TPMReadyCallbackList tpm_ready_callback_list_; SECMODModule* chaps_module_; - PK11SlotInfo* software_slot_; - PK11SlotInfo* test_slot_; - PK11SlotInfo* tpm_slot_; + crypto::ScopedPK11Slot tpm_slot_; SECMODModule* root_; - bool chromeos_user_logged_in_; #if defined(OS_CHROMEOS) typedef std::map<std::string, ChromeOSUserData*> ChromeOSUserMap; ChromeOSUserMap chromeos_user_map_; + ScopedPK11Slot test_system_slot_; #endif #if defined(USE_NSS) // TODO(davidben): When https://bugzilla.mozilla.org/show_bug.cgi?id=564011 @@ -927,9 +871,24 @@ base::LazyInstance<NSSInitSingleton>::Leaky g_nss_singleton = LAZY_INSTANCE_INITIALIZER; } // namespace -const char kTestTPMTokenName[] = "Test DB"; - #if defined(USE_NSS) +ScopedPK11Slot OpenSoftwareNSSDB(const base::FilePath& path, + const std::string& description) { + const std::string modspec = + base::StringPrintf("configDir='sql:%s' tokenDescription='%s'", + path.value().c_str(), + description.c_str()); + PK11SlotInfo* db_slot = SECMOD_OpenUserDB(modspec.c_str()); + if (db_slot) { + if (PK11_NeedUserInit(db_slot)) + PK11_InitPin(db_slot, NULL, NULL); + } else { + LOG(ERROR) << "Error opening persistent database (" << modspec + << "): " << GetNSSErrorMessage(); + } + return ScopedPK11Slot(db_slot); +} + void EarlySetupForNSSInit() { base::FilePath database_dir = GetInitialConfigDirectory(); if (!database_dir.empty()) @@ -1028,19 +987,6 @@ bool CheckNSSVersion(const char* version) { } #if defined(USE_NSS) -ScopedTestNSSDB::ScopedTestNSSDB() - : is_open_(g_nss_singleton.Get().OpenTestNSSDB()) { -} - -ScopedTestNSSDB::~ScopedTestNSSDB() { - // Don't close when NSS is < 3.15.1, because it would require an additional - // sleep for 1 second after closing the database, due to - // http://bugzil.la/875601. - if (NSS_VersionCheck("3.15.1")) { - g_nss_singleton.Get().CloseTestNSSDB(); - } -} - base::Lock* GetNSSWriteLock() { return g_nss_singleton.Get().write_lock(); } @@ -1066,12 +1012,16 @@ AutoSECMODListReadLock::AutoSECMODListReadLock() AutoSECMODListReadLock::~AutoSECMODListReadLock() { SECMOD_ReleaseReadLock(lock_); } - #endif // defined(USE_NSS) #if defined(OS_CHROMEOS) -void OpenPersistentNSSDB() { - g_nss_singleton.Get().OpenPersistentNSSDB(); +ScopedPK11Slot GetSystemNSSKeySlot( + const base::Callback<void(ScopedPK11Slot)>& callback) { + return g_nss_singleton.Get().GetSystemNSSKeySlot(callback); +} + +void SetSystemKeySlotForTesting(ScopedPK11Slot slot) { + g_nss_singleton.Get().SetSystemKeySlotForTesting(slot.Pass()); } void EnableTPMTokenForNSS() { @@ -1086,59 +1036,54 @@ bool IsTPMTokenReady(const base::Closure& callback) { return g_nss_singleton.Get().IsTPMTokenReady(callback); } -void InitializeTPMToken(int token_slot_id, - const base::Callback<void(bool)>& callback) { - g_nss_singleton.Get().InitializeTPMToken(token_slot_id, callback); +void InitializeTPMTokenAndSystemSlot( + int token_slot_id, + const base::Callback<void(bool)>& callback) { + g_nss_singleton.Get().InitializeTPMTokenAndSystemSlot(token_slot_id, + callback); } -ScopedTestNSSChromeOSUser::ScopedTestNSSChromeOSUser( - const std::string& username_hash) - : username_hash_(username_hash), constructed_successfully_(false) { - if (!temp_dir_.CreateUniqueTempDir()) - return; - constructed_successfully_ = - InitializeNSSForChromeOSUser(username_hash, - username_hash, - false /* is_primary_user */, - temp_dir_.path()); +bool InitializeNSSForChromeOSUser(const std::string& username_hash, + const base::FilePath& path) { + return g_nss_singleton.Get().InitializeNSSForChromeOSUser(username_hash, + path); } -ScopedTestNSSChromeOSUser::~ScopedTestNSSChromeOSUser() { - if (constructed_successfully_) - g_nss_singleton.Get().CloseTestChromeOSUser(username_hash_); +bool ShouldInitializeTPMForChromeOSUser(const std::string& username_hash) { + return g_nss_singleton.Get().ShouldInitializeTPMForChromeOSUser( + username_hash); } -void ScopedTestNSSChromeOSUser::FinishInit() { - InitializePrivateSoftwareSlotForChromeOSUser(username_hash_); +void WillInitializeTPMForChromeOSUser(const std::string& username_hash) { + g_nss_singleton.Get().WillInitializeTPMForChromeOSUser(username_hash); } -bool InitializeNSSForChromeOSUser( - const std::string& email, - const std::string& username_hash, - bool is_primary_user, - const base::FilePath& path) { - return g_nss_singleton.Get().InitializeNSSForChromeOSUser( - email, username_hash, is_primary_user, path); -} void InitializeTPMForChromeOSUser( const std::string& username_hash, CK_SLOT_ID slot_id) { g_nss_singleton.Get().InitializeTPMForChromeOSUser(username_hash, slot_id); } + void InitializePrivateSoftwareSlotForChromeOSUser( const std::string& username_hash) { g_nss_singleton.Get().InitializePrivateSoftwareSlotForChromeOSUser( username_hash); } + ScopedPK11Slot GetPublicSlotForChromeOSUser(const std::string& username_hash) { return g_nss_singleton.Get().GetPublicSlotForChromeOSUser(username_hash); } + ScopedPK11Slot GetPrivateSlotForChromeOSUser( const std::string& username_hash, const base::Callback<void(ScopedPK11Slot)>& callback) { return g_nss_singleton.Get().GetPrivateSlotForChromeOSUser(username_hash, callback); } + +void CloseChromeOSUserForTesting(const std::string& username_hash) { + g_nss_singleton.Get().CloseChromeOSUserForTesting(username_hash); +} #endif // defined(OS_CHROMEOS) base::Time PRTimeToBaseTime(PRTime prtime) { @@ -1150,12 +1095,10 @@ PRTime BaseTimeToPRTime(base::Time time) { return time.ToInternalValue() - base::Time::UnixEpoch().ToInternalValue(); } -PK11SlotInfo* GetPublicNSSKeySlot() { - return g_nss_singleton.Get().GetPublicNSSKeySlot(); -} - -PK11SlotInfo* GetPrivateNSSKeySlot() { - return g_nss_singleton.Get().GetPrivateNSSKeySlot(); +#if !defined(OS_CHROMEOS) +PK11SlotInfo* GetPersistentNSSKeySlot() { + return g_nss_singleton.Get().GetPersistentNSSKeySlot(); } +#endif } // namespace crypto diff --git a/chromium/crypto/nss_util.h b/chromium/crypto/nss_util.h index e94c4f6daca..56fdfa6b659 100644 --- a/chromium/crypto/nss_util.h +++ b/chromium/crypto/nss_util.h @@ -9,7 +9,6 @@ #include "base/basictypes.h" #include "base/callback.h" #include "base/compiler_specific.h" -#include "base/files/scoped_temp_dir.h" #include "crypto/crypto_export.h" namespace base { @@ -23,9 +22,6 @@ class Time; // initialization functions. namespace crypto { -// The TPMToken name used for the NSS slot opened by ScopedTestNSSDB. -CRYPTO_EXPORT extern const char kTestTPMTokenName[]; - #if defined(USE_NSS) // EarlySetupForNSSInit performs lightweight setup which must occur before the // process goes multithreaded. This does not initialise NSS. For test, see @@ -95,14 +91,9 @@ CRYPTO_EXPORT void LoadNSSLibraries(); bool CheckNSSVersion(const char* version); #if defined(OS_CHROMEOS) -// Open the r/w nssdb that's stored inside the user's encrypted home -// directory. This is the default slot returned by -// GetPublicNSSKeySlot(). -CRYPTO_EXPORT void OpenPersistentNSSDB(); - -// Indicates that NSS should load the Chaps library so that we -// can access the TPM through NSS. Once this is called, -// GetPrivateNSSKeySlot() will return the TPM slot if one was found. +// Indicates that NSS should use the Chaps library so that we +// can access the TPM through NSS. InitializeTPMTokenAndSystemSlot and +// InitializeTPMForChromeOSUser must still be called to load the slots. CRYPTO_EXPORT void EnableTPMTokenForNSS(); // Returns true if EnableTPMTokenForNSS has been called. @@ -118,34 +109,14 @@ CRYPTO_EXPORT bool IsTPMTokenEnabledForNSS(); CRYPTO_EXPORT bool IsTPMTokenReady(const base::Closure& callback) WARN_UNUSED_RESULT; -// Initialize the TPM token. The |callback| will run on the same thread with -// true if the token and slot were successfully loaded or were already -// initialized. |callback| will be passed false if loading failed. -// Once called, InitializeTPMToken must not be called again until the |callback| -// has been run. -CRYPTO_EXPORT void InitializeTPMToken( - int token_slot_id, +// Initialize the TPM token and system slot. The |callback| will run on the same +// thread with true if the token and slot were successfully loaded or were +// already initialized. |callback| will be passed false if loading failed. Once +// called, InitializeTPMTokenAndSystemSlot must not be called again until the +// |callback| has been run. +CRYPTO_EXPORT void InitializeTPMTokenAndSystemSlot( + int system_slot_id, const base::Callback<void(bool)>& callback); - -// Exposed for unittests only. -class CRYPTO_EXPORT_PRIVATE ScopedTestNSSChromeOSUser { - public: - explicit ScopedTestNSSChromeOSUser(const std::string& username_hash); - ~ScopedTestNSSChromeOSUser(); - - std::string username_hash() const { return username_hash_; } - bool constructed_successfully() const { return constructed_successfully_; } - - // Completes initialization of user. Causes any waiting private slot callbacks - // to run. - void FinishInit(); - - private: - const std::string username_hash_; - base::ScopedTempDir temp_dir_; - bool constructed_successfully_; - DISALLOW_COPY_AND_ASSIGN(ScopedTestNSSChromeOSUser); -}; #endif // Convert a NSS PRTime value into a base::Time object. @@ -157,23 +128,6 @@ CRYPTO_EXPORT base::Time PRTimeToBaseTime(int64 prtime); CRYPTO_EXPORT int64 BaseTimeToPRTime(base::Time time); #if defined(USE_NSS) -// Exposed for unittests only. -// TODO(mattm): When NSS 3.14 is the minimum version required, -// switch back to using a separate user DB for each test. -// Because of https://bugzilla.mozilla.org/show_bug.cgi?id=588269 , the -// opened user DB is not automatically closed. -class CRYPTO_EXPORT_PRIVATE ScopedTestNSSDB { - public: - ScopedTestNSSDB(); - ~ScopedTestNSSDB(); - - bool is_open() { return is_open_; } - - private: - bool is_open_; - DISALLOW_COPY_AND_ASSIGN(ScopedTestNSSDB); -}; - // NSS has a bug which can cause a deadlock or stall in some cases when writing // to the certDB and keyDB. It also has a bug which causes concurrent key pair // generations to scribble over each other. To work around this, we synchronize @@ -194,7 +148,6 @@ class CRYPTO_EXPORT AutoNSSWriteLock { base::Lock *lock_; DISALLOW_COPY_AND_ASSIGN(AutoNSSWriteLock); }; - #endif // defined(USE_NSS) } // namespace crypto diff --git a/chromium/crypto/nss_util_internal.h b/chromium/crypto/nss_util_internal.h index 262a59a1ba9..f321343d956 100644 --- a/chromium/crypto/nss_util_internal.h +++ b/chromium/crypto/nss_util_internal.h @@ -21,17 +21,18 @@ class FilePath; namespace crypto { -// Returns a reference to the default NSS key slot for storing -// public-key data only (e.g. server certs). Caller must release -// returned reference with PK11_FreeSlot. -CRYPTO_EXPORT PK11SlotInfo* GetPublicNSSKeySlot() WARN_UNUSED_RESULT; - -// Returns a reference to the default slot for storing private-key and -// mixed private-key/public-key data. Returns a hardware (TPM) NSS -// key slot if on ChromeOS and EnableTPMForNSS() has been called -// successfully. Caller must release returned reference with -// PK11_FreeSlot. -CRYPTO_EXPORT PK11SlotInfo* GetPrivateNSSKeySlot() WARN_UNUSED_RESULT; +// Opens an NSS software database in folder |path|, with the (potentially) +// user-visible description |description|. Returns the slot for the opened +// database, or NULL if the database could not be opened. +CRYPTO_EXPORT_PRIVATE ScopedPK11Slot + OpenSoftwareNSSDB(const base::FilePath& path, + const std::string& description); + +#if !defined(OS_CHROMEOS) +// Returns a reference to the default NSS key slot for storing persistent data. +// Caller must release returned reference with PK11_FreeSlot. +CRYPTO_EXPORT PK11SlotInfo* GetPersistentNSSKeySlot() WARN_UNUSED_RESULT; +#endif // A helper class that acquires the SECMOD list read lock while the // AutoSECMODListReadLock is in scope. @@ -46,13 +47,38 @@ class CRYPTO_EXPORT AutoSECMODListReadLock { }; #if defined(OS_CHROMEOS) +// Returns a reference to the system-wide TPM slot if it is loaded. If it is not +// loaded and |callback| is non-null, the |callback| will be run once the slot +// is loaded. +CRYPTO_EXPORT ScopedPK11Slot GetSystemNSSKeySlot( + const base::Callback<void(ScopedPK11Slot)>& callback) WARN_UNUSED_RESULT; + +// Sets the test system slot to |slot|, which means that |slot| will be exposed +// through |GetSystemNSSKeySlot| and |IsTPMTokenReady| will return true. +// |InitializeTPMTokenAndSystemSlot|, which triggers the TPM initialization, +// does not have to be called if the test system slot is set. +// This must must not be called consecutively with a |slot| != NULL. If |slot| +// is NULL, the test system slot is unset. +CRYPTO_EXPORT_PRIVATE void SetSystemKeySlotForTesting(ScopedPK11Slot slot); + // Prepare per-user NSS slot mapping. It is safe to call this function multiple // times. Returns true if the user was added, or false if it already existed. CRYPTO_EXPORT bool InitializeNSSForChromeOSUser( - const std::string& email, const std::string& username_hash, - bool is_primary_user, - const base::FilePath& path) WARN_UNUSED_RESULT; + const base::FilePath& path); + +// Returns whether TPM for ChromeOS user still needs initialization. If +// true is returned, the caller can proceed to initialize TPM slot for the +// user, but should call |WillInitializeTPMForChromeOSUser| first. +// |InitializeNSSForChromeOSUser| must have been called first. +CRYPTO_EXPORT bool ShouldInitializeTPMForChromeOSUser( + const std::string& username_hash) WARN_UNUSED_RESULT; + +// Makes |ShouldInitializeTPMForChromeOSUser| start returning false. +// Should be called before starting TPM initialization for the user. +// Assumes |InitializeNSSForChromeOSUser| had already been called. +CRYPTO_EXPORT void WillInitializeTPMForChromeOSUser( + const std::string& username_hash); // Use TPM slot |slot_id| for user. InitializeNSSForChromeOSUser must have been // called first. @@ -75,6 +101,11 @@ CRYPTO_EXPORT ScopedPK11Slot GetPublicSlotForChromeOSUser( CRYPTO_EXPORT ScopedPK11Slot GetPrivateSlotForChromeOSUser( const std::string& username_hash, const base::Callback<void(ScopedPK11Slot)>& callback) WARN_UNUSED_RESULT; + +// Closes the NSS DB for |username_hash| that was previously opened by the +// *Initialize*ForChromeOSUser functions. +CRYPTO_EXPORT_PRIVATE void CloseChromeOSUserForTesting( + const std::string& username_hash); #endif // defined(OS_CHROMEOS) } // namespace crypto diff --git a/chromium/crypto/nss_util_unittest.cc b/chromium/crypto/nss_util_unittest.cc index b68788513c6..28591916d3f 100644 --- a/chromium/crypto/nss_util_unittest.cc +++ b/chromium/crypto/nss_util_unittest.cc @@ -19,14 +19,17 @@ TEST(NSSUtilTest, PRTimeConversion) { prxtime.tm_params.tp_gmt_offset = 0; prxtime.tm_params.tp_dst_offset = 0; base::Time::Exploded exploded; - prxtime.tm_year = exploded.year = 2011; + exploded.year = prxtime.tm_year = 2011; exploded.month = 12; prxtime.tm_month = 11; - prxtime.tm_wday = exploded.day_of_week = 0; // Should be unusued. - prxtime.tm_mday = exploded.day_of_month = 10; - prxtime.tm_hour = exploded.hour = 2; - prxtime.tm_min = exploded.minute = 52; - prxtime.tm_sec = exploded.second = 19; + // PRExplodedTime::tm_wday is a smaller type than Exploded::day_of_week, so + // assigning the two in this order instead of the reverse avoids potential + // warnings about type downcasting. + exploded.day_of_week = prxtime.tm_wday = 0; // Should be unused. + exploded.day_of_month = prxtime.tm_mday = 10; + exploded.hour = prxtime.tm_hour = 2; + exploded.minute = prxtime.tm_min = 52; + exploded.second = prxtime.tm_sec = 19; exploded.millisecond = 342; prxtime.tm_usec = 342000; diff --git a/chromium/crypto/openssl_bio_string_unittest.cc b/chromium/crypto/openssl_bio_string_unittest.cc index 39d3a9aeaed..9dfa0e70f73 100644 --- a/chromium/crypto/openssl_bio_string_unittest.cc +++ b/chromium/crypto/openssl_bio_string_unittest.cc @@ -6,39 +6,34 @@ #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()), BIO_printf(bio.get(), "a %s\nb %i\n", "one", 2)); EXPECT_EQ(expected1, s); - EXPECT_EQ(static_cast<int>(expected1.size()), BIO_tell(bio.get())); EXPECT_EQ(1, BIO_flush(bio.get())); - EXPECT_EQ(-1, BIO_seek(bio.get(), 0)); EXPECT_EQ(expected1, s); EXPECT_EQ(static_cast<int>(expected2.size()), BIO_write(bio.get(), expected2.data(), expected2.size())); EXPECT_EQ(expected1 + expected2, s); - EXPECT_EQ(static_cast<int>(expected1.size() + expected2.size()), - BIO_tell(bio.get())); EXPECT_EQ(static_cast<int>(expected3.size()), BIO_puts(bio.get(), expected3.c_str())); EXPECT_EQ(expected1 + expected2 + expected3, s); - EXPECT_EQ(static_cast<int>(expected1.size() + expected2.size() + - expected3.size()), - BIO_tell(bio.get())); } EXPECT_EQ(expected1 + expected2 + expected3, s); } @@ -48,7 +43,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 +59,5 @@ TEST(OpenSSLBIOString, TestReset) { } EXPECT_EQ(expected2, s); } + +} // namespace crypto diff --git a/chromium/crypto/openssl_util.cc b/chromium/crypto/openssl_util.cc index 34af810c1d0..f41b55a8fff 100644 --- a/chromium/crypto/openssl_util.cc +++ b/chromium/crypto/openssl_util.cc @@ -6,6 +6,7 @@ #include <openssl/err.h> #include <openssl/ssl.h> +#include <openssl/cpu.h> #include "base/logging.h" #include "base/memory/scoped_vector.h" @@ -16,14 +17,16 @@ #if defined(OS_ANDROID) && defined(ARCH_CPU_ARMEL) #include <cpu-features.h> +#include "base/cpu.h" #endif namespace crypto { namespace { -unsigned long CurrentThreadId() { - return static_cast<unsigned long>(base::PlatformThread::CurrentId()); +void CurrentThreadId(CRYPTO_THREADID* id) { + CRYPTO_THREADID_set_numeric( + id, static_cast<unsigned long>(base::PlatformThread::CurrentId())); } // Singleton for initializing and cleaning up the OpenSSL library. @@ -47,19 +50,21 @@ class OpenSSLInitSingleton { OpenSSLInitSingleton() { SSL_load_error_strings(); SSL_library_init(); - OpenSSL_add_all_algorithms(); int num_locks = CRYPTO_num_locks(); locks_.reserve(num_locks); for (int i = 0; i < num_locks; ++i) locks_.push_back(new base::Lock()); CRYPTO_set_locking_callback(LockingCallback); - CRYPTO_set_id_callback(CurrentThreadId); + CRYPTO_THREADID_set_callback(CurrentThreadId); #if defined(OS_ANDROID) && defined(ARCH_CPU_ARMEL) const bool has_neon = (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) != 0; if (has_neon) CRYPTO_set_NEON_capable(1); + // See https://code.google.com/p/chromium/issues/detail?id=341598 + base::CPU cpu; + CRYPTO_set_NEON_functional(!cpu.has_broken_neon()); #endif } diff --git a/chromium/crypto/openssl_util.h b/chromium/crypto/openssl_util.h index bf83e470eb3..2743883dc17 100644 --- a/chromium/crypto/openssl_util.h +++ b/chromium/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/chromium/crypto/p224.cc b/chromium/crypto/p224.cc index ac0a081037f..5f76fbc259b 100644 --- a/chromium/crypto/p224.cc +++ b/chromium/crypto/p224.cc @@ -149,7 +149,7 @@ void ReduceLarge(FieldElement* out, LargeFieldElement* inptr) { // Eliminate the term at 2*224 that we introduced while keeping the same // value mod p. in[0] -= in[8]; // reflection off the "+1" term of p. - (*out)[3] += static_cast<uint32>(in[8] & 0xffff) << 12; // "-2**96" term + (*out)[3] += static_cast<uint32>(in[8] & 0xffff) << 12; // "-2**96" term (*out)[4] += static_cast<uint32>(in[8] >> 16); // rest of "-2**96" term // in[0] < 2**64 // out[3] < 2**29 @@ -638,7 +638,7 @@ void Put224Bits(uint32* out, const uint32* in) { out[0] = HostToNet32((in[6] >> 24) | (in[7] << 4)); } -} // anonymous namespace +} // anonymous namespace namespace crypto { diff --git a/chromium/crypto/p224_spake_unittest.cc b/chromium/crypto/p224_spake_unittest.cc index ca35f7245b9..589cdbfcf0d 100644 --- a/chromium/crypto/p224_spake_unittest.cc +++ b/chromium/crypto/p224_spake_unittest.cc @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <string> #include <crypto/p224_spake.h> #include "base/logging.h" @@ -13,7 +14,6 @@ namespace { bool RunExchange(P224EncryptedKeyExchange* client, P224EncryptedKeyExchange* server) { - for (;;) { std::string client_message, server_message; client_message = client->GetMessage(); diff --git a/chromium/crypto/rsa_private_key.h b/chromium/crypto/rsa_private_key.h index cb190677b16..221e341a6fe 100644 --- a/chromium/crypto/rsa_private_key.h +++ b/chromium/crypto/rsa_private_key.h @@ -216,6 +216,12 @@ class CRYPTO_EXPORT RSAPrivateKey { static RSAPrivateKey* FindFromPublicKeyInfoInSlot( const std::vector<uint8>& input, PK11SlotInfo* slot); +#elif defined(USE_OPENSSL) + // Create a new instance from an existing EVP_PKEY, taking a + // reference to it. |key| must be an RSA key. Returns NULL on + // failure. + static RSAPrivateKey* CreateFromKey(EVP_PKEY* key); + #endif #if defined(USE_OPENSSL) diff --git a/chromium/crypto/rsa_private_key_nss_unittest.cc b/chromium/crypto/rsa_private_key_nss_unittest.cc index 66d352a0bd2..b91b431c3ee 100644 --- a/chromium/crypto/rsa_private_key_nss_unittest.cc +++ b/chromium/crypto/rsa_private_key_nss_unittest.cc @@ -8,7 +8,7 @@ #include <pk11pub.h> #include "base/memory/scoped_ptr.h" -#include "crypto/nss_util.h" +#include "crypto/scoped_test_nss_db.h" #include "testing/gtest/include/gtest/gtest.h" namespace crypto { @@ -18,39 +18,12 @@ class RSAPrivateKeyNSSTest : public testing::Test { RSAPrivateKeyNSSTest() {} virtual ~RSAPrivateKeyNSSTest() {} - virtual void SetUp() { -#if defined(OS_CHROMEOS) - OpenPersistentNSSDB(); -#endif - } - private: ScopedTestNSSDB test_nssdb_; DISALLOW_COPY_AND_ASSIGN(RSAPrivateKeyNSSTest); }; -TEST_F(RSAPrivateKeyNSSTest, CreateFromKeyTest) { - scoped_ptr<crypto::RSAPrivateKey> key_pair(RSAPrivateKey::Create(256)); - - scoped_ptr<crypto::RSAPrivateKey> key_copy( - RSAPrivateKey::CreateFromKey(key_pair->key())); - ASSERT_TRUE(key_copy.get()); - - std::vector<uint8> privkey; - std::vector<uint8> pubkey; - ASSERT_TRUE(key_pair->ExportPrivateKey(&privkey)); - ASSERT_TRUE(key_pair->ExportPublicKey(&pubkey)); - - std::vector<uint8> privkey_copy; - std::vector<uint8> pubkey_copy; - ASSERT_TRUE(key_copy->ExportPrivateKey(&privkey_copy)); - ASSERT_TRUE(key_copy->ExportPublicKey(&pubkey_copy)); - - ASSERT_EQ(privkey, privkey_copy); - ASSERT_EQ(pubkey, pubkey_copy); -} - TEST_F(RSAPrivateKeyNSSTest, FindFromPublicKey) { // Create a keypair, which will put the keys in the user's NSSDB. scoped_ptr<crypto::RSAPrivateKey> key_pair(RSAPrivateKey::Create(256)); diff --git a/chromium/crypto/rsa_private_key_openssl.cc b/chromium/crypto/rsa_private_key_openssl.cc index f191e393288..053c4a2f930 100644 --- a/chromium/crypto/rsa_private_key_openssl.cc +++ b/chromium/crypto/rsa_private_key_openssl.cc @@ -4,6 +4,8 @@ #include "crypto/rsa_private_key.h" +#include <openssl/bio.h> +#include <openssl/bn.h> #include <openssl/evp.h> #include <openssl/pkcs12.h> #include <openssl/rsa.h> @@ -11,6 +13,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 +32,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 +53,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 +78,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; @@ -95,6 +98,16 @@ RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfo( return result.release(); } +// static +RSAPrivateKey* RSAPrivateKey::CreateFromKey(EVP_PKEY* key) { + DCHECK(key); + if (EVP_PKEY_type(key->type) != EVP_PKEY_RSA) + return NULL; + RSAPrivateKey* copy = new RSAPrivateKey(); + copy->key_ = EVP_PKEY_dup(key); + return copy; +} + RSAPrivateKey::RSAPrivateKey() : key_(NULL) { } @@ -106,11 +119,11 @@ RSAPrivateKey::~RSAPrivateKey() { RSAPrivateKey* RSAPrivateKey::Copy() const { scoped_ptr<RSAPrivateKey> copy(new RSAPrivateKey()); - RSA* rsa = EVP_PKEY_get1_RSA(key_); + ScopedRSA rsa(EVP_PKEY_get1_RSA(key_)); if (!rsa) return NULL; copy->key_ = EVP_PKEY_new(); - if (!EVP_PKEY_set1_RSA(copy->key_, rsa)) + if (!EVP_PKEY_set1_RSA(copy->key_, rsa.get())) return NULL; return copy.release(); } diff --git a/chromium/crypto/rsa_private_key_unittest.cc b/chromium/crypto/rsa_private_key_unittest.cc index b981bda07d4..d53d50228d2 100644 --- a/chromium/crypto/rsa_private_key_unittest.cc +++ b/chromium/crypto/rsa_private_key_unittest.cc @@ -208,168 +208,168 @@ TEST(RSAPrivateKeyUnitTest, PublicKeyTest) { // This test case verifies these two failures modes don't occur. TEST(RSAPrivateKeyUnitTest, ShortIntegers) { const uint8 short_integer_with_high_bit[] = { - 0x30, 0x82, 0x02, 0x77, 0x02, 0x01, 0x00, 0x30, - 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, - 0x02, 0x61, 0x30, 0x82, 0x02, 0x5d, 0x02, 0x01, - 0x00, 0x02, 0x81, 0x81, 0x00, 0x92, 0x59, 0x32, - 0x7d, 0x8e, 0xaf, 0x2e, 0xd5, 0xb2, 0x5c, 0x67, - 0xc8, 0x7d, 0x48, 0xb7, 0x84, 0x12, 0xd0, 0x76, - 0xda, 0xe1, 0xa3, 0x1e, 0x40, 0x01, 0x14, 0x5c, - 0xef, 0x26, 0x6e, 0x28, 0xa2, 0xf7, 0xa5, 0xb4, - 0x02, 0x37, 0xd0, 0x53, 0x10, 0xcb, 0x7c, 0x6a, - 0xf4, 0x53, 0x9f, 0xb8, 0xe0, 0x83, 0x93, 0xd1, - 0x19, 0xd8, 0x28, 0xd1, 0xd1, 0xd8, 0x87, 0x8f, - 0x92, 0xfd, 0x73, 0xc0, 0x4d, 0x3e, 0x07, 0x22, - 0x1f, 0xc1, 0x20, 0xb0, 0x70, 0xb2, 0x3b, 0xea, - 0xb1, 0xe5, 0x0a, 0xfd, 0x56, 0x49, 0x5e, 0x39, - 0x90, 0x91, 0xce, 0x04, 0x83, 0x29, 0xaa, 0xfd, - 0x12, 0xa4, 0x42, 0x26, 0x6c, 0x6e, 0x79, 0x70, - 0x77, 0x03, 0xb2, 0x07, 0x01, 0x3d, 0x85, 0x81, - 0x95, 0x9e, 0xda, 0x5a, 0xa3, 0xf4, 0x2d, 0x38, - 0x04, 0x58, 0xf5, 0x6b, 0xc9, 0xf1, 0xb5, 0x65, - 0xfe, 0x66, 0x0d, 0xa2, 0xd5, 0x02, 0x03, 0x01, - 0x00, 0x01, 0x02, 0x81, 0x80, 0x5e, 0x01, 0x5f, - 0xb6, 0x59, 0x1d, 0xdc, 0x36, 0xb6, 0x60, 0x36, - 0xe6, 0x08, 0xdb, 0xd9, 0xcd, 0xc3, 0x8c, 0x16, - 0x9c, 0x98, 0x8d, 0x7f, 0xd3, 0xdb, 0x1d, 0xaa, - 0x68, 0x8f, 0xc5, 0xf8, 0xe2, 0x5d, 0xb3, 0x19, - 0xc2, 0xc6, 0xf9, 0x51, 0x32, 0x1b, 0x93, 0x6a, - 0xdc, 0x50, 0x8e, 0xeb, 0x61, 0x84, 0x03, 0x42, - 0x30, 0x98, 0xb1, 0xf7, 0xbd, 0x14, 0x9a, 0x57, - 0x36, 0x33, 0x09, 0xd4, 0x3e, 0x90, 0xda, 0xef, - 0x09, 0x6e, 0xef, 0x49, 0xb6, 0x60, 0x68, 0x5e, - 0x54, 0x17, 0x25, 0x5b, 0x37, 0xe3, 0x35, 0x63, - 0x5b, 0x60, 0x3c, 0xbd, 0x50, 0xdf, 0x46, 0x43, - 0x08, 0xa4, 0x71, 0x21, 0xf1, 0x30, 0x71, 0xdc, - 0xda, 0xd7, 0x6f, 0xd2, 0x18, 0xbd, 0x39, 0xf1, - 0xe1, 0xbe, 0xa8, 0x8d, 0x62, 0xdf, 0xa2, 0x3e, - 0xb6, 0x15, 0x26, 0xb6, 0x57, 0xbd, 0x63, 0xdb, - 0xc1, 0x91, 0xec, 0xb8, 0x01, 0x02, 0x41, 0x00, - 0xc6, 0x1a, 0x06, 0x48, 0xf2, 0x12, 0x1c, 0x9f, - 0x74, 0x20, 0x5c, 0x85, 0xa2, 0xda, 0xe5, 0x62, - 0x96, 0x8d, 0x22, 0x7b, 0x78, 0x73, 0xea, 0xbb, - 0x9f, 0x59, 0x42, 0x13, 0x15, 0xc8, 0x11, 0x50, - 0x6c, 0x55, 0xf6, 0xdf, 0x8b, 0xfe, 0xc7, 0xdd, - 0xa8, 0xca, 0x54, 0x41, 0xe8, 0xce, 0xbe, 0x7d, - 0xbd, 0xe2, 0x13, 0x4b, 0x5b, 0x61, 0xeb, 0x69, - 0x6c, 0xb1, 0x9b, 0x28, 0x68, 0x5b, 0xd6, 0x01, - 0x02, 0x41, 0x00, 0xbd, 0x1e, 0xfe, 0x51, 0x99, - 0xb6, 0xe3, 0x84, 0xfe, 0xf1, 0x9e, 0xfd, 0x9c, - 0xe7, 0x86, 0x43, 0x68, 0x7f, 0x2f, 0x6a, 0x2a, - 0x4c, 0xae, 0xa6, 0x41, 0x1c, 0xf0, 0x10, 0x37, - 0x54, 0x23, 0xba, 0x05, 0x0d, 0x18, 0x27, 0x8d, - 0xb8, 0xe4, 0x8f, 0xf2, 0x25, 0x73, 0x8a, 0xd7, - 0x05, 0x98, 0x6b, 0x3d, 0x55, 0xb7, 0x6f, 0x7c, - 0xec, 0x77, 0x61, 0x54, 0x7b, 0xb6, 0x6b, 0x31, - 0xec, 0x94, 0xd5, 0x02, 0x41, 0x00, 0x90, 0xa2, - 0xa5, 0x9e, 0x12, 0xa7, 0x68, 0xa0, 0x7e, 0xdf, - 0xb5, 0xcd, 0x98, 0x26, 0xab, 0xbd, 0xbc, 0x5f, - 0xd5, 0x22, 0x42, 0xc2, 0x97, 0x4a, 0x5f, 0x40, - 0x82, 0xfe, 0x7e, 0x33, 0xb1, 0x78, 0x7f, 0x70, - 0x90, 0x2b, 0x8d, 0x01, 0xfb, 0x18, 0xfa, 0x48, - 0xa7, 0x15, 0xec, 0x0d, 0x2e, 0x85, 0x8d, 0xe2, - 0x86, 0xe5, 0xc9, 0x15, 0x88, 0x14, 0x53, 0xd8, - 0xa4, 0x88, 0xef, 0x10, 0xc6, 0x01, 0x02, 0x41, - 0x00, 0xba, 0xe4, 0xaf, 0x14, 0xfa, 0xdf, 0xf6, - 0xd5, 0xce, 0x8f, 0xfe, 0xbb, 0xc8, 0x5c, 0x30, - 0x9d, 0xda, 0xdd, 0x9d, 0x80, 0xc0, 0x0e, 0x89, - 0xa5, 0xb8, 0xc1, 0x1d, 0x28, 0x19, 0x55, 0x67, - 0xfd, 0x03, 0xd2, 0xdd, 0xe4, 0xf0, 0xb4, 0x20, - 0x03, 0x74, 0x9b, 0xb8, 0x24, 0x23, 0xbb, 0xde, - 0xd5, 0x53, 0x86, 0xaa, 0xc1, 0x5d, 0x65, 0xdd, - 0xcf, 0xec, 0x8a, 0x59, 0x4a, 0x73, 0xca, 0xc5, - 0x85, 0x02, 0x40, 0x00, 0xc4, 0x5e, 0x8d, 0xa4, - 0xea, 0xbb, 0x6a, 0x9b, 0xe6, 0x3a, 0x4d, 0xc1, - 0xdb, 0xe5, 0x52, 0x38, 0xf9, 0x59, 0x91, 0x2d, - 0x90, 0x82, 0xe3, 0x31, 0x1b, 0x48, 0xb7, 0x42, - 0xfa, 0x1d, 0x83, 0xd5, 0x3d, 0x02, 0xc2, 0x12, - 0x71, 0x10, 0x3a, 0xbd, 0x92, 0x8f, 0x9b, 0xa2, - 0x6b, 0x2d, 0x21, 0xa4, 0x65, 0xe9, 0xfa, 0x8c, - 0x30, 0x2a, 0x89, 0xce, 0xd0, 0xa7, 0x67, 0xd8, + 0x30, 0x82, 0x02, 0x77, 0x02, 0x01, 0x00, 0x30, + 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, + 0x02, 0x61, 0x30, 0x82, 0x02, 0x5d, 0x02, 0x01, + 0x00, 0x02, 0x81, 0x81, 0x00, 0x92, 0x59, 0x32, + 0x7d, 0x8e, 0xaf, 0x2e, 0xd5, 0xb2, 0x5c, 0x67, + 0xc8, 0x7d, 0x48, 0xb7, 0x84, 0x12, 0xd0, 0x76, + 0xda, 0xe1, 0xa3, 0x1e, 0x40, 0x01, 0x14, 0x5c, + 0xef, 0x26, 0x6e, 0x28, 0xa2, 0xf7, 0xa5, 0xb4, + 0x02, 0x37, 0xd0, 0x53, 0x10, 0xcb, 0x7c, 0x6a, + 0xf4, 0x53, 0x9f, 0xb8, 0xe0, 0x83, 0x93, 0xd1, + 0x19, 0xd8, 0x28, 0xd1, 0xd1, 0xd8, 0x87, 0x8f, + 0x92, 0xfd, 0x73, 0xc0, 0x4d, 0x3e, 0x07, 0x22, + 0x1f, 0xc1, 0x20, 0xb0, 0x70, 0xb2, 0x3b, 0xea, + 0xb1, 0xe5, 0x0a, 0xfd, 0x56, 0x49, 0x5e, 0x39, + 0x90, 0x91, 0xce, 0x04, 0x83, 0x29, 0xaa, 0xfd, + 0x12, 0xa4, 0x42, 0x26, 0x6c, 0x6e, 0x79, 0x70, + 0x77, 0x03, 0xb2, 0x07, 0x01, 0x3d, 0x85, 0x81, + 0x95, 0x9e, 0xda, 0x5a, 0xa3, 0xf4, 0x2d, 0x38, + 0x04, 0x58, 0xf5, 0x6b, 0xc9, 0xf1, 0xb5, 0x65, + 0xfe, 0x66, 0x0d, 0xa2, 0xd5, 0x02, 0x03, 0x01, + 0x00, 0x01, 0x02, 0x81, 0x80, 0x5e, 0x01, 0x5f, + 0xb6, 0x59, 0x1d, 0xdc, 0x36, 0xb6, 0x60, 0x36, + 0xe6, 0x08, 0xdb, 0xd9, 0xcd, 0xc3, 0x8c, 0x16, + 0x9c, 0x98, 0x8d, 0x7f, 0xd3, 0xdb, 0x1d, 0xaa, + 0x68, 0x8f, 0xc5, 0xf8, 0xe2, 0x5d, 0xb3, 0x19, + 0xc2, 0xc6, 0xf9, 0x51, 0x32, 0x1b, 0x93, 0x6a, + 0xdc, 0x50, 0x8e, 0xeb, 0x61, 0x84, 0x03, 0x42, + 0x30, 0x98, 0xb1, 0xf7, 0xbd, 0x14, 0x9a, 0x57, + 0x36, 0x33, 0x09, 0xd4, 0x3e, 0x90, 0xda, 0xef, + 0x09, 0x6e, 0xef, 0x49, 0xb6, 0x60, 0x68, 0x5e, + 0x54, 0x17, 0x25, 0x5b, 0x37, 0xe3, 0x35, 0x63, + 0x5b, 0x60, 0x3c, 0xbd, 0x50, 0xdf, 0x46, 0x43, + 0x08, 0xa4, 0x71, 0x21, 0xf1, 0x30, 0x71, 0xdc, + 0xda, 0xd7, 0x6f, 0xd2, 0x18, 0xbd, 0x39, 0xf1, + 0xe1, 0xbe, 0xa8, 0x8d, 0x62, 0xdf, 0xa2, 0x3e, + 0xb6, 0x15, 0x26, 0xb6, 0x57, 0xbd, 0x63, 0xdb, + 0xc1, 0x91, 0xec, 0xb8, 0x01, 0x02, 0x41, 0x00, + 0xc6, 0x1a, 0x06, 0x48, 0xf2, 0x12, 0x1c, 0x9f, + 0x74, 0x20, 0x5c, 0x85, 0xa2, 0xda, 0xe5, 0x62, + 0x96, 0x8d, 0x22, 0x7b, 0x78, 0x73, 0xea, 0xbb, + 0x9f, 0x59, 0x42, 0x13, 0x15, 0xc8, 0x11, 0x50, + 0x6c, 0x55, 0xf6, 0xdf, 0x8b, 0xfe, 0xc7, 0xdd, + 0xa8, 0xca, 0x54, 0x41, 0xe8, 0xce, 0xbe, 0x7d, + 0xbd, 0xe2, 0x13, 0x4b, 0x5b, 0x61, 0xeb, 0x69, + 0x6c, 0xb1, 0x9b, 0x28, 0x68, 0x5b, 0xd6, 0x01, + 0x02, 0x41, 0x00, 0xbd, 0x1e, 0xfe, 0x51, 0x99, + 0xb6, 0xe3, 0x84, 0xfe, 0xf1, 0x9e, 0xfd, 0x9c, + 0xe7, 0x86, 0x43, 0x68, 0x7f, 0x2f, 0x6a, 0x2a, + 0x4c, 0xae, 0xa6, 0x41, 0x1c, 0xf0, 0x10, 0x37, + 0x54, 0x23, 0xba, 0x05, 0x0d, 0x18, 0x27, 0x8d, + 0xb8, 0xe4, 0x8f, 0xf2, 0x25, 0x73, 0x8a, 0xd7, + 0x05, 0x98, 0x6b, 0x3d, 0x55, 0xb7, 0x6f, 0x7c, + 0xec, 0x77, 0x61, 0x54, 0x7b, 0xb6, 0x6b, 0x31, + 0xec, 0x94, 0xd5, 0x02, 0x41, 0x00, 0x90, 0xa2, + 0xa5, 0x9e, 0x12, 0xa7, 0x68, 0xa0, 0x7e, 0xdf, + 0xb5, 0xcd, 0x98, 0x26, 0xab, 0xbd, 0xbc, 0x5f, + 0xd5, 0x22, 0x42, 0xc2, 0x97, 0x4a, 0x5f, 0x40, + 0x82, 0xfe, 0x7e, 0x33, 0xb1, 0x78, 0x7f, 0x70, + 0x90, 0x2b, 0x8d, 0x01, 0xfb, 0x18, 0xfa, 0x48, + 0xa7, 0x15, 0xec, 0x0d, 0x2e, 0x85, 0x8d, 0xe2, + 0x86, 0xe5, 0xc9, 0x15, 0x88, 0x14, 0x53, 0xd8, + 0xa4, 0x88, 0xef, 0x10, 0xc6, 0x01, 0x02, 0x41, + 0x00, 0xba, 0xe4, 0xaf, 0x14, 0xfa, 0xdf, 0xf6, + 0xd5, 0xce, 0x8f, 0xfe, 0xbb, 0xc8, 0x5c, 0x30, + 0x9d, 0xda, 0xdd, 0x9d, 0x80, 0xc0, 0x0e, 0x89, + 0xa5, 0xb8, 0xc1, 0x1d, 0x28, 0x19, 0x55, 0x67, + 0xfd, 0x03, 0xd2, 0xdd, 0xe4, 0xf0, 0xb4, 0x20, + 0x03, 0x74, 0x9b, 0xb8, 0x24, 0x23, 0xbb, 0xde, + 0xd5, 0x53, 0x86, 0xaa, 0xc1, 0x5d, 0x65, 0xdd, + 0xcf, 0xec, 0x8a, 0x59, 0x4a, 0x73, 0xca, 0xc5, + 0x85, 0x02, 0x40, 0x00, 0xc4, 0x5e, 0x8d, 0xa4, + 0xea, 0xbb, 0x6a, 0x9b, 0xe6, 0x3a, 0x4d, 0xc1, + 0xdb, 0xe5, 0x52, 0x38, 0xf9, 0x59, 0x91, 0x2d, + 0x90, 0x82, 0xe3, 0x31, 0x1b, 0x48, 0xb7, 0x42, + 0xfa, 0x1d, 0x83, 0xd5, 0x3d, 0x02, 0xc2, 0x12, + 0x71, 0x10, 0x3a, 0xbd, 0x92, 0x8f, 0x9b, 0xa2, + 0x6b, 0x2d, 0x21, 0xa4, 0x65, 0xe9, 0xfa, 0x8c, + 0x30, 0x2a, 0x89, 0xce, 0xd0, 0xa7, 0x67, 0xd8, 0x45, 0x84, 0xb0 }; const uint8 short_integer_without_high_bit[] = { - 0x30, 0x82, 0x02, 0x76, 0x02, 0x01, 0x00, 0x30, - 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, - 0x02, 0x60, 0x30, 0x82, 0x02, 0x5c, 0x02, 0x01, - 0x00, 0x02, 0x81, 0x81, 0x00, 0xc3, 0x9e, 0x8d, - 0xc4, 0x6d, 0x38, 0xe8, 0x0e, 0x9f, 0x84, 0x03, - 0x40, 0x8e, 0x81, 0x2e, 0x56, 0x67, 0x78, 0x11, - 0x85, 0x27, 0x81, 0x52, 0xf2, 0x1b, 0x3e, 0x5b, - 0xf8, 0xab, 0xfc, 0xaf, 0xca, 0x5c, 0x26, 0xd5, - 0xfa, 0xd4, 0x55, 0x50, 0x38, 0xb9, 0x9d, 0x89, - 0x92, 0x7e, 0x34, 0xcf, 0x37, 0x82, 0x48, 0x2d, - 0xaa, 0xc4, 0x6a, 0x0e, 0x93, 0xea, 0xad, 0x8a, - 0x33, 0xf0, 0x42, 0x23, 0xe0, 0x4c, 0x98, 0xbf, - 0x01, 0x00, 0x1b, 0xfe, 0x06, 0x15, 0xc6, 0xe3, - 0x80, 0x79, 0x6d, 0xfe, 0x48, 0xcd, 0x40, 0xbb, - 0xf9, 0x58, 0xe6, 0xbf, 0xd5, 0x4c, 0x29, 0x48, - 0x53, 0x78, 0x06, 0x03, 0x0d, 0x59, 0xf5, 0x20, - 0xe0, 0xe6, 0x8c, 0xb2, 0xf5, 0xd8, 0x61, 0x52, - 0x7e, 0x40, 0x83, 0xd7, 0x69, 0xae, 0xd7, 0x75, - 0x02, 0x2d, 0x49, 0xd5, 0x15, 0x5b, 0xf1, 0xd9, - 0x4d, 0x60, 0x7d, 0x62, 0xa5, 0x02, 0x03, 0x01, - 0x00, 0x01, 0x02, 0x7f, 0x6d, 0x45, 0x23, 0xeb, - 0x95, 0x17, 0x34, 0x88, 0xf6, 0x91, 0xc7, 0x3f, - 0x48, 0x5a, 0xe0, 0x87, 0x63, 0x44, 0xae, 0x84, - 0xb2, 0x8c, 0x8a, 0xc8, 0xb2, 0x6f, 0x22, 0xf0, - 0xc5, 0x21, 0x61, 0x10, 0xa8, 0x69, 0x09, 0x1e, - 0x13, 0x7d, 0x94, 0x52, 0x1b, 0x5c, 0xe4, 0x7b, - 0xf0, 0x03, 0x8f, 0xbc, 0x72, 0x09, 0xdf, 0x78, - 0x84, 0x3e, 0xb9, 0xe5, 0xe6, 0x31, 0x0a, 0x01, - 0xf9, 0x32, 0xf8, 0xd6, 0x57, 0xa3, 0x87, 0xe6, - 0xf5, 0x98, 0xbc, 0x8e, 0x41, 0xb9, 0x50, 0x17, - 0x7b, 0xd3, 0x97, 0x5a, 0x44, 0x3a, 0xee, 0xff, - 0x6b, 0xb3, 0x3a, 0x52, 0xe7, 0xa4, 0x96, 0x9a, - 0xf6, 0x83, 0xc8, 0x97, 0x1c, 0x63, 0xa1, 0xd6, - 0xb3, 0xa8, 0xb2, 0xc7, 0x73, 0x25, 0x0f, 0x58, - 0x36, 0xb9, 0x7a, 0x47, 0xa7, 0x4d, 0x30, 0xfe, - 0x4d, 0x74, 0x56, 0xe8, 0xfb, 0xd6, 0x50, 0xe5, - 0xe0, 0x28, 0x15, 0x02, 0x41, 0x00, 0xeb, 0x15, - 0x62, 0xb6, 0x37, 0x41, 0x7c, 0xc5, 0x00, 0x22, - 0x2c, 0x5a, 0x5e, 0xe4, 0xb2, 0x11, 0x87, 0x89, - 0xad, 0xf4, 0x57, 0x68, 0x90, 0xb7, 0x9f, 0xe2, - 0x79, 0x20, 0x6b, 0x98, 0x00, 0x0d, 0x3a, 0x3b, - 0xc1, 0xcd, 0x36, 0xf9, 0x27, 0xda, 0x40, 0x36, - 0x1d, 0xb8, 0x5c, 0x96, 0xeb, 0x04, 0x08, 0xe1, - 0x3f, 0xfa, 0x94, 0x8b, 0x0f, 0xa0, 0xff, 0xc1, - 0x51, 0xea, 0x90, 0xad, 0x15, 0xc7, 0x02, 0x41, - 0x00, 0xd5, 0x06, 0x45, 0xd7, 0x55, 0x63, 0x1a, - 0xf0, 0x89, 0x81, 0xae, 0x87, 0x23, 0xa2, 0x39, - 0xfe, 0x3d, 0x82, 0xc7, 0xcb, 0x15, 0xb9, 0xe3, - 0xe2, 0x5b, 0xc6, 0xd2, 0x55, 0xdd, 0xab, 0x55, - 0x29, 0x7c, 0xda, 0x0e, 0x1c, 0x09, 0xfc, 0x73, - 0x0d, 0x01, 0xed, 0x6d, 0x2f, 0x05, 0xd0, 0xd5, - 0x1d, 0xce, 0x18, 0x7f, 0xb0, 0xc8, 0x47, 0x77, - 0xd2, 0xa9, 0x9e, 0xfc, 0x39, 0x4b, 0x3d, 0x94, - 0x33, 0x02, 0x41, 0x00, 0x8f, 0x94, 0x09, 0x2d, - 0x17, 0x44, 0x75, 0x0a, 0xf1, 0x10, 0xee, 0x1b, - 0xe7, 0xd7, 0x2f, 0xf6, 0xca, 0xdc, 0x49, 0x15, - 0x72, 0x09, 0x58, 0x51, 0xfe, 0x61, 0xd8, 0xee, - 0xf7, 0x27, 0xe7, 0xe8, 0x2c, 0x47, 0xf1, 0x0f, - 0x00, 0x63, 0x5e, 0x76, 0xcb, 0x3f, 0x02, 0x19, - 0xe6, 0xda, 0xfa, 0x01, 0x05, 0xd7, 0x65, 0x37, - 0x0b, 0x60, 0x7f, 0x94, 0x2a, 0x80, 0x8d, 0x22, - 0x81, 0x68, 0x65, 0x63, 0x02, 0x41, 0x00, 0xc2, - 0xd4, 0x18, 0xde, 0x47, 0x9e, 0xfb, 0x8d, 0x91, - 0x05, 0xc5, 0x3c, 0x9d, 0xcf, 0x8a, 0x60, 0xc7, - 0x9b, 0x2b, 0xe5, 0xc6, 0xba, 0x1b, 0xfc, 0xf3, - 0xd9, 0x54, 0x97, 0xe9, 0xc4, 0x00, 0x80, 0x90, - 0x4a, 0xd2, 0x6a, 0xbc, 0x8b, 0x62, 0x22, 0x3c, - 0x68, 0x0c, 0xda, 0xdb, 0xe3, 0xd2, 0x76, 0x8e, - 0xff, 0x03, 0x12, 0x09, 0x2a, 0xac, 0x21, 0x44, - 0xb7, 0x3e, 0x91, 0x9c, 0x09, 0xf6, 0xd7, 0x02, - 0x41, 0x00, 0xc0, 0xa1, 0xbb, 0x70, 0xdc, 0xf8, - 0xeb, 0x17, 0x61, 0xd4, 0x8c, 0x7c, 0x3b, 0x82, - 0x91, 0x58, 0xff, 0xf9, 0x19, 0xac, 0x3a, 0x73, - 0xa7, 0x20, 0xe5, 0x22, 0x02, 0xc4, 0xf6, 0xb9, - 0xb9, 0x43, 0x53, 0x35, 0x88, 0xe1, 0x05, 0xb6, - 0x43, 0x9b, 0x39, 0xc8, 0x04, 0x4d, 0x2b, 0x01, - 0xf7, 0xe6, 0x1b, 0x8d, 0x7e, 0x89, 0xe3, 0x43, - 0xd4, 0xf3, 0xab, 0x28, 0xd4, 0x5a, 0x1f, 0x20, + 0x30, 0x82, 0x02, 0x76, 0x02, 0x01, 0x00, 0x30, + 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, + 0x02, 0x60, 0x30, 0x82, 0x02, 0x5c, 0x02, 0x01, + 0x00, 0x02, 0x81, 0x81, 0x00, 0xc3, 0x9e, 0x8d, + 0xc4, 0x6d, 0x38, 0xe8, 0x0e, 0x9f, 0x84, 0x03, + 0x40, 0x8e, 0x81, 0x2e, 0x56, 0x67, 0x78, 0x11, + 0x85, 0x27, 0x81, 0x52, 0xf2, 0x1b, 0x3e, 0x5b, + 0xf8, 0xab, 0xfc, 0xaf, 0xca, 0x5c, 0x26, 0xd5, + 0xfa, 0xd4, 0x55, 0x50, 0x38, 0xb9, 0x9d, 0x89, + 0x92, 0x7e, 0x34, 0xcf, 0x37, 0x82, 0x48, 0x2d, + 0xaa, 0xc4, 0x6a, 0x0e, 0x93, 0xea, 0xad, 0x8a, + 0x33, 0xf0, 0x42, 0x23, 0xe0, 0x4c, 0x98, 0xbf, + 0x01, 0x00, 0x1b, 0xfe, 0x06, 0x15, 0xc6, 0xe3, + 0x80, 0x79, 0x6d, 0xfe, 0x48, 0xcd, 0x40, 0xbb, + 0xf9, 0x58, 0xe6, 0xbf, 0xd5, 0x4c, 0x29, 0x48, + 0x53, 0x78, 0x06, 0x03, 0x0d, 0x59, 0xf5, 0x20, + 0xe0, 0xe6, 0x8c, 0xb2, 0xf5, 0xd8, 0x61, 0x52, + 0x7e, 0x40, 0x83, 0xd7, 0x69, 0xae, 0xd7, 0x75, + 0x02, 0x2d, 0x49, 0xd5, 0x15, 0x5b, 0xf1, 0xd9, + 0x4d, 0x60, 0x7d, 0x62, 0xa5, 0x02, 0x03, 0x01, + 0x00, 0x01, 0x02, 0x7f, 0x6d, 0x45, 0x23, 0xeb, + 0x95, 0x17, 0x34, 0x88, 0xf6, 0x91, 0xc7, 0x3f, + 0x48, 0x5a, 0xe0, 0x87, 0x63, 0x44, 0xae, 0x84, + 0xb2, 0x8c, 0x8a, 0xc8, 0xb2, 0x6f, 0x22, 0xf0, + 0xc5, 0x21, 0x61, 0x10, 0xa8, 0x69, 0x09, 0x1e, + 0x13, 0x7d, 0x94, 0x52, 0x1b, 0x5c, 0xe4, 0x7b, + 0xf0, 0x03, 0x8f, 0xbc, 0x72, 0x09, 0xdf, 0x78, + 0x84, 0x3e, 0xb9, 0xe5, 0xe6, 0x31, 0x0a, 0x01, + 0xf9, 0x32, 0xf8, 0xd6, 0x57, 0xa3, 0x87, 0xe6, + 0xf5, 0x98, 0xbc, 0x8e, 0x41, 0xb9, 0x50, 0x17, + 0x7b, 0xd3, 0x97, 0x5a, 0x44, 0x3a, 0xee, 0xff, + 0x6b, 0xb3, 0x3a, 0x52, 0xe7, 0xa4, 0x96, 0x9a, + 0xf6, 0x83, 0xc8, 0x97, 0x1c, 0x63, 0xa1, 0xd6, + 0xb3, 0xa8, 0xb2, 0xc7, 0x73, 0x25, 0x0f, 0x58, + 0x36, 0xb9, 0x7a, 0x47, 0xa7, 0x4d, 0x30, 0xfe, + 0x4d, 0x74, 0x56, 0xe8, 0xfb, 0xd6, 0x50, 0xe5, + 0xe0, 0x28, 0x15, 0x02, 0x41, 0x00, 0xeb, 0x15, + 0x62, 0xb6, 0x37, 0x41, 0x7c, 0xc5, 0x00, 0x22, + 0x2c, 0x5a, 0x5e, 0xe4, 0xb2, 0x11, 0x87, 0x89, + 0xad, 0xf4, 0x57, 0x68, 0x90, 0xb7, 0x9f, 0xe2, + 0x79, 0x20, 0x6b, 0x98, 0x00, 0x0d, 0x3a, 0x3b, + 0xc1, 0xcd, 0x36, 0xf9, 0x27, 0xda, 0x40, 0x36, + 0x1d, 0xb8, 0x5c, 0x96, 0xeb, 0x04, 0x08, 0xe1, + 0x3f, 0xfa, 0x94, 0x8b, 0x0f, 0xa0, 0xff, 0xc1, + 0x51, 0xea, 0x90, 0xad, 0x15, 0xc7, 0x02, 0x41, + 0x00, 0xd5, 0x06, 0x45, 0xd7, 0x55, 0x63, 0x1a, + 0xf0, 0x89, 0x81, 0xae, 0x87, 0x23, 0xa2, 0x39, + 0xfe, 0x3d, 0x82, 0xc7, 0xcb, 0x15, 0xb9, 0xe3, + 0xe2, 0x5b, 0xc6, 0xd2, 0x55, 0xdd, 0xab, 0x55, + 0x29, 0x7c, 0xda, 0x0e, 0x1c, 0x09, 0xfc, 0x73, + 0x0d, 0x01, 0xed, 0x6d, 0x2f, 0x05, 0xd0, 0xd5, + 0x1d, 0xce, 0x18, 0x7f, 0xb0, 0xc8, 0x47, 0x77, + 0xd2, 0xa9, 0x9e, 0xfc, 0x39, 0x4b, 0x3d, 0x94, + 0x33, 0x02, 0x41, 0x00, 0x8f, 0x94, 0x09, 0x2d, + 0x17, 0x44, 0x75, 0x0a, 0xf1, 0x10, 0xee, 0x1b, + 0xe7, 0xd7, 0x2f, 0xf6, 0xca, 0xdc, 0x49, 0x15, + 0x72, 0x09, 0x58, 0x51, 0xfe, 0x61, 0xd8, 0xee, + 0xf7, 0x27, 0xe7, 0xe8, 0x2c, 0x47, 0xf1, 0x0f, + 0x00, 0x63, 0x5e, 0x76, 0xcb, 0x3f, 0x02, 0x19, + 0xe6, 0xda, 0xfa, 0x01, 0x05, 0xd7, 0x65, 0x37, + 0x0b, 0x60, 0x7f, 0x94, 0x2a, 0x80, 0x8d, 0x22, + 0x81, 0x68, 0x65, 0x63, 0x02, 0x41, 0x00, 0xc2, + 0xd4, 0x18, 0xde, 0x47, 0x9e, 0xfb, 0x8d, 0x91, + 0x05, 0xc5, 0x3c, 0x9d, 0xcf, 0x8a, 0x60, 0xc7, + 0x9b, 0x2b, 0xe5, 0xc6, 0xba, 0x1b, 0xfc, 0xf3, + 0xd9, 0x54, 0x97, 0xe9, 0xc4, 0x00, 0x80, 0x90, + 0x4a, 0xd2, 0x6a, 0xbc, 0x8b, 0x62, 0x22, 0x3c, + 0x68, 0x0c, 0xda, 0xdb, 0xe3, 0xd2, 0x76, 0x8e, + 0xff, 0x03, 0x12, 0x09, 0x2a, 0xac, 0x21, 0x44, + 0xb7, 0x3e, 0x91, 0x9c, 0x09, 0xf6, 0xd7, 0x02, + 0x41, 0x00, 0xc0, 0xa1, 0xbb, 0x70, 0xdc, 0xf8, + 0xeb, 0x17, 0x61, 0xd4, 0x8c, 0x7c, 0x3b, 0x82, + 0x91, 0x58, 0xff, 0xf9, 0x19, 0xac, 0x3a, 0x73, + 0xa7, 0x20, 0xe5, 0x22, 0x02, 0xc4, 0xf6, 0xb9, + 0xb9, 0x43, 0x53, 0x35, 0x88, 0xe1, 0x05, 0xb6, + 0x43, 0x9b, 0x39, 0xc8, 0x04, 0x4d, 0x2b, 0x01, + 0xf7, 0xe6, 0x1b, 0x8d, 0x7e, 0x89, 0xe3, 0x43, + 0xd4, 0xf3, 0xab, 0x28, 0xd4, 0x5a, 0x1f, 0x20, 0xea, 0xbe }; @@ -403,3 +403,30 @@ TEST(RSAPrivateKeyUnitTest, ShortIntegers) { ASSERT_TRUE(0 == memcmp(&output2.front(), &input2.front(), input2.size())); } + +// The following test can run if either USE_NSS or USE_OPENSSL is defined, but +// not otherwise (since it uses crypto::RSAPrivateKey::CreateFromKey). +#if defined(USE_NSS) || defined(USE_OPENSSL) +TEST(RSAPrivateKeyUnitTest, CreateFromKeyTest) { + scoped_ptr<crypto::RSAPrivateKey> key_pair( + crypto::RSAPrivateKey::Create(256)); + + scoped_ptr<crypto::RSAPrivateKey> key_copy( + crypto::RSAPrivateKey::CreateFromKey(key_pair->key())); + ASSERT_TRUE(key_copy.get()); + + std::vector<uint8> privkey; + std::vector<uint8> pubkey; + ASSERT_TRUE(key_pair->ExportPrivateKey(&privkey)); + ASSERT_TRUE(key_pair->ExportPublicKey(&pubkey)); + + std::vector<uint8> privkey_copy; + std::vector<uint8> pubkey_copy; + ASSERT_TRUE(key_copy->ExportPrivateKey(&privkey_copy)); + ASSERT_TRUE(key_copy->ExportPublicKey(&pubkey_copy)); + + ASSERT_EQ(privkey, privkey_copy); + ASSERT_EQ(pubkey, pubkey_copy); +} +#endif + diff --git a/chromium/crypto/scoped_capi_types.h b/chromium/crypto/scoped_capi_types.h index 9ab28d9aacc..ac92e394b9c 100644 --- a/chromium/crypto/scoped_capi_types.h +++ b/chromium/crypto/scoped_capi_types.h @@ -6,11 +6,11 @@ #define CRYPTO_SCOPED_CAPI_TYPES_H_ #include <windows.h> -#include <wincrypt.h> #include <algorithm> #include "base/logging.h" +#include "crypto/wincrypt_shim.h" namespace crypto { diff --git a/chromium/crypto/scoped_nss_types.h b/chromium/crypto/scoped_nss_types.h index d5aebc5dd20..fdfb83c154f 100644 --- a/chromium/crypto/scoped_nss_types.h +++ b/chromium/crypto/scoped_nss_types.h @@ -16,17 +16,17 @@ namespace crypto { template <typename Type, void (*Destroyer)(Type*)> struct NSSDestroyer { + typedef void AllowSelfReset; void operator()(Type* ptr) const { - if (ptr) - Destroyer(ptr); + Destroyer(ptr); } }; template <typename Type, void (*Destroyer)(Type*, PRBool), PRBool freeit> struct NSSDestroyer1 { + typedef void AllowSelfReset; void operator()(Type* ptr) const { - if (ptr) - Destroyer(ptr, freeit); + Destroyer(ptr, freeit); } }; diff --git a/chromium/crypto/scoped_openssl_types.h b/chromium/crypto/scoped_openssl_types.h new file mode 100644 index 00000000000..cc056e49efe --- /dev/null +++ b/chromium/crypto/scoped_openssl_types.h @@ -0,0 +1,59 @@ +// 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/bio.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 { + typedef void AllowSelfReset; + void operator()(Type* ptr) const { Destroyer(ptr); } +}; + +template <typename PointerType, void (*Destroyer)(PointerType*)> +struct ScopedOpenSSL { + typedef scoped_ptr<PointerType, OpenSSLDestroyer<PointerType, Destroyer> > + Type; +}; + +struct OpenSSLFree { + void operator()(uint8_t* ptr) const { OPENSSL_free(ptr); } +}; + +// 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<EVP_PKEY_CTX, EVP_PKEY_CTX_free>::Type ScopedEVP_PKEY_CTX; +typedef ScopedOpenSSL<RSA, RSA_free>::Type ScopedRSA; + +// The bytes must have been allocated with OPENSSL_malloc. +typedef scoped_ptr<uint8_t, OpenSSLFree> ScopedOpenSSLBytes; + +} // namespace crypto + +#endif // CRYPTO_SCOPED_OPENSSL_TYPES_H_ diff --git a/chromium/crypto/scoped_test_nss_chromeos_user.cc b/chromium/crypto/scoped_test_nss_chromeos_user.cc new file mode 100644 index 00000000000..aec25d8dff0 --- /dev/null +++ b/chromium/crypto/scoped_test_nss_chromeos_user.cc @@ -0,0 +1,37 @@ +// 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. + +#include "crypto/scoped_test_nss_chromeos_user.h" + +#include "base/logging.h" +#include "crypto/nss_util.h" +#include "crypto/nss_util_internal.h" + +namespace crypto { + +ScopedTestNSSChromeOSUser::ScopedTestNSSChromeOSUser( + const std::string& username_hash) + : username_hash_(username_hash), constructed_successfully_(false) { + if (!temp_dir_.CreateUniqueTempDir()) + return; + // This opens a software DB in the given folder. In production code that is in + // the home folder, but for testing the temp folder is used. + constructed_successfully_ = + InitializeNSSForChromeOSUser(username_hash, temp_dir_.path()); +} + +ScopedTestNSSChromeOSUser::~ScopedTestNSSChromeOSUser() { + if (constructed_successfully_) + CloseChromeOSUserForTesting(username_hash_); +} + +void ScopedTestNSSChromeOSUser::FinishInit() { + DCHECK(constructed_successfully_); + if (!ShouldInitializeTPMForChromeOSUser(username_hash_)) + return; + WillInitializeTPMForChromeOSUser(username_hash_); + InitializePrivateSoftwareSlotForChromeOSUser(username_hash_); +} + +} // namespace crypto diff --git a/chromium/crypto/scoped_test_nss_chromeos_user.h b/chromium/crypto/scoped_test_nss_chromeos_user.h new file mode 100644 index 00000000000..1638517704d --- /dev/null +++ b/chromium/crypto/scoped_test_nss_chromeos_user.h @@ -0,0 +1,43 @@ +// 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_TEST_NSS_CHROMEOS_USER_H_ +#define CRYPTO_SCOPED_TEST_NSS_CHROMEOS_USER_H_ + +#include <string> + +#include "base/files/scoped_temp_dir.h" +#include "base/macros.h" +#include "crypto/crypto_export.h" + +namespace crypto { + +// Opens a persistent NSS software database in a temporary directory for the +// user with |username_hash|. This database will be used for both the user's +// public and private slot. +class CRYPTO_EXPORT_PRIVATE ScopedTestNSSChromeOSUser { + public: + // Opens the software database and sets the public slot for the user. The + // private slot will not be initialized until FinishInit() is called. + explicit ScopedTestNSSChromeOSUser(const std::string& username_hash); + ~ScopedTestNSSChromeOSUser(); + + std::string username_hash() const { return username_hash_; } + bool constructed_successfully() const { return constructed_successfully_; } + + // Completes initialization of user. Causes any waiting private slot callbacks + // to run, see GetPrivateSlotForChromeOSUser(). + void FinishInit(); + + private: + const std::string username_hash_; + base::ScopedTempDir temp_dir_; + bool constructed_successfully_; + + DISALLOW_COPY_AND_ASSIGN(ScopedTestNSSChromeOSUser); +}; + +} // namespace crypto + +#endif // CRYPTO_SCOPED_TEST_NSS_CHROMEOS_USER_H_ diff --git a/chromium/crypto/scoped_test_nss_db.cc b/chromium/crypto/scoped_test_nss_db.cc new file mode 100644 index 00000000000..452c26d73e5 --- /dev/null +++ b/chromium/crypto/scoped_test_nss_db.cc @@ -0,0 +1,53 @@ +// 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. + +#include "crypto/scoped_test_nss_db.h" + +#include "base/logging.h" +#include "base/threading/thread_restrictions.h" +#include "crypto/nss_util.h" +#include "crypto/nss_util_internal.h" + +namespace crypto { + +ScopedTestNSSDB::ScopedTestNSSDB() { + EnsureNSSInit(); + // NSS is allowed to do IO on the current thread since dispatching + // to a dedicated thread would still have the affect of blocking + // the current thread, due to NSS's internal locking requirements + base::ThreadRestrictions::ScopedAllowIO allow_io; + + if (!temp_dir_.CreateUniqueTempDir()) + return; + + const char kTestDescription[] = "Test DB"; + slot_ = OpenSoftwareNSSDB(temp_dir_.path(), kTestDescription); +} + +ScopedTestNSSDB::~ScopedTestNSSDB() { + // Don't close when NSS is < 3.15.1, because it would require an additional + // sleep for 1 second after closing the database, due to + // http://bugzil.la/875601. + if (!NSS_VersionCheck("3.15.1")) { + LOG(ERROR) << "NSS version is < 3.15.1, test DB will not be closed."; + temp_dir_.Take(); + return; + } + + // NSS is allowed to do IO on the current thread since dispatching + // to a dedicated thread would still have the affect of blocking + // the current thread, due to NSS's internal locking requirements + base::ThreadRestrictions::ScopedAllowIO allow_io; + + if (slot_) { + SECStatus status = SECMOD_CloseUserDB(slot_.get()); + if (status != SECSuccess) + PLOG(ERROR) << "SECMOD_CloseUserDB failed: " << PORT_GetError(); + } + + if (!temp_dir_.Delete()) + LOG(ERROR) << "Could not delete temporary directory."; +} + +} // namespace crypto diff --git a/chromium/crypto/scoped_test_nss_db.h b/chromium/crypto/scoped_test_nss_db.h new file mode 100644 index 00000000000..88c2d55dbe4 --- /dev/null +++ b/chromium/crypto/scoped_test_nss_db.h @@ -0,0 +1,35 @@ +// 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_TEST_NSS_DB_H_ +#define CRYPTO_SCOPED_TEST_NSS_DB_H_ + +#include "base/files/scoped_temp_dir.h" +#include "base/macros.h" +#include "crypto/crypto_export.h" +#include "crypto/scoped_nss_types.h" + +namespace crypto { + +// Opens a persistent NSS database in a temporary directory. +// Prior NSS version 3.15.1, because of http://bugzil.la/875601 , the opened DB +// will not be closed automatically. +class CRYPTO_EXPORT_PRIVATE ScopedTestNSSDB { + public: + ScopedTestNSSDB(); + ~ScopedTestNSSDB(); + + bool is_open() const { return slot_; } + PK11SlotInfo* slot() const { return slot_.get(); } + + private: + base::ScopedTempDir temp_dir_; + ScopedPK11Slot slot_; + + DISALLOW_COPY_AND_ASSIGN(ScopedTestNSSDB); +}; + +} // namespace crypto + +#endif // CRYPTO_SCOPED_TEST_NSS_DB_H_ diff --git a/chromium/crypto/scoped_test_system_nss_key_slot.cc b/chromium/crypto/scoped_test_system_nss_key_slot.cc new file mode 100644 index 00000000000..53fbbffc1a9 --- /dev/null +++ b/chromium/crypto/scoped_test_system_nss_key_slot.cc @@ -0,0 +1,32 @@ +// 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. + +#include "crypto/scoped_test_system_nss_key_slot.h" + +#include "crypto/nss_util_internal.h" +#include "crypto/scoped_test_nss_db.h" + +namespace crypto { + +ScopedTestSystemNSSKeySlot::ScopedTestSystemNSSKeySlot() + : test_db_(new ScopedTestNSSDB) { + if (!test_db_->is_open()) + return; + SetSystemKeySlotForTesting( + ScopedPK11Slot(PK11_ReferenceSlot(test_db_->slot()))); +} + +ScopedTestSystemNSSKeySlot::~ScopedTestSystemNSSKeySlot() { + SetSystemKeySlotForTesting(ScopedPK11Slot()); +} + +bool ScopedTestSystemNSSKeySlot::ConstructedSuccessfully() const { + return test_db_->is_open(); +} + +PK11SlotInfo* ScopedTestSystemNSSKeySlot::slot() const { + return test_db_->slot(); +} + +} // namespace crypto diff --git a/chromium/crypto/scoped_test_system_nss_key_slot.h b/chromium/crypto/scoped_test_system_nss_key_slot.h new file mode 100644 index 00000000000..ac3b72c4ce0 --- /dev/null +++ b/chromium/crypto/scoped_test_system_nss_key_slot.h @@ -0,0 +1,43 @@ +// 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_TEST_SYSTEM_NSS_KEY_SLOT_H_ +#define CRYPTO_SCOPED_TEST_SYSTEM_NSS_KEY_SLOT_H_ + +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "crypto/crypto_export.h" + +// Forward declaration, from <pk11pub.h> +typedef struct PK11SlotInfoStr PK11SlotInfo; + +namespace crypto { + +class ScopedTestNSSDB; + +// Opens a persistent NSS software database in a temporary directory and sets +// the test system slot to the opened database. This helper should be created in +// tests to fake the system token that is usually provided by the Chaps module. +// |slot| is exposed through |GetSystemNSSKeySlot| and |IsTPMTokenReady| will +// return true. +// |InitializeTPMTokenAndSystemSlot|, which triggers the TPM initialization, +// does not have to be called if this helper is used. +// At most one instance of this helper must be used at a time. +class CRYPTO_EXPORT_PRIVATE ScopedTestSystemNSSKeySlot { + public: + explicit ScopedTestSystemNSSKeySlot(); + ~ScopedTestSystemNSSKeySlot(); + + bool ConstructedSuccessfully() const; + PK11SlotInfo* slot() const; + + private: + scoped_ptr<ScopedTestNSSDB> test_db_; + + DISALLOW_COPY_AND_ASSIGN(ScopedTestSystemNSSKeySlot); +}; + +} // namespace crypto + +#endif // CRYPTO_SCOPED_TEST_SYSTEM_NSS_KEY_SLOT_H_ diff --git a/chromium/crypto/secure_hash_default.cc b/chromium/crypto/secure_hash_default.cc index 7b912e1af60..1f5e59ba2ab 100644 --- a/chromium/crypto/secure_hash_default.cc +++ b/chromium/crypto/secure_hash_default.cc @@ -28,17 +28,17 @@ class SecureHashSHA256NSS : public SecureHash { } // SecureHash implementation: - virtual void Update(const void* input, size_t len) OVERRIDE { + virtual void Update(const void* input, size_t len) override { SHA256_Update(&ctx_, static_cast<const unsigned char*>(input), len); } - virtual void Finish(void* output, size_t len) OVERRIDE { + virtual void Finish(void* output, size_t len) override { SHA256_End(&ctx_, static_cast<unsigned char*>(output), NULL, static_cast<unsigned int>(len)); } - virtual bool Serialize(Pickle* pickle) OVERRIDE; - virtual bool Deserialize(PickleIterator* data_iterator) OVERRIDE; + virtual bool Serialize(Pickle* pickle) override; + virtual bool Deserialize(PickleIterator* data_iterator) override; private: SHA256Context ctx_; diff --git a/chromium/crypto/secure_hash_openssl.cc b/chromium/crypto/secure_hash_openssl.cc index 84d28a52725..61946a8da81 100644 --- a/chromium/crypto/secure_hash_openssl.cc +++ b/chromium/crypto/secure_hash_openssl.cc @@ -30,18 +30,18 @@ class SecureHashSHA256OpenSSL : public SecureHash { OPENSSL_cleanse(&ctx_, sizeof(ctx_)); } - virtual void Update(const void* input, size_t len) OVERRIDE { + virtual void Update(const void* input, size_t len) override { SHA256_Update(&ctx_, static_cast<const unsigned char*>(input), len); } - virtual void Finish(void* output, size_t len) OVERRIDE { + virtual void Finish(void* output, size_t len) override { ScopedOpenSSLSafeSizeBuffer<SHA256_DIGEST_LENGTH> result( static_cast<unsigned char*>(output), len); SHA256_Final(result.safe_buffer(), &ctx_); } - virtual bool Serialize(Pickle* pickle) OVERRIDE; - virtual bool Deserialize(PickleIterator* data_iterator) OVERRIDE; + virtual bool Serialize(Pickle* pickle) override; + virtual bool Deserialize(PickleIterator* data_iterator) override; private: SHA256_CTX ctx_; diff --git a/chromium/crypto/secure_hash_unittest.cc b/chromium/crypto/secure_hash_unittest.cc index 42b9ade3593..c21c365b1c2 100644 --- a/chromium/crypto/secure_hash_unittest.cc +++ b/chromium/crypto/secure_hash_unittest.cc @@ -4,6 +4,8 @@ #include "crypto/secure_hash.h" +#include <string> + #include "base/basictypes.h" #include "base/memory/scoped_ptr.h" #include "base/pickle.h" diff --git a/chromium/crypto/signature_creator.h b/chromium/crypto/signature_creator.h index 6074bcbe9cb..840d1ff0b80 100644 --- a/chromium/crypto/signature_creator.h +++ b/chromium/crypto/signature_creator.h @@ -5,10 +5,9 @@ #ifndef CRYPTO_SIGNATURE_CREATOR_H_ #define CRYPTO_SIGNATURE_CREATOR_H_ -#include "build/build_config.h" - #include <vector> +#include "build/build_config.h" #include "base/basictypes.h" #include "crypto/crypto_export.h" @@ -25,18 +24,27 @@ namespace crypto { class RSAPrivateKey; // 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 { public: + // The set of supported hash functions. Extend as required. + enum HashAlgorithm { + SHA1, + SHA256, + }; + ~SignatureCreator(); // Create an instance. The caller must ensure that the provided PrivateKey - // instance outlives the created SignatureCreator. - static SignatureCreator* Create(RSAPrivateKey* key); + // instance outlives the created SignatureCreator. Uses the HashAlgorithm + // 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. static bool Sign(RSAPrivateKey* key, + HashAlgorithm hash_alg, const uint8* data, int data_len, std::vector<uint8>* signature); diff --git a/chromium/crypto/signature_creator_nss.cc b/chromium/crypto/signature_creator_nss.cc index bc8dc449a43..47728b07563 100644 --- a/chromium/crypto/signature_creator_nss.cc +++ b/chromium/crypto/signature_creator_nss.cc @@ -15,6 +15,30 @@ 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() { if (sign_context_) { SGN_DestroyContext(sign_context_, PR_TRUE); @@ -23,12 +47,12 @@ SignatureCreator::~SignatureCreator() { } // static -SignatureCreator* SignatureCreator::Create(RSAPrivateKey* key) { +SignatureCreator* SignatureCreator::Create(RSAPrivateKey* key, + HashAlgorithm hash_alg) { scoped_ptr<SignatureCreator> result(new SignatureCreator); result->key_ = key; - result->sign_context_ = SGN_NewContext(SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION, - key->key()); + result->sign_context_ = SGN_NewContext(ToNSSSigOid(hash_alg), key->key()); if (!result->sign_context_) { NOTREACHED(); return NULL; @@ -45,6 +69,7 @@ SignatureCreator* SignatureCreator::Create(RSAPrivateKey* key) { // static bool SignatureCreator::Sign(RSAPrivateKey* key, + HashAlgorithm hash_alg, const uint8* data, int data_len, std::vector<uint8>* signature) { @@ -54,7 +79,7 @@ bool SignatureCreator::Sign(RSAPrivateKey* key, data_item.len = data_len; 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); if (rv != SECSuccess) { NOTREACHED(); diff --git a/chromium/crypto/signature_creator_openssl.cc b/chromium/crypto/signature_creator_openssl.cc index e46d3d002c1..7a1349b5a5a 100644 --- a/chromium/crypto/signature_creator_openssl.cc +++ b/chromium/crypto/signature_creator_openssl.cc @@ -12,33 +12,64 @@ #include "base/stl_util.h" #include "crypto/openssl_util.h" #include "crypto/rsa_private_key.h" +#include "crypto/scoped_openssl_types.h" 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 -SignatureCreator* SignatureCreator::Create(RSAPrivateKey* key) { +SignatureCreator* SignatureCreator::Create(RSAPrivateKey* key, + HashAlgorithm hash_alg) { OpenSSLErrStackTracer err_tracer(FROM_HERE); scoped_ptr<SignatureCreator> result(new SignatureCreator); 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 result.release(); } // static bool SignatureCreator::Sign(RSAPrivateKey* key, + HashAlgorithm hash_alg, const uint8* data, int data_len, std::vector<uint8>* signature) { - RSA* rsa_key = EVP_PKEY_get1_RSA(key->key()); + ScopedRSA rsa_key(EVP_PKEY_get1_RSA(key->key())); if (!rsa_key) return false; - signature->resize(RSA_size(rsa_key)); + signature->resize(RSA_size(rsa_key.get())); unsigned int len = 0; - bool success = RSA_sign(NID_sha1, data, data_len, vector_as_array(signature), - &len, rsa_key); - if (!success) { + if (!RSA_sign(ToOpenSSLDigestType(hash_alg), data, data_len, + vector_as_array(signature), &len, rsa_key.get())) { signature->clear(); return false; } diff --git a/chromium/crypto/signature_creator_unittest.cc b/chromium/crypto/signature_creator_unittest.cc index f0a888816e6..694becdcb44 100644 --- a/chromium/crypto/signature_creator_unittest.cc +++ b/chromium/crypto/signature_creator_unittest.cc @@ -7,6 +7,7 @@ #include "base/memory/scoped_ptr.h" #include "base/sha1.h" #include "crypto/rsa_private_key.h" +#include "crypto/sha2.h" #include "crypto/signature_creator.h" #include "crypto/signature_verifier.h" #include "testing/gtest/include/gtest/gtest.h" @@ -19,6 +20,12 @@ const uint8 kSHA1WithRSAAlgorithmID[] = { 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) { @@ -34,7 +41,8 @@ TEST(SignatureCreatorTest, BasicTest) { ASSERT_TRUE(key.get()); scoped_ptr<crypto::SignatureCreator> signer( - crypto::SignatureCreator::Create(key.get())); + crypto::SignatureCreator::Create(key.get(), + crypto::SignatureCreator::SHA1)); ASSERT_TRUE(signer.get()); std::string data("Hello, World!"); @@ -76,6 +84,7 @@ TEST(SignatureCreatorTest, SignDigestTest) { std::vector<uint8> signature; ASSERT_TRUE(crypto::SignatureCreator::Sign( key.get(), + crypto::SignatureCreator::SHA1, reinterpret_cast<const uint8*>(sha1.c_str()), sha1.size(), &signature)); @@ -94,3 +103,41 @@ TEST(SignatureCreatorTest, SignDigestTest) { data.size()); 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()); +} diff --git a/chromium/crypto/signature_verifier.h b/chromium/crypto/signature_verifier.h index 93591d2a82d..fbf87d4cc64 100644 --- a/chromium/crypto/signature_verifier.h +++ b/chromium/crypto/signature_verifier.h @@ -5,10 +5,9 @@ #ifndef CRYPTO_SIGNATURE_VERIFIER_H_ #define CRYPTO_SIGNATURE_VERIFIER_H_ -#include "build/build_config.h" - #include <vector> +#include "build/build_config.h" #include "base/basictypes.h" #include "crypto/crypto_export.h" diff --git a/chromium/crypto/signature_verifier_openssl.cc b/chromium/crypto/signature_verifier_openssl.cc index a85f00b491e..a855120ef83 100644 --- a/chromium/crypto/signature_verifier_openssl.cc +++ b/chromium/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 { @@ -25,13 +26,13 @@ const EVP_MD* ToOpenSSLDigest(SignatureVerifier::HashAlgorithm hash_alg) { case SignatureVerifier::SHA256: return EVP_sha256(); } - return EVP_md_null(); + return NULL; } } // 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; @@ -79,8 +80,11 @@ bool SignatureVerifier::VerifyInitRSAPSS(HashAlgorithm hash_alg, const uint8* public_key_info, int public_key_info_len) { OpenSSLErrStackTracer err_tracer(FROM_HERE); - const EVP_MD* digest = ToOpenSSLDigest(hash_alg); + const EVP_MD* const digest = ToOpenSSLDigest(hash_alg); DCHECK(digest); + if (!digest) { + return false; + } EVP_PKEY_CTX* pkey_ctx; if (!CommonInit(digest, signature, signature_len, public_key_info, @@ -91,8 +95,12 @@ bool SignatureVerifier::VerifyInitRSAPSS(HashAlgorithm hash_alg, int rv = EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING); if (rv != 1) return false; - rv = EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, - ToOpenSSLDigest(mask_hash_alg)); + const EVP_MD* const mgf_digest = ToOpenSSLDigest(mask_hash_alg); + DCHECK(mgf_digest); + if (!mgf_digest) { + return false; + } + rv = EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, mgf_digest); if (rv != 1) return false; rv = EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx, salt_len); @@ -135,13 +143,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; diff --git a/chromium/crypto/signature_verifier_unittest.cc b/chromium/crypto/signature_verifier_unittest.cc index 332979971c6..f6c42e0fdc7 100644 --- a/chromium/crypto/signature_verifier_unittest.cc +++ b/chromium/crypto/signature_verifier_unittest.cc @@ -3,6 +3,8 @@ // found in the LICENSE file. #include "crypto/signature_verifier.h" + +#include "base/numerics/safe_conversions.h" #include "testing/gtest/include/gtest/gtest.h" TEST(SignatureVerifierTest, BasicTest) { @@ -1005,36 +1007,36 @@ static bool EncodeRSAPublicKey(const std::vector<uint8>& modulus_n, public_key_info->insert(public_key_info->begin(), public_exponent_e.begin(), public_exponent_e.end()); - uint8 length = public_exponent_e.size(); - public_key_info->insert(public_key_info->begin(), length); + uint8 exponent_size = base::checked_cast<uint8>(public_exponent_e.size()); + public_key_info->insert(public_key_info->begin(), exponent_size); public_key_info->insert(public_key_info->begin(), kIntegerTag); // Encode the modulus n as an INTEGER. public_key_info->insert(public_key_info->begin(), modulus_n.begin(), modulus_n.end()); - uint16 length16 = modulus_n.size(); + uint16 modulus_size = base::checked_cast<uint16>(modulus_n.size()); if (modulus_n[0] & 0x80) { public_key_info->insert(public_key_info->begin(), 0x00); - length16++; + modulus_size++; } - public_key_info->insert(public_key_info->begin(), length16 & 0xff); - public_key_info->insert(public_key_info->begin(), (length16 >> 8) & 0xff); + public_key_info->insert(public_key_info->begin(), modulus_size & 0xff); + public_key_info->insert(public_key_info->begin(), (modulus_size >> 8) & 0xff); public_key_info->insert(public_key_info->begin(), 0x82); public_key_info->insert(public_key_info->begin(), kIntegerTag); // Encode the RSAPublicKey SEQUENCE. - length16 = public_key_info->size(); - public_key_info->insert(public_key_info->begin(), length16 & 0xff); - public_key_info->insert(public_key_info->begin(), (length16 >> 8) & 0xff); + uint16 info_size = base::checked_cast<uint16>(public_key_info->size()); + public_key_info->insert(public_key_info->begin(), info_size & 0xff); + public_key_info->insert(public_key_info->begin(), (info_size >> 8) & 0xff); public_key_info->insert(public_key_info->begin(), 0x82); public_key_info->insert(public_key_info->begin(), kSequenceTag); // Encode the BIT STRING. // Number of unused bits. public_key_info->insert(public_key_info->begin(), 0x00); - length16 = public_key_info->size(); - public_key_info->insert(public_key_info->begin(), length16 & 0xff); - public_key_info->insert(public_key_info->begin(), (length16 >> 8) & 0xff); + info_size = base::checked_cast<uint16>(public_key_info->size()); + public_key_info->insert(public_key_info->begin(), info_size & 0xff); + public_key_info->insert(public_key_info->begin(), (info_size >> 8) & 0xff); public_key_info->insert(public_key_info->begin(), 0x82); public_key_info->insert(public_key_info->begin(), kBitStringTag); @@ -1049,9 +1051,9 @@ static bool EncodeRSAPublicKey(const std::vector<uint8>& modulus_n, algorithm, algorithm + sizeof(algorithm)); // Encode the outermost SEQUENCE. - length16 = public_key_info->size(); - public_key_info->insert(public_key_info->begin(), length16 & 0xff); - public_key_info->insert(public_key_info->begin(), (length16 >> 8) & 0xff); + info_size = base::checked_cast<uint16>(public_key_info->size()); + public_key_info->insert(public_key_info->begin(), info_size & 0xff); + public_key_info->insert(public_key_info->begin(), (info_size >> 8) & 0xff); public_key_info->insert(public_key_info->begin(), 0x82); public_key_info->insert(public_key_info->begin(), kSequenceTag); diff --git a/chromium/crypto/symmetric_key.h b/chromium/crypto/symmetric_key.h index 413f61e0bca..ab105c1754c 100644 --- a/chromium/crypto/symmetric_key.h +++ b/chromium/crypto/symmetric_key.h @@ -57,10 +57,10 @@ class CRYPTO_EXPORT SymmetricKey { // size for use with |algorithm|. The caller owns the returned SymmetricKey. static SymmetricKey* Import(Algorithm algorithm, const std::string& raw_key); -#if defined(USE_OPENSSL) - const std::string& key() { return key_; } -#elif defined(NACL_WIN64) +#if defined(NACL_WIN64) HCRYPTKEY key() const { return key_.get(); } +#elif defined(USE_OPENSSL) + const std::string& key() { return key_; } #elif defined(USE_NSS) || defined(OS_WIN) || defined(OS_MACOSX) PK11SymKey* key() const { return key_.get(); } #endif @@ -71,10 +71,7 @@ class CRYPTO_EXPORT SymmetricKey { bool GetRawKey(std::string* raw_key); private: -#if defined(USE_OPENSSL) - SymmetricKey() {} - std::string key_; -#elif defined(NACL_WIN64) +#if defined(NACL_WIN64) SymmetricKey(HCRYPTPROV provider, HCRYPTKEY key, const void* key_data, size_t key_size_in_bytes); @@ -88,6 +85,9 @@ class CRYPTO_EXPORT SymmetricKey { // TODO(rsleevi): See if KP_EFFECTIVE_KEYLEN is the reason why CryptExportKey // fails with NTE_BAD_KEY/NTE_BAD_LEN std::string raw_key_; +#elif defined(USE_OPENSSL) + SymmetricKey() {} + std::string key_; #elif defined(USE_NSS) || defined(OS_WIN) || defined(OS_MACOSX) explicit SymmetricKey(PK11SymKey* key); ScopedPK11SymKey key_; diff --git a/chromium/crypto/symmetric_key_nss.cc b/chromium/crypto/symmetric_key_nss.cc index b438b376b25..95ca9bd073e 100644 --- a/chromium/crypto/symmetric_key_nss.cc +++ b/chromium/crypto/symmetric_key_nss.cc @@ -20,7 +20,11 @@ SymmetricKey* SymmetricKey::GenerateRandomKey(Algorithm algorithm, DCHECK_EQ(AES, algorithm); EnsureNSSInit(); - if (key_size_in_bits == 0) + + // Whitelist supported key sizes to avoid accidentaly relying on + // algorithms available in NSS but not BoringSSL and vice + // versa. Note that BoringSSL does not support AES-192. + if (key_size_in_bits != 128 && key_size_in_bits != 256) return NULL; ScopedPK11Slot slot(PK11_GetInternalSlot()); @@ -45,6 +49,14 @@ SymmetricKey* SymmetricKey::DeriveKeyFromPassword(Algorithm algorithm, if (salt.empty() || iterations == 0 || key_size_in_bits == 0) return NULL; + if (algorithm == AES) { + // Whitelist supported key sizes to avoid accidentaly relying on + // algorithms available in NSS but not BoringSSL and vice + // versa. Note that BoringSSL does not support AES-192. + if (key_size_in_bits != 128 && key_size_in_bits != 256) + return NULL; + } + SECItem password_item; password_item.type = siBuffer; password_item.data = reinterpret_cast<unsigned char*>( @@ -84,6 +96,15 @@ SymmetricKey* SymmetricKey::DeriveKeyFromPassword(Algorithm algorithm, SymmetricKey* SymmetricKey::Import(Algorithm algorithm, const std::string& raw_key) { EnsureNSSInit(); + + if (algorithm == AES) { + // Whitelist supported key sizes to avoid accidentaly relying on + // algorithms available in NSS but not BoringSSL and vice + // versa. Note that BoringSSL does not support AES-192. + if (raw_key.size() != 128/8 && raw_key.size() != 256/8) + return NULL; + } + CK_MECHANISM_TYPE cipher = algorithm == AES ? CKM_AES_CBC : CKM_SHA_1_HMAC; diff --git a/chromium/crypto/symmetric_key_openssl.cc b/chromium/crypto/symmetric_key_openssl.cc index e1c6fb7eded..e268a1d0f98 100644 --- a/chromium/crypto/symmetric_key_openssl.cc +++ b/chromium/crypto/symmetric_key_openssl.cc @@ -24,6 +24,13 @@ SymmetricKey::~SymmetricKey() { SymmetricKey* SymmetricKey::GenerateRandomKey(Algorithm algorithm, size_t key_size_in_bits) { DCHECK_EQ(AES, algorithm); + + // Whitelist supported key sizes to avoid accidentaly relying on + // algorithms available in NSS but not BoringSSL and vice + // versa. Note that BoringSSL does not support AES-192. + if (key_size_in_bits != 128 && key_size_in_bits != 256) + return NULL; + size_t key_size_in_bytes = key_size_in_bits / 8; DCHECK_EQ(key_size_in_bits, key_size_in_bytes * 8); @@ -46,6 +53,15 @@ SymmetricKey* SymmetricKey::DeriveKeyFromPassword(Algorithm algorithm, size_t iterations, size_t key_size_in_bits) { DCHECK(algorithm == AES || algorithm == HMAC_SHA1); + + if (algorithm == AES) { + // Whitelist supported key sizes to avoid accidentaly relying on + // algorithms available in NSS but not BoringSSL and vice + // versa. Note that BoringSSL does not support AES-192. + if (key_size_in_bits != 128 && key_size_in_bits != 256) + return NULL; + } + size_t key_size_in_bytes = key_size_in_bits / 8; DCHECK_EQ(key_size_in_bits, key_size_in_bytes * 8); @@ -67,6 +83,14 @@ SymmetricKey* SymmetricKey::DeriveKeyFromPassword(Algorithm algorithm, // static SymmetricKey* SymmetricKey::Import(Algorithm algorithm, const std::string& raw_key) { + if (algorithm == AES) { + // Whitelist supported key sizes to avoid accidentaly relying on + // algorithms available in NSS but not BoringSSL and vice + // versa. Note that BoringSSL does not support AES-192. + if (raw_key.size() != 128/8 && raw_key.size() != 256/8) + return NULL; + } + scoped_ptr<SymmetricKey> key(new SymmetricKey); key->key_ = raw_key; return key.release(); diff --git a/chromium/crypto/symmetric_key_unittest.cc b/chromium/crypto/symmetric_key_unittest.cc index f0b4a60a4c5..28e44d27da7 100644 --- a/chromium/crypto/symmetric_key_unittest.cc +++ b/chromium/crypto/symmetric_key_unittest.cc @@ -100,7 +100,7 @@ TEST_P(SymmetricKeyDeriveKeyFromPasswordTest, DeriveKeyFromPassword) { key->GetRawKey(&raw_key); EXPECT_EQ(test_data.key_size_in_bits / 8, raw_key.size()); EXPECT_EQ(test_data.expected, - StringToLowerASCII(base::HexEncode(raw_key.data(), + base::StringToLowerASCII(base::HexEncode(raw_key.data(), raw_key.size()))); } @@ -172,7 +172,7 @@ static const PBKDF2TestVector kTestVectors[] = { { crypto::SymmetricKey::HMAC_SHA1, "password", - "\0224VxxV4\022", /* 0x1234567878563412 */ + "\022" "4VxxV4\022", /* 0x1234567878563412 */ 5, 160, "d1daa78615f287e6a1c8b120d7062a493f98d203", diff --git a/chromium/crypto/wincrypt_shim.h b/chromium/crypto/wincrypt_shim.h new file mode 100644 index 00000000000..799ac49feeb --- /dev/null +++ b/chromium/crypto/wincrypt_shim.h @@ -0,0 +1,25 @@ +// 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 NET_CRYPTO_WINCRYPT_SHIM_H_ +#define NET_CRYPTO_WINCRYPT_SHIM_H_ + +// wincrypt.h defines macros which conflict with OpenSSL's types. This header +// includes wincrypt and undefines the OpenSSL macros which conflict. Any +// Chromium headers which include wincrypt should instead include this header. + +#include <windows.h> +#include <wincrypt.h> + +// Undefine the macros which conflict with OpenSSL and define replacements. See +// http://msdn.microsoft.com/en-us/library/windows/desktop/aa378145(v=vs.85).aspx +#undef X509_CERT_PAIR +#undef X509_EXTENSIONS +#undef X509_NAME + +#define WINCRYPT_X509_CERT_PAIR ((LPCSTR) 53) +#define WINCRYPT_X509_EXTENSIONS ((LPCSTR) 5) +#define WINCRYPT_X509_NAME ((LPCSTR) 7) + +#endif // NET_CRYPTO_WINCRYPT_SHIM_H_
\ No newline at end of file |