| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "crypto/ec_private_key.h" | 5 #include "crypto/ec_private_key.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 | 9 |
| 10 #include <utility> | 10 #include <utility> |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 88 if (!pkey || CBS_len(&cbs) != 0 || EVP_PKEY_id(pkey.get()) != EVP_PKEY_EC) | 88 if (!pkey || CBS_len(&cbs) != 0 || EVP_PKEY_id(pkey.get()) != EVP_PKEY_EC) |
| 89 return nullptr; | 89 return nullptr; |
| 90 | 90 |
| 91 std::unique_ptr<ECPrivateKey> result(new ECPrivateKey()); | 91 std::unique_ptr<ECPrivateKey> result(new ECPrivateKey()); |
| 92 result->key_ = std::move(pkey); | 92 result->key_ = std::move(pkey); |
| 93 return result; | 93 return result; |
| 94 } | 94 } |
| 95 | 95 |
| 96 // static | 96 // static |
| 97 std::unique_ptr<ECPrivateKey> ECPrivateKey::CreateFromEncryptedPrivateKeyInfo( | 97 std::unique_ptr<ECPrivateKey> ECPrivateKey::CreateFromEncryptedPrivateKeyInfo( |
| 98 const std::string& password, | |
| 99 const std::vector<uint8_t>& encrypted_private_key_info, | 98 const std::vector<uint8_t>& encrypted_private_key_info, |
| 100 const std::vector<uint8_t>& subject_public_key_info) { | 99 const std::vector<uint8_t>& subject_public_key_info) { |
| 101 // NOTE: The |subject_public_key_info| can be ignored here, it is only | 100 // NOTE: The |subject_public_key_info| can be ignored here, it is only |
| 102 // useful for the NSS implementation (which uses the public key's SHA1 | 101 // useful for the NSS implementation (which uses the public key's SHA1 |
| 103 // as a lookup key when storing the private one in its store). | 102 // as a lookup key when storing the private one in its store). |
| 104 if (encrypted_private_key_info.empty()) | 103 if (encrypted_private_key_info.empty()) |
| 105 return nullptr; | 104 return nullptr; |
| 106 | 105 |
| 107 OpenSSLErrStackTracer err_tracer(FROM_HERE); | 106 OpenSSLErrStackTracer err_tracer(FROM_HERE); |
| 108 | 107 |
| 109 const uint8_t* data = &encrypted_private_key_info[0]; | 108 const uint8_t* data = &encrypted_private_key_info[0]; |
| 110 const uint8_t* ptr = data; | 109 const uint8_t* ptr = data; |
| 111 bssl::UniquePtr<X509_SIG> p8_encrypted( | 110 bssl::UniquePtr<X509_SIG> p8_encrypted( |
| 112 d2i_X509_SIG(nullptr, &ptr, encrypted_private_key_info.size())); | 111 d2i_X509_SIG(nullptr, &ptr, encrypted_private_key_info.size())); |
| 113 if (!p8_encrypted || ptr != data + encrypted_private_key_info.size()) | 112 if (!p8_encrypted || ptr != data + encrypted_private_key_info.size()) |
| 114 return nullptr; | 113 return nullptr; |
| 115 | 114 |
| 116 bssl::UniquePtr<PKCS8_PRIV_KEY_INFO> p8_decrypted; | 115 // Hack for reading keys generated by an older version of the OpenSSL code. |
| 117 if (password.empty()) { | 116 // Some implementations encode the empty password as "\0\0" (passwords are |
| 118 // Hack for reading keys generated by an older version of the OpenSSL | 117 // normally encoded in big-endian UCS-2 with a NUL terminator) and some |
| 119 // code. OpenSSL used to use "\0\0" rather than the empty string because it | 118 // encode as the empty string. PKCS8_decrypt distinguishes the two by whether |
| 120 // would treat the password as an ASCII string to be converted to UCS-2 | 119 // the password is nullptr. |
| 121 // while NSS used a byte string. | 120 bssl::UniquePtr<PKCS8_PRIV_KEY_INFO> p8_decrypted( |
| 122 p8_decrypted.reset(PKCS8_decrypt_pbe( | 121 PKCS8_decrypt(p8_encrypted.get(), "", 0)); |
| 123 p8_encrypted.get(), reinterpret_cast<const uint8_t*>("\0\0"), 2)); | 122 if (!p8_decrypted) |
| 124 } | 123 p8_decrypted.reset(PKCS8_decrypt(p8_encrypted.get(), nullptr, 0)); |
| 125 if (!p8_decrypted) { | |
| 126 p8_decrypted.reset(PKCS8_decrypt_pbe( | |
| 127 p8_encrypted.get(), | |
| 128 reinterpret_cast<const uint8_t*>(password.data()), | |
| 129 password.size())); | |
| 130 } | |
| 131 | 124 |
| 132 if (!p8_decrypted) | 125 if (!p8_decrypted) |
| 133 return nullptr; | 126 return nullptr; |
| 134 | 127 |
| 135 // Create a new EVP_PKEY for it. | 128 // Create a new EVP_PKEY for it. |
| 136 std::unique_ptr<ECPrivateKey> result(new ECPrivateKey()); | 129 std::unique_ptr<ECPrivateKey> result(new ECPrivateKey()); |
| 137 result->key_.reset(EVP_PKCS82PKEY(p8_decrypted.get())); | 130 result->key_.reset(EVP_PKCS82PKEY(p8_decrypted.get())); |
| 138 if (!result->key_ || EVP_PKEY_id(result->key_.get()) != EVP_PKEY_EC) | 131 if (!result->key_ || EVP_PKEY_id(result->key_.get()) != EVP_PKEY_EC) |
| 139 return nullptr; | 132 return nullptr; |
| 140 | 133 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 159 !EVP_marshal_private_key(cbb.get(), key_.get()) || | 152 !EVP_marshal_private_key(cbb.get(), key_.get()) || |
| 160 !CBB_finish(cbb.get(), &der, &der_len)) { | 153 !CBB_finish(cbb.get(), &der, &der_len)) { |
| 161 return false; | 154 return false; |
| 162 } | 155 } |
| 163 output->assign(der, der + der_len); | 156 output->assign(der, der + der_len); |
| 164 OPENSSL_free(der); | 157 OPENSSL_free(der); |
| 165 return true; | 158 return true; |
| 166 } | 159 } |
| 167 | 160 |
| 168 bool ECPrivateKey::ExportEncryptedPrivateKey( | 161 bool ECPrivateKey::ExportEncryptedPrivateKey( |
| 169 const std::string& password, | |
| 170 int iterations, | |
| 171 std::vector<uint8_t>* output) const { | 162 std::vector<uint8_t>* output) const { |
| 172 OpenSSLErrStackTracer err_tracer(FROM_HERE); | 163 OpenSSLErrStackTracer err_tracer(FROM_HERE); |
| 173 // Convert into a PKCS#8 object. | 164 // Convert into a PKCS#8 object. |
| 174 bssl::UniquePtr<PKCS8_PRIV_KEY_INFO> pkcs8(EVP_PKEY2PKCS8(key_.get())); | 165 bssl::UniquePtr<PKCS8_PRIV_KEY_INFO> pkcs8(EVP_PKEY2PKCS8(key_.get())); |
| 175 if (!pkcs8) | 166 if (!pkcs8) |
| 176 return false; | 167 return false; |
| 177 | 168 |
| 178 // Encrypt the object. | 169 // Encrypt the object. |
| 179 // NOTE: NSS uses SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC | 170 // NOTE: NSS uses SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC |
| 180 // so use NID_pbe_WithSHA1And3_Key_TripleDES_CBC which should be the OpenSSL | 171 // so use NID_pbe_WithSHA1And3_Key_TripleDES_CBC which should be the OpenSSL |
| 181 // equivalent. | 172 // equivalent. |
| 182 bssl::UniquePtr<X509_SIG> encrypted( | 173 bssl::UniquePtr<X509_SIG> encrypted( |
| 183 PKCS8_encrypt_pbe(NID_pbe_WithSHA1And3_Key_TripleDES_CBC, nullptr, | 174 PKCS8_encrypt(NID_pbe_WithSHA1And3_Key_TripleDES_CBC, nullptr, nullptr, 0, |
| 184 reinterpret_cast<const uint8_t*>(password.data()), | 175 nullptr, 0, 1, pkcs8.get())); |
| 185 password.size(), nullptr, 0, iterations, pkcs8.get())); | |
| 186 if (!encrypted) | 176 if (!encrypted) |
| 187 return false; | 177 return false; |
| 188 | 178 |
| 189 // Write it into |*output| | 179 // Write it into |*output| |
| 190 return ExportKeyWithBio(encrypted.get(), | 180 return ExportKeyWithBio(encrypted.get(), |
| 191 reinterpret_cast<ExportBioFunction>(i2d_PKCS8_bio), | 181 reinterpret_cast<ExportBioFunction>(i2d_PKCS8_bio), |
| 192 output); | 182 output); |
| 193 } | 183 } |
| 194 | 184 |
| 195 bool ECPrivateKey::ExportPublicKey(std::vector<uint8_t>* output) const { | 185 bool ECPrivateKey::ExportPublicKey(std::vector<uint8_t>* output) const { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 225 return false; | 215 return false; |
| 226 } | 216 } |
| 227 | 217 |
| 228 output->assign(reinterpret_cast<const char*>(buf), sizeof(buf)); | 218 output->assign(reinterpret_cast<const char*>(buf), sizeof(buf)); |
| 229 return true; | 219 return true; |
| 230 } | 220 } |
| 231 | 221 |
| 232 ECPrivateKey::ECPrivateKey() {} | 222 ECPrivateKey::ECPrivateKey() {} |
| 233 | 223 |
| 234 } // namespace crypto | 224 } // namespace crypto |
| OLD | NEW |