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 <openssl/ec.h> | 7 #include <openssl/ec.h> |
8 #include <openssl/evp.h> | 8 #include <openssl/evp.h> |
9 #include <openssl/pkcs12.h> | 9 #include <openssl/pkcs12.h> |
10 #include <openssl/x509.h> | 10 #include <openssl/x509.h> |
11 | 11 |
12 #include "base/logging.h" | 12 #include "base/logging.h" |
13 #include "base/memory/scoped_ptr.h" | 13 #include "base/memory/scoped_ptr.h" |
14 #include "crypto/openssl_util.h" | 14 #include "crypto/openssl_util.h" |
| 15 #include "crypto/scoped_openssl_types.h" |
15 | 16 |
16 namespace crypto { | 17 namespace crypto { |
17 | 18 |
18 namespace { | 19 namespace { |
19 | 20 |
20 // Function pointer definition, for injecting the required key export function | 21 // Function pointer definition, for injecting the required key export function |
21 // into ExportKeyWithBio, below. |bio| is a temporary memory BIO object, and | 22 // into ExportKeyWithBio, below. |bio| is a temporary memory BIO object, and |
22 // |key| is a handle to the input key object. Return 1 on success, 0 otherwise. | 23 // |key| is a handle to the input key object. Return 1 on success, 0 otherwise. |
23 // NOTE: Used with OpenSSL functions, which do not comply with the Chromium | 24 // NOTE: Used with OpenSSL functions, which do not comply with the Chromium |
24 // style guide, hence the unusual parameter placement / types. | 25 // style guide, hence the unusual parameter placement / types. |
25 typedef int (*ExportBioFunction)(BIO* bio, const void* key); | 26 typedef int (*ExportBioFunction)(BIO* bio, const void* key); |
26 | 27 |
| 28 typedef ScopedOpenSSL<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_free>::Type |
| 29 ScopedPKCS8_PRIV_KEY_INFO; |
| 30 typedef ScopedOpenSSL<X509_SIG, X509_SIG_free>::Type ScopedX509_SIG; |
| 31 |
27 // Helper to export |key| into |output| via the specified ExportBioFunction. | 32 // Helper to export |key| into |output| via the specified ExportBioFunction. |
28 bool ExportKeyWithBio(const void* key, | 33 bool ExportKeyWithBio(const void* key, |
29 ExportBioFunction export_fn, | 34 ExportBioFunction export_fn, |
30 std::vector<uint8>* output) { | 35 std::vector<uint8>* output) { |
31 if (!key) | 36 if (!key) |
32 return false; | 37 return false; |
33 | 38 |
34 ScopedOpenSSL<BIO, BIO_free_all> bio(BIO_new(BIO_s_mem())); | 39 ScopedBIO bio(BIO_new(BIO_s_mem())); |
35 if (!bio.get()) | 40 if (!bio.get()) |
36 return false; | 41 return false; |
37 | 42 |
38 if (!export_fn(bio.get(), key)) | 43 if (!export_fn(bio.get(), key)) |
39 return false; | 44 return false; |
40 | 45 |
41 char* data = NULL; | 46 char* data = NULL; |
42 long len = BIO_get_mem_data(bio.get(), &data); | 47 long len = BIO_get_mem_data(bio.get(), &data); |
43 if (!data || len < 0) | 48 if (!data || len < 0) |
44 return false; | 49 return false; |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
80 EVP_PKEY_free(key_); | 85 EVP_PKEY_free(key_); |
81 } | 86 } |
82 | 87 |
83 // static | 88 // static |
84 bool ECPrivateKey::IsSupported() { return true; } | 89 bool ECPrivateKey::IsSupported() { return true; } |
85 | 90 |
86 // static | 91 // static |
87 ECPrivateKey* ECPrivateKey::Create() { | 92 ECPrivateKey* ECPrivateKey::Create() { |
88 OpenSSLErrStackTracer err_tracer(FROM_HERE); | 93 OpenSSLErrStackTracer err_tracer(FROM_HERE); |
89 | 94 |
90 ScopedOpenSSL<EC_KEY, EC_KEY_free> ec_key( | 95 ScopedEC_KEY ec_key(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)); |
91 EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)); | |
92 if (!ec_key.get() || !EC_KEY_generate_key(ec_key.get())) | 96 if (!ec_key.get() || !EC_KEY_generate_key(ec_key.get())) |
93 return NULL; | 97 return NULL; |
94 | 98 |
95 scoped_ptr<ECPrivateKey> result(new ECPrivateKey()); | 99 scoped_ptr<ECPrivateKey> result(new ECPrivateKey()); |
96 result->key_ = EVP_PKEY_new(); | 100 result->key_ = EVP_PKEY_new(); |
97 if (!result->key_ || !EVP_PKEY_set1_EC_KEY(result->key_, ec_key.get())) | 101 if (!result->key_ || !EVP_PKEY_set1_EC_KEY(result->key_, ec_key.get())) |
98 return NULL; | 102 return NULL; |
99 | 103 |
100 CHECK_EQ(EVP_PKEY_EC, EVP_PKEY_type(result->key_->type)); | 104 CHECK_EQ(EVP_PKEY_EC, EVP_PKEY_type(result->key_->type)); |
101 return result.release(); | 105 return result.release(); |
102 } | 106 } |
103 | 107 |
104 // static | 108 // static |
105 ECPrivateKey* ECPrivateKey::CreateFromEncryptedPrivateKeyInfo( | 109 ECPrivateKey* ECPrivateKey::CreateFromEncryptedPrivateKeyInfo( |
106 const std::string& password, | 110 const std::string& password, |
107 const std::vector<uint8>& encrypted_private_key_info, | 111 const std::vector<uint8>& encrypted_private_key_info, |
108 const std::vector<uint8>& subject_public_key_info) { | 112 const std::vector<uint8>& subject_public_key_info) { |
109 // NOTE: The |subject_public_key_info| can be ignored here, it is only | 113 // NOTE: The |subject_public_key_info| can be ignored here, it is only |
110 // useful for the NSS implementation (which uses the public key's SHA1 | 114 // useful for the NSS implementation (which uses the public key's SHA1 |
111 // as a lookup key when storing the private one in its store). | 115 // as a lookup key when storing the private one in its store). |
112 if (encrypted_private_key_info.empty()) | 116 if (encrypted_private_key_info.empty()) |
113 return NULL; | 117 return NULL; |
114 | 118 |
115 OpenSSLErrStackTracer err_tracer(FROM_HERE); | 119 OpenSSLErrStackTracer err_tracer(FROM_HERE); |
116 // Write the encrypted private key into a memory BIO. | 120 // Write the encrypted private key into a memory BIO. |
117 char* private_key_data = reinterpret_cast<char*>( | 121 char* private_key_data = reinterpret_cast<char*>( |
118 const_cast<uint8*>(&encrypted_private_key_info[0])); | 122 const_cast<uint8*>(&encrypted_private_key_info[0])); |
119 int private_key_data_len = | 123 int private_key_data_len = |
120 static_cast<int>(encrypted_private_key_info.size()); | 124 static_cast<int>(encrypted_private_key_info.size()); |
121 ScopedOpenSSL<BIO, BIO_free_all> bio( | 125 ScopedBIO bio(BIO_new_mem_buf(private_key_data, private_key_data_len)); |
122 BIO_new_mem_buf(private_key_data, private_key_data_len)); | |
123 if (!bio.get()) | 126 if (!bio.get()) |
124 return NULL; | 127 return NULL; |
125 | 128 |
126 // Convert it, then decrypt it into a PKCS#8 object. | 129 // Convert it, then decrypt it into a PKCS#8 object. |
127 ScopedOpenSSL<X509_SIG, X509_SIG_free> p8_encrypted( | 130 ScopedX509_SIG p8_encrypted(d2i_PKCS8_bio(bio.get(), NULL)); |
128 d2i_PKCS8_bio(bio.get(), NULL)); | |
129 if (!p8_encrypted.get()) | 131 if (!p8_encrypted.get()) |
130 return NULL; | 132 return NULL; |
131 | 133 |
132 ScopedOpenSSL<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_free> p8_decrypted( | 134 ScopedPKCS8_PRIV_KEY_INFO p8_decrypted(PKCS8_decrypt( |
133 PKCS8_decrypt(p8_encrypted.get(), | 135 p8_encrypted.get(), password.c_str(), static_cast<int>(password.size()))); |
134 password.c_str(), | |
135 static_cast<int>(password.size()))); | |
136 if (!p8_decrypted.get() && password.empty()) { | 136 if (!p8_decrypted.get() && password.empty()) { |
137 // Hack for reading keys generated by ec_private_key_nss. Passing NULL | 137 // Hack for reading keys generated by ec_private_key_nss. Passing NULL |
138 // causes OpenSSL to use an empty password instead of "\0\0". | 138 // causes OpenSSL to use an empty password instead of "\0\0". |
139 p8_decrypted.reset(PKCS8_decrypt(p8_encrypted.get(), NULL, 0)); | 139 p8_decrypted.reset(PKCS8_decrypt(p8_encrypted.get(), NULL, 0)); |
140 } | 140 } |
141 if (!p8_decrypted.get()) | 141 if (!p8_decrypted.get()) |
142 return NULL; | 142 return NULL; |
143 | 143 |
144 // Create a new EVP_PKEY for it. | 144 // Create a new EVP_PKEY for it. |
145 scoped_ptr<ECPrivateKey> result(new ECPrivateKey); | 145 scoped_ptr<ECPrivateKey> result(new ECPrivateKey); |
146 result->key_ = EVP_PKCS82PKEY(p8_decrypted.get()); | 146 result->key_ = EVP_PKCS82PKEY(p8_decrypted.get()); |
147 if (!result->key_ || EVP_PKEY_type(result->key_->type) != EVP_PKEY_EC) | 147 if (!result->key_ || EVP_PKEY_type(result->key_->type) != EVP_PKEY_EC) |
148 return NULL; | 148 return NULL; |
149 | 149 |
150 return result.release(); | 150 return result.release(); |
151 } | 151 } |
152 | 152 |
153 bool ECPrivateKey::ExportEncryptedPrivateKey( | 153 bool ECPrivateKey::ExportEncryptedPrivateKey( |
154 const std::string& password, | 154 const std::string& password, |
155 int iterations, | 155 int iterations, |
156 std::vector<uint8>* output) { | 156 std::vector<uint8>* output) { |
157 OpenSSLErrStackTracer err_tracer(FROM_HERE); | 157 OpenSSLErrStackTracer err_tracer(FROM_HERE); |
158 // Convert into a PKCS#8 object. | 158 // Convert into a PKCS#8 object. |
159 ScopedOpenSSL<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_free> pkcs8( | 159 ScopedPKCS8_PRIV_KEY_INFO pkcs8(EVP_PKEY2PKCS8(key_)); |
160 EVP_PKEY2PKCS8(key_)); | |
161 if (!pkcs8.get()) | 160 if (!pkcs8.get()) |
162 return false; | 161 return false; |
163 | 162 |
164 // Encrypt the object. | 163 // Encrypt the object. |
165 // NOTE: NSS uses SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC | 164 // NOTE: NSS uses SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC |
166 // so use NID_pbe_WithSHA1And3_Key_TripleDES_CBC which should be the OpenSSL | 165 // so use NID_pbe_WithSHA1And3_Key_TripleDES_CBC which should be the OpenSSL |
167 // equivalent. | 166 // equivalent. |
168 ScopedOpenSSL<X509_SIG, X509_SIG_free> encrypted( | 167 ScopedX509_SIG encrypted(PKCS8_encrypt(NID_pbe_WithSHA1And3_Key_TripleDES_CBC, |
169 PKCS8_encrypt(NID_pbe_WithSHA1And3_Key_TripleDES_CBC, | 168 NULL, |
170 NULL, | 169 password.c_str(), |
171 password.c_str(), | 170 static_cast<int>(password.size()), |
172 static_cast<int>(password.size()), | 171 NULL, |
173 NULL, | 172 0, |
174 0, | 173 iterations, |
175 iterations, | 174 pkcs8.get())); |
176 pkcs8.get())); | |
177 if (!encrypted.get()) | 175 if (!encrypted.get()) |
178 return false; | 176 return false; |
179 | 177 |
180 // Write it into |*output| | 178 // Write it into |*output| |
181 return ExportKeyWithBio(encrypted.get(), | 179 return ExportKeyWithBio(encrypted.get(), |
182 reinterpret_cast<ExportBioFunction>(i2d_PKCS8_bio), | 180 reinterpret_cast<ExportBioFunction>(i2d_PKCS8_bio), |
183 output); | 181 output); |
184 } | 182 } |
185 | 183 |
186 bool ECPrivateKey::ExportPublicKey(std::vector<uint8>* output) { | 184 bool ECPrivateKey::ExportPublicKey(std::vector<uint8>* output) { |
(...skipping 17 matching lines...) Expand all Loading... |
204 len = i2d_PublicKey(key_, &derp); | 202 len = i2d_PublicKey(key_, &derp); |
205 if (len != kExpectedKeyLength) | 203 if (len != kExpectedKeyLength) |
206 return false; | 204 return false; |
207 | 205 |
208 output->assign(reinterpret_cast<char*>(buf + 1), kExpectedKeyLength - 1); | 206 output->assign(reinterpret_cast<char*>(buf + 1), kExpectedKeyLength - 1); |
209 return true; | 207 return true; |
210 } | 208 } |
211 | 209 |
212 bool ECPrivateKey::ExportValue(std::vector<uint8>* output) { | 210 bool ECPrivateKey::ExportValue(std::vector<uint8>* output) { |
213 OpenSSLErrStackTracer err_tracer(FROM_HERE); | 211 OpenSSLErrStackTracer err_tracer(FROM_HERE); |
214 ScopedOpenSSL<EC_KEY, EC_KEY_free> ec_key(EVP_PKEY_get1_EC_KEY(key_)); | 212 ScopedEC_KEY ec_key(EVP_PKEY_get1_EC_KEY(key_)); |
215 return ExportKey(ec_key.get(), | 213 return ExportKey(ec_key.get(), |
216 reinterpret_cast<ExportDataFunction>(i2d_ECPrivateKey), | 214 reinterpret_cast<ExportDataFunction>(i2d_ECPrivateKey), |
217 output); | 215 output); |
218 } | 216 } |
219 | 217 |
220 bool ECPrivateKey::ExportECParams(std::vector<uint8>* output) { | 218 bool ECPrivateKey::ExportECParams(std::vector<uint8>* output) { |
221 OpenSSLErrStackTracer err_tracer(FROM_HERE); | 219 OpenSSLErrStackTracer err_tracer(FROM_HERE); |
222 ScopedOpenSSL<EC_KEY, EC_KEY_free> ec_key(EVP_PKEY_get1_EC_KEY(key_)); | 220 ScopedEC_KEY ec_key(EVP_PKEY_get1_EC_KEY(key_)); |
223 return ExportKey(ec_key.get(), | 221 return ExportKey(ec_key.get(), |
224 reinterpret_cast<ExportDataFunction>(i2d_ECParameters), | 222 reinterpret_cast<ExportDataFunction>(i2d_ECParameters), |
225 output); | 223 output); |
226 } | 224 } |
227 | 225 |
228 ECPrivateKey::ECPrivateKey() : key_(NULL) {} | 226 ECPrivateKey::ECPrivateKey() : key_(NULL) {} |
229 | 227 |
230 } // namespace crypto | 228 } // namespace crypto |
OLD | NEW |