1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker #include "crypto/ec_private_key.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include <stddef.h>
8*6777b538SAndroid Build Coastguard Worker #include <stdint.h>
9*6777b538SAndroid Build Coastguard Worker
10*6777b538SAndroid Build Coastguard Worker #include <utility>
11*6777b538SAndroid Build Coastguard Worker
12*6777b538SAndroid Build Coastguard Worker #include "base/check_op.h"
13*6777b538SAndroid Build Coastguard Worker #include "crypto/openssl_util.h"
14*6777b538SAndroid Build Coastguard Worker #include "third_party/boringssl/src/include/openssl/bytestring.h"
15*6777b538SAndroid Build Coastguard Worker #include "third_party/boringssl/src/include/openssl/ec.h"
16*6777b538SAndroid Build Coastguard Worker #include "third_party/boringssl/src/include/openssl/ec_key.h"
17*6777b538SAndroid Build Coastguard Worker #include "third_party/boringssl/src/include/openssl/evp.h"
18*6777b538SAndroid Build Coastguard Worker #include "third_party/boringssl/src/include/openssl/mem.h"
19*6777b538SAndroid Build Coastguard Worker #include "third_party/boringssl/src/include/openssl/pkcs8.h"
20*6777b538SAndroid Build Coastguard Worker
21*6777b538SAndroid Build Coastguard Worker namespace crypto {
22*6777b538SAndroid Build Coastguard Worker
23*6777b538SAndroid Build Coastguard Worker ECPrivateKey::~ECPrivateKey() = default;
24*6777b538SAndroid Build Coastguard Worker
25*6777b538SAndroid Build Coastguard Worker // static
Create()26*6777b538SAndroid Build Coastguard Worker std::unique_ptr<ECPrivateKey> ECPrivateKey::Create() {
27*6777b538SAndroid Build Coastguard Worker OpenSSLErrStackTracer err_tracer(FROM_HERE);
28*6777b538SAndroid Build Coastguard Worker
29*6777b538SAndroid Build Coastguard Worker bssl::UniquePtr<EC_KEY> ec_key(
30*6777b538SAndroid Build Coastguard Worker EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
31*6777b538SAndroid Build Coastguard Worker if (!ec_key || !EC_KEY_generate_key(ec_key.get()))
32*6777b538SAndroid Build Coastguard Worker return nullptr;
33*6777b538SAndroid Build Coastguard Worker
34*6777b538SAndroid Build Coastguard Worker std::unique_ptr<ECPrivateKey> result(new ECPrivateKey());
35*6777b538SAndroid Build Coastguard Worker result->key_.reset(EVP_PKEY_new());
36*6777b538SAndroid Build Coastguard Worker if (!result->key_ || !EVP_PKEY_set1_EC_KEY(result->key_.get(), ec_key.get()))
37*6777b538SAndroid Build Coastguard Worker return nullptr;
38*6777b538SAndroid Build Coastguard Worker
39*6777b538SAndroid Build Coastguard Worker CHECK_EQ(EVP_PKEY_EC, EVP_PKEY_id(result->key_.get()));
40*6777b538SAndroid Build Coastguard Worker return result;
41*6777b538SAndroid Build Coastguard Worker }
42*6777b538SAndroid Build Coastguard Worker
43*6777b538SAndroid Build Coastguard Worker // static
CreateFromPrivateKeyInfo(base::span<const uint8_t> input)44*6777b538SAndroid Build Coastguard Worker std::unique_ptr<ECPrivateKey> ECPrivateKey::CreateFromPrivateKeyInfo(
45*6777b538SAndroid Build Coastguard Worker base::span<const uint8_t> input) {
46*6777b538SAndroid Build Coastguard Worker OpenSSLErrStackTracer err_tracer(FROM_HERE);
47*6777b538SAndroid Build Coastguard Worker
48*6777b538SAndroid Build Coastguard Worker CBS cbs;
49*6777b538SAndroid Build Coastguard Worker CBS_init(&cbs, input.data(), input.size());
50*6777b538SAndroid Build Coastguard Worker bssl::UniquePtr<EVP_PKEY> pkey(EVP_parse_private_key(&cbs));
51*6777b538SAndroid Build Coastguard Worker if (!pkey || CBS_len(&cbs) != 0 || EVP_PKEY_id(pkey.get()) != EVP_PKEY_EC)
52*6777b538SAndroid Build Coastguard Worker return nullptr;
53*6777b538SAndroid Build Coastguard Worker
54*6777b538SAndroid Build Coastguard Worker std::unique_ptr<ECPrivateKey> result(new ECPrivateKey());
55*6777b538SAndroid Build Coastguard Worker result->key_ = std::move(pkey);
56*6777b538SAndroid Build Coastguard Worker return result;
57*6777b538SAndroid Build Coastguard Worker }
58*6777b538SAndroid Build Coastguard Worker
59*6777b538SAndroid Build Coastguard Worker // static
CreateFromEncryptedPrivateKeyInfo(base::span<const uint8_t> encrypted_private_key_info)60*6777b538SAndroid Build Coastguard Worker std::unique_ptr<ECPrivateKey> ECPrivateKey::CreateFromEncryptedPrivateKeyInfo(
61*6777b538SAndroid Build Coastguard Worker base::span<const uint8_t> encrypted_private_key_info) {
62*6777b538SAndroid Build Coastguard Worker OpenSSLErrStackTracer err_tracer(FROM_HERE);
63*6777b538SAndroid Build Coastguard Worker
64*6777b538SAndroid Build Coastguard Worker CBS cbs;
65*6777b538SAndroid Build Coastguard Worker CBS_init(&cbs, encrypted_private_key_info.data(),
66*6777b538SAndroid Build Coastguard Worker encrypted_private_key_info.size());
67*6777b538SAndroid Build Coastguard Worker bssl::UniquePtr<EVP_PKEY> pkey(
68*6777b538SAndroid Build Coastguard Worker PKCS8_parse_encrypted_private_key(&cbs, "", 0));
69*6777b538SAndroid Build Coastguard Worker
70*6777b538SAndroid Build Coastguard Worker // Hack for reading keys generated by an older version of the OpenSSL code.
71*6777b538SAndroid Build Coastguard Worker // Some implementations encode the empty password as "\0\0" (passwords are
72*6777b538SAndroid Build Coastguard Worker // normally encoded in big-endian UCS-2 with a NUL terminator) and some
73*6777b538SAndroid Build Coastguard Worker // encode as the empty string. PKCS8_parse_encrypted_private_key
74*6777b538SAndroid Build Coastguard Worker // distinguishes the two by whether the password is nullptr.
75*6777b538SAndroid Build Coastguard Worker if (!pkey) {
76*6777b538SAndroid Build Coastguard Worker CBS_init(&cbs, encrypted_private_key_info.data(),
77*6777b538SAndroid Build Coastguard Worker encrypted_private_key_info.size());
78*6777b538SAndroid Build Coastguard Worker pkey.reset(PKCS8_parse_encrypted_private_key(&cbs, nullptr, 0));
79*6777b538SAndroid Build Coastguard Worker }
80*6777b538SAndroid Build Coastguard Worker
81*6777b538SAndroid Build Coastguard Worker if (!pkey || CBS_len(&cbs) != 0 || EVP_PKEY_id(pkey.get()) != EVP_PKEY_EC)
82*6777b538SAndroid Build Coastguard Worker return nullptr;
83*6777b538SAndroid Build Coastguard Worker
84*6777b538SAndroid Build Coastguard Worker std::unique_ptr<ECPrivateKey> result(new ECPrivateKey());
85*6777b538SAndroid Build Coastguard Worker result->key_ = std::move(pkey);
86*6777b538SAndroid Build Coastguard Worker return result;
87*6777b538SAndroid Build Coastguard Worker }
88*6777b538SAndroid Build Coastguard Worker
Copy() const89*6777b538SAndroid Build Coastguard Worker std::unique_ptr<ECPrivateKey> ECPrivateKey::Copy() const {
90*6777b538SAndroid Build Coastguard Worker std::unique_ptr<ECPrivateKey> copy(new ECPrivateKey());
91*6777b538SAndroid Build Coastguard Worker copy->key_ = bssl::UpRef(key_);
92*6777b538SAndroid Build Coastguard Worker return copy;
93*6777b538SAndroid Build Coastguard Worker }
94*6777b538SAndroid Build Coastguard Worker
ExportPrivateKey(std::vector<uint8_t> * output) const95*6777b538SAndroid Build Coastguard Worker bool ECPrivateKey::ExportPrivateKey(std::vector<uint8_t>* output) const {
96*6777b538SAndroid Build Coastguard Worker OpenSSLErrStackTracer err_tracer(FROM_HERE);
97*6777b538SAndroid Build Coastguard Worker uint8_t* der;
98*6777b538SAndroid Build Coastguard Worker size_t der_len;
99*6777b538SAndroid Build Coastguard Worker bssl::ScopedCBB cbb;
100*6777b538SAndroid Build Coastguard Worker if (!CBB_init(cbb.get(), 0) ||
101*6777b538SAndroid Build Coastguard Worker !EVP_marshal_private_key(cbb.get(), key_.get()) ||
102*6777b538SAndroid Build Coastguard Worker !CBB_finish(cbb.get(), &der, &der_len)) {
103*6777b538SAndroid Build Coastguard Worker return false;
104*6777b538SAndroid Build Coastguard Worker }
105*6777b538SAndroid Build Coastguard Worker output->assign(der, der + der_len);
106*6777b538SAndroid Build Coastguard Worker OPENSSL_free(der);
107*6777b538SAndroid Build Coastguard Worker return true;
108*6777b538SAndroid Build Coastguard Worker }
109*6777b538SAndroid Build Coastguard Worker
ExportPublicKey(std::vector<uint8_t> * output) const110*6777b538SAndroid Build Coastguard Worker bool ECPrivateKey::ExportPublicKey(std::vector<uint8_t>* output) const {
111*6777b538SAndroid Build Coastguard Worker OpenSSLErrStackTracer err_tracer(FROM_HERE);
112*6777b538SAndroid Build Coastguard Worker uint8_t* der;
113*6777b538SAndroid Build Coastguard Worker size_t der_len;
114*6777b538SAndroid Build Coastguard Worker bssl::ScopedCBB cbb;
115*6777b538SAndroid Build Coastguard Worker if (!CBB_init(cbb.get(), 0) ||
116*6777b538SAndroid Build Coastguard Worker !EVP_marshal_public_key(cbb.get(), key_.get()) ||
117*6777b538SAndroid Build Coastguard Worker !CBB_finish(cbb.get(), &der, &der_len)) {
118*6777b538SAndroid Build Coastguard Worker return false;
119*6777b538SAndroid Build Coastguard Worker }
120*6777b538SAndroid Build Coastguard Worker output->assign(der, der + der_len);
121*6777b538SAndroid Build Coastguard Worker OPENSSL_free(der);
122*6777b538SAndroid Build Coastguard Worker return true;
123*6777b538SAndroid Build Coastguard Worker }
124*6777b538SAndroid Build Coastguard Worker
ExportRawPublicKey(std::string * output) const125*6777b538SAndroid Build Coastguard Worker bool ECPrivateKey::ExportRawPublicKey(std::string* output) const {
126*6777b538SAndroid Build Coastguard Worker OpenSSLErrStackTracer err_tracer(FROM_HERE);
127*6777b538SAndroid Build Coastguard Worker
128*6777b538SAndroid Build Coastguard Worker std::array<uint8_t, 65> buf;
129*6777b538SAndroid Build Coastguard Worker EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(key_.get());
130*6777b538SAndroid Build Coastguard Worker if (!EC_POINT_point2oct(EC_KEY_get0_group(ec_key),
131*6777b538SAndroid Build Coastguard Worker EC_KEY_get0_public_key(ec_key),
132*6777b538SAndroid Build Coastguard Worker POINT_CONVERSION_UNCOMPRESSED, buf.data(), buf.size(),
133*6777b538SAndroid Build Coastguard Worker /*ctx=*/nullptr)) {
134*6777b538SAndroid Build Coastguard Worker return false;
135*6777b538SAndroid Build Coastguard Worker }
136*6777b538SAndroid Build Coastguard Worker
137*6777b538SAndroid Build Coastguard Worker output->assign(buf.begin(), buf.end());
138*6777b538SAndroid Build Coastguard Worker return true;
139*6777b538SAndroid Build Coastguard Worker }
140*6777b538SAndroid Build Coastguard Worker
141*6777b538SAndroid Build Coastguard Worker ECPrivateKey::ECPrivateKey() = default;
142*6777b538SAndroid Build Coastguard Worker
143*6777b538SAndroid Build Coastguard Worker } // namespace crypto
144