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