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 |