diff options
author | Cronet Mainline Eng <cronet-mainline-eng+copybara@google.com> | 2023-03-22 02:58:49 -0800 |
---|---|---|
committer | Patrick Rohr <prohr@google.com> | 2023-03-22 04:40:18 -0700 |
commit | c175721cfcc03e339122be17d569239df9762b2b (patch) | |
tree | 64fed42a909067904ef77b573e554a172241bdfe /crypto/unexportable_key_win.cc | |
parent | 26b17131b27be4b84fc089d96dcc1998e686ecf9 (diff) | |
download | cronet-c175721cfcc03e339122be17d569239df9762b2b.tar.gz |
Import Cronet version 110.0.5481.154
Project import generated by Copybara.
FolderOrigin-RevId: /tmp/copybara-origin/src
Test: none
Change-Id: I534a69efa61b40fdc95613bce5bc5dd9a432f646
Diffstat (limited to 'crypto/unexportable_key_win.cc')
-rw-r--r-- | crypto/unexportable_key_win.cc | 91 |
1 files changed, 38 insertions, 53 deletions
diff --git a/crypto/unexportable_key_win.cc b/crypto/unexportable_key_win.cc index 99f9c3afd..34371c727 100644 --- a/crypto/unexportable_key_win.cc +++ b/crypto/unexportable_key_win.cc @@ -12,7 +12,6 @@ #include "base/logging.h" #include "base/numerics/checked_math.h" -#include "base/scoped_generic.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_piece.h" #include "base/strings/string_util.h" @@ -21,6 +20,7 @@ #include "base/threading/scoped_blocking_call.h" #include "base/threading/scoped_thread_priority.h" #include "crypto/random.h" +#include "crypto/scoped_cng_types.h" #include "crypto/sha2.h" #include "crypto/unexportable_key.h" #include "third_party/boringssl/src/include/openssl/bn.h" @@ -36,24 +36,6 @@ namespace crypto { namespace { -// NCrypt has a style of returning handles by writing opaque pointers to -// caller-provided locations. These pointers must be passed to -// |NCryptFreeObject| when no longer needed. -template <typename T> -struct NCryptObjectTraits { - // In practice a value of zero makes |NCryptFreeObject| a no-op, but this - // isn't specified by the documentation so the code below avoids depending on - // this by releasing() values that were never initialised. - static T InvalidValue() { return 0; } - static void Free(T handle) { NCryptFreeObject(handle); } -}; - -using ScopedProvider = - base::ScopedGeneric<NCRYPT_PROV_HANDLE, - NCryptObjectTraits<NCRYPT_PROV_HANDLE>>; -using ScopedKey = base::ScopedGeneric<NCRYPT_KEY_HANDLE, - NCryptObjectTraits<NCRYPT_KEY_HANDLE>>; - std::vector<uint8_t> CBBToVector(const CBB* cbb) { return std::vector<uint8_t>(CBB_data(cbb), CBB_data(cbb) + CBB_len(cbb)); } @@ -152,12 +134,30 @@ absl::optional<std::vector<uint8_t>> GetP256ECDSASPKI(NCRYPT_KEY_HANDLE key) { memcpy(&header, pub_key->data(), sizeof(header)); // |cbKey| is documented[1] as "the length, in bytes, of the key". It is // not. For ECDSA public keys it is the length of a field element. - if (header.dwMagic != BCRYPT_ECDSA_PUBLIC_P256_MAGIC || + if ((header.dwMagic != BCRYPT_ECDSA_PUBLIC_P256_MAGIC && + header.dwMagic != BCRYPT_ECDSA_PUBLIC_GENERIC_MAGIC) || header.cbKey != 256 / 8 || pub_key->size() - sizeof(BCRYPT_ECCKEY_BLOB) != 64) { return absl::nullopt; } + // Sometimes NCrypt will return a generic dwMagic even when asked for a P-256 + // key. In that case, do extra validation to make sure that `key` is in fact + // a P-256 key. + if (header.dwMagic == BCRYPT_ECDSA_PUBLIC_GENERIC_MAGIC) { + const absl::optional<std::vector<uint8_t>> curve_name = + GetKeyProperty(key, NCRYPT_ECC_CURVE_NAME_PROPERTY); + if (!curve_name) { + return absl::nullopt; + } + + if (curve_name->size() != sizeof(BCRYPT_ECC_CURVE_NISTP256) || + memcmp(curve_name->data(), BCRYPT_ECC_CURVE_NISTP256, + sizeof(BCRYPT_ECC_CURVE_NISTP256)) != 0) { + return absl::nullopt; + } + } + uint8_t x962[1 + 32 + 32]; x962[0] = POINT_CONVERSION_UNCOMPRESSED; memcpy(&x962[1], pub_key->data() + sizeof(BCRYPT_ECCKEY_BLOB), 64); @@ -229,8 +229,8 @@ absl::optional<std::vector<uint8_t>> GetRSASPKI(NCRYPT_KEY_HANDLE key) { // ECDSAKey wraps a TPM-stored P-256 ECDSA key. class ECDSAKey : public UnexportableSigningKey { public: - ECDSAKey(ScopedProvider provider, - ScopedKey key, + ECDSAKey(ScopedNCryptProvider provider, + ScopedNCryptKey key, std::vector<uint8_t> wrapped, std::vector<uint8_t> spki) : provider_(std::move(provider)), @@ -281,8 +281,8 @@ class ECDSAKey : public UnexportableSigningKey { } private: - ScopedProvider provider_; - ScopedKey key_; + ScopedNCryptProvider provider_; + ScopedNCryptKey key_; const std::vector<uint8_t> wrapped_; const std::vector<uint8_t> spki_; }; @@ -290,8 +290,8 @@ class ECDSAKey : public UnexportableSigningKey { // RSAKey wraps a TPM-stored RSA key. class RSAKey : public UnexportableSigningKey { public: - RSAKey(ScopedProvider provider, - ScopedKey key, + RSAKey(ScopedNCryptProvider provider, + ScopedNCryptKey key, std::vector<uint8_t> wrapped, std::vector<uint8_t> spki) : provider_(std::move(provider)), @@ -338,8 +338,8 @@ class RSAKey : public UnexportableSigningKey { } private: - ScopedProvider provider_; - ScopedKey key_; + ScopedNCryptProvider provider_; + ScopedNCryptKey key_; const std::vector<uint8_t> wrapped_; const std::vector<uint8_t> spki_; }; @@ -353,15 +353,12 @@ class UnexportableKeyProviderWin : public UnexportableKeyProvider { absl::optional<SignatureVerifier::SignatureAlgorithm> SelectAlgorithm( base::span<const SignatureVerifier::SignatureAlgorithm> acceptable_algorithms) override { - ScopedProvider provider; + ScopedNCryptProvider provider; { SCOPED_MAY_LOAD_LIBRARY_AT_BACKGROUND_PRIORITY(); if (FAILED(NCryptOpenStorageProvider( - ScopedProvider::Receiver(provider).get(), + ScopedNCryptProvider::Receiver(provider).get(), MS_PLATFORM_CRYPTO_PROVIDER, /*flags=*/0))) { - // If the operation failed then |provider| doesn't have a valid handle - // in it and we shouldn't try to free it. - std::ignore = provider.release(); return absl::nullopt; } } @@ -375,15 +372,12 @@ class UnexportableKeyProviderWin : public UnexportableKeyProvider { base::ScopedBlockingCall scoped_blocking_call( FROM_HERE, base::BlockingType::WILL_BLOCK); - ScopedProvider provider; + ScopedNCryptProvider provider; { SCOPED_MAY_LOAD_LIBRARY_AT_BACKGROUND_PRIORITY(); if (FAILED(NCryptOpenStorageProvider( - ScopedProvider::Receiver(provider).get(), + ScopedNCryptProvider::Receiver(provider).get(), MS_PLATFORM_CRYPTO_PROVIDER, /*flags=*/0))) { - // If the operation failed when |provider| doesn't have a valid handle - // in it and we shouldn't try to free it. - std::ignore = provider.release(); return nullptr; } } @@ -394,17 +388,14 @@ class UnexportableKeyProviderWin : public UnexportableKeyProvider { return nullptr; } - ScopedKey key; + ScopedNCryptKey key; { SCOPED_MAY_LOAD_LIBRARY_AT_BACKGROUND_PRIORITY(); // An empty key name stops the key being persisted to disk. if (FAILED(NCryptCreatePersistedKey( - provider.get(), ScopedKey::Receiver(key).get(), + provider.get(), ScopedNCryptKey::Receiver(key).get(), BCryptAlgorithmFor(*algo).value(), /*pszKeyName=*/nullptr, /*dwLegacyKeySpec=*/0, /*dwFlags=*/0))) { - // If the operation failed then |key| doesn't have a valid handle in it - // and we shouldn't try and free it. - std::ignore = key.release(); return nullptr; } @@ -447,27 +438,21 @@ class UnexportableKeyProviderWin : public UnexportableKeyProvider { base::ScopedBlockingCall scoped_blocking_call( FROM_HERE, base::BlockingType::WILL_BLOCK); - ScopedProvider provider; - ScopedKey key; + ScopedNCryptProvider provider; + ScopedNCryptKey key; { SCOPED_MAY_LOAD_LIBRARY_AT_BACKGROUND_PRIORITY(); if (FAILED(NCryptOpenStorageProvider( - ScopedProvider::Receiver(provider).get(), + ScopedNCryptProvider::Receiver(provider).get(), MS_PLATFORM_CRYPTO_PROVIDER, /*flags=*/0))) { - // If the operation failed when |provider| doesn't have a valid handle - // in it and we shouldn't try to free it. - std::ignore = provider.release(); return nullptr; } if (FAILED(NCryptImportKey( provider.get(), /*hImportKey=*/NULL, BCRYPT_OPAQUE_KEY_BLOB, - /*pParameterList=*/nullptr, ScopedKey::Receiver(key).get(), + /*pParameterList=*/nullptr, ScopedNCryptKey::Receiver(key).get(), const_cast<PBYTE>(wrapped.data()), wrapped.size(), /*dwFlags=*/NCRYPT_SILENT_FLAG))) { - // If the operation failed then |key| doesn't have a valid handle in it - // and we shouldn't try and free it. - std::ignore = key.release(); return nullptr; } } |