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 OpenSSLErrStackTracer err_tracer(FROM_HERE); |
201 // key, is 0x04 (meaning uncompressed) followed by the x and y field | |
202 // elements as 32-byte, big-endian numbers. | |
203 static const int kExpectedKeyLength = 65; | |
204 | 187 |
205 int len = i2d_PublicKey(key_, NULL); | 188 // Export the x and y field elements as 32-byte, big-endian numbers. (This is |
206 if (len != kExpectedKeyLength) | 189 // the same as X9.62 uncompressed form without the leading 0x04 byte.) |
| 190 EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(key_); |
| 191 ScopedBIGNUM x(BN_new()); |
| 192 ScopedBIGNUM y(BN_new()); |
| 193 uint8_t buf[64]; |
| 194 if (!x || !y || |
| 195 !EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(ec_key), |
| 196 EC_KEY_get0_public_key(ec_key), |
| 197 x.get(), y.get(), nullptr) || |
| 198 !BN_bn2bin_padded(buf, 32, x.get()) || |
| 199 !BN_bn2bin_padded(buf + 32, 32, y.get())) { |
207 return false; | 200 return false; |
| 201 } |
208 | 202 |
209 uint8_t buf[kExpectedKeyLength]; | 203 output->assign(reinterpret_cast<const char*>(buf), sizeof(buf)); |
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; | 204 return true; |
217 } | 205 } |
218 | 206 |
219 bool ECPrivateKey::ExportValue(std::vector<uint8_t>* output) { | 207 bool ECPrivateKey::ExportValueForTesting(std::vector<uint8_t>* output) { |
220 OpenSSLErrStackTracer err_tracer(FROM_HERE); | 208 OpenSSLErrStackTracer err_tracer(FROM_HERE); |
221 ScopedEC_KEY ec_key(EVP_PKEY_get1_EC_KEY(key_)); | 209 EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(key_); |
222 return ExportKey(ec_key.get(), | 210 uint8_t *der; |
223 reinterpret_cast<ExportDataFunction>(i2d_ECPrivateKey), | 211 size_t der_len; |
224 output); | 212 AutoCBB cbb; |
225 } | 213 if (!CBB_init(cbb.get(), 0) || |
226 | 214 !EC_KEY_marshal_private_key(cbb.get(), ec_key, 0 /* enc_flags */) || |
227 bool ECPrivateKey::ExportECParams(std::vector<uint8_t>* output) { | 215 !CBB_finish(cbb.get(), &der, &der_len)) { |
228 OpenSSLErrStackTracer err_tracer(FROM_HERE); | 216 return false; |
229 ScopedEC_KEY ec_key(EVP_PKEY_get1_EC_KEY(key_)); | 217 } |
230 return ExportKey(ec_key.get(), | 218 output->assign(der, der + der_len); |
231 reinterpret_cast<ExportDataFunction>(i2d_ECParameters), | 219 OPENSSL_free(der); |
232 output); | 220 return true; |
233 } | 221 } |
234 | 222 |
235 ECPrivateKey::ECPrivateKey() : key_(NULL) {} | 223 ECPrivateKey::ECPrivateKey() : key_(NULL) {} |
236 | 224 |
237 } // namespace crypto | 225 } // namespace crypto |
OLD | NEW |