[go: nahoru, domu]

Reland "[DBSC] Make it easier to test binding keys on Linux and Mac"

This is a reland of commit 964303340b500b4c1d2e10fa00c3a91f9a786149

Orignal CL wasn't the cause for the test failures:
https://crbug.com/1464248#c3

Original change's description:
> [DBSC] Make it easier to test binding keys on Linux and Mac
>
> //crypto currently has an UnexportableKeyProvider support on Windows
> only. Since most of the future developers work on Linux and Mac, it will
> be helpful to be able to test the feature on these platforms.
>
> To facilite local development, this CL adds a mock software-backed
> implementation of an UnexportableKeyProvider behind a feature flag. This
> feature flag is expected to never be shipped to end users.
>
> The flag is checked on the UnexportableKeyService level, so only
> DBSC-related code will switch to an insecure implementation.
>
> Bug: b/290640296
> Change-Id: Iccd1d0c1733d3f5472380023377bd81df4e3f933
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4675882
> Reviewed-by: Adam Langley <agl@chromium.org>
> Reviewed-by: Kristian Monsen <kristianm@chromium.org>
> Commit-Queue: Alex Ilin <alexilin@chromium.org>
> Cr-Commit-Position: refs/heads/main@{#1168616}

Bug: b/290640296, 1464248
Change-Id: Ie749b8a48c2435d389bb13e5a9b69ccd7dbb7755
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4681330
Reviewed-by: Adam Langley <agl@chromium.org>
Commit-Queue: Adam Langley <agl@chromium.org>
Reviewed-by: Kristian Monsen <kristianm@chromium.org>
Auto-Submit: Alex Ilin <alexilin@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1171456}
diff --git a/crypto/BUILD.gn b/crypto/BUILD.gn
index 4444bb74..fb6b03d 100644
--- a/crypto/BUILD.gn
+++ b/crypto/BUILD.gn
@@ -56,6 +56,7 @@
     "unexportable_key.h",
     "unexportable_key_metrics.cc",
     "unexportable_key_metrics.h",
+    "unexportable_key_software_unsecure.cc",
   ]
 
   deps = [
diff --git a/crypto/scoped_mock_unexportable_key_provider.cc b/crypto/scoped_mock_unexportable_key_provider.cc
index 381e968..d0e3cf2 100644
--- a/crypto/scoped_mock_unexportable_key_provider.cc
+++ b/crypto/scoped_mock_unexportable_key_provider.cc
@@ -4,114 +4,15 @@
 
 #include <vector>
 
-#include "base/check.h"
 #include "crypto/scoped_mock_unexportable_key_provider.h"
-#include "crypto/sha2.h"
-#include "crypto/signature_verifier.h"
 #include "crypto/unexportable_key.h"
-#include "third_party/boringssl/src/include/openssl/bytestring.h"
-#include "third_party/boringssl/src/include/openssl/ec.h"
-#include "third_party/boringssl/src/include/openssl/ec_key.h"
-#include "third_party/boringssl/src/include/openssl/ecdsa.h"
-#include "third_party/boringssl/src/include/openssl/evp.h"
-#include "third_party/boringssl/src/include/openssl/obj.h"
 
 namespace crypto {
 
 namespace {
 
-std::vector<uint8_t> CBBToVector(const CBB* cbb) {
-  return std::vector<uint8_t>(CBB_data(cbb), CBB_data(cbb) + CBB_len(cbb));
-}
-
-class SoftwareECDSA : public UnexportableSigningKey {
- public:
-  explicit SoftwareECDSA(bssl::UniquePtr<EC_KEY> key) : key_(std::move(key)) {}
-  ~SoftwareECDSA() override = default;
-
-  SignatureVerifier::SignatureAlgorithm Algorithm() const override {
-    return SignatureVerifier::SignatureAlgorithm::ECDSA_SHA256;
-  }
-
-  std::vector<uint8_t> GetSubjectPublicKeyInfo() const override {
-    bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
-    CHECK(EVP_PKEY_set1_EC_KEY(pkey.get(), key_.get()));
-
-    bssl::ScopedCBB cbb;
-    CHECK(CBB_init(cbb.get(), /*initial_capacity=*/128) &&
-          EVP_marshal_public_key(cbb.get(), pkey.get()));
-    return CBBToVector(cbb.get());
-  }
-
-  std::vector<uint8_t> GetWrappedKey() const override {
-    bssl::ScopedCBB cbb;
-    CHECK(
-        CBB_init(cbb.get(), /*initial_capacity=*/128) &&
-        EC_KEY_marshal_private_key(cbb.get(), key_.get(),
-                                   EC_PKEY_NO_PARAMETERS | EC_PKEY_NO_PUBKEY));
-    return CBBToVector(cbb.get());
-  }
-
-  absl::optional<std::vector<uint8_t>> SignSlowly(
-      base::span<const uint8_t> data) override {
-    std::vector<uint8_t> ret(ECDSA_size(key_.get()));
-    std::array<uint8_t, kSHA256Length> digest = SHA256Hash(data);
-    unsigned int ret_size;
-    CHECK(ECDSA_sign(0, digest.data(), digest.size(), ret.data(), &ret_size,
-                     key_.get()));
-    ret.resize(ret_size);
-    return ret;
-  }
-
- private:
-  bssl::UniquePtr<EC_KEY> key_;
-};
-
-class SoftwareProvider : public UnexportableKeyProvider {
- public:
-  ~SoftwareProvider() override = default;
-
-  absl::optional<SignatureVerifier::SignatureAlgorithm> SelectAlgorithm(
-      base::span<const SignatureVerifier::SignatureAlgorithm>
-          acceptable_algorithms) override {
-    for (auto algo : acceptable_algorithms) {
-      if (algo == SignatureVerifier::SignatureAlgorithm::ECDSA_SHA256) {
-        return algo;
-      }
-    }
-
-    return absl::nullopt;
-  }
-
-  std::unique_ptr<UnexportableSigningKey> GenerateSigningKeySlowly(
-      base::span<const SignatureVerifier::SignatureAlgorithm>
-          acceptable_algorithms) override {
-    if (!SelectAlgorithm(acceptable_algorithms)) {
-      return nullptr;
-    }
-
-    bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
-    CHECK(EC_KEY_generate_key(key.get()));
-
-    return std::make_unique<SoftwareECDSA>(std::move(key));
-  }
-
-  std::unique_ptr<UnexportableSigningKey> FromWrappedSigningKeySlowly(
-      base::span<const uint8_t> wrapped_key) override {
-    bssl::UniquePtr<EC_GROUP> p256(
-        EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
-    CBS cbs;
-    CBS_init(&cbs, wrapped_key.data(), wrapped_key.size());
-    bssl::UniquePtr<EC_KEY> key(EC_KEY_parse_private_key(&cbs, p256.get()));
-    if (!key || CBS_len(&cbs) != 0) {
-      return nullptr;
-    }
-    return std::make_unique<SoftwareECDSA>(std::move(key));
-  }
-};
-
 std::unique_ptr<UnexportableKeyProvider> GetUnexportableKeyProviderMock() {
-  return std::make_unique<SoftwareProvider>();
+  return GetSoftwareUnsecureUnexportableKeyProvider();
 }
 
 std::unique_ptr<UnexportableKeyProvider> GetUnexportableKeyProviderNull() {
diff --git a/crypto/unexportable_key.cc b/crypto/unexportable_key.cc
index 4eb6378..5615125 100644
--- a/crypto/unexportable_key.cc
+++ b/crypto/unexportable_key.cc
@@ -26,6 +26,10 @@
 GetVirtualUnexportableKeyProviderWin();
 #endif
 
+// Implemented in unexportable_key_software_unsecure.cc.
+std::unique_ptr<UnexportableKeyProvider>
+GetUnexportableKeyProviderSoftwareUnsecure();
+
 std::unique_ptr<UnexportableKeyProvider> GetUnexportableKeyProvider() {
   if (g_mock_provider) {
     return g_mock_provider();
diff --git a/crypto/unexportable_key.h b/crypto/unexportable_key.h
index 61c25be..63acf4b6 100644
--- a/crypto/unexportable_key.h
+++ b/crypto/unexportable_key.h
@@ -191,6 +191,14 @@
 CRYPTO_EXPORT std::unique_ptr<VirtualUnexportableKeyProvider>
 GetVirtualUnexportableKeyProvider_DO_NOT_USE_METRICS_ONLY();
 
+// `GetSoftwareUnsecureUnexportableKeyProvider()` returns a mock software
+// implementation of `UnexportableKeyProvider` that can be used on platforms
+// that do not have a native secure implementation.
+// This should be used for development purposes only since these keys are not
+// backed by hardware and are not stored securely.
+CRYPTO_EXPORT std::unique_ptr<UnexportableKeyProvider>
+GetSoftwareUnsecureUnexportableKeyProvider();
+
 namespace internal {
 
 CRYPTO_EXPORT void SetUnexportableKeyProviderForTesting(
diff --git a/crypto/unexportable_key_software_unsecure.cc b/crypto/unexportable_key_software_unsecure.cc
new file mode 100644
index 0000000..64ca3f0
--- /dev/null
+++ b/crypto/unexportable_key_software_unsecure.cc
@@ -0,0 +1,118 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "crypto/unexportable_key.h"
+
+#include "base/check.h"
+#include "crypto/sha2.h"
+#include "crypto/signature_verifier.h"
+#include "third_party/boringssl/src/include/openssl/bytestring.h"
+#include "third_party/boringssl/src/include/openssl/ec.h"
+#include "third_party/boringssl/src/include/openssl/ec_key.h"
+#include "third_party/boringssl/src/include/openssl/ecdsa.h"
+#include "third_party/boringssl/src/include/openssl/evp.h"
+#include "third_party/boringssl/src/include/openssl/obj.h"
+
+namespace crypto {
+
+namespace {
+
+std::vector<uint8_t> CBBToVector(const CBB* cbb) {
+  return std::vector<uint8_t>(CBB_data(cbb), CBB_data(cbb) + CBB_len(cbb));
+}
+
+class SoftwareECDSA : public UnexportableSigningKey {
+ public:
+  explicit SoftwareECDSA(bssl::UniquePtr<EC_KEY> key) : key_(std::move(key)) {}
+  ~SoftwareECDSA() override = default;
+
+  SignatureVerifier::SignatureAlgorithm Algorithm() const override {
+    return SignatureVerifier::SignatureAlgorithm::ECDSA_SHA256;
+  }
+
+  std::vector<uint8_t> GetSubjectPublicKeyInfo() const override {
+    bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
+    CHECK(EVP_PKEY_set1_EC_KEY(pkey.get(), key_.get()));
+
+    bssl::ScopedCBB cbb;
+    CHECK(CBB_init(cbb.get(), /*initial_capacity=*/128) &&
+          EVP_marshal_public_key(cbb.get(), pkey.get()));
+    return CBBToVector(cbb.get());
+  }
+
+  std::vector<uint8_t> GetWrappedKey() const override {
+    bssl::ScopedCBB cbb;
+    CHECK(
+        CBB_init(cbb.get(), /*initial_capacity=*/128) &&
+        EC_KEY_marshal_private_key(cbb.get(), key_.get(),
+                                   EC_PKEY_NO_PARAMETERS | EC_PKEY_NO_PUBKEY));
+    return CBBToVector(cbb.get());
+  }
+
+  absl::optional<std::vector<uint8_t>> SignSlowly(
+      base::span<const uint8_t> data) override {
+    std::vector<uint8_t> ret(ECDSA_size(key_.get()));
+    std::array<uint8_t, kSHA256Length> digest = SHA256Hash(data);
+    unsigned int ret_size;
+    CHECK(ECDSA_sign(0, digest.data(), digest.size(), ret.data(), &ret_size,
+                     key_.get()));
+    ret.resize(ret_size);
+    return ret;
+  }
+
+ private:
+  bssl::UniquePtr<EC_KEY> key_;
+};
+
+class SoftwareProvider : public UnexportableKeyProvider {
+ public:
+  ~SoftwareProvider() override = default;
+
+  absl::optional<SignatureVerifier::SignatureAlgorithm> SelectAlgorithm(
+      base::span<const SignatureVerifier::SignatureAlgorithm>
+          acceptable_algorithms) override {
+    for (auto algo : acceptable_algorithms) {
+      if (algo == SignatureVerifier::SignatureAlgorithm::ECDSA_SHA256) {
+        return algo;
+      }
+    }
+
+    return absl::nullopt;
+  }
+
+  std::unique_ptr<UnexportableSigningKey> GenerateSigningKeySlowly(
+      base::span<const SignatureVerifier::SignatureAlgorithm>
+          acceptable_algorithms) override {
+    if (!SelectAlgorithm(acceptable_algorithms)) {
+      return nullptr;
+    }
+
+    bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
+    CHECK(EC_KEY_generate_key(key.get()));
+
+    return std::make_unique<SoftwareECDSA>(std::move(key));
+  }
+
+  std::unique_ptr<UnexportableSigningKey> FromWrappedSigningKeySlowly(
+      base::span<const uint8_t> wrapped_key) override {
+    bssl::UniquePtr<EC_GROUP> p256(
+        EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
+    CBS cbs;
+    CBS_init(&cbs, wrapped_key.data(), wrapped_key.size());
+    bssl::UniquePtr<EC_KEY> key(EC_KEY_parse_private_key(&cbs, p256.get()));
+    if (!key || CBS_len(&cbs) != 0) {
+      return nullptr;
+    }
+    return std::make_unique<SoftwareECDSA>(std::move(key));
+  }
+};
+
+}  // namespace
+
+std::unique_ptr<UnexportableKeyProvider>
+GetSoftwareUnsecureUnexportableKeyProvider() {
+  return std::make_unique<SoftwareProvider>();
+}
+
+}  // namespace crypto