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/ec.h> | 8 #include <openssl/ec.h> |
8 #include <openssl/evp.h> | 9 #include <openssl/evp.h> |
10 #include <openssl/mem.h> | |
9 #include <openssl/pkcs12.h> | 11 #include <openssl/pkcs12.h> |
10 #include <openssl/x509.h> | 12 #include <openssl/x509.h> |
11 #include <stddef.h> | 13 #include <stddef.h> |
12 #include <stdint.h> | 14 #include <stdint.h> |
13 | 15 |
14 #include "base/logging.h" | 16 #include "base/logging.h" |
15 #include "base/memory/scoped_ptr.h" | 17 #include "base/memory/scoped_ptr.h" |
18 #include "crypto/auto_cbb.h" | |
16 #include "crypto/openssl_util.h" | 19 #include "crypto/openssl_util.h" |
17 #include "crypto/scoped_openssl_types.h" | 20 #include "crypto/scoped_openssl_types.h" |
18 | 21 |
19 namespace crypto { | 22 namespace crypto { |
20 | 23 |
21 namespace { | 24 namespace { |
22 | 25 |
23 // Function pointer definition, for injecting the required key export function | 26 // Function pointer definition, for injecting the required key export function |
24 // into ExportKeyWithBio, below. |bio| is a temporary memory BIO object, and | 27 // into ExportKeyWithBio, below. |bio| is a temporary memory BIO object, and |
25 // |key| is a handle to the input key object. Return 1 on success, 0 otherwise. | 28 // |key| is a handle to the input key object. Return 1 on success, 0 otherwise. |
(...skipping 21 matching lines...) Expand all Loading... | |
47 | 50 |
48 char* data = NULL; | 51 char* data = NULL; |
49 long len = BIO_get_mem_data(bio.get(), &data); | 52 long len = BIO_get_mem_data(bio.get(), &data); |
50 if (!data || len < 0) | 53 if (!data || len < 0) |
51 return false; | 54 return false; |
52 | 55 |
53 output->assign(data, data + len); | 56 output->assign(data, data + len); |
54 return true; | 57 return true; |
55 } | 58 } |
56 | 59 |
57 // Function pointer definition, for injecting the required key export function | |
58 // into ExportKey below. |key| is a pointer to the input key object, | |
59 // and |data| is either NULL, or the address of an 'unsigned char*' pointer | |
60 // that points to the start of the output buffer. The function must return | |
61 // the number of bytes required to export the data, or -1 in case of error. | |
62 typedef int (*ExportDataFunction)(const void* key, unsigned char** data); | |
63 | |
64 // Helper to export |key| into |output| via the specified export function. | |
65 bool ExportKey(const void* key, | |
66 ExportDataFunction export_fn, | |
67 std::vector<uint8_t>* output) { | |
68 if (!key) | |
69 return false; | |
70 | |
71 int data_len = export_fn(key, NULL); | |
72 if (data_len < 0) | |
73 return false; | |
74 | |
75 output->resize(static_cast<size_t>(data_len)); | |
76 unsigned char* data = &(*output)[0]; | |
77 if (export_fn(key, &data) < 0) | |
78 return false; | |
79 | |
80 return true; | |
81 } | |
82 | |
83 } // namespace | 60 } // namespace |
84 | 61 |
85 ECPrivateKey::~ECPrivateKey() { | 62 ECPrivateKey::~ECPrivateKey() { |
86 if (key_) | 63 if (key_) |
87 EVP_PKEY_free(key_); | 64 EVP_PKEY_free(key_); |
88 } | 65 } |
89 | 66 |
90 ECPrivateKey* ECPrivateKey::Copy() const { | 67 ECPrivateKey* ECPrivateKey::Copy() const { |
91 scoped_ptr<ECPrivateKey> copy(new ECPrivateKey); | 68 scoped_ptr<ECPrivateKey> copy(new ECPrivateKey); |
92 if (key_) | 69 if (key_) |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
185 return false; | 162 return false; |
186 | 163 |
187 // Write it into |*output| | 164 // Write it into |*output| |
188 return ExportKeyWithBio(encrypted.get(), | 165 return ExportKeyWithBio(encrypted.get(), |
189 reinterpret_cast<ExportBioFunction>(i2d_PKCS8_bio), | 166 reinterpret_cast<ExportBioFunction>(i2d_PKCS8_bio), |
190 output); | 167 output); |
191 } | 168 } |
192 | 169 |
193 bool ECPrivateKey::ExportPublicKey(std::vector<uint8_t>* output) { | 170 bool ECPrivateKey::ExportPublicKey(std::vector<uint8_t>* output) { |
194 OpenSSLErrStackTracer err_tracer(FROM_HERE); | 171 OpenSSLErrStackTracer err_tracer(FROM_HERE); |
195 return ExportKeyWithBio( | 172 uint8_t *der; |
196 key_, reinterpret_cast<ExportBioFunction>(i2d_PUBKEY_bio), output); | 173 size_t der_len; |
174 AutoCBB cbb; | |
175 if (!CBB_init(cbb.get(), 0) || | |
176 !EVP_marshal_public_key(cbb.get(), key_) || | |
177 !CBB_finish(cbb.get(), &der, &der_len)) { | |
178 return false; | |
179 } | |
180 output->assign(der, der + der_len); | |
181 OPENSSL_free(der); | |
182 return true; | |
197 } | 183 } |
198 | 184 |
199 bool ECPrivateKey::ExportRawPublicKey(std::string* output) { | 185 bool ECPrivateKey::ExportRawPublicKey(std::string* output) { |
200 // i2d_PublicKey will produce an ANSI X9.62 public key which, for a P-256 | 186 // Export the x and y field elements as 32-byte, big-endian numbers. (This is |
201 // key, is 0x04 (meaning uncompressed) followed by the x and y field | 187 // the same as X9.62 uncompressed form without the leading 0x04 byte.) |
202 // elements as 32-byte, big-endian numbers. | 188 EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(key_); |
203 static const int kExpectedKeyLength = 65; | 189 ScopedBIGNUM x(BN_new()); |
190 ScopedBIGNUM y(BN_new()); | |
191 uint8_t buf[64]; | |
192 if (!x || !y || | |
193 !EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(ec_key), | |
194 EC_KEY_get0_public_key(ec_key), | |
195 x.get(), y.get(), nullptr) || | |
196 !BN_bn2bin_padded(buf, 32, x.get()) || | |
197 !BN_bn2bin_padded(buf + 32, 32, x.get())) { | |
198 return false; | |
199 } | |
204 | 200 |
205 int len = i2d_PublicKey(key_, NULL); | 201 output->assign(reinterpret_cast<const char*>(buf), sizeof(buf)); |
206 if (len != kExpectedKeyLength) | |
207 return false; | |
208 | |
209 uint8_t buf[kExpectedKeyLength]; | |
210 uint8_t* derp = buf; | |
211 len = i2d_PublicKey(key_, &derp); | |
212 if (len != kExpectedKeyLength) | |
213 return false; | |
214 | |
215 output->assign(reinterpret_cast<char*>(buf + 1), kExpectedKeyLength - 1); | |
216 return true; | 202 return true; |
217 } | 203 } |
218 | 204 |
219 bool ECPrivateKey::ExportValue(std::vector<uint8_t>* output) { | 205 bool ECPrivateKey::ExportValueForTesting(std::vector<uint8_t>* output) { |
220 OpenSSLErrStackTracer err_tracer(FROM_HERE); | 206 OpenSSLErrStackTracer err_tracer(FROM_HERE); |
Ryan Sleevi
2016/02/26 23:16:08
Did we also need this for line 186?
davidben
2016/02/26 23:45:35
Done. (One of these days, we'll figure out how to
| |
221 ScopedEC_KEY ec_key(EVP_PKEY_get1_EC_KEY(key_)); | 207 EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(key_); |
222 return ExportKey(ec_key.get(), | 208 uint8_t *der; |
223 reinterpret_cast<ExportDataFunction>(i2d_ECPrivateKey), | 209 size_t der_len; |
224 output); | 210 AutoCBB cbb; |
225 } | 211 if (!CBB_init(cbb.get(), 0) || |
226 | 212 !EC_KEY_marshal_private_key(cbb.get(), ec_key, 0 /* enc_flags */) || |
227 bool ECPrivateKey::ExportECParams(std::vector<uint8_t>* output) { | 213 !CBB_finish(cbb.get(), &der, &der_len)) { |
228 OpenSSLErrStackTracer err_tracer(FROM_HERE); | 214 return false; |
229 ScopedEC_KEY ec_key(EVP_PKEY_get1_EC_KEY(key_)); | 215 } |
230 return ExportKey(ec_key.get(), | 216 output->assign(der, der + der_len); |
231 reinterpret_cast<ExportDataFunction>(i2d_ECParameters), | 217 OPENSSL_free(der); |
232 output); | 218 return true; |
233 } | 219 } |
234 | 220 |
235 ECPrivateKey::ECPrivateKey() : key_(NULL) {} | 221 ECPrivateKey::ECPrivateKey() : key_(NULL) {} |
236 | 222 |
237 } // namespace crypto | 223 } // namespace crypto |
OLD | NEW |