diff --git a/dlls/bcrypt/bcrypt.spec b/dlls/bcrypt/bcrypt.spec index 28c2394ce45..78824d73b39 100644 --- a/dlls/bcrypt/bcrypt.spec +++ b/dlls/bcrypt/bcrypt.spec @@ -32,7 +32,7 @@ @ stdcall BCryptHash(ptr ptr long ptr long ptr long) @ stdcall BCryptHashData(ptr ptr long long) @ stdcall BCryptImportKey(ptr ptr wstr ptr ptr long ptr long long) -@ stub BCryptImportKeyPair +@ stdcall BCryptImportKeyPair(ptr ptr wstr ptr ptr long long) @ stdcall BCryptOpenAlgorithmProvider(ptr wstr wstr long) @ stub BCryptQueryContextConfiguration @ stub BCryptQueryContextFunctionConfiguration @@ -50,7 +50,7 @@ @ stub BCryptSignHash @ stub BCryptUnregisterConfigChangeNotify @ stdcall BCryptUnregisterProvider(wstr) -@ stub BCryptVerifySignature +@ stdcall BCryptVerifySignature(ptr ptr ptr long ptr long long) @ stub GetAsymmetricEncryptionInterface @ stub GetCipherInterface @ stub GetHashInterface diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c index 57cb3632d55..82a742cbc04 100644 --- a/dlls/bcrypt/bcrypt_main.c +++ b/dlls/bcrypt/bcrypt_main.c @@ -220,7 +220,9 @@ enum alg_id ALG_ID_SHA1, ALG_ID_SHA256, ALG_ID_SHA384, - ALG_ID_SHA512 + ALG_ID_SHA512, + ALG_ID_ECDSA_P256, + ALG_ID_ECDSA_P384, }; enum mode_id @@ -251,7 +253,9 @@ alg_props[] = /* ALG_ID_SHA1 */ { 278, 20, 512, BCRYPT_SHA1_ALGORITHM, FALSE }, /* ALG_ID_SHA256 */ { 286, 32, 512, BCRYPT_SHA256_ALGORITHM, FALSE }, /* ALG_ID_SHA384 */ { 382, 48, 1024, BCRYPT_SHA384_ALGORITHM, FALSE }, - /* ALG_ID_SHA512 */ { 382, 64, 1024, BCRYPT_SHA512_ALGORITHM, FALSE } + /* ALG_ID_SHA512 */ { 382, 64, 1024, BCRYPT_SHA512_ALGORITHM, FALSE }, + /* ALG_ID_ECDSA_P256 */ { 0, 0, 0, BCRYPT_ECDSA_P256_ALGORITHM, FALSE }, + /* ALG_ID_ECDSA_P384 */ { 0, 0, 0, BCRYPT_ECDSA_P384_ALGORITHM, FALSE }, }; struct algorithm @@ -327,6 +331,8 @@ NTSTATUS WINAPI BCryptOpenAlgorithmProvider( BCRYPT_ALG_HANDLE *handle, LPCWSTR else if (!strcmpW( id, BCRYPT_SHA256_ALGORITHM )) alg_id = ALG_ID_SHA256; else if (!strcmpW( id, BCRYPT_SHA384_ALGORITHM )) alg_id = ALG_ID_SHA384; else if (!strcmpW( id, BCRYPT_SHA512_ALGORITHM )) alg_id = ALG_ID_SHA512; + else if (!strcmpW( id, BCRYPT_ECDSA_P256_ALGORITHM )) alg_id = ALG_ID_ECDSA_P256; + else if (!strcmpW( id, BCRYPT_ECDSA_P384_ALGORITHM )) alg_id = ALG_ID_ECDSA_P384; else { FIXME( "algorithm %s not supported\n", debugstr_w(id) ); @@ -869,6 +875,12 @@ struct key_symmetric ULONG secret_len; }; +struct key_asymmetric +{ + UCHAR *pubkey; + ULONG pubkey_len; +}; + struct key { struct object hdr; @@ -876,6 +888,7 @@ struct key union { struct key_symmetric s; + struct key_asymmetric a; } u; }; @@ -890,6 +903,12 @@ struct key_symmetric ULONG secret_len; }; +struct key_asymmetric +{ + UCHAR *pubkey; + ULONG pubkey_len; +}; + struct key { struct object hdr; @@ -897,6 +916,7 @@ struct key union { struct key_symmetric s; + struct key_asymmetric a; } u; }; #else @@ -954,18 +974,28 @@ static NTSTATUS key_duplicate( struct key *key_orig, struct key *key_copy ) { UCHAR *buffer; - if (!key_is_symmetric( key_orig )) return STATUS_NOT_IMPLEMENTED; - - if (!(buffer = heap_alloc( key_orig->u.s.secret_len ))) return STATUS_NO_MEMORY; - memcpy( buffer, key_orig->u.s.secret, key_orig->u.s.secret_len ); - memset( key_copy, 0, sizeof(*key_copy) ); - key_copy->hdr = key_orig->hdr; - key_copy->alg_id = key_orig->alg_id; - key_copy->u.s.mode = key_orig->u.s.mode; - key_copy->u.s.block_size = key_orig->u.s.block_size; - key_copy->u.s.secret = buffer; - key_copy->u.s.secret_len = key_orig->u.s.secret_len; + key_copy->hdr = key_orig->hdr; + key_copy->alg_id = key_orig->alg_id; + + if (key_is_symmetric( key_orig )) + { + if (!(buffer = heap_alloc( key_orig->u.s.secret_len ))) return STATUS_NO_MEMORY; + memcpy( buffer, key_orig->u.s.secret, key_orig->u.s.secret_len ); + + key_copy->u.s.mode = key_orig->u.s.mode; + key_copy->u.s.block_size = key_orig->u.s.block_size; + key_copy->u.s.secret = buffer; + key_copy->u.s.secret_len = key_orig->u.s.secret_len; + } + else + { + if (!(buffer = heap_alloc( key_orig->u.a.pubkey_len ))) return STATUS_NO_MEMORY; + memcpy( buffer, key_orig->u.a.pubkey, key_orig->u.a.pubkey_len ); + + key_copy->u.a.pubkey = buffer; + key_copy->u.a.pubkey_len = key_orig->u.a.pubkey_len; + } return STATUS_SUCCESS; } @@ -1149,10 +1179,41 @@ static NTSTATUS key_symmetric_get_tag( struct key *key, UCHAR *tag, ULONG len ) return STATUS_SUCCESS; } +static NTSTATUS key_asymmetric_init( struct key *key, struct algorithm *alg, const UCHAR *pubkey, ULONG pubkey_len ) +{ + UCHAR *buffer; + + if (!libgnutls_handle) return STATUS_INTERNAL_ERROR; + + switch (alg->id) + { + case ALG_ID_ECDSA_P256: + case ALG_ID_ECDSA_P384: + break; + + default: + FIXME( "algorithm %u not supported\n", alg->id ); + return STATUS_NOT_SUPPORTED; + } + + if (!(buffer = heap_alloc( pubkey_len ))) return STATUS_NO_MEMORY; + memcpy( buffer, pubkey, pubkey_len ); + + key->alg_id = alg->id; + key->u.a.pubkey = buffer; + key->u.a.pubkey_len = pubkey_len; + + return STATUS_SUCCESS; +} + static NTSTATUS key_destroy( struct key *key ) { - if (key->u.s.handle) pgnutls_cipher_deinit( key->u.s.handle ); - heap_free( key->u.s.secret ); + if (key_is_symmetric( key )) + { + if (key->u.s.handle) pgnutls_cipher_deinit( key->u.s.handle ); + heap_free( key->u.s.secret ); + } + else heap_free( key->u.a.pubkey ); heap_free( key ); return STATUS_SUCCESS; } @@ -1315,6 +1376,12 @@ static NTSTATUS key_destroy( struct key *key ) heap_free( key ); return STATUS_SUCCESS; } + +static NTSTATUS key_asymmetric_init( struct key *key, struct algorithm *alg, const UCHAR *pubkey, ULONG pubkey_len ) +{ + FIXME( "not implemented on Mac\n" ); + return STATUS_NOT_IMPLEMENTED; +} #else static NTSTATUS key_symmetric_init( struct key *key, struct algorithm *alg, const UCHAR *secret, ULONG secret_len ) { @@ -1383,6 +1450,12 @@ static inline BOOL key_is_symmetric( struct key *key ) ERR( "support for keys not available at build time\n" ); return FALSE; } + +static NTSTATUS key_asymmetric_init( struct key *key, struct algorithm *alg, const UCHAR *pubkey, ULONG pubkey_len ) +{ + ERR( "support for keys not available at build time\n" ); + return STATUS_NOT_IMPLEMENTED; +} #endif NTSTATUS WINAPI BCryptGenerateSymmetricKey( BCRYPT_ALG_HANDLE algorithm, BCRYPT_KEY_HANDLE *handle, @@ -1498,6 +1571,78 @@ NTSTATUS WINAPI BCryptDuplicateKey( BCRYPT_KEY_HANDLE handle, BCRYPT_KEY_HANDLE return STATUS_SUCCESS; } +NTSTATUS WINAPI BCryptImportKeyPair( BCRYPT_ALG_HANDLE algorithm, BCRYPT_KEY_HANDLE decrypt_key, const WCHAR *type, + BCRYPT_KEY_HANDLE *ret_key, UCHAR *input, ULONG input_len, ULONG flags ) +{ + struct algorithm *alg = algorithm; + NTSTATUS status; + struct key *key; + + TRACE( "%p, %p, %s, %p, %p, %u, %08x\n", algorithm, decrypt_key, debugstr_w(type), ret_key, input, + input_len, flags ); + + if (!alg || alg->hdr.magic != MAGIC_ALG) return STATUS_INVALID_HANDLE; + if (!ret_key || !type || !input) return STATUS_INVALID_PARAMETER; + if (decrypt_key) + { + FIXME( "decryption of key not yet supported\n" ); + return STATUS_NOT_IMPLEMENTED; + } + + if (!strcmpW( type, BCRYPT_ECCPUBLIC_BLOB )) + { + BCRYPT_ECCKEY_BLOB *ecc_blob = (BCRYPT_ECCKEY_BLOB *)input; + DWORD key_size, magic; + + if (input_len < sizeof(*ecc_blob)) return STATUS_INVALID_PARAMETER; + + switch (alg->id) + { + case ALG_ID_ECDSA_P256: + key_size = 32; + magic = BCRYPT_ECDSA_PUBLIC_P256_MAGIC; + break; + + case ALG_ID_ECDSA_P384: + key_size = 48; + magic = BCRYPT_ECDSA_PUBLIC_P384_MAGIC; + break; + + default: + FIXME( "algorithm %u does not yet support importing blob of type %s\n", alg->id, debugstr_w(type) ); + return STATUS_NOT_SUPPORTED; + } + + if (ecc_blob->dwMagic != magic) return STATUS_NOT_SUPPORTED; + if (ecc_blob->cbKey != key_size) return STATUS_INVALID_PARAMETER; + + if (!(key = heap_alloc( sizeof(*key) ))) return STATUS_NO_MEMORY; + key->hdr.magic = MAGIC_KEY; + if ((status = key_asymmetric_init( key, alg, (BYTE *)ecc_blob, sizeof(*ecc_blob) + ecc_blob->cbKey * 2 ))) + { + heap_free( key ); + return status; + } + + *ret_key = key; + return STATUS_SUCCESS; + } + + FIXME( "unsupported key type %s\n", debugstr_w(type) ); + return STATUS_NOT_SUPPORTED; +} + +NTSTATUS WINAPI BCryptVerifySignature( BCRYPT_KEY_HANDLE handle, void *padding, UCHAR *hash, ULONG hash_len, + UCHAR *signature, ULONG signature_len, ULONG flags ) +{ + struct key *key = handle; + + FIXME( "%p, %p, %p, %u, %p, %u, %08x: stub!\n", handle, padding, hash, hash_len, signature, signature_len, flags ); + + if (!key || key->hdr.magic != MAGIC_KEY) return STATUS_INVALID_HANDLE; + return STATUS_NOT_IMPLEMENTED; +} + NTSTATUS WINAPI BCryptDestroyKey( BCRYPT_KEY_HANDLE handle ) { struct key *key = handle; diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c index 57d04882b54..fa244d19249 100644 --- a/dlls/bcrypt/tests/bcrypt.c +++ b/dlls/bcrypt/tests/bcrypt.c @@ -1486,10 +1486,10 @@ static void test_ECDSA(void) ok(!status, "BCryptImportKeyPair failed: %08x\n", status); status = pBCryptVerifySignature(key, NULL, certHash, sizeof(certHash) - 1, certSignature, sizeof(certSignature), 0); - ok(status == STATUS_INVALID_SIGNATURE, "Expected STATUS_INVALID_SIGNATURE, got %08x\n", status); + todo_wine ok(status == STATUS_INVALID_SIGNATURE, "Expected STATUS_INVALID_SIGNATURE, got %08x\n", status); status = pBCryptVerifySignature(key, NULL, certHash, sizeof(certHash), certSignature, sizeof(certSignature), 0); - ok(!status, "BCryptVerifySignature failed: %08x\n", status); + todo_wine ok(!status, "BCryptVerifySignature failed: %08x\n", status); pBCryptDestroyKey(key); pBCryptCloseAlgorithmProvider(alg, 0); diff --git a/dlls/ncrypt/ncrypt.spec b/dlls/ncrypt/ncrypt.spec index d0f0f56cc4c..e7b12e00596 100644 --- a/dlls/ncrypt/ncrypt.spec +++ b/dlls/ncrypt/ncrypt.spec @@ -34,7 +34,7 @@ @ stdcall BCryptHash(ptr ptr long ptr long ptr long) bcrypt.BCryptHash @ stdcall BCryptHashData(ptr ptr long long) bcrypt.BCryptHashData @ stdcall BCryptImportKey(ptr ptr wstr ptr ptr long ptr long long) bcrypt.BCryptImportKey -@ stub BCryptImportKeyPair +@ stdcall BCryptImportKeyPair(ptr ptr wstr ptr ptr long long) bcrypt.BCryptImportKeyPair @ stub BCryptKeyDerivation @ stdcall BCryptOpenAlgorithmProvider(ptr wstr wstr long) bcrypt.BCryptOpenAlgorithmProvider @ stub BCryptQueryContextConfiguration @@ -53,7 +53,7 @@ @ stub BCryptSignHash @ stub BCryptUnregisterConfigChangeNotify @ stdcall BCryptUnregisterProvider(wstr) bcrypt.BCryptUnregisterProvider -@ stub BCryptVerifySignature +@ stdcall BCryptVerifySignature(ptr ptr ptr long ptr long long) bcrypt.BCryptVerifySignature @ stub GetIsolationServerInterface @ stub GetKeyStorageInterface @ stub GetSChannelInterface diff --git a/include/bcrypt.h b/include/bcrypt.h index 717d77c7319..f28b0d395d1 100644 --- a/include/bcrypt.h +++ b/include/bcrypt.h @@ -211,8 +211,10 @@ NTSTATUS WINAPI BCryptGetFipsAlgorithmMode(BOOLEAN *); NTSTATUS WINAPI BCryptGetProperty(BCRYPT_HANDLE, LPCWSTR, PUCHAR, ULONG, ULONG *, ULONG); NTSTATUS WINAPI BCryptHash(BCRYPT_ALG_HANDLE, PUCHAR, ULONG, PUCHAR, ULONG, PUCHAR, ULONG); NTSTATUS WINAPI BCryptHashData(BCRYPT_HASH_HANDLE, PUCHAR, ULONG, ULONG); +NTSTATUS WINAPI BCryptImportKeyPair(BCRYPT_ALG_HANDLE, BCRYPT_KEY_HANDLE, LPCWSTR, BCRYPT_KEY_HANDLE *, UCHAR *, ULONG, ULONG); NTSTATUS WINAPI BCryptOpenAlgorithmProvider(BCRYPT_ALG_HANDLE *, LPCWSTR, LPCWSTR, ULONG); NTSTATUS WINAPI BCryptSetProperty(BCRYPT_HANDLE, LPCWSTR, PUCHAR, ULONG, ULONG); NTSTATUS WINAPI BCryptDuplicateHash(BCRYPT_HASH_HANDLE, BCRYPT_HASH_HANDLE *, UCHAR *, ULONG, ULONG); +NTSTATUS WINAPI BCryptVerifySignature(BCRYPT_KEY_HANDLE, void *, UCHAR *, ULONG, UCHAR *, ULONG, ULONG); #endif /* __WINE_BCRYPT_H */