summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordavidben@chromium.org <davidben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-08-06 23:11:09 +0000
committerdavidben@chromium.org <davidben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-08-06 23:11:09 +0000
commitdc06f75b3eeef693d0c4bc95ba6d8f91948e62c8 (patch)
tree7af647b45ee265b0da804b1d8de36b248dc3520b
parent519317c7d6c060ab0c21c7f3897a7ca687e02015 (diff)
downloadchromium_src-dc06f75b3eeef693d0c4bc95ba6d8f91948e62c8.zip
chromium_src-dc06f75b3eeef693d0c4bc95ba6d8f91948e62c8.tar.gz
chromium_src-dc06f75b3eeef693d0c4bc95ba6d8f91948e62c8.tar.bz2
Align OpenSSL and NSS ChannelID formats.
NSS would use "" as the password while OpenSSL would use "\0\0" (UCS-2 encoding of a NUL-terminated string) because of how PKCS#12 recommended encoding passwords. Make the OpenSSL code use the same format so that we can freely switch back and forth between NSS and OpenSSL. (This is in case we need to roll back an OpenSSL cutover and the release has hit some early release channel already.) BUG=399121 Review URL: https://codereview.chromium.org/435593003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@287890 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--crypto/ec_private_key_openssl.cc55
-rw-r--r--crypto/ec_private_key_unittest.cc60
2 files changed, 78 insertions, 37 deletions
diff --git a/crypto/ec_private_key_openssl.cc b/crypto/ec_private_key_openssl.cc
index beda29f..2d44759 100644
--- a/crypto/ec_private_key_openssl.cc
+++ b/crypto/ec_private_key_openssl.cc
@@ -117,28 +117,31 @@ 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());
- ScopedBIO bio(BIO_new_mem_buf(private_key_data, private_key_data_len));
- if (!bio.get())
- return NULL;
- // Convert it, then decrypt it into a PKCS#8 object.
- ScopedX509_SIG 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;
- ScopedPKCS8_PRIV_KEY_INFO p8_decrypted(PKCS8_decrypt(
- p8_encrypted.get(), password.c_str(), static_cast<int>(password.size())));
- if (!p8_decrypted.get() && password.empty()) {
- // Hack for reading keys generated by ec_private_key_nss. Passing NULL
- // causes OpenSSL to use an empty password instead of "\0\0".
- 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.get())
+ if (!p8_decrypted) {
+ p8_decrypted.reset(PKCS8_decrypt_pbe(
+ p8_encrypted.get(),
+ reinterpret_cast<const uint8_t*>(password.data()),
+ password.size()));
+ }
+
+ if (!p8_decrypted)
return NULL;
// Create a new EVP_PKEY for it.
@@ -164,14 +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.
- ScopedX509_SIG encrypted(PKCS8_encrypt(NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
- NULL,
- password.c_str(),
- static_cast<int>(password.size()),
- NULL,
- 0,
- iterations,
- pkcs8.get()));
+ 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;
diff --git a/crypto/ec_private_key_unittest.cc b/crypto/ec_private_key_unittest.cc
index 0f4479b..6993a20 100644
--- a/crypto/ec_private_key_unittest.cc
+++ b/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"
@@ -152,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,
@@ -162,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,
@@ -214,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,
@@ -244,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());
}