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/bytestring.h> | 7 #include <openssl/bytestring.h> |
8 #include <openssl/ec.h> | 8 #include <openssl/ec.h> |
9 #include <openssl/evp.h> | 9 #include <openssl/evp.h> |
10 #include <openssl/mem.h> | 10 #include <openssl/mem.h> |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
78 | 78 |
79 ScopedEC_KEY ec_key(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)); | 79 ScopedEC_KEY ec_key(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)); |
80 if (!ec_key.get() || !EC_KEY_generate_key(ec_key.get())) | 80 if (!ec_key.get() || !EC_KEY_generate_key(ec_key.get())) |
81 return NULL; | 81 return NULL; |
82 | 82 |
83 std::unique_ptr<ECPrivateKey> result(new ECPrivateKey()); | 83 std::unique_ptr<ECPrivateKey> result(new ECPrivateKey()); |
84 result->key_ = EVP_PKEY_new(); | 84 result->key_ = EVP_PKEY_new(); |
85 if (!result->key_ || !EVP_PKEY_set1_EC_KEY(result->key_, ec_key.get())) | 85 if (!result->key_ || !EVP_PKEY_set1_EC_KEY(result->key_, ec_key.get())) |
86 return NULL; | 86 return NULL; |
87 | 87 |
88 CHECK_EQ(EVP_PKEY_EC, EVP_PKEY_type(result->key_->type)); | 88 CHECK_EQ(EVP_PKEY_EC, EVP_PKEY_id(result->key_)); |
89 return result.release(); | 89 return result.release(); |
90 } | 90 } |
91 | 91 |
92 // static | 92 // static |
| 93 std::unique_ptr<ECPrivateKey> ECPrivateKey::CreateFromPrivateKeyInfo( |
| 94 const std::vector<uint8_t>& input) { |
| 95 OpenSSLErrStackTracer err_tracer(FROM_HERE); |
| 96 |
| 97 CBS cbs; |
| 98 CBS_init(&cbs, input.data(), input.size()); |
| 99 ScopedEVP_PKEY pkey(EVP_parse_private_key(&cbs)); |
| 100 if (!pkey || CBS_len(&cbs) != 0 || EVP_PKEY_id(pkey.get()) != EVP_PKEY_EC) |
| 101 return nullptr; |
| 102 |
| 103 std::unique_ptr<ECPrivateKey> result(new ECPrivateKey); |
| 104 result->key_ = pkey.release(); |
| 105 return result; |
| 106 } |
| 107 |
| 108 // static |
93 ECPrivateKey* ECPrivateKey::CreateFromEncryptedPrivateKeyInfo( | 109 ECPrivateKey* ECPrivateKey::CreateFromEncryptedPrivateKeyInfo( |
94 const std::string& password, | 110 const std::string& password, |
95 const std::vector<uint8_t>& encrypted_private_key_info, | 111 const std::vector<uint8_t>& encrypted_private_key_info, |
96 const std::vector<uint8_t>& subject_public_key_info) { | 112 const std::vector<uint8_t>& subject_public_key_info) { |
97 // 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 |
98 // 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 |
99 // 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). |
100 if (encrypted_private_key_info.empty()) | 116 if (encrypted_private_key_info.empty()) |
101 return NULL; | 117 return NULL; |
102 | 118 |
(...skipping 21 matching lines...) Expand all Loading... |
124 reinterpret_cast<const uint8_t*>(password.data()), | 140 reinterpret_cast<const uint8_t*>(password.data()), |
125 password.size())); | 141 password.size())); |
126 } | 142 } |
127 | 143 |
128 if (!p8_decrypted) | 144 if (!p8_decrypted) |
129 return NULL; | 145 return NULL; |
130 | 146 |
131 // Create a new EVP_PKEY for it. | 147 // Create a new EVP_PKEY for it. |
132 std::unique_ptr<ECPrivateKey> result(new ECPrivateKey); | 148 std::unique_ptr<ECPrivateKey> result(new ECPrivateKey); |
133 result->key_ = EVP_PKCS82PKEY(p8_decrypted.get()); | 149 result->key_ = EVP_PKCS82PKEY(p8_decrypted.get()); |
134 if (!result->key_ || EVP_PKEY_type(result->key_->type) != EVP_PKEY_EC) | 150 if (!result->key_ || EVP_PKEY_id(result->key_) != EVP_PKEY_EC) |
135 return NULL; | 151 return NULL; |
136 | 152 |
137 return result.release(); | 153 return result.release(); |
138 } | 154 } |
139 | 155 |
140 bool ECPrivateKey::ExportEncryptedPrivateKey(const std::string& password, | 156 bool ECPrivateKey::ExportPrivateKey(std::vector<uint8_t>* output) const { |
141 int iterations, | 157 OpenSSLErrStackTracer err_tracer(FROM_HERE); |
142 std::vector<uint8_t>* output) { | 158 uint8_t* der; |
| 159 size_t der_len; |
| 160 AutoCBB cbb; |
| 161 if (!CBB_init(cbb.get(), 0) || !EVP_marshal_private_key(cbb.get(), key_) || |
| 162 !CBB_finish(cbb.get(), &der, &der_len)) { |
| 163 return false; |
| 164 } |
| 165 output->assign(der, der + der_len); |
| 166 OPENSSL_free(der); |
| 167 return true; |
| 168 } |
| 169 |
| 170 bool ECPrivateKey::ExportEncryptedPrivateKey( |
| 171 const std::string& password, |
| 172 int iterations, |
| 173 std::vector<uint8_t>* output) const { |
143 OpenSSLErrStackTracer err_tracer(FROM_HERE); | 174 OpenSSLErrStackTracer err_tracer(FROM_HERE); |
144 // Convert into a PKCS#8 object. | 175 // Convert into a PKCS#8 object. |
145 ScopedPKCS8_PRIV_KEY_INFO pkcs8(EVP_PKEY2PKCS8(key_)); | 176 ScopedPKCS8_PRIV_KEY_INFO pkcs8(EVP_PKEY2PKCS8(key_)); |
146 if (!pkcs8.get()) | 177 if (!pkcs8.get()) |
147 return false; | 178 return false; |
148 | 179 |
149 // Encrypt the object. | 180 // Encrypt the object. |
150 // NOTE: NSS uses SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC | 181 // NOTE: NSS uses SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC |
151 // so use NID_pbe_WithSHA1And3_Key_TripleDES_CBC which should be the OpenSSL | 182 // so use NID_pbe_WithSHA1And3_Key_TripleDES_CBC which should be the OpenSSL |
152 // equivalent. | 183 // equivalent. |
153 ScopedX509_SIG encrypted(PKCS8_encrypt_pbe( | 184 ScopedX509_SIG encrypted(PKCS8_encrypt_pbe( |
154 NID_pbe_WithSHA1And3_Key_TripleDES_CBC, | 185 NID_pbe_WithSHA1And3_Key_TripleDES_CBC, |
155 nullptr, | 186 nullptr, |
156 reinterpret_cast<const uint8_t*>(password.data()), | 187 reinterpret_cast<const uint8_t*>(password.data()), |
157 password.size(), | 188 password.size(), |
158 nullptr, | 189 nullptr, |
159 0, | 190 0, |
160 iterations, | 191 iterations, |
161 pkcs8.get())); | 192 pkcs8.get())); |
162 if (!encrypted.get()) | 193 if (!encrypted.get()) |
163 return false; | 194 return false; |
164 | 195 |
165 // Write it into |*output| | 196 // Write it into |*output| |
166 return ExportKeyWithBio(encrypted.get(), | 197 return ExportKeyWithBio(encrypted.get(), |
167 reinterpret_cast<ExportBioFunction>(i2d_PKCS8_bio), | 198 reinterpret_cast<ExportBioFunction>(i2d_PKCS8_bio), |
168 output); | 199 output); |
169 } | 200 } |
170 | 201 |
171 bool ECPrivateKey::ExportPublicKey(std::vector<uint8_t>* output) { | 202 bool ECPrivateKey::ExportPublicKey(std::vector<uint8_t>* output) const { |
172 OpenSSLErrStackTracer err_tracer(FROM_HERE); | 203 OpenSSLErrStackTracer err_tracer(FROM_HERE); |
173 uint8_t *der; | 204 uint8_t *der; |
174 size_t der_len; | 205 size_t der_len; |
175 AutoCBB cbb; | 206 AutoCBB cbb; |
176 if (!CBB_init(cbb.get(), 0) || | 207 if (!CBB_init(cbb.get(), 0) || |
177 !EVP_marshal_public_key(cbb.get(), key_) || | 208 !EVP_marshal_public_key(cbb.get(), key_) || |
178 !CBB_finish(cbb.get(), &der, &der_len)) { | 209 !CBB_finish(cbb.get(), &der, &der_len)) { |
179 return false; | 210 return false; |
180 } | 211 } |
181 output->assign(der, der + der_len); | 212 output->assign(der, der + der_len); |
182 OPENSSL_free(der); | 213 OPENSSL_free(der); |
183 return true; | 214 return true; |
184 } | 215 } |
185 | 216 |
186 bool ECPrivateKey::ExportRawPublicKey(std::string* output) { | 217 bool ECPrivateKey::ExportRawPublicKey(std::string* output) const { |
187 OpenSSLErrStackTracer err_tracer(FROM_HERE); | 218 OpenSSLErrStackTracer err_tracer(FROM_HERE); |
188 | 219 |
189 // Export the x and y field elements as 32-byte, big-endian numbers. (This is | 220 // Export the x and y field elements as 32-byte, big-endian numbers. (This is |
190 // the same as X9.62 uncompressed form without the leading 0x04 byte.) | 221 // the same as X9.62 uncompressed form without the leading 0x04 byte.) |
191 EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(key_); | 222 EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(key_); |
192 ScopedBIGNUM x(BN_new()); | 223 ScopedBIGNUM x(BN_new()); |
193 ScopedBIGNUM y(BN_new()); | 224 ScopedBIGNUM y(BN_new()); |
194 uint8_t buf[64]; | 225 uint8_t buf[64]; |
195 if (!x || !y || | 226 if (!x || !y || |
196 !EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(ec_key), | 227 !EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(ec_key), |
197 EC_KEY_get0_public_key(ec_key), | 228 EC_KEY_get0_public_key(ec_key), |
198 x.get(), y.get(), nullptr) || | 229 x.get(), y.get(), nullptr) || |
199 !BN_bn2bin_padded(buf, 32, x.get()) || | 230 !BN_bn2bin_padded(buf, 32, x.get()) || |
200 !BN_bn2bin_padded(buf + 32, 32, y.get())) { | 231 !BN_bn2bin_padded(buf + 32, 32, y.get())) { |
201 return false; | 232 return false; |
202 } | 233 } |
203 | 234 |
204 output->assign(reinterpret_cast<const char*>(buf), sizeof(buf)); | 235 output->assign(reinterpret_cast<const char*>(buf), sizeof(buf)); |
205 return true; | 236 return true; |
206 } | 237 } |
207 | 238 |
208 bool ECPrivateKey::ExportValueForTesting(std::vector<uint8_t>* output) { | |
209 OpenSSLErrStackTracer err_tracer(FROM_HERE); | |
210 EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(key_); | |
211 uint8_t *der; | |
212 size_t der_len; | |
213 AutoCBB cbb; | |
214 if (!CBB_init(cbb.get(), 0) || | |
215 !EC_KEY_marshal_private_key(cbb.get(), ec_key, 0 /* enc_flags */) || | |
216 !CBB_finish(cbb.get(), &der, &der_len)) { | |
217 return false; | |
218 } | |
219 output->assign(der, der + der_len); | |
220 OPENSSL_free(der); | |
221 return true; | |
222 } | |
223 | |
224 ECPrivateKey::ECPrivateKey() : key_(NULL) {} | 239 ECPrivateKey::ECPrivateKey() : key_(NULL) {} |
225 | 240 |
226 } // namespace crypto | 241 } // namespace crypto |
OLD | NEW |