blob: 290770a50c57da4e5e6a4f2f5e10523feb9c4545 [file] [log] [blame]
[email protected]ab782c92012-07-09 23:12:141// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]eaa60482011-11-09 05:08:512// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "crypto/ec_private_key.h"
6
avidd373b8b2015-12-21 21:34:437#include <stddef.h>
8#include <stdint.h>
[email protected]d4db0b62013-10-17 16:09:249
davidben74f67442016-10-01 01:45:2210#include <utility>
11
[email protected]eaa60482011-11-09 05:08:5112#include "base/logging.h"
[email protected]d4db0b62013-10-17 16:09:2413#include "crypto/openssl_util.h"
tfarina29a3a1742016-10-28 18:47:3314#include "third_party/boringssl/src/include/openssl/bn.h"
15#include "third_party/boringssl/src/include/openssl/bytestring.h"
16#include "third_party/boringssl/src/include/openssl/ec.h"
17#include "third_party/boringssl/src/include/openssl/ec_key.h"
18#include "third_party/boringssl/src/include/openssl/evp.h"
19#include "third_party/boringssl/src/include/openssl/mem.h"
davidbenb8adc352017-04-03 21:10:3220#include "third_party/boringssl/src/include/openssl/pkcs8.h"
[email protected]eaa60482011-11-09 05:08:5121
22namespace crypto {
23
Chris Watkinsa850a302017-11-30 03:53:4924ECPrivateKey::~ECPrivateKey() = default;
[email protected]ab782c92012-07-09 23:12:1425
26// static
rsleeviffe5a132016-06-28 01:51:5227std::unique_ptr<ECPrivateKey> ECPrivateKey::Create() {
[email protected]d4db0b62013-10-17 16:09:2428 OpenSSLErrStackTracer err_tracer(FROM_HERE);
29
davidben74f67442016-10-01 01:45:2230 bssl::UniquePtr<EC_KEY> ec_key(
31 EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
rsleeviffe5a132016-06-28 01:51:5232 if (!ec_key || !EC_KEY_generate_key(ec_key.get()))
33 return nullptr;
[email protected]d4db0b62013-10-17 16:09:2434
thakisd1a18472016-04-08 22:30:4135 std::unique_ptr<ECPrivateKey> result(new ECPrivateKey());
davidben74f67442016-10-01 01:45:2236 result->key_.reset(EVP_PKEY_new());
37 if (!result->key_ || !EVP_PKEY_set1_EC_KEY(result->key_.get(), ec_key.get()))
rsleeviffe5a132016-06-28 01:51:5238 return nullptr;
[email protected]d4db0b62013-10-17 16:09:2439
davidben74f67442016-10-01 01:45:2240 CHECK_EQ(EVP_PKEY_EC, EVP_PKEY_id(result->key_.get()));
rsleeviffe5a132016-06-28 01:51:5241 return result;
[email protected]eaa60482011-11-09 05:08:5142}
43
44// static
davidben212cdf62016-06-07 17:11:0945std::unique_ptr<ECPrivateKey> ECPrivateKey::CreateFromPrivateKeyInfo(
46 const std::vector<uint8_t>& input) {
47 OpenSSLErrStackTracer err_tracer(FROM_HERE);
48
49 CBS cbs;
50 CBS_init(&cbs, input.data(), input.size());
davidben74f67442016-10-01 01:45:2251 bssl::UniquePtr<EVP_PKEY> pkey(EVP_parse_private_key(&cbs));
davidben212cdf62016-06-07 17:11:0952 if (!pkey || CBS_len(&cbs) != 0 || EVP_PKEY_id(pkey.get()) != EVP_PKEY_EC)
53 return nullptr;
54
rsleeviffe5a132016-06-28 01:51:5255 std::unique_ptr<ECPrivateKey> result(new ECPrivateKey());
davidben74f67442016-10-01 01:45:2256 result->key_ = std::move(pkey);
davidben212cdf62016-06-07 17:11:0957 return result;
58}
59
60// static
rsleeviffe5a132016-06-28 01:51:5261std::unique_ptr<ECPrivateKey> ECPrivateKey::CreateFromEncryptedPrivateKeyInfo(
David Benjaminb86b0a082017-09-21 16:55:3662 const std::vector<uint8_t>& encrypted_private_key_info) {
[email protected]d4db0b62013-10-17 16:09:2463 OpenSSLErrStackTracer err_tracer(FROM_HERE);
[email protected]dc06f752014-08-06 23:11:0964
davidbenb8adc352017-04-03 21:10:3265 CBS cbs;
66 CBS_init(&cbs, encrypted_private_key_info.data(),
67 encrypted_private_key_info.size());
68 bssl::UniquePtr<EVP_PKEY> pkey(
69 PKCS8_parse_encrypted_private_key(&cbs, "", 0));
[email protected]d4db0b62013-10-17 16:09:2470
davidben1c02c94c2017-01-04 13:54:3271 // Hack for reading keys generated by an older version of the OpenSSL code.
72 // Some implementations encode the empty password as "\0\0" (passwords are
73 // normally encoded in big-endian UCS-2 with a NUL terminator) and some
davidbenb8adc352017-04-03 21:10:3274 // encode as the empty string. PKCS8_parse_encrypted_private_key
75 // distinguishes the two by whether the password is nullptr.
76 if (!pkey) {
77 CBS_init(&cbs, encrypted_private_key_info.data(),
78 encrypted_private_key_info.size());
79 pkey.reset(PKCS8_parse_encrypted_private_key(&cbs, nullptr, 0));
80 }
[email protected]dc06f752014-08-06 23:11:0981
davidbenb8adc352017-04-03 21:10:3282 if (!pkey || CBS_len(&cbs) != 0 || EVP_PKEY_id(pkey.get()) != EVP_PKEY_EC)
rsleeviffe5a132016-06-28 01:51:5283 return nullptr;
[email protected]d4db0b62013-10-17 16:09:2484
rsleeviffe5a132016-06-28 01:51:5285 std::unique_ptr<ECPrivateKey> result(new ECPrivateKey());
davidbenb8adc352017-04-03 21:10:3286 result->key_ = std::move(pkey);
rsleeviffe5a132016-06-28 01:51:5287 return result;
88}
89
90std::unique_ptr<ECPrivateKey> ECPrivateKey::Copy() const {
91 std::unique_ptr<ECPrivateKey> copy(new ECPrivateKey());
agl5a7cadf2016-07-13 16:52:5392 if (key_) {
davidben74f67442016-10-01 01:45:2293 EVP_PKEY_up_ref(key_.get());
94 copy->key_.reset(key_.get());
agl5a7cadf2016-07-13 16:52:5395 }
rsleeviffe5a132016-06-28 01:51:5296 return copy;
[email protected]eaa60482011-11-09 05:08:5197}
98
davidben212cdf62016-06-07 17:11:0999bool ECPrivateKey::ExportPrivateKey(std::vector<uint8_t>* output) const {
100 OpenSSLErrStackTracer err_tracer(FROM_HERE);
101 uint8_t* der;
102 size_t der_len;
davidben74f67442016-10-01 01:45:22103 bssl::ScopedCBB cbb;
104 if (!CBB_init(cbb.get(), 0) ||
105 !EVP_marshal_private_key(cbb.get(), key_.get()) ||
davidben212cdf62016-06-07 17:11:09106 !CBB_finish(cbb.get(), &der, &der_len)) {
107 return false;
108 }
109 output->assign(der, der + der_len);
110 OPENSSL_free(der);
111 return true;
112}
113
114bool ECPrivateKey::ExportEncryptedPrivateKey(
davidben212cdf62016-06-07 17:11:09115 std::vector<uint8_t>* output) const {
[email protected]d4db0b62013-10-17 16:09:24116 OpenSSLErrStackTracer err_tracer(FROM_HERE);
[email protected]d4db0b62013-10-17 16:09:24117
118 // Encrypt the object.
119 // NOTE: NSS uses SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC
120 // so use NID_pbe_WithSHA1And3_Key_TripleDES_CBC which should be the OpenSSL
121 // equivalent.
davidbenb8adc352017-04-03 21:10:32122 uint8_t* der;
123 size_t der_len;
124 bssl::ScopedCBB cbb;
125 if (!CBB_init(cbb.get(), 0) ||
126 !PKCS8_marshal_encrypted_private_key(
127 cbb.get(), NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
128 nullptr /* cipher */, nullptr /* no password */, 0 /* pass_len */,
129 nullptr /* salt */, 0 /* salt_len */, 1 /* iterations */,
130 key_.get()) ||
131 !CBB_finish(cbb.get(), &der, &der_len)) {
[email protected]d4db0b62013-10-17 16:09:24132 return false;
davidbenb8adc352017-04-03 21:10:32133 }
134 output->assign(der, der + der_len);
135 OPENSSL_free(der);
136 return true;
[email protected]eaa60482011-11-09 05:08:51137}
138
davidben212cdf62016-06-07 17:11:09139bool ECPrivateKey::ExportPublicKey(std::vector<uint8_t>* output) const {
[email protected]d4db0b62013-10-17 16:09:24140 OpenSSLErrStackTracer err_tracer(FROM_HERE);
davidben7dad2a32016-03-01 23:47:47141 uint8_t *der;
142 size_t der_len;
davidben74f67442016-10-01 01:45:22143 bssl::ScopedCBB cbb;
davidben7dad2a32016-03-01 23:47:47144 if (!CBB_init(cbb.get(), 0) ||
davidben74f67442016-10-01 01:45:22145 !EVP_marshal_public_key(cbb.get(), key_.get()) ||
davidben7dad2a32016-03-01 23:47:47146 !CBB_finish(cbb.get(), &der, &der_len)) {
[email protected]ac30ed0e2014-06-24 04:12:34147 return false;
davidben7dad2a32016-03-01 23:47:47148 }
149 output->assign(der, der + der_len);
150 OPENSSL_free(der);
[email protected]ac30ed0e2014-06-24 04:12:34151 return true;
152}
153
davidben212cdf62016-06-07 17:11:09154bool ECPrivateKey::ExportRawPublicKey(std::string* output) const {
[email protected]d4db0b62013-10-17 16:09:24155 OpenSSLErrStackTracer err_tracer(FROM_HERE);
davidben7dad2a32016-03-01 23:47:47156
157 // Export the x and y field elements as 32-byte, big-endian numbers. (This is
158 // the same as X9.62 uncompressed form without the leading 0x04 byte.)
davidben74f67442016-10-01 01:45:22159 EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(key_.get());
160 bssl::UniquePtr<BIGNUM> x(BN_new());
161 bssl::UniquePtr<BIGNUM> y(BN_new());
davidben7dad2a32016-03-01 23:47:47162 uint8_t buf[64];
163 if (!x || !y ||
164 !EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(ec_key),
165 EC_KEY_get0_public_key(ec_key),
166 x.get(), y.get(), nullptr) ||
167 !BN_bn2bin_padded(buf, 32, x.get()) ||
168 !BN_bn2bin_padded(buf + 32, 32, y.get())) {
169 return false;
170 }
171
172 output->assign(reinterpret_cast<const char*>(buf), sizeof(buf));
173 return true;
[email protected]eaa60482011-11-09 05:08:51174}
175
Chris Watkinsa850a302017-11-30 03:53:49176ECPrivateKey::ECPrivateKey() = default;
[email protected]d4db0b62013-10-17 16:09:24177
[email protected]eaa60482011-11-09 05:08:51178} // namespace crypto