diff options
author | Cronet Mainline Eng <cronet-mainline-eng+copybara@google.com> | 2023-08-14 17:15:38 +0000 |
---|---|---|
committer | Mohannad Farrag <aymanm@google.com> | 2023-08-14 17:22:36 +0000 |
commit | ec3a8e8db24bb3ce4b078106b358ca1c4389c14f (patch) | |
tree | 823f64849ad509483bfebb2252199a5fe79b8e43 /crypto | |
parent | d12afe756882b2521faa0b33cbd4813fcea04c22 (diff) | |
download | cronet-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.gn | 1 | ||||
-rw-r--r-- | crypto/apple_keychain_ios.mm | 141 | ||||
-rw-r--r-- | crypto/chaps_support.cc | 9 | ||||
-rw-r--r-- | crypto/rsa_private_key_unittest.cc | 2 | ||||
-rw-r--r-- | crypto/scoped_mock_unexportable_key_provider.cc | 101 | ||||
-rw-r--r-- | crypto/unexportable_key.cc | 4 | ||||
-rw-r--r-- | crypto/unexportable_key.h | 10 | ||||
-rw-r--r-- | crypto/unexportable_key_metrics.cc | 4 | ||||
-rw-r--r-- | crypto/unexportable_key_software_unsecure.cc | 118 | ||||
-rw-r--r-- | crypto/unexportable_key_win.cc | 40 |
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 |