summaryrefslogtreecommitdiff
path: root/crypto
diff options
context:
space:
mode:
authorCronet Mainline Eng <cronet-mainline-eng+copybara@google.com>2023-08-14 17:15:38 +0000
committerMohannad Farrag <aymanm@google.com>2023-08-14 17:22:36 +0000
commitec3a8e8db24bb3ce4b078106b358ca1c4389c14f (patch)
tree823f64849ad509483bfebb2252199a5fe79b8e43 /crypto
parentd12afe756882b2521faa0b33cbd4813fcea04c22 (diff)
downloadcronet-ec3a8e8db24bb3ce4b078106b358ca1c4389c14f.tar.gz
Import Cronet version 117.0.5938.0
Project import generated by Copybara. FolderOrigin-RevId: /tmp/copybara-origin/src Change-Id: Ib7683d0ed240e11ed9068152600c8092afba4571
Diffstat (limited to 'crypto')
-rw-r--r--crypto/BUILD.gn1
-rw-r--r--crypto/apple_keychain_ios.mm141
-rw-r--r--crypto/chaps_support.cc9
-rw-r--r--crypto/rsa_private_key_unittest.cc2
-rw-r--r--crypto/scoped_mock_unexportable_key_provider.cc101
-rw-r--r--crypto/unexportable_key.cc4
-rw-r--r--crypto/unexportable_key.h10
-rw-r--r--crypto/unexportable_key_metrics.cc4
-rw-r--r--crypto/unexportable_key_software_unsecure.cc118
-rw-r--r--crypto/unexportable_key_win.cc40
10 files changed, 231 insertions, 199 deletions
diff --git a/crypto/BUILD.gn b/crypto/BUILD.gn
index df7a0dd5a..a54329473 100644
--- a/crypto/BUILD.gn
+++ b/crypto/BUILD.gn
@@ -56,6 +56,7 @@ component("crypto") {
"unexportable_key.h",
"unexportable_key_metrics.cc",
"unexportable_key_metrics.h",
+ "unexportable_key_software_unsecure.cc",
]
deps = [
diff --git a/crypto/apple_keychain_ios.mm b/crypto/apple_keychain_ios.mm
index d4501d6fa..8cc9eb05f 100644
--- a/crypto/apple_keychain_ios.mm
+++ b/crypto/apple_keychain_ios.mm
@@ -6,9 +6,9 @@
#import <Foundation/Foundation.h>
+#include "base/apple/bridging.h"
#include "base/mac/foundation_util.h"
#include "base/mac/scoped_cftyperef.h"
-#include "base/mac/scoped_nsobject.h"
namespace {
@@ -17,65 +17,65 @@ enum KeychainAction {
kKeychainActionUpdate
};
+base::ScopedCFTypeRef<CFStringRef> StringWithBytesAndLength(const char* bytes,
+ UInt32 length) {
+ return base::ScopedCFTypeRef<CFStringRef>(
+ CFStringCreateWithBytes(nullptr, reinterpret_cast<const UInt8*>(bytes),
+ length, kCFStringEncodingUTF8,
+ /*isExternalRepresentation=*/false));
+}
+
// Creates a dictionary that can be used to query the keystore.
-// Ownership follows the Create rule.
-CFDictionaryRef CreateGenericPasswordQuery(UInt32 serviceNameLength,
- const char* serviceName,
- UInt32 accountNameLength,
- const char* accountName) {
+base::ScopedCFTypeRef<CFDictionaryRef> MakeGenericPasswordQuery(
+ UInt32 serviceNameLength,
+ const char* serviceName,
+ UInt32 accountNameLength,
+ const char* accountName) {
CFMutableDictionaryRef query =
- CFDictionaryCreateMutable(NULL,
- 5,
- &kCFTypeDictionaryKeyCallBacks,
+ CFDictionaryCreateMutable(nullptr, 5, &kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
// Type of element is generic password.
CFDictionarySetValue(query, kSecClass, kSecClassGenericPassword);
// Set the service name.
- base::scoped_nsobject<NSString> service_name_ns(
- [[NSString alloc] initWithBytes:serviceName
- length:serviceNameLength
- encoding:NSUTF8StringEncoding]);
- CFDictionarySetValue(query, kSecAttrService,
- base::mac::NSToCFCast(service_name_ns));
+ CFDictionarySetValue(
+ query, kSecAttrService,
+ StringWithBytesAndLength(serviceName, serviceNameLength));
// Set the account name.
- base::scoped_nsobject<NSString> account_name_ns(
- [[NSString alloc] initWithBytes:accountName
- length:accountNameLength
- encoding:NSUTF8StringEncoding]);
- CFDictionarySetValue(query, kSecAttrAccount,
- base::mac::NSToCFCast(account_name_ns));
+ CFDictionarySetValue(
+ query, kSecAttrAccount,
+ StringWithBytesAndLength(accountName, accountNameLength));
// Use the proper search constants, return only the data of the first match.
CFDictionarySetValue(query, kSecMatchLimit, kSecMatchLimitOne);
CFDictionarySetValue(query, kSecReturnData, kCFBooleanTrue);
- return query;
+
+ return base::ScopedCFTypeRef<CFDictionaryRef>(query);
}
-// Creates a dictionary conatining the data to save into the keychain.
-// Ownership follows the Create rule.
-CFDictionaryRef CreateKeychainData(UInt32 serviceNameLength,
- const char* serviceName,
- UInt32 accountNameLength,
- const char* accountName,
- UInt32 passwordLength,
- const void* passwordData,
- KeychainAction action) {
+// Creates a dictionary containing the data to save into the keychain.
+base::ScopedCFTypeRef<CFDictionaryRef> MakeKeychainData(
+ UInt32 serviceNameLength,
+ const char* serviceName,
+ UInt32 accountNameLength,
+ const char* accountName,
+ UInt32 passwordLength,
+ const void* passwordData,
+ KeychainAction action) {
CFMutableDictionaryRef keychain_data =
- CFDictionaryCreateMutable(NULL,
- 0,
- &kCFTypeDictionaryKeyCallBacks,
+ CFDictionaryCreateMutable(nullptr, 0, &kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
// Set the password.
NSData* password = [NSData dataWithBytes:passwordData length:passwordLength];
CFDictionarySetValue(keychain_data, kSecValueData,
- base::mac::NSToCFCast(password));
+ base::apple::NSToCFPtrCast(password));
// If this is not a creation, no structural information is needed.
- if (action != kKeychainActionCreate)
- return keychain_data;
+ if (action != kKeychainActionCreate) {
+ return base::ScopedCFTypeRef<CFDictionaryRef>(keychain_data);
+ }
// Set the type of the data.
CFDictionarySetValue(keychain_data, kSecClass, kSecClassGenericPassword);
@@ -86,31 +86,25 @@ CFDictionaryRef CreateKeychainData(UInt32 serviceNameLength,
kSecAttrAccessibleWhenUnlocked);
// Set the service name.
- base::scoped_nsobject<NSString> service_name_ns(
- [[NSString alloc] initWithBytes:serviceName
- length:serviceNameLength
- encoding:NSUTF8StringEncoding]);
- CFDictionarySetValue(keychain_data, kSecAttrService,
- base::mac::NSToCFCast(service_name_ns));
+ CFDictionarySetValue(
+ keychain_data, kSecAttrService,
+ StringWithBytesAndLength(serviceName, serviceNameLength));
// Set the account name.
- base::scoped_nsobject<NSString> account_name_ns(
- [[NSString alloc] initWithBytes:accountName
- length:accountNameLength
- encoding:NSUTF8StringEncoding]);
- CFDictionarySetValue(keychain_data, kSecAttrAccount,
- base::mac::NSToCFCast(account_name_ns));
-
- return keychain_data;
+ CFDictionarySetValue(
+ keychain_data, kSecAttrAccount,
+ StringWithBytesAndLength(accountName, accountNameLength));
+
+ return base::ScopedCFTypeRef<CFDictionaryRef>(keychain_data);
}
} // namespace
namespace crypto {
-AppleKeychain::AppleKeychain() {}
+AppleKeychain::AppleKeychain() = default;
-AppleKeychain::~AppleKeychain() {}
+AppleKeychain::~AppleKeychain() = default;
OSStatus AppleKeychain::ItemFreeContent(void* data) const {
free(data);
@@ -125,31 +119,21 @@ OSStatus AppleKeychain::AddGenericPassword(
UInt32 passwordLength,
const void* passwordData,
AppleSecKeychainItemRef* itemRef) const {
- base::ScopedCFTypeRef<CFDictionaryRef> query(CreateGenericPasswordQuery(
- serviceNameLength, serviceName, accountNameLength, accountName));
+ base::ScopedCFTypeRef<CFDictionaryRef> query = MakeGenericPasswordQuery(
+ serviceNameLength, serviceName, accountNameLength, accountName);
// Check that there is not already a password.
- OSStatus status = SecItemCopyMatching(query, NULL);
+ OSStatus status = SecItemCopyMatching(query, /*result=*/nullptr);
if (status == errSecItemNotFound) {
// A new entry must be created.
- base::ScopedCFTypeRef<CFDictionaryRef> keychain_data(
- CreateKeychainData(serviceNameLength,
- serviceName,
- accountNameLength,
- accountName,
- passwordLength,
- passwordData,
- kKeychainActionCreate));
- status = SecItemAdd(keychain_data, NULL);
+ base::ScopedCFTypeRef<CFDictionaryRef> keychain_data = MakeKeychainData(
+ serviceNameLength, serviceName, accountNameLength, accountName,
+ passwordLength, passwordData, kKeychainActionCreate);
+ status = SecItemAdd(keychain_data, /*result=*/nullptr);
} else if (status == noErr) {
// The entry must be updated.
- base::ScopedCFTypeRef<CFDictionaryRef> keychain_data(
- CreateKeychainData(serviceNameLength,
- serviceName,
- accountNameLength,
- accountName,
- passwordLength,
- passwordData,
- kKeychainActionUpdate));
+ base::ScopedCFTypeRef<CFDictionaryRef> keychain_data = MakeKeychainData(
+ serviceNameLength, serviceName, accountNameLength, accountName,
+ passwordLength, passwordData, kKeychainActionUpdate);
status = SecItemUpdate(query, keychain_data);
}
@@ -166,17 +150,16 @@ OSStatus AppleKeychain::FindGenericPassword(
AppleSecKeychainItemRef* itemRef) const {
DCHECK((passwordData && passwordLength) ||
(!passwordData && !passwordLength));
- base::ScopedCFTypeRef<CFDictionaryRef> query(CreateGenericPasswordQuery(
- serviceNameLength, serviceName, accountNameLength, accountName));
+ base::ScopedCFTypeRef<CFDictionaryRef> query = MakeGenericPasswordQuery(
+ serviceNameLength, serviceName, accountNameLength, accountName);
// Get the keychain item containing the password.
- CFTypeRef resultRef = NULL;
- OSStatus status = SecItemCopyMatching(query, &resultRef);
- base::ScopedCFTypeRef<CFTypeRef> result(resultRef);
+ base::ScopedCFTypeRef<CFTypeRef> result;
+ OSStatus status = SecItemCopyMatching(query, result.InitializeInto());
if (status != noErr) {
if (passwordData) {
- *passwordData = NULL;
+ *passwordData = nullptr;
*passwordLength = 0;
}
return status;
diff --git a/crypto/chaps_support.cc b/crypto/chaps_support.cc
index 4b176ae60..2ea8dd5a0 100644
--- a/crypto/chaps_support.cc
+++ b/crypto/chaps_support.cc
@@ -9,6 +9,8 @@
#include <secmodt.h>
#include "base/logging.h"
+#include "base/memory/raw_ptr_exclusion.h"
+#include "base/memory/stack_allocated.h"
#include "base/threading/scoped_blocking_call.h"
#include "crypto/scoped_nss_types.h"
#include "nss_util_internal.h"
@@ -22,13 +24,18 @@ const char kChapsModuleName[] = "Chaps";
const char kChapsPath[] = "libchaps.so";
class ScopedChapsLoadFixup {
+ STACK_ALLOCATED();
+
public:
ScopedChapsLoadFixup();
~ScopedChapsLoadFixup();
private:
#if defined(COMPONENT_BUILD)
- void* chaps_handle_;
+ // This field stores a handle and is not a pointer to PA memory.
+ // Also, this class is always stack-allocated and visibility is limited.
+ // Hence no benefit from using raw_ptr<void>.
+ RAW_PTR_EXCLUSION void* chaps_handle_;
#endif
};
diff --git a/crypto/rsa_private_key_unittest.cc b/crypto/rsa_private_key_unittest.cc
index 67d3a9d86..d123185ea 100644
--- a/crypto/rsa_private_key_unittest.cc
+++ b/crypto/rsa_private_key_unittest.cc
@@ -353,7 +353,7 @@ TEST(RSAPrivateKeyUnitTest, ShortIntegers) {
TEST(RSAPrivateKeyUnitTest, CreateFromKeyTest) {
std::unique_ptr<crypto::RSAPrivateKey> key_pair(
- crypto::RSAPrivateKey::Create(512));
+ crypto::RSAPrivateKey::Create(2048));
ASSERT_TRUE(key_pair.get());
std::unique_ptr<crypto::RSAPrivateKey> key_copy(
diff --git a/crypto/scoped_mock_unexportable_key_provider.cc b/crypto/scoped_mock_unexportable_key_provider.cc
index 381e9687d..d0e3cf29c 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 4eb637852..5615125d4 100644
--- a/crypto/unexportable_key.cc
+++ b/crypto/unexportable_key.cc
@@ -26,6 +26,10 @@ std::unique_ptr<VirtualUnexportableKeyProvider>
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 afac7ec61..63acf4b6d 100644
--- a/crypto/unexportable_key.h
+++ b/crypto/unexportable_key.h
@@ -139,7 +139,7 @@ class CRYPTO_EXPORT VirtualUnexportableSigningKey {
// Deletes the key from storage in the virtual machine. As the virtual machine
// has limited storage shared by all applications it is important to delete
// keys no longer in use.
- virtual bool DeleteKey() = 0;
+ virtual void DeleteKey() = 0;
};
// VirtualUnexportableKeyProvider creates |VirtualUnexportableSigningKey|s.
@@ -191,6 +191,14 @@ GetUnexportableKeyProvider();
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_metrics.cc b/crypto/unexportable_key_metrics.cc
index cd4ed6064..2b4b9a95e 100644
--- a/crypto/unexportable_key_metrics.cc
+++ b/crypto/unexportable_key_metrics.cc
@@ -296,7 +296,9 @@ void MaybeMeasureTpmOperations() {
base::FEATURE_ENABLED_BY_DEFAULT);
if (base::FeatureList::IsEnabled(kTpmLatencyMetrics)) {
base::ThreadPool::PostTask(
- FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+ FROM_HERE,
+ {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+ base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
base::BindOnce(&MeasureTpmOperationsInternal));
}
}
diff --git a/crypto/unexportable_key_software_unsecure.cc b/crypto/unexportable_key_software_unsecure.cc
new file mode 100644
index 000000000..64ca3f0cd
--- /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
diff --git a/crypto/unexportable_key_win.cc b/crypto/unexportable_key_win.cc
index 18306034b..41e5d8bb8 100644
--- a/crypto/unexportable_key_win.cc
+++ b/crypto/unexportable_key_win.cc
@@ -524,28 +524,32 @@ class ECDSASoftwareKey : public VirtualUnexportableSigningKey {
absl::optional<std::vector<uint8_t>> Sign(
base::span<const uint8_t> data) override {
- if (!valid_) {
+ if (!key_.is_valid()) {
return absl::nullopt;
}
return SignECDSA(key_.get(), data);
}
- bool DeleteKey() override {
- if (!valid_) {
- return false;
+ void DeleteKey() override {
+ if (!key_.is_valid()) {
+ return;
}
- auto status = NCryptDeleteKey(key_.get(), NCRYPT_SILENT_FLAG);
- valid_ = false;
- return !FAILED(status);
+ // If key deletion succeeds, NCryptDeleteKey frees the key. To avoid double
+ // free, we need to release the key from the ScopedNCryptKey RAII object.
+ // Key deletion can fail in circumstances which are not under the
+ // application's control. For these cases, ScopedNCrypt key should free the
+ // key.
+ if (NCryptDeleteKey(key_.get(), NCRYPT_SILENT_FLAG) == ERROR_SUCCESS) {
+ static_cast<void>(key_.release());
+ }
}
private:
ScopedNCryptKey key_;
const std::string name_;
const std::vector<uint8_t> spki_;
- bool valid_ = true;
};
// RSASoftwareKey wraps a Credential Guard stored RSA key.
@@ -568,28 +572,32 @@ class RSASoftwareKey : public VirtualUnexportableSigningKey {
absl::optional<std::vector<uint8_t>> Sign(
base::span<const uint8_t> data) override {
- if (!valid_) {
+ if (!key_.is_valid()) {
return absl::nullopt;
}
return SignRSA(key_.get(), data);
}
- bool DeleteKey() override {
- if (!valid_) {
- return false;
+ void DeleteKey() override {
+ if (!key_.is_valid()) {
+ return;
}
- auto status = NCryptDeleteKey(key_.get(), NCRYPT_SILENT_FLAG);
- valid_ = false;
- return !FAILED(status);
+ // If key deletion succeeds, NCryptDeleteKey frees the key. To avoid double
+ // free, we need to release the key from the ScopedNCryptKey RAII object.
+ // Key deletion can fail in circumstances which are not under the
+ // application's control. For these cases, ScopedNCrypt key should free the
+ // key.
+ if (NCryptDeleteKey(key_.get(), NCRYPT_SILENT_FLAG) == ERROR_SUCCESS) {
+ static_cast<void>(key_.release());
+ }
}
private:
ScopedNCryptKey key_;
std::string name_;
const std::vector<uint8_t> spki_;
- bool valid_ = true;
};
// UnexportableKeyProviderWin uses NCrypt and the Platform Crypto