Signed-off-by: Santino Mazza mazzasantino1206@gmail.com --- dlls/bcrypt/bcrypt_main.c | 398 ++++++++++++++++++++++--------------- dlls/bcrypt/tests/bcrypt.c | 12 ++ 2 files changed, 255 insertions(+), 155 deletions(-)
diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c index 9fb9b6adf87..2ef67bc3024 100644 --- a/dlls/bcrypt/bcrypt_main.c +++ b/dlls/bcrypt/bcrypt_main.c @@ -1318,207 +1318,295 @@ static NTSTATUS key_symmetric_decrypt( struct key *key, UCHAR *input, ULONG inpu return status; }
-static NTSTATUS key_import_pair( struct algorithm *alg, const WCHAR *type, BCRYPT_KEY_HANDLE *ret_key, UCHAR *input, - ULONG input_len ) +static NTSTATUS key_import_ecc_public( struct algorithm *alg, BCRYPT_KEY_HANDLE *ret_key, UCHAR *input, + ULONG input_len ) { - struct key_import_params params; - struct key *key; - NTSTATUS status; + BCRYPT_ECCKEY_BLOB *ecc_blob = (BCRYPT_ECCKEY_BLOB *)input; + DWORD key_size, magic; ULONG size;
- if (!wcscmp( type, BCRYPT_ECCPUBLIC_BLOB )) + if (input_len < sizeof(*ecc_blob)) return STATUS_INVALID_PARAMETER; + + switch (alg->id) { - BCRYPT_ECCKEY_BLOB *ecc_blob = (BCRYPT_ECCKEY_BLOB *)input; - DWORD key_size, magic; + case ALG_ID_ECDH_P256: + key_size = 32; + magic = BCRYPT_ECDH_PUBLIC_P256_MAGIC; + break;
- if (input_len < sizeof(*ecc_blob)) return STATUS_INVALID_PARAMETER; + case ALG_ID_ECDSA_P256: + key_size = 32; + magic = BCRYPT_ECDSA_PUBLIC_P256_MAGIC; + break;
- switch (alg->id) - { - case ALG_ID_ECDH_P256: - key_size = 32; - magic = BCRYPT_ECDH_PUBLIC_P256_MAGIC; - break; + case ALG_ID_ECDSA_P384: + key_size = 48; + magic = BCRYPT_ECDSA_PUBLIC_P384_MAGIC; + break;
- case ALG_ID_ECDSA_P256: - key_size = 32; - magic = BCRYPT_ECDSA_PUBLIC_P256_MAGIC; - break; + default: + FIXME( "algorithm %u does not yet support importing blob of type %s\n", alg->id, debugstr_w(BCRYPT_ECCPUBLIC_BLOB) ); + return STATUS_NOT_SUPPORTED; + }
- case ALG_ID_ECDSA_P384: - key_size = 48; - magic = BCRYPT_ECDSA_PUBLIC_P384_MAGIC; - break; + if (ecc_blob->dwMagic != magic) return STATUS_INVALID_PARAMETER; + if (ecc_blob->cbKey != key_size || input_len < sizeof(*ecc_blob) + ecc_blob->cbKey * 2) + return STATUS_INVALID_PARAMETER;
- default: - FIXME( "algorithm %u does not yet support importing blob of type %s\n", alg->id, debugstr_w(type) ); - return STATUS_NOT_SUPPORTED; - } + size = sizeof(*ecc_blob) + ecc_blob->cbKey * 2; + return key_asymmetric_create( (struct key **)ret_key, alg, key_size * 8, (BYTE *)ecc_blob, size ); +}
- if (ecc_blob->dwMagic != magic) return STATUS_INVALID_PARAMETER; - if (ecc_blob->cbKey != key_size || input_len < sizeof(*ecc_blob) + ecc_blob->cbKey * 2) - return STATUS_INVALID_PARAMETER; +static NTSTATUS key_import_ecc_private( struct algorithm *alg, BCRYPT_KEY_HANDLE *ret_key, UCHAR *input, + ULONG input_len ) +{ + struct key_import_params params; + struct key *key; + BCRYPT_ECCKEY_BLOB *ecc_blob = (BCRYPT_ECCKEY_BLOB *)input; + DWORD key_size, magic; + NTSTATUS status; + DWORD size; + + if (input_len < sizeof(*ecc_blob)) return STATUS_INVALID_PARAMETER; + + switch (alg->id) + { + case ALG_ID_ECDH_P256: + key_size = 32; + magic = BCRYPT_ECDH_PRIVATE_P256_MAGIC; + break; + case ALG_ID_ECDSA_P256: + key_size = 32; + magic = BCRYPT_ECDSA_PRIVATE_P256_MAGIC; + break;
- size = sizeof(*ecc_blob) + ecc_blob->cbKey * 2; - return key_asymmetric_create( (struct key **)ret_key, alg, key_size * 8, (BYTE *)ecc_blob, size ); + default: + FIXME( "algorithm %u does not yet support importing blob of type %s\n", alg->id, debugstr_w(BCRYPT_ECCPUBLIC_BLOB) ); + return STATUS_NOT_SUPPORTED; } - else if (!wcscmp( type, BCRYPT_ECCPRIVATE_BLOB )) + + if (ecc_blob->dwMagic != magic) return STATUS_INVALID_PARAMETER; + if (ecc_blob->cbKey != key_size || input_len < sizeof(*ecc_blob) + ecc_blob->cbKey * 3) + return STATUS_INVALID_PARAMETER; + + size = sizeof(*ecc_blob) + key_size * 2; + if ((status = key_asymmetric_create( &key, alg, key_size * 8, NULL, size ))) return status; + + params.key = key; + params.buf = input; + params.len = input_len; + if ((status = UNIX_CALL( key_import_ecc, ¶ms ))) { - BCRYPT_ECCKEY_BLOB *ecc_blob = (BCRYPT_ECCKEY_BLOB *)input; - DWORD key_size, magic; + BCryptDestroyKey( key ); + return status; + }
- if (input_len < sizeof(*ecc_blob)) return STATUS_INVALID_PARAMETER; + *ret_key = key; + return STATUS_SUCCESS; +}
- switch (alg->id) - { - case ALG_ID_ECDH_P256: - key_size = 32; - magic = BCRYPT_ECDH_PRIVATE_P256_MAGIC; - break; - case ALG_ID_ECDSA_P256: - key_size = 32; - magic = BCRYPT_ECDSA_PRIVATE_P256_MAGIC; - break; +static NTSTATUS key_import_rsa_public( struct algorithm *alg, BCRYPT_KEY_HANDLE *ret_key, UCHAR *input, + ULONG input_len ) +{ + BCRYPT_RSAKEY_BLOB *rsa_blob = (BCRYPT_RSAKEY_BLOB *)input; + DWORD size;
- default: - FIXME( "algorithm %u does not yet support importing blob of type %s\n", alg->id, debugstr_w(type) ); - return STATUS_NOT_SUPPORTED; - } + if (input_len < sizeof(*rsa_blob)) return STATUS_INVALID_PARAMETER; + if ((alg->id != ALG_ID_RSA && alg->id != ALG_ID_RSA_SIGN) || rsa_blob->Magic != BCRYPT_RSAPUBLIC_MAGIC) + return STATUS_NOT_SUPPORTED;
- if (ecc_blob->dwMagic != magic) return STATUS_INVALID_PARAMETER; - if (ecc_blob->cbKey != key_size || input_len < sizeof(*ecc_blob) + ecc_blob->cbKey * 3) - return STATUS_INVALID_PARAMETER; + size = sizeof(*rsa_blob) + rsa_blob->cbPublicExp + rsa_blob->cbModulus; + return key_asymmetric_create( (struct key **)ret_key, alg, rsa_blob->BitLength, (BYTE *)rsa_blob, size ); +}
- size = sizeof(*ecc_blob) + key_size * 2; - if ((status = key_asymmetric_create( &key, alg, key_size * 8, NULL, size ))) return status; +static NTSTATUS key_import_rsa_private( struct algorithm *alg, BCRYPT_KEY_HANDLE *ret_key, UCHAR *input, + ULONG input_len ) +{ + BCRYPT_RSAKEY_BLOB *rsa_blob = (BCRYPT_RSAKEY_BLOB *)input; + struct key_import_params params; + struct key *key; + NTSTATUS status; + DWORD size;
- params.key = key; - params.buf = input; - params.len = input_len; - if ((status = UNIX_CALL( key_import_ecc, ¶ms ))) - { - BCryptDestroyKey( key ); - return status; - } + if (input_len < sizeof(*rsa_blob)) return STATUS_INVALID_PARAMETER; + if (alg->id != ALG_ID_RSA || (rsa_blob->Magic != BCRYPT_RSAPRIVATE_MAGIC && + rsa_blob->Magic != BCRYPT_RSAFULLPRIVATE_MAGIC)) return STATUS_NOT_SUPPORTED;
- *ret_key = key; - return STATUS_SUCCESS; - } - else if (!wcscmp( type, BCRYPT_RSAPUBLIC_BLOB )) + size = sizeof(*rsa_blob) + rsa_blob->cbPublicExp + rsa_blob->cbModulus; + if ((status = key_asymmetric_create( &key, alg, rsa_blob->BitLength, (BYTE *)rsa_blob, size ))) + return status; + params.key = key; + params.buf = input; + params.len = input_len; + if ((status = UNIX_CALL( key_import_rsa, ¶ms ))) { - BCRYPT_RSAKEY_BLOB *rsa_blob = (BCRYPT_RSAKEY_BLOB *)input; + BCryptDestroyKey( key ); + return status; + }
- if (input_len < sizeof(*rsa_blob)) return STATUS_INVALID_PARAMETER; - if ((alg->id != ALG_ID_RSA && alg->id != ALG_ID_RSA_SIGN) || rsa_blob->Magic != BCRYPT_RSAPUBLIC_MAGIC) - return STATUS_NOT_SUPPORTED; + *ret_key = key; + return STATUS_SUCCESS; +}
- size = sizeof(*rsa_blob) + rsa_blob->cbPublicExp + rsa_blob->cbModulus; - return key_asymmetric_create( (struct key **)ret_key, alg, rsa_blob->BitLength, (BYTE *)rsa_blob, size ); - } - else if (!wcscmp( type, BCRYPT_RSAPRIVATE_BLOB ) || !wcscmp( type, BCRYPT_RSAFULLPRIVATE_BLOB )) - { - BCRYPT_RSAKEY_BLOB *rsa_blob = (BCRYPT_RSAKEY_BLOB *)input; +static NTSTATUS key_import_dsa_public( struct algorithm *alg, BCRYPT_KEY_HANDLE *ret_key, UCHAR *input, + ULONG input_len ) +{ + BCRYPT_DSA_KEY_BLOB *dsa_blob = (BCRYPT_DSA_KEY_BLOB *)input; + DWORD size;
- if (input_len < sizeof(*rsa_blob)) return STATUS_INVALID_PARAMETER; - if (alg->id != ALG_ID_RSA || (rsa_blob->Magic != BCRYPT_RSAPRIVATE_MAGIC && - rsa_blob->Magic != BCRYPT_RSAFULLPRIVATE_MAGIC)) return STATUS_NOT_SUPPORTED; + if (input_len < sizeof(*dsa_blob)) return STATUS_INVALID_PARAMETER; + if ((alg->id != ALG_ID_DSA) || dsa_blob->dwMagic != BCRYPT_DSA_PUBLIC_MAGIC) + return STATUS_NOT_SUPPORTED;
- size = sizeof(*rsa_blob) + rsa_blob->cbPublicExp + rsa_blob->cbModulus; - if ((status = key_asymmetric_create( &key, alg, rsa_blob->BitLength, (BYTE *)rsa_blob, size ))) - return status; - params.key = key; - params.buf = input; - params.len = input_len; - if ((status = UNIX_CALL( key_import_rsa, ¶ms ))) - { - BCryptDestroyKey( key ); - return status; - } + size = sizeof(*dsa_blob) + dsa_blob->cbKey * 3; + return key_asymmetric_create( (struct key **)ret_key, alg, dsa_blob->cbKey * 8, (BYTE *)dsa_blob, size ); +}
- *ret_key = key; - return STATUS_SUCCESS; - } - else if (!wcscmp( type, BCRYPT_DSA_PUBLIC_BLOB )) - { - BCRYPT_DSA_KEY_BLOB *dsa_blob = (BCRYPT_DSA_KEY_BLOB *)input; +static NTSTATUS key_import_legacy_dsa_v2_public( struct algorithm *alg, BCRYPT_KEY_HANDLE *ret_key, UCHAR *input, + ULONG input_len ) +{ + BLOBHEADER *hdr = (BLOBHEADER *)input; + DSSPUBKEY *pubkey; + struct key_import_params params; + struct key *key; + DWORD size; + NTSTATUS status;
- if (input_len < sizeof(*dsa_blob)) return STATUS_INVALID_PARAMETER; - if ((alg->id != ALG_ID_DSA) || dsa_blob->dwMagic != BCRYPT_DSA_PUBLIC_MAGIC) - return STATUS_NOT_SUPPORTED; + if (alg->id != ALG_ID_DSA) return STATUS_NOT_SUPPORTED; + if (input_len < sizeof(*hdr)) return STATUS_INVALID_PARAMETER;
- size = sizeof(*dsa_blob) + dsa_blob->cbKey * 3; - return key_asymmetric_create( (struct key **)ret_key, alg, dsa_blob->cbKey * 8, (BYTE *)dsa_blob, size ); - } - else if (!wcscmp( type, LEGACY_DSA_V2_PRIVATE_BLOB )) + if (hdr->bType != PUBLICKEYBLOB && hdr->bVersion != 2 && hdr->aiKeyAlg != CALG_DSS_SIGN) { - BLOBHEADER *hdr = (BLOBHEADER *)input; - DSSPUBKEY *pubkey; + FIXME( "blob type %u version %u alg id %u not supported\n", hdr->bType, hdr->bVersion, hdr->aiKeyAlg ); + return STATUS_NOT_SUPPORTED; + }
- if (input_len < sizeof(*hdr)) return STATUS_INVALID_PARAMETER; + if (input_len < sizeof(*hdr) + sizeof(*pubkey)) return STATUS_INVALID_PARAMETER; + pubkey = (DSSPUBKEY *)(hdr + 1); + if (pubkey->magic != MAGIC_DSS1) return STATUS_NOT_SUPPORTED;
- if (hdr->bType != PRIVATEKEYBLOB && hdr->bVersion != 2 && hdr->aiKeyAlg != CALG_DSS_SIGN) - { - FIXME( "blob type %u version %u alg id %u not supported\n", hdr->bType, hdr->bVersion, hdr->aiKeyAlg ); - return STATUS_NOT_SUPPORTED; - } - if (alg->id != ALG_ID_DSA) - { - FIXME( "algorithm %u does not support importing blob of type %s\n", alg->id, debugstr_w(type) ); - return STATUS_NOT_SUPPORTED; - } + size = sizeof(*hdr) + sizeof(*pubkey) + (pubkey->bitlen / 8) * 3 + 20 + sizeof(DSSSEED); + if (input_len < size) return STATUS_INVALID_PARAMETER;
- if (input_len < sizeof(*hdr) + sizeof(*pubkey)) return STATUS_INVALID_PARAMETER; - pubkey = (DSSPUBKEY *)(hdr + 1); - if (pubkey->magic != MAGIC_DSS2) return STATUS_NOT_SUPPORTED; + if ((status = key_asymmetric_create( &key, alg, pubkey->bitlen, (BYTE *)hdr, size ))) return status; + key->u.a.flags |= KEY_FLAG_LEGACY_DSA_V2;
- if (input_len < sizeof(*hdr) + sizeof(*pubkey) + (pubkey->bitlen / 8) * 2 + 40 + sizeof(DSSSEED)) - return STATUS_INVALID_PARAMETER; + *ret_key = key; + return STATUS_SUCCESS; +}
- size = sizeof(*hdr) + sizeof(*pubkey) + (pubkey->bitlen / 8) * 3 + 20 + sizeof(DSSSEED); - if ((status = key_asymmetric_create( &key, alg, pubkey->bitlen, NULL, size ))) return status; +static NTSTATUS key_import_legacy_dsa_v2_private( struct algorithm *alg, BCRYPT_KEY_HANDLE *ret_key, UCHAR *input, + ULONG input_len ) +{ + BLOBHEADER *hdr = (BLOBHEADER *)input; + DSSPUBKEY *pubkey; + struct key_import_params params; + struct key *key; + NTSTATUS status; + DWORD size;
- params.key = key; - params.buf = input; - params.len = input_len; - if ((status = UNIX_CALL( key_import_dsa_capi, ¶ms ))) - { - BCryptDestroyKey( key ); - return status; - } + if (input_len < sizeof(*hdr)) return STATUS_INVALID_PARAMETER;
- *ret_key = key; - return STATUS_SUCCESS; + if (hdr->bType != PRIVATEKEYBLOB && hdr->bVersion != 2 && hdr->aiKeyAlg != CALG_DSS_SIGN) + { + FIXME( "blob type %u version %u alg id %u not supported\n", hdr->bType, hdr->bVersion, hdr->aiKeyAlg ); + return STATUS_NOT_SUPPORTED; } - else if (!wcscmp( type, LEGACY_DSA_V2_PUBLIC_BLOB )) /* not supported on native */ + if (alg->id != ALG_ID_DSA) { - BLOBHEADER *hdr = (BLOBHEADER *)input; - DSSPUBKEY *pubkey; + FIXME( "algorithm %u does not support importing blob of type %s\n", alg->id, debugstr_w(LEGACY_DSA_V2_PRIVATE_BLOB) ); + return STATUS_NOT_SUPPORTED; + }
- if (alg->id != ALG_ID_DSA) return STATUS_NOT_SUPPORTED; - if (input_len < sizeof(*hdr)) return STATUS_INVALID_PARAMETER; + if (input_len < sizeof(*hdr) + sizeof(*pubkey)) return STATUS_INVALID_PARAMETER; + pubkey = (DSSPUBKEY *)(hdr + 1); + if (pubkey->magic != MAGIC_DSS2) return STATUS_NOT_SUPPORTED;
- if (hdr->bType != PUBLICKEYBLOB && hdr->bVersion != 2 && hdr->aiKeyAlg != CALG_DSS_SIGN) - { - FIXME( "blob type %u version %u alg id %u not supported\n", hdr->bType, hdr->bVersion, hdr->aiKeyAlg ); - return STATUS_NOT_SUPPORTED; - } + if (input_len < sizeof(*hdr) + sizeof(*pubkey) + (pubkey->bitlen / 8) * 2 + 40 + sizeof(DSSSEED)) + return STATUS_INVALID_PARAMETER; + + size = sizeof(*hdr) + sizeof(*pubkey) + (pubkey->bitlen / 8) * 3 + 20 + sizeof(DSSSEED); + if ((status = key_asymmetric_create( &key, alg, pubkey->bitlen, NULL, size ))) return status;
- if (input_len < sizeof(*hdr) + sizeof(*pubkey)) return STATUS_INVALID_PARAMETER; - pubkey = (DSSPUBKEY *)(hdr + 1); - if (pubkey->magic != MAGIC_DSS1) return STATUS_NOT_SUPPORTED; + params.key = key; + params.buf = input; + params.len = input_len; + if ((status = UNIX_CALL( key_import_dsa_capi, ¶ms ))) + { + BCryptDestroyKey( key ); + return status; + }
- size = sizeof(*hdr) + sizeof(*pubkey) + (pubkey->bitlen / 8) * 3 + 20 + sizeof(DSSSEED); - if (input_len < size) return STATUS_INVALID_PARAMETER; + *ret_key = key; + return STATUS_SUCCESS; +}
- if ((status = key_asymmetric_create( &key, alg, pubkey->bitlen, (BYTE *)hdr, size ))) return status; - key->u.a.flags |= KEY_FLAG_LEGACY_DSA_V2; +static NTSTATUS key_import_pair( struct algorithm *alg, const WCHAR *type, BCRYPT_KEY_HANDLE *ret_key, UCHAR *input, + ULONG input_len ) +{ + WCHAR *final_type = type; + NTSTATUS status;
- *ret_key = key; - return STATUS_SUCCESS; + if (!wcscmp( type, BCRYPT_PUBLIC_KEY_BLOB )) + { + DWORD magic = *(DWORD *)input; + switch(magic) + { + case BCRYPT_ECDH_PUBLIC_P256_MAGIC: + case BCRYPT_ECDSA_PUBLIC_P256_MAGIC: + case BCRYPT_ECDSA_PUBLIC_P384_MAGIC: + final_type = malloc( sizeof(BCRYPT_ECCPUBLIC_BLOB) ); + wcscpy( final_type, BCRYPT_ECCPUBLIC_BLOB ); + break; + case BCRYPT_RSAPUBLIC_MAGIC: + final_type = malloc( sizeof(BCRYPT_RSAPUBLIC_BLOB) ); + wcscpy( final_type, BCRYPT_RSAPUBLIC_BLOB ); + break; + default: + { + FIXME( "Unsupported key magic %#lx\n", magic ); + return STATUS_NOT_SUPPORTED; + } + } }
- FIXME( "unsupported key type %s\n", debugstr_w(type) ); - return STATUS_NOT_SUPPORTED; + if (!wcscmp( final_type, BCRYPT_ECCPUBLIC_BLOB )) + { + status = key_import_ecc_public( alg, ret_key, input, input_len ); + } + else if (!wcscmp( final_type, BCRYPT_ECCPRIVATE_BLOB )) + { + status = key_import_ecc_private( alg, ret_key, input, input_len ); + } + else if (!wcscmp( final_type, BCRYPT_RSAPUBLIC_BLOB )) + { + status = key_import_rsa_public(alg, ret_key, input, input_len); + } + else if (!wcscmp( final_type, BCRYPT_RSAPRIVATE_BLOB ) || !wcscmp( type, BCRYPT_RSAFULLPRIVATE_BLOB )) + { + status = key_import_rsa_private( alg, ret_key, input, input_len ); + } + else if (!wcscmp( final_type, BCRYPT_DSA_PUBLIC_BLOB )) + { + status = key_import_dsa_public( alg, ret_key, input, input_len ); + } + else if (!wcscmp( final_type, LEGACY_DSA_V2_PRIVATE_BLOB )) + { + status = key_import_legacy_dsa_v2_private( alg, ret_key, input, input_len ); + } + else if (!wcscmp( final_type, LEGACY_DSA_V2_PUBLIC_BLOB )) /* not supported on native */ + { + status = key_import_legacy_dsa_v2_public( alg, ret_key, input, input_len ); + } + else + { + FIXME( "unsupported key type %s\n", debugstr_w(type) ); + return STATUS_NOT_SUPPORTED; + } + + if (!wcscmp( type, BCRYPT_PUBLIC_KEY_BLOB )) free(final_type); + + return status; }
static ULONG get_block_size( struct algorithm *alg ) diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c index e7619897cfd..6fc4097492b 100644 --- a/dlls/bcrypt/tests/bcrypt.c +++ b/dlls/bcrypt/tests/bcrypt.c @@ -1845,6 +1845,10 @@ static void test_ECDSA(void)
ecckey->dwMagic = BCRYPT_ECDSA_PUBLIC_P256_MAGIC; ecckey->cbKey = 32; + status = BCryptImportKeyPair(alg, NULL, BCRYPT_PUBLIC_KEY_BLOB, &key, buffer, size, 0); + ok(!status, "BCryptImportKeyPair failed: %#lx\n", status); + BCryptDestroyKey(key); + status = BCryptImportKeyPair(alg, NULL, BCRYPT_ECCPUBLIC_BLOB, &key, buffer, size, 0); ok(!status, "BCryptImportKeyPair failed: %#lx\n", status);
@@ -1997,6 +2001,10 @@ static void test_RSA(void) ok(schemes, "schemes not set\n"); ok(size == sizeof(schemes), "got %lu\n", size);
+ ret = BCryptImportKeyPair(alg, NULL, BCRYPT_PUBLIC_KEY_BLOB, &key, rsaPublicBlob, sizeof(rsaPublicBlob), 0); + ok(!ret, "BCryptImportKeyPair failed: %#lx\n", ret); + BCryptDestroyKey(key); + ret = BCryptImportKeyPair(alg, NULL, BCRYPT_RSAPUBLIC_BLOB, &key, rsaPublicBlob, sizeof(rsaPublicBlob), 0); ok(!ret, "BCryptImportKeyPair failed: %#lx\n", ret);
@@ -2317,6 +2325,10 @@ static void test_ECDH(void) ok(ecckey->cbKey == 32, "got %lu\n", ecckey->cbKey); ok(size == sizeof(*ecckey) + ecckey->cbKey * 2, "got %lu\n", size);
+ status = BCryptImportKeyPair(alg, NULL, BCRYPT_PUBLIC_KEY_BLOB, &pubkey, buf, size, 0); + ok(status == STATUS_SUCCESS, "got %#lx\n", status); + BCryptDestroyKey(pubkey); + status = BCryptImportKeyPair(alg, NULL, BCRYPT_ECCPUBLIC_BLOB, &pubkey, buf, size, 0); ok(status == STATUS_SUCCESS, "got %#lx\n", status); HeapFree(GetProcessHeap(), 0, buf);