xref: /aosp_15_r20/external/cronet/crypto/ec_private_key.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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