[v3 PATCH 3/5] bcrypt: Add support for computing/comparing cipher tag.
Alistair Leslie-Hughes
leslie_alistair at hotmail.com
Tue Mar 20 15:27:09 CDT 2018
From: Michael Müller <michael at fds-team.de>
Signed-off-by: Alistair Leslie-Hughes <leslie_alistair at hotmail.com>
---
dlls/bcrypt/bcrypt_main.c | 47 +++++++++++++++++++++++++++++++++++++++++++++-
dlls/bcrypt/tests/bcrypt.c | 10 +++++-----
2 files changed, 51 insertions(+), 6 deletions(-)
diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c
index 573cd374a4..a08eb00269 100644
--- a/dlls/bcrypt/bcrypt_main.c
+++ b/dlls/bcrypt/bcrypt_main.c
@@ -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;
}
diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c
index e3cbc87db4..1176796dbc 100644
--- a/dlls/bcrypt/tests/bcrypt.c
+++ b/dlls/bcrypt/tests/bcrypt.c
@@ -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);
--
2.16.2
More information about the wine-devel
mailing list