bcrypt: Add support for computing/comparing cipher tag.

Signed-off-by: Alistair Leslie-Hughes <leslie_alistair@hotmail.com>
Signed-off-by: Hans Leidekker <hans@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
oldstable
Michael Müller 2018-03-20 20:27:09 +00:00 committed by Alexandre Julliard
parent 8d2b1d276d
commit c7b46e8e3c
2 changed files with 51 additions and 6 deletions

View File

@ -50,6 +50,9 @@ static HINSTANCE instance;
#if defined(HAVE_GNUTLS_CIPHER_INIT) && !defined(HAVE_COMMONCRYPTO_COMMONCRYPTOR_H)
WINE_DECLARE_DEBUG_CHANNEL(winediag);
/* Not present in gnutls version < 3.0 */
static int (*pgnutls_cipher_tag)(gnutls_cipher_hd_t handle, void * tag, size_t tag_size);
static void *libgnutls_handle;
#define MAKE_FUNCPTR(f) static typeof(f) * p##f
MAKE_FUNCPTR(gnutls_cipher_decrypt2);
@ -69,6 +72,11 @@ MAKE_FUNCPTR(gnutls_perror);
#define GNUTLS_CIPHER_AES_256_GCM 94
#endif
static int compat_gnutls_cipher_tag(gnutls_cipher_hd_t handle, void * tag, size_t tag_size)
{
return GNUTLS_E_UNKNOWN_CIPHER_TYPE;
}
static void gnutls_log( int level, const char *msg )
{
TRACE( "<%d> %s", level, msg );
@ -102,6 +110,12 @@ static BOOL gnutls_initialize(void)
LOAD_FUNCPTR(gnutls_perror)
#undef LOAD_FUNCPTR
if (!(pgnutls_cipher_tag = wine_dlsym( libgnutls_handle, "gnutls_cipher_tag", NULL, 0 )))
{
WARN("gnutls_cipher_tag not found\n");
pgnutls_cipher_tag = compat_gnutls_cipher_tag;
}
if ((ret = pgnutls_global_init()) != GNUTLS_E_SUCCESS)
{
pgnutls_perror( ret );
@ -1018,6 +1032,19 @@ static NTSTATUS key_decrypt( struct key *key, const UCHAR *input, ULONG input_le
return STATUS_SUCCESS;
}
static NTSTATUS key_get_tag( struct key *key, UCHAR *tag, ULONG len )
{
int ret;
if ((ret = pgnutls_cipher_tag( key->handle, tag, len )))
{
pgnutls_perror( ret );
return STATUS_INTERNAL_ERROR;
}
return STATUS_SUCCESS;
}
static NTSTATUS key_destroy( struct key *key )
{
if (key->handle) pgnutls_cipher_deinit( key->handle );
@ -1123,6 +1150,12 @@ static NTSTATUS key_decrypt( struct key *key, const UCHAR *input, ULONG input_le
return STATUS_SUCCESS;
}
static NTSTATUS key_get_tag( struct key *key, UCHAR *tag, ULONG len )
{
FIXME( "not implemented on Mac\n" );
return STATUS_NOT_IMPLEMENTED;
}
static NTSTATUS key_destroy( struct key *key )
{
if (key->ref_encrypt) CCCryptorRelease( key->ref_encrypt );
@ -1158,6 +1191,12 @@ static NTSTATUS key_decrypt( struct key *key, const UCHAR *input, ULONG input_le
return STATUS_NOT_IMPLEMENTED;
}
static NTSTATUS key_get_tag( struct key *key, UCHAR *tag, ULONG len )
{
ERR( "support for keys not available at build time\n" );
return STATUS_NOT_IMPLEMENTED;
}
static NTSTATUS key_destroy( struct key *key )
{
ERR( "support for keys not available at build time\n" );
@ -1311,7 +1350,7 @@ NTSTATUS WINAPI BCryptEncrypt( BCRYPT_KEY_HANDLE handle, UCHAR *input, ULONG inp
if ((status = key_encrypt( key, input, input_len, output, output_len )))
return status;
return STATUS_SUCCESS;
return key_get_tag( key, auth_info->pbTag, auth_info->cbTag );
}
if ((status = key_set_params( key, iv, iv_len ))) return status;
@ -1370,6 +1409,7 @@ NTSTATUS WINAPI BCryptDecrypt( BCRYPT_KEY_HANDLE handle, UCHAR *input, ULONG inp
if (key->mode == MODE_ID_GCM)
{
BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO *auth_info = padding;
UCHAR tag[16];
if (!auth_info) return STATUS_INVALID_PARAMETER;
if (!auth_info->pbNonce) return STATUS_INVALID_PARAMETER;
@ -1387,6 +1427,11 @@ NTSTATUS WINAPI BCryptDecrypt( BCRYPT_KEY_HANDLE handle, UCHAR *input, ULONG inp
if ((status = key_decrypt( key, input, input_len, output, output_len )))
return status;
if ((status = key_get_tag( key, tag, sizeof(tag) )))
return status;
if (memcmp( tag, auth_info->pbTag, auth_info->cbTag ))
return STATUS_AUTH_TAG_MISMATCH;
return STATUS_SUCCESS;
}

View File

@ -754,11 +754,11 @@ static void test_BCryptEncrypt(void)
ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
ok(size == 32, "got %u\n", size);
ok(!memcmp(ciphertext, expected4, sizeof(expected4)), "wrong data\n");
todo_wine ok(!memcmp(tag, expected_tag, sizeof(expected_tag)), "wrong tag\n");
ok(!memcmp(tag, expected_tag, sizeof(expected_tag)), "wrong tag\n");
for (i = 0; i < 32; i++)
ok(ciphertext[i] == expected4[i], "%u: %02x != %02x\n", i, ciphertext[i], expected4[i]);
for (i = 0; i < 16; i++)
todo_wine ok(tag[i] == expected_tag[i], "%u: %02x != %02x\n", i, tag[i], expected_tag[i]);
ok(tag[i] == expected_tag[i], "%u: %02x != %02x\n", i, tag[i], expected_tag[i]);
/* input size is not multiple of block size */
size = 0;
@ -769,11 +769,11 @@ static void test_BCryptEncrypt(void)
ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
ok(size == 24, "got %u\n", size);
ok(!memcmp(ciphertext, expected4, 24), "wrong data\n");
todo_wine ok(!memcmp(tag, expected_tag2, sizeof(expected_tag2)), "wrong tag\n");
ok(!memcmp(tag, expected_tag2, sizeof(expected_tag2)), "wrong tag\n");
for (i = 0; i < 24; i++)
ok(ciphertext[i] == expected4[i], "%u: %02x != %02x\n", i, ciphertext[i], expected4[i]);
for (i = 0; i < 16; i++)
todo_wine ok(tag[i] == expected_tag2[i], "%u: %02x != %02x\n", i, tag[i], expected_tag2[i]);
ok(tag[i] == expected_tag2[i], "%u: %02x != %02x\n", i, tag[i], expected_tag2[i]);
/* test with padding */
memcpy(ivbuf, iv, sizeof(iv));
@ -977,7 +977,7 @@ static void test_BCryptDecrypt(void)
memcpy(ivbuf, iv, sizeof(iv));
auth_info.pbTag = iv; /* wrong tag */
ret = pBCryptDecrypt(key, ciphertext4, 32, &auth_info, ivbuf, 16, plaintext, 32, &size, 0);
todo_wine ok(ret == STATUS_AUTH_TAG_MISMATCH, "got %08x\n", ret);
ok(ret == STATUS_AUTH_TAG_MISMATCH, "got %08x\n", ret);
ok(size == 32, "got %u\n", size);
ret = pBCryptDestroyKey(key);