bcrypt: Add support for RSA OAEP padding.

Needs GnuTLS 3.8.4.
This commit is contained in:
Hans Leidekker 2024-03-26 11:56:22 +01:00 committed by Alexandre Julliard
parent 1304bf7fb9
commit ce2ae79f9d
4 changed files with 210 additions and 52 deletions

View file

@ -241,19 +241,23 @@ struct key_asymmetric_decrypt_params
struct key *key;
UCHAR *input;
unsigned input_len;
void *padding;
UCHAR *output;
ULONG output_len;
ULONG *ret_len;
ULONG flags;
};
struct key_asymmetric_encrypt_params
{
struct key *key;
UCHAR *input;
unsigned input_len;
unsigned input_len;
void *padding;
UCHAR *output;
ULONG output_len;
ULONG output_len;
ULONG *ret_len;
ULONG flags;
};
struct key_asymmetric_duplicate_params

View file

@ -732,7 +732,7 @@ static NTSTATUS get_rsa_property( enum chain_mode mode, const WCHAR *prop, UCHAR
{
*ret_size = sizeof(ULONG);
if (size < sizeof(ULONG)) return STATUS_BUFFER_TOO_SMALL;
if (buf) *(ULONG *)buf = BCRYPT_SUPPORTED_PAD_PKCS1_SIG;
if (buf) *(ULONG *)buf = BCRYPT_SUPPORTED_PAD_PKCS1_SIG | BCRYPT_SUPPORTED_PAD_OAEP;
return STATUS_SUCCESS;
}
@ -2254,7 +2254,7 @@ NTSTATUS WINAPI BCryptEncrypt( BCRYPT_KEY_HANDLE handle, UCHAR *input, ULONG inp
}
else
{
if (flags & BCRYPT_PAD_NONE || flags & BCRYPT_PAD_OAEP)
if (flags & BCRYPT_PAD_NONE)
{
FIXME( "flags %#lx not implemented\n", flags );
return STATUS_NOT_IMPLEMENTED;
@ -2263,10 +2263,12 @@ NTSTATUS WINAPI BCryptEncrypt( BCRYPT_KEY_HANDLE handle, UCHAR *input, ULONG inp
asymmetric_params.input = input;
asymmetric_params.input_len = input_len;
asymmetric_params.padding = padding;
asymmetric_params.key = key;
asymmetric_params.output = output;
asymmetric_params.output_len = output_len;
asymmetric_params.ret_len = ret_len;
asymmetric_params.flags = flags;
ret = UNIX_CALL(key_asymmetric_encrypt, &asymmetric_params);
}
@ -2299,7 +2301,7 @@ NTSTATUS WINAPI BCryptDecrypt( BCRYPT_KEY_HANDLE handle, UCHAR *input, ULONG inp
}
else
{
if (flags & BCRYPT_PAD_NONE || flags & BCRYPT_PAD_OAEP)
if (flags & BCRYPT_PAD_NONE)
{
FIXME( "flags %#lx not implemented\n", flags );
return STATUS_NOT_IMPLEMENTED;
@ -2309,9 +2311,11 @@ NTSTATUS WINAPI BCryptDecrypt( BCRYPT_KEY_HANDLE handle, UCHAR *input, ULONG inp
params.key = key;
params.input = input;
params.input_len = input_len;
params.padding = padding;
params.output = output;
params.output_len = output_len;
params.ret_len = ret_len;
params.flags = flags;
ret = UNIX_CALL(key_asymmetric_decrypt, &params);
}

View file

@ -162,6 +162,9 @@ static int (*pgnutls_privkey_import_dh_raw)(gnutls_privkey_t, const gnutls_dh_pa
const gnutls_datum_t *);
static int (*pgnutls_pubkey_import_dh_raw)(gnutls_pubkey_t, const gnutls_dh_params_t, const gnutls_datum_t *);
/* Not present in gnutls version < 3.8.4 */
static int (*pgnutls_x509_spki_set_rsa_oaep_params)(gnutls_x509_spki_t, gnutls_digest_algorithm_t, gnutls_datum_t *);
static void *libgnutls_handle;
#define MAKE_FUNCPTR(f) static typeof(f) * p##f
MAKE_FUNCPTR(gnutls_cipher_decrypt2);
@ -303,6 +306,12 @@ static void compat_gnutls_x509_spki_deinit(gnutls_x509_spki_t spki)
{
}
static int compat_gnutls_x509_spki_set_rsa_oaep_params(gnutls_x509_spki_t spki, gnutls_digest_algorithm_t dig,
gnutls_datum_t *label)
{
return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
}
static void compat_gnutls_x509_spki_set_rsa_pss_params(gnutls_x509_spki_t spki, gnutls_digest_algorithm_t dig,
unsigned int salt_size)
{
@ -444,6 +453,7 @@ static NTSTATUS gnutls_process_attach( void *args )
LOAD_FUNCPTR_OPT(gnutls_pubkey_verify_hash2)
LOAD_FUNCPTR_OPT(gnutls_x509_spki_deinit)
LOAD_FUNCPTR_OPT(gnutls_x509_spki_init)
LOAD_FUNCPTR_OPT(gnutls_x509_spki_set_rsa_oaep_params)
LOAD_FUNCPTR_OPT(gnutls_x509_spki_set_rsa_pss_params)
#undef LOAD_FUNCPTR_OPT
@ -2617,6 +2627,27 @@ static NTSTATUS key_asymmetric_duplicate( void *args )
return STATUS_SUCCESS;
}
static NTSTATUS privkey_set_rsa_oaep_params( gnutls_privkey_t key, gnutls_digest_algorithm_t dig, gnutls_datum_t *label )
{
gnutls_x509_spki_t spki;
int ret;
if (((ret = pgnutls_x509_spki_init( &spki ) < 0)))
{
pgnutls_perror( ret );
return STATUS_INTERNAL_ERROR;
}
pgnutls_x509_spki_set_rsa_oaep_params( spki, dig, label );
ret = pgnutls_privkey_set_spki( key, spki, 0 );
pgnutls_x509_spki_deinit( spki );
if (ret < 0)
{
pgnutls_perror( ret );
return STATUS_INTERNAL_ERROR;
}
return STATUS_SUCCESS;
}
static NTSTATUS key_asymmetric_decrypt( void *args )
{
const struct key_asymmetric_decrypt_params *params = args;
@ -2624,6 +2655,28 @@ static NTSTATUS key_asymmetric_decrypt( void *args )
NTSTATUS status = STATUS_SUCCESS;
int ret;
if (params->key->alg_id == ALG_ID_RSA && params->flags & BCRYPT_PAD_OAEP)
{
BCRYPT_OAEP_PADDING_INFO *pad = params->padding;
gnutls_digest_algorithm_t dig;
gnutls_datum_t label;
if (!pad || !pad->pszAlgId)
{
WARN( "padding info not found\n" );
return STATUS_INVALID_PARAMETER;
}
if ((dig = get_digest_from_id( pad->pszAlgId )) == GNUTLS_DIG_UNKNOWN)
{
FIXME( "hash algorithm %s not recognized\n", debugstr_w(pad->pszAlgId) );
return STATUS_NOT_SUPPORTED;
}
label.data = pad->pbLabel;
label.size = pad->cbLabel;
if ((status = privkey_set_rsa_oaep_params( key_data(params->key)->a.privkey, dig, &label ))) return status;
}
e.data = params->input;
e.size = params->input_len;
if ((ret = pgnutls_privkey_decrypt_data( key_data(params->key)->a.privkey, 0, &e, &d )))
@ -2634,12 +2687,33 @@ static NTSTATUS key_asymmetric_decrypt( void *args )
*params->ret_len = d.size;
if (params->output_len >= d.size) memcpy( params->output, d.data, *params->ret_len );
else status = STATUS_BUFFER_TOO_SMALL;
else if (params->output) status = STATUS_BUFFER_TOO_SMALL;
free( d.data );
return status;
}
static NTSTATUS pubkey_set_rsa_oaep_params( gnutls_pubkey_t key, gnutls_digest_algorithm_t dig, gnutls_datum_t *label )
{
gnutls_x509_spki_t spki;
int ret;
if (((ret = pgnutls_x509_spki_init( &spki ) < 0)))
{
pgnutls_perror( ret );
return STATUS_INTERNAL_ERROR;
}
pgnutls_x509_spki_set_rsa_oaep_params( spki, dig, label );
ret = pgnutls_pubkey_set_spki( key, spki, 0 );
pgnutls_x509_spki_deinit( spki );
if (ret < 0)
{
pgnutls_perror( ret );
return STATUS_INTERNAL_ERROR;
}
return STATUS_SUCCESS;
}
static NTSTATUS key_asymmetric_encrypt( void *args )
{
const struct key_asymmetric_encrypt_params *params = args;
@ -2649,6 +2723,28 @@ static NTSTATUS key_asymmetric_encrypt( void *args )
if (!key_data(params->key)->a.pubkey) return STATUS_INVALID_HANDLE;
if (params->key->alg_id == ALG_ID_RSA && params->flags & BCRYPT_PAD_OAEP)
{
BCRYPT_OAEP_PADDING_INFO *pad = params->padding;
gnutls_digest_algorithm_t dig;
gnutls_datum_t label;
if (!pad || !pad->pszAlgId || !pad->pbLabel)
{
WARN( "padding info not found\n" );
return STATUS_INVALID_PARAMETER;
}
if ((dig = get_digest_from_id( pad->pszAlgId )) == GNUTLS_DIG_UNKNOWN)
{
FIXME( "hash algorithm %s not recognized\n", debugstr_w(pad->pszAlgId) );
return STATUS_NOT_SUPPORTED;
}
label.data = pad->pbLabel;
label.size = pad->cbLabel;
if ((status = pubkey_set_rsa_oaep_params( key_data(params->key)->a.pubkey, dig, &label ))) return status;
}
d.data = params->input;
d.size = params->input_len;
if ((ret = pgnutls_pubkey_encrypt_data(key_data(params->key)->a.pubkey, 0, &d, &e)))
@ -2751,12 +2847,19 @@ struct key32
union padding
{
BCRYPT_OAEP_PADDING_INFO oaep;
BCRYPT_PKCS1_PADDING_INFO pkcs1;
BCRYPT_PSS_PADDING_INFO pss;
};
union padding32
{
struct
{
PTR32 pszAlgId;
PTR32 pbLabel;
ULONG cbLabel;
} oaep;
struct
{
PTR32 pszAlgId;
@ -2774,13 +2877,21 @@ static union padding *get_padding( union padding32 *padding32, union padding *pa
switch (flags)
{
case BCRYPT_PAD_OAEP:
padding->oaep.pszAlgId = ULongToPtr( padding32->oaep.pszAlgId );
padding->oaep.pbLabel = ULongToPtr( padding32->oaep.pbLabel );
padding->oaep.cbLabel = padding32->oaep.cbLabel;
return padding;
case BCRYPT_PAD_PKCS1:
padding->pkcs1.pszAlgId = ULongToPtr( padding32->pkcs1.pszAlgId );
return padding;
case BCRYPT_PAD_PSS:
padding->pss.pszAlgId = ULongToPtr( padding32->pss.pszAlgId );
padding->pss.cbSalt = padding32->pss.cbSalt;
return padding;
default:
break;
}
@ -2965,22 +3076,27 @@ static NTSTATUS wow64_key_asymmetric_decrypt( void *args )
PTR32 key;
PTR32 input;
ULONG input_len;
PTR32 padding;
PTR32 output;
ULONG output_len;
PTR32 ret_len;
ULONG flags;
} const *params32 = args;
NTSTATUS ret;
struct key key;
union padding padding;
struct key32 *key32 = ULongToPtr( params32->key );
struct key_asymmetric_decrypt_params params =
{
get_asymmetric_key( key32, &key ),
ULongToPtr(params32->input),
params32->input_len,
get_padding( ULongToPtr(params32->padding), &padding, params32->flags ),
ULongToPtr(params32->output),
params32->output_len,
ULongToPtr(params32->ret_len)
ULongToPtr(params32->ret_len),
params32->flags
};
ret = key_asymmetric_decrypt( &params );
@ -2995,22 +3111,27 @@ static NTSTATUS wow64_key_asymmetric_encrypt( void *args )
PTR32 key;
PTR32 input;
ULONG input_len;
PTR32 padding;
PTR32 output;
ULONG output_len;
PTR32 ret_len;
ULONG flags;
} const *params32 = args;
NTSTATUS ret;
struct key key;
union padding padding;
struct key32 *key32 = ULongToPtr( params32->key );
struct key_asymmetric_encrypt_params params =
{
get_asymmetric_key( key32, &key ),
ULongToPtr(params32->input),
params32->input_len,
get_padding( ULongToPtr(params32->padding), &padding, params32->flags ),
ULongToPtr(params32->output),
params32->output_len,
ULongToPtr(params32->ret_len)
ULongToPtr(params32->ret_len),
params32->flags
};
ret = key_asymmetric_encrypt( &params );

View file

@ -2444,20 +2444,16 @@ static const UCHAR rsa_encrypted_no_padding[] =
static void test_rsa_encrypt(void)
{
static UCHAR input[] = "Hello World!";
static UCHAR input_no_padding[64] = { 0 };
UCHAR encrypted[64], decrypted[64];
BCRYPT_ALG_HANDLE rsa = 0;
BCRYPT_KEY_HANDLE key = 0, key2;
NTSTATUS ret = 0;
DWORD encrypted_size = 60;
UCHAR *encrypted_a = NULL;
UCHAR *encrypted_b = NULL;
DWORD decrypted_size = 0;
UCHAR input[] = "Hello World!", input_no_padding[64] = { 0 }, encrypted[64], decrypted[64];
BCRYPT_ALG_HANDLE rsa;
BCRYPT_KEY_HANDLE key, key2;
NTSTATUS ret;
DWORD encrypted_size, decrypted_size;
UCHAR *encrypted_a = NULL, *encrypted_b = NULL;
BCRYPT_OAEP_PADDING_INFO oaep_pad;
oaep_pad.pszAlgId = BCRYPT_MD5_ALGORITHM;
oaep_pad.pbLabel = (PUCHAR)"test";
oaep_pad.pszAlgId = BCRYPT_SHA256_ALGORITHM;
oaep_pad.pbLabel = (UCHAR *)"test";
oaep_pad.cbLabel = 5;
ret = BCryptOpenAlgorithmProvider(&rsa, BCRYPT_RSA_ALGORITHM, NULL, 0);
@ -2478,10 +2474,11 @@ static void test_rsa_encrypt(void)
ret = BCryptImportKeyPair(rsa, NULL, BCRYPT_RSAPRIVATE_BLOB, &key, rsaPrivateBlob, sizeof(rsaPrivateBlob), 0);
ok(ret == STATUS_SUCCESS, "got %#lx\n", ret);
todo_wine {
/* No padding */
todo_wine {
memset(input_no_padding, 0, sizeof(input_no_padding));
strcpy((char *)input_no_padding, "Hello World");
encrypted_size = 0;
ret = BCryptEncrypt(key, input_no_padding, sizeof(input_no_padding), NULL, NULL, 0, NULL, 0, &encrypted_size, BCRYPT_PAD_NONE);
ok(ret == STATUS_SUCCESS, "got %lx\n", ret);
ok(encrypted_size == 64, "got size of %ld\n", encrypted_size);
@ -2496,22 +2493,32 @@ static void test_rsa_encrypt(void)
ret = BCryptEncrypt(key, input_no_padding, sizeof(input_no_padding), NULL, NULL, 0, encrypted_a, 12, &encrypted_size, BCRYPT_PAD_NONE);
ok(ret == STATUS_BUFFER_TOO_SMALL, "got %lx\n", ret);
ok(encrypted_size == 64, "got size of %ld\n", encrypted_size);
ret = BCryptEncrypt(key, input_no_padding, sizeof(input_no_padding), NULL, NULL, 0, encrypted_a, encrypted_size, &encrypted_size, BCRYPT_PAD_NONE);
ok(ret == STATUS_SUCCESS, "got %lx\n", ret);
ok(encrypted_size == 64, "got size of %ld\n", encrypted_size);
ret = BCryptEncrypt(key, input_no_padding, sizeof(input_no_padding), NULL, NULL, 0, encrypted_b, encrypted_size, &encrypted_size, BCRYPT_PAD_NONE);
ok(ret == STATUS_SUCCESS, "got %lx\n", ret);
}
ok(!memcmp(encrypted_a, encrypted_b, encrypted_size), "Both outputs should be the same\n");
ok(!memcmp(encrypted_b, rsa_encrypted_no_padding, encrypted_size), "Data mismatch.\n");
BCryptDecrypt(key, encrypted_a, encrypted_size, NULL, NULL, 0, NULL, 0, &decrypted_size, BCRYPT_PAD_NONE);
todo_wine {
decrypted_size = 0;
ret = BCryptDecrypt(key, encrypted_a, encrypted_size, NULL, NULL, 0, NULL, 0, &decrypted_size, BCRYPT_PAD_NONE);
ok(ret == STATUS_SUCCESS, "got %lx\n", ret);
ok(decrypted_size == sizeof(input_no_padding), "got %lu\n", decrypted_size);
BCryptDecrypt(key, encrypted_a, encrypted_size, NULL, NULL, 0, decrypted, decrypted_size, &decrypted_size, BCRYPT_PAD_NONE);
ok(!memcmp(decrypted, input_no_padding, sizeof(input_no_padding)), "Decrypted output it's not what expected\n");
ret = BCryptDecrypt(key, encrypted_a, encrypted_size, NULL, NULL, 0, decrypted, decrypted_size, &decrypted_size, BCRYPT_PAD_NONE);
ok(ret == STATUS_SUCCESS, "got %lx\n", ret);
ok(decrypted_size == sizeof(input_no_padding), "got %lu\n", decrypted_size);
ok(!memcmp(decrypted, input_no_padding, sizeof(input_no_padding)), "unexpected output\n");
}
encrypted_size = 60;
/* PKCS1 Padding */
encrypted_size = 0;
ret = BCryptEncrypt(key, input, sizeof(input), NULL, NULL, 0, NULL, 0, &encrypted_size, BCRYPT_PAD_PKCS1);
ok(ret == STATUS_SUCCESS, "got %lx\n", ret);
ok(encrypted_size == 64, "got size of %ld\n", encrypted_size);
@ -2523,22 +2530,54 @@ static void test_rsa_encrypt(void)
ret = BCryptEncrypt(key, input, sizeof(input), NULL, NULL, 0, encrypted_a, encrypted_size, &encrypted_size, BCRYPT_PAD_PKCS1);
ok(ret == STATUS_SUCCESS, "got %lx\n", ret);
ok(encrypted_size == 64, "got size of %ld\n", encrypted_size);
ret = BCryptEncrypt(key, input, sizeof(input), NULL, NULL, 0, encrypted_b, encrypted_size, &encrypted_size, BCRYPT_PAD_PKCS1);
ok(ret == STATUS_SUCCESS, "got %lx\n", ret);
ok(encrypted_size == 64, "got size of %ld\n", encrypted_size);
ok(memcmp(encrypted_a, encrypted_b, encrypted_size), "Both outputs are the same\n");
BCryptDecrypt(key, encrypted_a, encrypted_size, NULL, NULL, 0, NULL, 0, &decrypted_size, BCRYPT_PAD_PKCS1);
decrypted_size = 0;
ret = BCryptDecrypt(key, encrypted_a, encrypted_size, NULL, NULL, 0, NULL, 0, &decrypted_size, BCRYPT_PAD_PKCS1);
ok(ret == STATUS_SUCCESS, "got %lx\n", ret);
ok(decrypted_size == sizeof(input), "got size of %ld\n", decrypted_size);
BCryptDecrypt(key, encrypted_a, encrypted_size, NULL, NULL, 0, decrypted, decrypted_size, &decrypted_size, BCRYPT_PAD_PKCS1);
ok(!memcmp(decrypted, input, sizeof(input)), "Decrypted output it's not what expected\n");
todo_wine {
encrypted_size = 60;
/* OAEP Padding */
ret = BCryptEncrypt(key, input, sizeof(input), &oaep_pad, NULL, 0, NULL, 0, &encrypted_size, BCRYPT_PAD_OAEP);
ret = BCryptDecrypt(key, encrypted_a, encrypted_size, NULL, NULL, 0, decrypted, decrypted_size, &decrypted_size, BCRYPT_PAD_PKCS1);
ok(ret == STATUS_SUCCESS, "got %lx\n", ret);
ok(decrypted_size == sizeof(input), "got size of %ld\n", decrypted_size);
ok(!memcmp(decrypted, input, sizeof(input)), "unexpected output\n");
ret = BCryptImportKeyPair(rsa, NULL, LEGACY_RSAPRIVATE_BLOB, &key2, (UCHAR *)&rsaLegacyPrivateBlob,
sizeof(rsaLegacyPrivateBlob), 0);
ok(ret == STATUS_SUCCESS, "got %#lx\n", ret);
ret = BCryptEncrypt(key2, input, sizeof(input), NULL, NULL, 0, encrypted, sizeof(encrypted),
&encrypted_size, BCRYPT_PAD_PKCS1);
ok(ret == STATUS_SUCCESS, "got %lx\n", ret);
ok(encrypted_size == 64, "got size of %ld\n", encrypted_size);
memset(decrypted, 0, sizeof(decrypted));
ret = BCryptDecrypt(key, encrypted, sizeof(encrypted), NULL, NULL, 0, decrypted, sizeof(decrypted),
&decrypted_size, BCRYPT_PAD_PKCS1);
ok(ret == STATUS_SUCCESS, "got %lx\n", ret);
ok(decrypted_size == sizeof(input), "got size of %ld\n", decrypted_size);
ok(!memcmp(decrypted, input, sizeof(input)), "unexpected output\n");
BCryptDestroyKey(key2);
BCryptDestroyKey(key);
/* OAEP Padding */
ret = BCryptGenerateKeyPair(rsa, &key, 640 /* minimum size for sha256 hash */, 0);
ok(ret == STATUS_SUCCESS, "got %lx\n", ret);
ret = BCryptFinalizeKeyPair(key, 0);
ok(ret == STATUS_SUCCESS, "got %#lx\n", ret);
todo_wine {
encrypted_size = 0;
ret = BCryptEncrypt(key, input, sizeof(input), &oaep_pad, NULL, 0, NULL, 0, &encrypted_size, BCRYPT_PAD_OAEP);
ok(ret == STATUS_SUCCESS, "got %lx\n", ret);
ok(encrypted_size == 80, "got size of %ld\n", encrypted_size);
encrypted_a = realloc(encrypted_a, encrypted_size);
memset(encrypted_a, 0, encrypted_size);
encrypted_b = realloc(encrypted_b, encrypted_size);
@ -2546,38 +2585,28 @@ static void test_rsa_encrypt(void)
ret = BCryptEncrypt(key, input, sizeof(input), &oaep_pad, NULL, 0, encrypted_a, encrypted_size, &encrypted_size, BCRYPT_PAD_OAEP);
ok(ret == STATUS_SUCCESS, "got %lx\n", ret);
ok(encrypted_size == 80, "got size of %ld\n", encrypted_size);
ret = BCryptEncrypt(key, input, sizeof(input), &oaep_pad, NULL, 0, encrypted_b, encrypted_size, &encrypted_size, BCRYPT_PAD_OAEP);
ok(ret == STATUS_SUCCESS, "got %lx\n", ret);
ok(encrypted_size == 80, "got size of %ld\n", encrypted_size);
ok(memcmp(encrypted_a, encrypted_b, encrypted_size), "Both outputs are the same\n");
decrypted_size = 0;
memset(decrypted, 0, sizeof(decrypted));
BCryptDecrypt(key, encrypted_a, encrypted_size, &oaep_pad, NULL, 0, NULL, 0, &decrypted_size, BCRYPT_PAD_OAEP);
ret = BCryptDecrypt(key, encrypted_a, encrypted_size, &oaep_pad, NULL, 0, NULL, 0, &decrypted_size, BCRYPT_PAD_OAEP);
ok(ret == STATUS_SUCCESS, "got %lx\n", ret);
ok(decrypted_size == sizeof(input), "got %lu\n", decrypted_size);
BCryptDecrypt(key, encrypted_a, encrypted_size, &oaep_pad, NULL, 0, decrypted, decrypted_size, &decrypted_size, BCRYPT_PAD_OAEP);
ok(!memcmp(decrypted, input, sizeof(input)), "Decrypted output it's not what expected\n");
ret = BCryptDecrypt(key, encrypted_a, encrypted_size, &oaep_pad, NULL, 0, decrypted, decrypted_size, &decrypted_size, BCRYPT_PAD_OAEP);
ok(ret == STATUS_SUCCESS, "got %lx\n", ret);
ok(decrypted_size == sizeof(input), "got %lu\n", decrypted_size);
ok(!memcmp(decrypted, input, sizeof(input)), "unexpected output\n");
}
free(encrypted_a);
free(encrypted_b);
ret = BCryptImportKeyPair(rsa, NULL, LEGACY_RSAPRIVATE_BLOB, &key2,
(UCHAR *)&rsaLegacyPrivateBlob, sizeof(rsaLegacyPrivateBlob), 0);
ok(ret == STATUS_SUCCESS, "got %#lx\n", ret);
ret = BCryptEncrypt(key2, input, sizeof(input), NULL, NULL, 0,
encrypted, sizeof(encrypted), &encrypted_size, BCRYPT_PAD_PKCS1);
ok(ret == STATUS_SUCCESS, "got %lx\n", ret);
ok(encrypted_size == 64, "got size of %ld\n", encrypted_size);
memset(decrypted, 0, sizeof(decrypted));
ret = BCryptDecrypt(key, encrypted, sizeof(encrypted), NULL, NULL, 0,
decrypted, sizeof(decrypted), &decrypted_size, BCRYPT_PAD_PKCS1);
ok(ret == STATUS_SUCCESS, "got %lx\n", ret);
ok(decrypted_size == sizeof(input), "got size of %ld\n", decrypted_size);
ok(!memcmp(decrypted, input, sizeof(input)), "Decrypted output it's not what expected\n");
BCryptDestroyKey(key2);
BCryptDestroyKey(key);
if (pBCryptHash)