• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifdef UNSAFE_BUFFERS_BUILD
6 // TODO(crbug.com/351564777): Remove this and convert code to safer constructs.
7 #pragma allow_unsafe_buffers
8 #endif
9 
10 #include "base/check.h"
11 #include "build/build_config.h"
12 #include "crypto/sha2.h"
13 #include "crypto/signature_verifier.h"
14 #include "crypto/unexportable_key.h"
15 #include "third_party/boringssl/src/include/openssl/bn.h"
16 #include "third_party/boringssl/src/include/openssl/bytestring.h"
17 #include "third_party/boringssl/src/include/openssl/ec.h"
18 #include "third_party/boringssl/src/include/openssl/ec_key.h"
19 #include "third_party/boringssl/src/include/openssl/ecdsa.h"
20 #include "third_party/boringssl/src/include/openssl/evp.h"
21 #include "third_party/boringssl/src/include/openssl/obj.h"
22 #include "third_party/boringssl/src/include/openssl/rsa.h"
23 
24 #if BUILDFLAG(IS_MAC)
25 #include "base/notreached.h"
26 #endif  // BUILDFLAG(IS_MAC)
27 
28 namespace crypto {
29 
30 namespace {
31 
CBBToVector(const CBB * cbb)32 std::vector<uint8_t> CBBToVector(const CBB* cbb) {
33   return std::vector<uint8_t>(CBB_data(cbb), CBB_data(cbb) + CBB_len(cbb));
34 }
35 
36 class SoftwareECDSA : public UnexportableSigningKey {
37  public:
SoftwareECDSA(bssl::UniquePtr<EC_KEY> key)38   explicit SoftwareECDSA(bssl::UniquePtr<EC_KEY> key) : key_(std::move(key)) {}
39   ~SoftwareECDSA() override = default;
40 
Algorithm() const41   SignatureVerifier::SignatureAlgorithm Algorithm() const override {
42     return SignatureVerifier::SignatureAlgorithm::ECDSA_SHA256;
43   }
44 
GetSubjectPublicKeyInfo() const45   std::vector<uint8_t> GetSubjectPublicKeyInfo() const override {
46     bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
47     CHECK(EVP_PKEY_set1_EC_KEY(pkey.get(), key_.get()));
48 
49     bssl::ScopedCBB cbb;
50     CHECK(CBB_init(cbb.get(), /*initial_capacity=*/128) &&
51           EVP_marshal_public_key(cbb.get(), pkey.get()));
52     return CBBToVector(cbb.get());
53   }
54 
GetWrappedKey() const55   std::vector<uint8_t> GetWrappedKey() const override {
56     bssl::ScopedCBB cbb;
57     CHECK(
58         CBB_init(cbb.get(), /*initial_capacity=*/128) &&
59         EC_KEY_marshal_private_key(cbb.get(), key_.get(),
60                                    EC_PKEY_NO_PARAMETERS | EC_PKEY_NO_PUBKEY));
61     return CBBToVector(cbb.get());
62   }
63 
SignSlowly(base::span<const uint8_t> data)64   std::optional<std::vector<uint8_t>> SignSlowly(
65       base::span<const uint8_t> data) override {
66     std::vector<uint8_t> ret(ECDSA_size(key_.get()));
67     std::array<uint8_t, kSHA256Length> digest = SHA256Hash(data);
68     unsigned int ret_size;
69     CHECK(ECDSA_sign(0, digest.data(), digest.size(), ret.data(), &ret_size,
70                      key_.get()));
71     ret.resize(ret_size);
72     return ret;
73   }
74 
75 #if BUILDFLAG(IS_MAC)
GetSecKeyRef() const76   SecKeyRef GetSecKeyRef() const override { NOTREACHED(); }
77 #endif  // BUILDFLAG(IS_MAC)
78 
79  private:
80   bssl::UniquePtr<EC_KEY> key_;
81 };
82 
83 class SoftwareRSA : public UnexportableSigningKey {
84  public:
SoftwareRSA(bssl::UniquePtr<RSA> key)85   explicit SoftwareRSA(bssl::UniquePtr<RSA> key) : key_(std::move(key)) {}
86   ~SoftwareRSA() override = default;
87 
Algorithm() const88   SignatureVerifier::SignatureAlgorithm Algorithm() const override {
89     return SignatureVerifier::SignatureAlgorithm::RSA_PKCS1_SHA256;
90   }
91 
GetSubjectPublicKeyInfo() const92   std::vector<uint8_t> GetSubjectPublicKeyInfo() const override {
93     bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
94     CHECK(EVP_PKEY_set1_RSA(pkey.get(), key_.get()));
95 
96     bssl::ScopedCBB cbb;
97     CHECK(CBB_init(cbb.get(), /*initial_capacity=*/384) &&
98           EVP_marshal_public_key(cbb.get(), pkey.get()));
99     return CBBToVector(cbb.get());
100   }
101 
GetWrappedKey() const102   std::vector<uint8_t> GetWrappedKey() const override {
103     bssl::ScopedCBB cbb;
104     CHECK(CBB_init(cbb.get(), 384) &&
105           RSA_marshal_private_key(cbb.get(), key_.get()));
106     return CBBToVector(cbb.get());
107   }
108 
SignSlowly(base::span<const uint8_t> data)109   std::optional<std::vector<uint8_t>> SignSlowly(
110       base::span<const uint8_t> data) override {
111     std::vector<uint8_t> ret(RSA_size(key_.get()));
112     std::array<uint8_t, kSHA256Length> digest = SHA256Hash(data);
113     unsigned int ret_size;
114     CHECK(RSA_sign(NID_sha256, digest.data(), digest.size(), ret.data(),
115                    &ret_size, key_.get()));
116     ret.resize(ret_size);
117     return ret;
118   }
119 
120 #if BUILDFLAG(IS_MAC)
GetSecKeyRef() const121   SecKeyRef GetSecKeyRef() const override { NOTREACHED(); }
122 #endif  // BUILDFLAG(IS_MAC)
123 
124  private:
125   bssl::UniquePtr<RSA> key_;
126 };
127 
128 class SoftwareProvider : public UnexportableKeyProvider {
129  public:
130   ~SoftwareProvider() override = default;
131 
SelectAlgorithm(base::span<const SignatureVerifier::SignatureAlgorithm> acceptable_algorithms)132   std::optional<SignatureVerifier::SignatureAlgorithm> SelectAlgorithm(
133       base::span<const SignatureVerifier::SignatureAlgorithm>
134           acceptable_algorithms) override {
135     for (auto algo : acceptable_algorithms) {
136       switch (algo) {
137         case SignatureVerifier::SignatureAlgorithm::ECDSA_SHA256:
138         case SignatureVerifier::SignatureAlgorithm::RSA_PKCS1_SHA256:
139           return algo;
140         case SignatureVerifier::SignatureAlgorithm::RSA_PKCS1_SHA1:
141         case SignatureVerifier::SignatureAlgorithm::RSA_PSS_SHA256:
142           continue;  // Not supported
143       }
144     }
145 
146     return std::nullopt;
147   }
148 
GenerateSigningKeySlowly(base::span<const SignatureVerifier::SignatureAlgorithm> acceptable_algorithms)149   std::unique_ptr<UnexportableSigningKey> GenerateSigningKeySlowly(
150       base::span<const SignatureVerifier::SignatureAlgorithm>
151           acceptable_algorithms) override {
152     if (!SelectAlgorithm(acceptable_algorithms)) {
153       return nullptr;
154     }
155 
156     for (auto algo : acceptable_algorithms) {
157       switch (algo) {
158         case SignatureVerifier::SignatureAlgorithm::ECDSA_SHA256: {
159           bssl::UniquePtr<EC_KEY> key(
160               EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
161           CHECK(EC_KEY_generate_key(key.get()));
162           return std::make_unique<SoftwareECDSA>(std::move(key));
163         }
164 
165         case SignatureVerifier::SignatureAlgorithm::RSA_PKCS1_SHA256: {
166           bssl::UniquePtr<RSA> key(RSA_new());
167           bssl::UniquePtr<BIGNUM> e(BN_new());
168           BN_set_word(e.get(), RSA_F4);
169           RSA_generate_key_ex(key.get(), 2048, e.get(), nullptr);
170           return std::make_unique<SoftwareRSA>(std::move(key));
171         }
172         case SignatureVerifier::SignatureAlgorithm::RSA_PKCS1_SHA1:
173         case SignatureVerifier::SignatureAlgorithm::RSA_PSS_SHA256:
174           continue;  // Not supported
175       }
176     }
177 
178     return nullptr;
179   }
180 
FromWrappedSigningKeySlowly(base::span<const uint8_t> wrapped_key)181   std::unique_ptr<UnexportableSigningKey> FromWrappedSigningKeySlowly(
182       base::span<const uint8_t> wrapped_key) override {
183     {  // Try to parse ECDSA
184       CBS cbs;
185       CBS_init(&cbs, wrapped_key.data(), wrapped_key.size());
186       bssl::UniquePtr<EC_GROUP> p256(
187           EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
188       bssl::UniquePtr<EC_KEY> key(EC_KEY_parse_private_key(&cbs, p256.get()));
189       if (key && CBS_len(&cbs) == 0) {
190         return std::make_unique<SoftwareECDSA>(std::move(key));
191       }
192     }
193 
194     {  // Try RSA
195       CBS cbs;
196       CBS_init(&cbs, wrapped_key.data(), wrapped_key.size());
197       bssl::UniquePtr<RSA> key(RSA_parse_private_key(&cbs));
198       if (key && CBS_len(&cbs) == 0) {
199         return std::make_unique<SoftwareRSA>(std::move(key));
200       }
201     }
202 
203     return nullptr;
204   }
205 
DeleteSigningKeySlowly(base::span<const uint8_t> wrapped_key)206   bool DeleteSigningKeySlowly(base::span<const uint8_t> wrapped_key) override {
207     // Unexportable software keys are stateless.
208     return true;
209   }
210 };
211 
212 }  // namespace
213 
214 std::unique_ptr<UnexportableKeyProvider>
GetSoftwareUnsecureUnexportableKeyProvider()215 GetSoftwareUnsecureUnexportableKeyProvider() {
216   return std::make_unique<SoftwareProvider>();
217 }
218 
219 }  // namespace crypto
220