summaryrefslogtreecommitdiffstats
path: root/contrib/restricted/aws/aws-c-cal/source/windows
diff options
context:
space:
mode:
authorthegeorg <[email protected]>2025-05-12 15:51:24 +0300
committerthegeorg <[email protected]>2025-05-12 16:06:27 +0300
commitd629bb70c8773d2c0c43f5088ddbb5a86d8c37ea (patch)
tree4f678e0d65ad08c800db21c657d3b0f71fafed06 /contrib/restricted/aws/aws-c-cal/source/windows
parent92c4b696d7a1c03d54e13aff7a7c20a078d90dd7 (diff)
Update contrib/restricted/aws libraries to nixpkgs 24.05
commit_hash:f8083acb039e6005e820cdee77b84e0a6b6c6d6d
Diffstat (limited to 'contrib/restricted/aws/aws-c-cal/source/windows')
-rw-r--r--contrib/restricted/aws/aws-c-cal/source/windows/bcrypt_aes.c9
-rw-r--r--contrib/restricted/aws/aws-c-cal/source/windows/bcrypt_ecc.c11
-rw-r--r--contrib/restricted/aws/aws-c-cal/source/windows/bcrypt_platform_init.c2
-rw-r--r--contrib/restricted/aws/aws-c-cal/source/windows/bcrypt_rsa.c422
4 files changed, 435 insertions, 9 deletions
diff --git a/contrib/restricted/aws/aws-c-cal/source/windows/bcrypt_aes.c b/contrib/restricted/aws/aws-c-cal/source/windows/bcrypt_aes.c
index aeb646e66a3..0229de3a80d 100644
--- a/contrib/restricted/aws/aws-c-cal/source/windows/bcrypt_aes.c
+++ b/contrib/restricted/aws/aws-c-cal/source/windows/bcrypt_aes.c
@@ -277,9 +277,12 @@ static void s_clear_reusable_components(struct aws_symmetric_cipher *cipher) {
}
aws_byte_buf_secure_zero(&cipher_impl->overflow);
- aws_byte_buf_secure_zero(&cipher_impl->working_mac_buffer);
- /* windows handles this, just go ahead and tell the API it's got a length. */
- cipher_impl->working_mac_buffer.len = AWS_AES_256_CIPHER_BLOCK_SIZE;
+
+ if (cipher_impl->working_mac_buffer.capacity != 0) {
+ aws_byte_buf_secure_zero(&cipher_impl->working_mac_buffer);
+ /* windows handles this, just go ahead and tell the API it's got a length. */
+ cipher_impl->working_mac_buffer.len = AWS_AES_256_CIPHER_BLOCK_SIZE;
+ }
}
static int s_reset_cbc_cipher(struct aws_symmetric_cipher *cipher) {
diff --git a/contrib/restricted/aws/aws-c-cal/source/windows/bcrypt_ecc.c b/contrib/restricted/aws/aws-c-cal/source/windows/bcrypt_ecc.c
index a9e890d0556..268b29b5111 100644
--- a/contrib/restricted/aws/aws-c-cal/source/windows/bcrypt_ecc.c
+++ b/contrib/restricted/aws/aws-c-cal/source/windows/bcrypt_ecc.c
@@ -130,11 +130,11 @@ static int s_sign_message(
struct aws_byte_cursor integer_cur = aws_byte_cursor_from_array(temp_signature_buf.buffer, coordinate_len);
/* trim off the leading zero padding for DER encoding */
integer_cur = aws_byte_cursor_left_trim_pred(&integer_cur, s_trim_zeros_predicate);
- aws_der_encoder_write_integer(encoder, integer_cur);
+ aws_der_encoder_write_unsigned_integer(encoder, integer_cur);
integer_cur = aws_byte_cursor_from_array(temp_signature_buf.buffer + coordinate_len, coordinate_len);
/* trim off the leading zero padding for DER encoding */
integer_cur = aws_byte_cursor_left_trim_pred(&integer_cur, s_trim_zeros_predicate);
- aws_der_encoder_write_integer(encoder, integer_cur);
+ aws_der_encoder_write_unsigned_integer(encoder, integer_cur);
aws_der_encoder_end_sequence(encoder);
struct aws_byte_cursor signature_out_cur;
@@ -178,8 +178,7 @@ static int s_append_coordinate(
size_t leading_zero_count = coordinate_size - coordinate->len;
AWS_FATAL_ASSERT(leading_zero_count + buffer->len <= buffer->capacity);
- memset(buffer->buffer + buffer->len, 0, leading_zero_count);
- buffer->len += leading_zero_count;
+ aws_byte_buf_write_u8_n(buffer, 0x0, leading_zero_count);
}
return aws_byte_buf_append(buffer, coordinate);
@@ -216,7 +215,7 @@ static int s_verify_signature(
/* there will be two coordinates. They need to be concatenated together. */
struct aws_byte_cursor coordinate;
AWS_ZERO_STRUCT(coordinate);
- if (aws_der_decoder_tlv_integer(decoder, &coordinate)) {
+ if (aws_der_decoder_tlv_unsigned_integer(decoder, &coordinate)) {
aws_raise_error(AWS_ERROR_CAL_MALFORMED_ASN1_ENCOUNTERED);
goto error;
}
@@ -230,7 +229,7 @@ static int s_verify_signature(
goto error;
}
AWS_ZERO_STRUCT(coordinate);
- if (aws_der_decoder_tlv_integer(decoder, &coordinate)) {
+ if (aws_der_decoder_tlv_unsigned_integer(decoder, &coordinate)) {
aws_raise_error(AWS_ERROR_CAL_MALFORMED_ASN1_ENCOUNTERED);
goto error;
}
diff --git a/contrib/restricted/aws/aws-c-cal/source/windows/bcrypt_platform_init.c b/contrib/restricted/aws/aws-c-cal/source/windows/bcrypt_platform_init.c
index decedcdafa2..f2da2805673 100644
--- a/contrib/restricted/aws/aws-c-cal/source/windows/bcrypt_platform_init.c
+++ b/contrib/restricted/aws/aws-c-cal/source/windows/bcrypt_platform_init.c
@@ -10,3 +10,5 @@ void aws_cal_platform_init(struct aws_allocator *allocator) {
}
void aws_cal_platform_clean_up(void) {}
+
+void aws_cal_platform_thread_clean_up(void) {}
diff --git a/contrib/restricted/aws/aws-c-cal/source/windows/bcrypt_rsa.c b/contrib/restricted/aws/aws-c-cal/source/windows/bcrypt_rsa.c
new file mode 100644
index 00000000000..d9e7c8d229f
--- /dev/null
+++ b/contrib/restricted/aws/aws-c-cal/source/windows/bcrypt_rsa.c
@@ -0,0 +1,422 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+#include <aws/cal/private/rsa.h>
+
+#include <aws/cal/cal.h>
+#include <aws/cal/private/der.h>
+#include <aws/common/encoding.h>
+
+#define WIN32_NO_STATUS
+#include <windows.h>
+#undef WIN32_NO_STATUS
+
+#include <bcrypt.h>
+#include <ntstatus.h>
+
+static BCRYPT_ALG_HANDLE s_rsa_alg = NULL;
+
+static aws_thread_once s_rsa_thread_once = AWS_THREAD_ONCE_STATIC_INIT;
+
+static void s_load_alg_handle(void *user_data) {
+ (void)user_data;
+ /* this function is incredibly slow, LET IT LEAK*/
+ NTSTATUS status = BCryptOpenAlgorithmProvider(&s_rsa_alg, BCRYPT_RSA_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0);
+ AWS_FATAL_ASSERT(s_rsa_alg && "BCryptOpenAlgorithmProvider() failed");
+ AWS_FATAL_ASSERT(BCRYPT_SUCCESS(status));
+}
+
+struct bcrypt_rsa_key_pair {
+ struct aws_rsa_key_pair base;
+ BCRYPT_KEY_HANDLE key_handle;
+ struct aws_byte_buf key_buf;
+};
+
+static void s_rsa_destroy_key(void *key_pair) {
+ if (key_pair == NULL) {
+ return;
+ }
+
+ struct aws_rsa_key_pair *base = key_pair;
+ struct bcrypt_rsa_key_pair *impl = base->impl;
+
+ if (impl->key_handle) {
+ BCryptDestroyKey(impl->key_handle);
+ }
+ aws_byte_buf_clean_up_secure(&impl->key_buf);
+
+ aws_rsa_key_pair_base_clean_up(base);
+
+ aws_mem_release(base->allocator, impl);
+}
+
+/*
+ * Transforms bcrypt error code into crt error code and raises it as necessary.
+ */
+static int s_reinterpret_bc_error_as_crt(NTSTATUS error, const char *function_name) {
+ if (BCRYPT_SUCCESS(error)) {
+ return AWS_OP_SUCCESS;
+ }
+
+ int crt_error = AWS_OP_ERR;
+ switch (error) {
+ case STATUS_BUFFER_TOO_SMALL: {
+ crt_error = AWS_ERROR_SHORT_BUFFER;
+ goto on_error;
+ }
+ case STATUS_NOT_SUPPORTED: {
+ crt_error = AWS_ERROR_CAL_UNSUPPORTED_ALGORITHM;
+ goto on_error;
+ }
+ }
+
+ crt_error = AWS_ERROR_CAL_CRYPTO_OPERATION_FAILED;
+
+on_error:
+ AWS_LOGF_ERROR(
+ AWS_LS_CAL_RSA, "%s() failed. returned: %X aws_error:%s", function_name, error, aws_error_name(crt_error));
+
+ return aws_raise_error(crt_error);
+}
+
+static int s_check_encryption_algorithm(enum aws_rsa_encryption_algorithm algorithm) {
+ if (algorithm != AWS_CAL_RSA_ENCRYPTION_PKCS1_5 && algorithm != AWS_CAL_RSA_ENCRYPTION_OAEP_SHA256 &&
+ algorithm != AWS_CAL_RSA_ENCRYPTION_OAEP_SHA512) {
+ return aws_raise_error(AWS_ERROR_CAL_UNSUPPORTED_ALGORITHM);
+ }
+ return AWS_OP_SUCCESS;
+}
+
+static int s_rsa_encrypt(
+ const struct aws_rsa_key_pair *key_pair,
+ enum aws_rsa_encryption_algorithm algorithm,
+ struct aws_byte_cursor plaintext,
+ struct aws_byte_buf *out) {
+ struct bcrypt_rsa_key_pair *key_pair_impl = key_pair->impl;
+
+ if (s_check_encryption_algorithm(algorithm)) {
+ return AWS_OP_ERR;
+ }
+
+ BCRYPT_OAEP_PADDING_INFO padding_info_oaep = {
+ .pszAlgId = algorithm == AWS_CAL_RSA_ENCRYPTION_OAEP_SHA256 ? BCRYPT_SHA256_ALGORITHM : BCRYPT_SHA512_ALGORITHM,
+ .pbLabel = NULL,
+ .cbLabel = 0};
+
+ ULONG length_written = 0;
+ NTSTATUS status = BCryptEncrypt(
+ key_pair_impl->key_handle,
+ plaintext.ptr,
+ (ULONG)plaintext.len,
+ algorithm == AWS_CAL_RSA_ENCRYPTION_PKCS1_5 ? NULL : &padding_info_oaep,
+ NULL,
+ 0,
+ out->buffer + out->len,
+ (ULONG)(out->capacity - out->len),
+ &length_written,
+ algorithm == AWS_CAL_RSA_ENCRYPTION_PKCS1_5 ? BCRYPT_PAD_PKCS1 : BCRYPT_PAD_OAEP);
+
+ if (s_reinterpret_bc_error_as_crt(status, "BCryptEncrypt")) {
+ return AWS_OP_ERR;
+ }
+
+ out->len += length_written;
+ return AWS_OP_SUCCESS;
+}
+
+static int s_rsa_decrypt(
+ const struct aws_rsa_key_pair *key_pair,
+ enum aws_rsa_encryption_algorithm algorithm,
+ struct aws_byte_cursor ciphertext,
+ struct aws_byte_buf *out) {
+ struct bcrypt_rsa_key_pair *key_pair_impl = key_pair->impl;
+
+ /* There is a bug in old versions of BCryptDecrypt, where it does not return
+ * error status if out buffer is too short. So manually check that buffer is
+ * large enough.
+ */
+ if ((out->capacity - out->len) < aws_rsa_key_pair_block_length(key_pair)) {
+ return aws_raise_error(AWS_ERROR_SHORT_BUFFER);
+ }
+
+ if (s_check_encryption_algorithm(algorithm)) {
+ return AWS_OP_ERR;
+ }
+
+ BCRYPT_OAEP_PADDING_INFO padding_info_oaep = {
+ .pszAlgId = algorithm == AWS_CAL_RSA_ENCRYPTION_OAEP_SHA256 ? BCRYPT_SHA256_ALGORITHM : BCRYPT_SHA512_ALGORITHM,
+ .pbLabel = NULL,
+ .cbLabel = 0};
+
+ ULONG length_written = 0;
+ NTSTATUS status = BCryptDecrypt(
+ key_pair_impl->key_handle,
+ ciphertext.ptr,
+ (ULONG)ciphertext.len,
+ algorithm == AWS_CAL_RSA_ENCRYPTION_PKCS1_5 ? NULL : &padding_info_oaep,
+ NULL,
+ 0,
+ out->buffer + out->len,
+ (ULONG)(out->capacity - out->len),
+ &length_written,
+ algorithm == AWS_CAL_RSA_ENCRYPTION_PKCS1_5 ? BCRYPT_PAD_PKCS1 : BCRYPT_PAD_OAEP);
+
+ if (s_reinterpret_bc_error_as_crt(status, "BCryptDecrypt")) {
+ return AWS_OP_ERR;
+ }
+
+ out->len += length_written;
+ return AWS_OP_SUCCESS;
+}
+
+union sign_padding_info {
+ BCRYPT_PKCS1_PADDING_INFO pkcs1;
+ BCRYPT_PSS_PADDING_INFO pss;
+};
+
+static int s_sign_padding_info_init(union sign_padding_info *info, enum aws_rsa_signature_algorithm algorithm) {
+ memset(info, 0, sizeof(union sign_padding_info));
+
+ if (algorithm == AWS_CAL_RSA_SIGNATURE_PKCS1_5_SHA256) {
+ info->pkcs1.pszAlgId = BCRYPT_SHA256_ALGORITHM;
+ return AWS_OP_SUCCESS;
+ } else if (algorithm == AWS_CAL_RSA_SIGNATURE_PSS_SHA256) {
+ info->pss.pszAlgId = BCRYPT_SHA256_ALGORITHM;
+ info->pss.cbSalt = 32;
+ return AWS_OP_SUCCESS;
+ }
+
+ return aws_raise_error(AWS_ERROR_CAL_UNSUPPORTED_ALGORITHM);
+}
+
+static int s_rsa_sign(
+ const struct aws_rsa_key_pair *key_pair,
+ enum aws_rsa_signature_algorithm algorithm,
+ struct aws_byte_cursor digest,
+ struct aws_byte_buf *out) {
+ struct bcrypt_rsa_key_pair *key_pair_impl = key_pair->impl;
+
+ union sign_padding_info padding_info;
+ if (s_sign_padding_info_init(&padding_info, algorithm)) {
+ return aws_raise_error(AWS_ERROR_CAL_UNSUPPORTED_ALGORITHM);
+ }
+
+ ULONG length_written = 0;
+ NTSTATUS status = BCryptSignHash(
+ key_pair_impl->key_handle,
+ &padding_info,
+ digest.ptr,
+ (ULONG)digest.len,
+ out->buffer + out->len,
+ (ULONG)(out->capacity - out->len),
+ (ULONG *)&length_written,
+ algorithm == AWS_CAL_RSA_SIGNATURE_PKCS1_5_SHA256 ? BCRYPT_PAD_PKCS1 : BCRYPT_PAD_PSS);
+
+ if (s_reinterpret_bc_error_as_crt(status, "BCryptSignHash")) {
+ goto on_error;
+ }
+
+ out->len += length_written;
+
+ return AWS_OP_SUCCESS;
+
+on_error:
+ return AWS_OP_ERR;
+}
+
+static int s_rsa_verify(
+ const struct aws_rsa_key_pair *key_pair,
+ enum aws_rsa_signature_algorithm algorithm,
+ struct aws_byte_cursor digest,
+ struct aws_byte_cursor signature) {
+ struct bcrypt_rsa_key_pair *key_pair_impl = key_pair->impl;
+
+ /* BCrypt raises invalid argument if signature does not have correct size.
+ * Verify size here and raise appropriate error and treat all other errors
+ * from BCrypt (including invalid arg) in reinterp. */
+ if (signature.len != aws_rsa_key_pair_signature_length(key_pair)) {
+ return aws_raise_error(AWS_ERROR_CAL_SIGNATURE_VALIDATION_FAILED);
+ }
+
+ union sign_padding_info padding_info;
+ if (s_sign_padding_info_init(&padding_info, algorithm)) {
+ return aws_raise_error(AWS_ERROR_CAL_UNSUPPORTED_ALGORITHM);
+ }
+ /* okay, now we've got a windows compatible signature, let's verify it. */
+ NTSTATUS status = BCryptVerifySignature(
+ key_pair_impl->key_handle,
+ &padding_info,
+ digest.ptr,
+ (ULONG)digest.len,
+ signature.ptr,
+ (ULONG)signature.len,
+ algorithm == AWS_CAL_RSA_SIGNATURE_PKCS1_5_SHA256 ? BCRYPT_PAD_PKCS1 : BCRYPT_PAD_PSS);
+
+ if (status == STATUS_INVALID_SIGNATURE) {
+ return aws_raise_error(AWS_ERROR_CAL_SIGNATURE_VALIDATION_FAILED);
+ }
+
+ if (s_reinterpret_bc_error_as_crt(status, "BCryptVerifySignature")) {
+ return AWS_OP_ERR;
+ }
+
+ return AWS_OP_SUCCESS;
+}
+
+static struct aws_rsa_key_vtable s_rsa_key_pair_vtable = {
+ .encrypt = s_rsa_encrypt,
+ .decrypt = s_rsa_decrypt,
+ .sign = s_rsa_sign,
+ .verify = s_rsa_verify,
+};
+
+struct aws_rsa_key_pair *aws_rsa_key_pair_new_from_private_key_pkcs1_impl(
+ struct aws_allocator *allocator,
+ struct aws_byte_cursor key) {
+
+ aws_thread_call_once(&s_rsa_thread_once, s_load_alg_handle, NULL);
+ struct bcrypt_rsa_key_pair *key_pair_impl = aws_mem_calloc(allocator, 1, sizeof(struct bcrypt_rsa_key_pair));
+
+ aws_ref_count_init(&key_pair_impl->base.ref_count, &key_pair_impl->base, s_rsa_destroy_key);
+ key_pair_impl->base.impl = key_pair_impl;
+ key_pair_impl->base.allocator = allocator;
+ aws_byte_buf_init_copy_from_cursor(&key_pair_impl->base.priv, allocator, key);
+
+ struct aws_der_decoder *decoder = aws_der_decoder_new(allocator, key);
+
+ if (!decoder) {
+ goto on_error;
+ }
+
+ struct aws_rsa_private_key_pkcs1 private_key_data;
+ AWS_ZERO_STRUCT(private_key_data);
+ if (aws_der_decoder_load_private_rsa_pkcs1(decoder, &private_key_data)) {
+ goto on_error;
+ }
+
+ /* Hard to predict final blob size, so use pkcs1 key size as upper bound. */
+ size_t total_buffer_size = key.len + sizeof(BCRYPT_RSAKEY_BLOB);
+
+ aws_byte_buf_init(&key_pair_impl->key_buf, allocator, total_buffer_size);
+
+ BCRYPT_RSAKEY_BLOB key_blob;
+ AWS_ZERO_STRUCT(key_blob);
+ key_blob.Magic = BCRYPT_RSAFULLPRIVATE_MAGIC;
+ key_blob.BitLength = (ULONG)private_key_data.modulus.len * 8;
+ key_blob.cbPublicExp = (ULONG)private_key_data.publicExponent.len;
+ key_blob.cbModulus = (ULONG)private_key_data.modulus.len;
+ key_blob.cbPrime1 = (ULONG)private_key_data.prime1.len;
+ key_blob.cbPrime2 = (ULONG)private_key_data.prime2.len;
+
+ struct aws_byte_cursor header = aws_byte_cursor_from_array(&key_blob, sizeof(key_blob));
+ aws_byte_buf_append(&key_pair_impl->key_buf, &header);
+
+ LPCWSTR blob_type = BCRYPT_RSAFULLPRIVATE_BLOB;
+ ULONG flags = 0;
+
+ aws_byte_buf_append(&key_pair_impl->key_buf, &private_key_data.publicExponent);
+ aws_byte_buf_append(&key_pair_impl->key_buf, &private_key_data.modulus);
+ aws_byte_buf_append(&key_pair_impl->key_buf, &private_key_data.prime1);
+ aws_byte_buf_append(&key_pair_impl->key_buf, &private_key_data.prime2);
+ aws_byte_buf_append(&key_pair_impl->key_buf, &private_key_data.exponent1);
+ aws_byte_buf_append(&key_pair_impl->key_buf, &private_key_data.exponent2);
+ aws_byte_buf_append(&key_pair_impl->key_buf, &private_key_data.coefficient);
+ aws_byte_buf_append(&key_pair_impl->key_buf, &private_key_data.privateExponent);
+
+ NTSTATUS status = BCryptImportKeyPair(
+ s_rsa_alg,
+ NULL,
+ blob_type,
+ &key_pair_impl->key_handle,
+ key_pair_impl->key_buf.buffer,
+ (ULONG)key_pair_impl->key_buf.len,
+ flags);
+
+ if (s_reinterpret_bc_error_as_crt(status, "BCryptImportKeyPair")) {
+ goto on_error;
+ }
+
+ key_pair_impl->base.vtable = &s_rsa_key_pair_vtable;
+ key_pair_impl->base.key_size_in_bits = private_key_data.modulus.len * 8;
+
+ aws_der_decoder_destroy(decoder);
+
+ return &key_pair_impl->base;
+
+on_error:
+ aws_der_decoder_destroy(decoder);
+ s_rsa_destroy_key(&key_pair_impl->base);
+ return NULL;
+}
+
+struct aws_rsa_key_pair *aws_rsa_key_pair_new_from_public_key_pkcs1_impl(
+ struct aws_allocator *allocator,
+ struct aws_byte_cursor key) {
+
+ aws_thread_call_once(&s_rsa_thread_once, s_load_alg_handle, NULL);
+ struct bcrypt_rsa_key_pair *key_pair_impl = aws_mem_calloc(allocator, 1, sizeof(struct bcrypt_rsa_key_pair));
+
+ aws_ref_count_init(&key_pair_impl->base.ref_count, &key_pair_impl->base, s_rsa_destroy_key);
+ key_pair_impl->base.impl = key_pair_impl;
+ key_pair_impl->base.allocator = allocator;
+ aws_byte_buf_init_copy_from_cursor(&key_pair_impl->base.pub, allocator, key);
+
+ struct aws_der_decoder *decoder = aws_der_decoder_new(allocator, key);
+
+ if (!decoder) {
+ goto on_error;
+ }
+
+ struct aws_rsa_public_key_pkcs1 public_key_data;
+ AWS_ZERO_STRUCT(public_key_data);
+ if (aws_der_decoder_load_public_rsa_pkcs1(decoder, &public_key_data)) {
+ goto on_error;
+ }
+
+ /* Hard to predict final blob size, so use pkcs1 key size as upper bound. */
+ size_t total_buffer_size = key.len + sizeof(BCRYPT_RSAKEY_BLOB);
+
+ aws_byte_buf_init(&key_pair_impl->key_buf, allocator, total_buffer_size);
+
+ BCRYPT_RSAKEY_BLOB key_blob;
+ AWS_ZERO_STRUCT(key_blob);
+ key_blob.Magic = BCRYPT_RSAPUBLIC_MAGIC;
+ key_blob.BitLength = (ULONG)public_key_data.modulus.len * 8;
+ key_blob.cbPublicExp = (ULONG)public_key_data.publicExponent.len;
+ key_blob.cbModulus = (ULONG)public_key_data.modulus.len;
+
+ struct aws_byte_cursor header = aws_byte_cursor_from_array(&key_blob, sizeof(key_blob));
+ aws_byte_buf_append(&key_pair_impl->key_buf, &header);
+
+ LPCWSTR blob_type = BCRYPT_PUBLIC_KEY_BLOB;
+ ULONG flags = 0;
+
+ aws_byte_buf_append(&key_pair_impl->key_buf, &public_key_data.publicExponent);
+ aws_byte_buf_append(&key_pair_impl->key_buf, &public_key_data.modulus);
+
+ NTSTATUS status = BCryptImportKeyPair(
+ s_rsa_alg,
+ NULL,
+ blob_type,
+ &key_pair_impl->key_handle,
+ key_pair_impl->key_buf.buffer,
+ (ULONG)key_pair_impl->key_buf.len,
+ flags);
+
+ if (s_reinterpret_bc_error_as_crt(status, "BCryptImportKeyPair")) {
+ goto on_error;
+ }
+
+ key_pair_impl->base.vtable = &s_rsa_key_pair_vtable;
+ key_pair_impl->base.key_size_in_bits = public_key_data.modulus.len * 8;
+
+ aws_der_decoder_destroy(decoder);
+
+ return &key_pair_impl->base;
+
+on_error:
+ aws_der_decoder_destroy(decoder);
+ s_rsa_destroy_key(&key_pair_impl->base);
+ return NULL;
+}