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 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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_type(result->key_->type)); |
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) | |
101 return nullptr; | |
102 | |
103 // Check this is a P-256 key. | |
104 EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(pkey.get()); | |
105 if (!ec_key || | |
106 EC_GROUP_get_curve_name(EC_KEY_get0_group(ec_key)) != | |
107 NID_X9_62_prime256v1) { | |
Ryan Sleevi
2016/05/02 23:26:56
Why? We don't enforce this elsewhere, AFAICT. It's
davidben
2016/06/01 17:19:39
I think it's a little poor to have parsing be able
davidben
2016/06/01 17:19:58
s/would never parse/would never create/
| |
108 return nullptr; | |
109 } | |
110 | |
111 std::unique_ptr<ECPrivateKey> result(new ECPrivateKey); | |
112 result->key_ = pkey.release(); | |
113 return result; | |
114 } | |
115 | |
116 // static | |
93 ECPrivateKey* ECPrivateKey::CreateFromEncryptedPrivateKeyInfo( | 117 ECPrivateKey* ECPrivateKey::CreateFromEncryptedPrivateKeyInfo( |
94 const std::string& password, | 118 const std::string& password, |
95 const std::vector<uint8_t>& encrypted_private_key_info, | 119 const std::vector<uint8_t>& encrypted_private_key_info, |
96 const std::vector<uint8_t>& subject_public_key_info) { | 120 const std::vector<uint8_t>& subject_public_key_info) { |
97 // NOTE: The |subject_public_key_info| can be ignored here, it is only | 121 // 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 | 122 // 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). | 123 // as a lookup key when storing the private one in its store). |
100 if (encrypted_private_key_info.empty()) | 124 if (encrypted_private_key_info.empty()) |
101 return NULL; | 125 return NULL; |
102 | 126 |
(...skipping 27 matching lines...) Expand all Loading... | |
130 | 154 |
131 // Create a new EVP_PKEY for it. | 155 // Create a new EVP_PKEY for it. |
132 std::unique_ptr<ECPrivateKey> result(new ECPrivateKey); | 156 std::unique_ptr<ECPrivateKey> result(new ECPrivateKey); |
133 result->key_ = EVP_PKCS82PKEY(p8_decrypted.get()); | 157 result->key_ = EVP_PKCS82PKEY(p8_decrypted.get()); |
134 if (!result->key_ || EVP_PKEY_type(result->key_->type) != EVP_PKEY_EC) | 158 if (!result->key_ || EVP_PKEY_type(result->key_->type) != EVP_PKEY_EC) |
135 return NULL; | 159 return NULL; |
136 | 160 |
137 return result.release(); | 161 return result.release(); |
138 } | 162 } |
139 | 163 |
140 bool ECPrivateKey::ExportEncryptedPrivateKey(const std::string& password, | 164 bool ECPrivateKey::ExportPrivateKey(std::vector<uint8_t>* output) const { |
141 int iterations, | 165 OpenSSLErrStackTracer err_tracer(FROM_HERE); |
142 std::vector<uint8_t>* output) { | 166 uint8_t* der; |
167 size_t der_len; | |
168 AutoCBB cbb; | |
169 if (!CBB_init(cbb.get(), 0) || !EVP_marshal_private_key(cbb.get(), key_) || | |
170 !CBB_finish(cbb.get(), &der, &der_len)) { | |
171 return false; | |
172 } | |
173 output->assign(der, der + der_len); | |
174 OPENSSL_free(der); | |
175 return true; | |
176 } | |
177 | |
178 bool ECPrivateKey::ExportEncryptedPrivateKey( | |
179 const std::string& password, | |
180 int iterations, | |
181 std::vector<uint8_t>* output) const { | |
143 OpenSSLErrStackTracer err_tracer(FROM_HERE); | 182 OpenSSLErrStackTracer err_tracer(FROM_HERE); |
144 // Convert into a PKCS#8 object. | 183 // Convert into a PKCS#8 object. |
145 ScopedPKCS8_PRIV_KEY_INFO pkcs8(EVP_PKEY2PKCS8(key_)); | 184 ScopedPKCS8_PRIV_KEY_INFO pkcs8(EVP_PKEY2PKCS8(key_)); |
146 if (!pkcs8.get()) | 185 if (!pkcs8.get()) |
147 return false; | 186 return false; |
148 | 187 |
149 // Encrypt the object. | 188 // Encrypt the object. |
150 // NOTE: NSS uses SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC | 189 // 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 | 190 // so use NID_pbe_WithSHA1And3_Key_TripleDES_CBC which should be the OpenSSL |
152 // equivalent. | 191 // equivalent. |
153 ScopedX509_SIG encrypted(PKCS8_encrypt_pbe( | 192 ScopedX509_SIG encrypted(PKCS8_encrypt_pbe( |
154 NID_pbe_WithSHA1And3_Key_TripleDES_CBC, | 193 NID_pbe_WithSHA1And3_Key_TripleDES_CBC, |
155 nullptr, | 194 nullptr, |
156 reinterpret_cast<const uint8_t*>(password.data()), | 195 reinterpret_cast<const uint8_t*>(password.data()), |
157 password.size(), | 196 password.size(), |
158 nullptr, | 197 nullptr, |
159 0, | 198 0, |
160 iterations, | 199 iterations, |
161 pkcs8.get())); | 200 pkcs8.get())); |
162 if (!encrypted.get()) | 201 if (!encrypted.get()) |
163 return false; | 202 return false; |
164 | 203 |
165 // Write it into |*output| | 204 // Write it into |*output| |
166 return ExportKeyWithBio(encrypted.get(), | 205 return ExportKeyWithBio(encrypted.get(), |
167 reinterpret_cast<ExportBioFunction>(i2d_PKCS8_bio), | 206 reinterpret_cast<ExportBioFunction>(i2d_PKCS8_bio), |
168 output); | 207 output); |
169 } | 208 } |
170 | 209 |
171 bool ECPrivateKey::ExportPublicKey(std::vector<uint8_t>* output) { | 210 bool ECPrivateKey::ExportPublicKey(std::vector<uint8_t>* output) const { |
172 OpenSSLErrStackTracer err_tracer(FROM_HERE); | 211 OpenSSLErrStackTracer err_tracer(FROM_HERE); |
173 uint8_t *der; | 212 uint8_t *der; |
174 size_t der_len; | 213 size_t der_len; |
175 AutoCBB cbb; | 214 AutoCBB cbb; |
176 if (!CBB_init(cbb.get(), 0) || | 215 if (!CBB_init(cbb.get(), 0) || |
177 !EVP_marshal_public_key(cbb.get(), key_) || | 216 !EVP_marshal_public_key(cbb.get(), key_) || |
178 !CBB_finish(cbb.get(), &der, &der_len)) { | 217 !CBB_finish(cbb.get(), &der, &der_len)) { |
179 return false; | 218 return false; |
180 } | 219 } |
181 output->assign(der, der + der_len); | 220 output->assign(der, der + der_len); |
182 OPENSSL_free(der); | 221 OPENSSL_free(der); |
183 return true; | 222 return true; |
184 } | 223 } |
185 | 224 |
186 bool ECPrivateKey::ExportRawPublicKey(std::string* output) { | 225 bool ECPrivateKey::ExportRawPublicKey(std::string* output) const { |
187 OpenSSLErrStackTracer err_tracer(FROM_HERE); | 226 OpenSSLErrStackTracer err_tracer(FROM_HERE); |
188 | 227 |
189 // Export the x and y field elements as 32-byte, big-endian numbers. (This is | 228 // 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.) | 229 // the same as X9.62 uncompressed form without the leading 0x04 byte.) |
191 EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(key_); | 230 EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(key_); |
192 ScopedBIGNUM x(BN_new()); | 231 ScopedBIGNUM x(BN_new()); |
193 ScopedBIGNUM y(BN_new()); | 232 ScopedBIGNUM y(BN_new()); |
194 uint8_t buf[64]; | 233 uint8_t buf[64]; |
195 if (!x || !y || | 234 if (!x || !y || |
196 !EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(ec_key), | 235 !EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(ec_key), |
197 EC_KEY_get0_public_key(ec_key), | 236 EC_KEY_get0_public_key(ec_key), |
198 x.get(), y.get(), nullptr) || | 237 x.get(), y.get(), nullptr) || |
199 !BN_bn2bin_padded(buf, 32, x.get()) || | 238 !BN_bn2bin_padded(buf, 32, x.get()) || |
200 !BN_bn2bin_padded(buf + 32, 32, y.get())) { | 239 !BN_bn2bin_padded(buf + 32, 32, y.get())) { |
201 return false; | 240 return false; |
202 } | 241 } |
203 | 242 |
204 output->assign(reinterpret_cast<const char*>(buf), sizeof(buf)); | 243 output->assign(reinterpret_cast<const char*>(buf), sizeof(buf)); |
205 return true; | 244 return true; |
206 } | 245 } |
207 | 246 |
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) {} | 247 ECPrivateKey::ECPrivateKey() : key_(NULL) {} |
225 | 248 |
226 } // namespace crypto | 249 } // namespace crypto |
OLD | NEW |