xref: /aosp_15_r20/external/cronet/crypto/unexportable_key_software_unsecure.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2023 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "base/check.h"
6 #include "build/build_config.h"
7 #include "crypto/sha2.h"
8 #include "crypto/signature_verifier.h"
9 #include "crypto/unexportable_key.h"
10 #include "third_party/boringssl/src/include/openssl/bytestring.h"
11 #include "third_party/boringssl/src/include/openssl/ec.h"
12 #include "third_party/boringssl/src/include/openssl/ec_key.h"
13 #include "third_party/boringssl/src/include/openssl/ecdsa.h"
14 #include "third_party/boringssl/src/include/openssl/evp.h"
15 #include "third_party/boringssl/src/include/openssl/obj.h"
16 
17 #if BUILDFLAG(IS_MAC)
18 #include "base/notreached.h"
19 #endif  // BUILDFLAG(IS_MAC)
20 
21 namespace crypto {
22 
23 namespace {
24 
CBBToVector(const CBB * cbb)25 std::vector<uint8_t> CBBToVector(const CBB* cbb) {
26   return std::vector<uint8_t>(CBB_data(cbb), CBB_data(cbb) + CBB_len(cbb));
27 }
28 
29 class SoftwareECDSA : public UnexportableSigningKey {
30  public:
SoftwareECDSA(bssl::UniquePtr<EC_KEY> key)31   explicit SoftwareECDSA(bssl::UniquePtr<EC_KEY> key) : key_(std::move(key)) {}
32   ~SoftwareECDSA() override = default;
33 
Algorithm() const34   SignatureVerifier::SignatureAlgorithm Algorithm() const override {
35     return SignatureVerifier::SignatureAlgorithm::ECDSA_SHA256;
36   }
37 
GetSubjectPublicKeyInfo() const38   std::vector<uint8_t> GetSubjectPublicKeyInfo() const override {
39     bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
40     CHECK(EVP_PKEY_set1_EC_KEY(pkey.get(), key_.get()));
41 
42     bssl::ScopedCBB cbb;
43     CHECK(CBB_init(cbb.get(), /*initial_capacity=*/128) &&
44           EVP_marshal_public_key(cbb.get(), pkey.get()));
45     return CBBToVector(cbb.get());
46   }
47 
GetWrappedKey() const48   std::vector<uint8_t> GetWrappedKey() const override {
49     bssl::ScopedCBB cbb;
50     CHECK(
51         CBB_init(cbb.get(), /*initial_capacity=*/128) &&
52         EC_KEY_marshal_private_key(cbb.get(), key_.get(),
53                                    EC_PKEY_NO_PARAMETERS | EC_PKEY_NO_PUBKEY));
54     return CBBToVector(cbb.get());
55   }
56 
SignSlowly(base::span<const uint8_t> data)57   std::optional<std::vector<uint8_t>> SignSlowly(
58       base::span<const uint8_t> data) override {
59     std::vector<uint8_t> ret(ECDSA_size(key_.get()));
60     std::array<uint8_t, kSHA256Length> digest = SHA256Hash(data);
61     unsigned int ret_size;
62     CHECK(ECDSA_sign(0, digest.data(), digest.size(), ret.data(), &ret_size,
63                      key_.get()));
64     ret.resize(ret_size);
65     return ret;
66   }
67 
68 #if BUILDFLAG(IS_MAC)
GetSecKeyRef() const69   SecKeyRef GetSecKeyRef() const override {
70     NOTREACHED();
71     return nullptr;
72   }
73 #endif  // BUILDFLAG(IS_MAC)
74 
75  private:
76   bssl::UniquePtr<EC_KEY> key_;
77 };
78 
79 class SoftwareProvider : public UnexportableKeyProvider {
80  public:
81   ~SoftwareProvider() override = default;
82 
SelectAlgorithm(base::span<const SignatureVerifier::SignatureAlgorithm> acceptable_algorithms)83   std::optional<SignatureVerifier::SignatureAlgorithm> SelectAlgorithm(
84       base::span<const SignatureVerifier::SignatureAlgorithm>
85           acceptable_algorithms) override {
86     for (auto algo : acceptable_algorithms) {
87       if (algo == SignatureVerifier::SignatureAlgorithm::ECDSA_SHA256) {
88         return algo;
89       }
90     }
91 
92     return std::nullopt;
93   }
94 
GenerateSigningKeySlowly(base::span<const SignatureVerifier::SignatureAlgorithm> acceptable_algorithms)95   std::unique_ptr<UnexportableSigningKey> GenerateSigningKeySlowly(
96       base::span<const SignatureVerifier::SignatureAlgorithm>
97           acceptable_algorithms) override {
98     if (!SelectAlgorithm(acceptable_algorithms)) {
99       return nullptr;
100     }
101 
102     bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
103     CHECK(EC_KEY_generate_key(key.get()));
104 
105     return std::make_unique<SoftwareECDSA>(std::move(key));
106   }
107 
FromWrappedSigningKeySlowly(base::span<const uint8_t> wrapped_key)108   std::unique_ptr<UnexportableSigningKey> FromWrappedSigningKeySlowly(
109       base::span<const uint8_t> wrapped_key) override {
110     bssl::UniquePtr<EC_GROUP> p256(
111         EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
112     CBS cbs;
113     CBS_init(&cbs, wrapped_key.data(), wrapped_key.size());
114     bssl::UniquePtr<EC_KEY> key(EC_KEY_parse_private_key(&cbs, p256.get()));
115     if (!key || CBS_len(&cbs) != 0) {
116       return nullptr;
117     }
118     return std::make_unique<SoftwareECDSA>(std::move(key));
119   }
120 
DeleteSigningKey(base::span<const uint8_t> wrapped_key)121   bool DeleteSigningKey(base::span<const uint8_t> wrapped_key) override {
122     // Unexportable software keys are stateless.
123     return true;
124   }
125 };
126 
127 }  // namespace
128 
129 std::unique_ptr<UnexportableKeyProvider>
GetSoftwareUnsecureUnexportableKeyProvider()130 GetSoftwareUnsecureUnexportableKeyProvider() {
131   return std::make_unique<SoftwareProvider>();
132 }
133 
134 }  // namespace crypto
135