Module: wine Branch: master Commit: 7c9291ce0799ebf6eadc266ee13a74cbc0b7ff50 URL: https://source.winehq.org/git/wine.git/?a=commit;h=7c9291ce0799ebf6eadc266ee...
Author: Michael Müller michael@fds-team.de Date: Tue Mar 20 20:27:06 2018 +0000
bcrypt: Implement BCryptEncrypt for AES GCM mode.
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
---
dlls/bcrypt/bcrypt_main.c | 59 +++++++++++++++++++++++++++++++++++++++------- dlls/bcrypt/tests/bcrypt.c | 18 +++++++------- 2 files changed, 60 insertions(+), 17 deletions(-)
diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c index fa80318..9669553 100644 --- a/dlls/bcrypt/bcrypt_main.c +++ b/dlls/bcrypt/bcrypt_main.c @@ -63,6 +63,12 @@ MAKE_FUNCPTR(gnutls_global_set_log_level); MAKE_FUNCPTR(gnutls_perror); #undef MAKE_FUNCPTR
+#if GNUTLS_VERSION_MAJOR < 3 +#define GNUTLS_CIPHER_AES_192_CBC 92 +#define GNUTLS_CIPHER_AES_128_GCM 93 +#define GNUTLS_CIPHER_AES_256_GCM 94 +#endif + static void gnutls_log( int level, const char *msg ) { TRACE( "<%d> %s", level, msg ); @@ -848,6 +854,7 @@ struct key { struct object hdr; enum alg_id alg_id; + enum mode_id mode; ULONG block_size; gnutls_cipher_hd_t handle; UCHAR *secret; @@ -858,6 +865,7 @@ struct key { struct object hdr; enum alg_id alg_id; + enum mode_id mode; ULONG block_size; CCCryptorRef ref_encrypt; CCCryptorRef ref_decrypt; @@ -868,6 +876,7 @@ struct key struct key { struct object hdr; + enum mode_id mode; ULONG block_size; }; #endif @@ -923,6 +932,7 @@ static NTSTATUS key_init( struct key *key, struct algorithm *alg, const UCHAR *s memcpy( buffer, secret, secret_len );
key->alg_id = alg->id; + key->mode = alg->mode; key->handle = 0; /* initialized on first use */ key->secret = buffer; key->secret_len = secret_len; @@ -935,9 +945,13 @@ static gnutls_cipher_algorithm_t get_gnutls_cipher( const struct key *key ) switch (key->alg_id) { case ALG_ID_AES: - FIXME( "handle block size and chaining mode\n" ); - return GNUTLS_CIPHER_AES_128_CBC; - + WARN( "handle block size\n" ); + switch (key->mode) + { + case MODE_ID_GCM: return GNUTLS_CIPHER_AES_128_GCM; + case MODE_ID_CBC: + default: return GNUTLS_CIPHER_AES_128_CBC; + } default: FIXME( "algorithm %u not supported\n", key->alg_id ); return GNUTLS_CIPHER_UNKNOWN; @@ -1019,6 +1033,14 @@ static NTSTATUS key_init( struct key *key, struct algorithm *alg, const UCHAR *s switch (alg->id) { case ALG_ID_AES: + switch (alg->mode) + { + case MODE_ID_CBC: + break; + default: + FIXME( "mode %u not supported\n", alg->mode ); + return STATUS_NOT_SUPPORTED; + } break;
default: @@ -1031,6 +1053,7 @@ static NTSTATUS key_init( struct key *key, struct algorithm *alg, const UCHAR *s memcpy( buffer, secret, secret_len );
key->alg_id = alg->id; + key->mode = alg->mode; key->ref_encrypt = NULL; /* initialized on first use */ key->ref_decrypt = NULL; key->secret = buffer; @@ -1260,17 +1283,37 @@ NTSTATUS WINAPI BCryptEncrypt( BCRYPT_KEY_HANDLE handle, UCHAR *input, ULONG inp padding, iv, iv_len, output, output_len, ret_len, flags );
if (!key || key->hdr.magic != MAGIC_KEY) return STATUS_INVALID_HANDLE; - if (padding) - { - FIXME( "padding info not implemented\n" ); - return STATUS_NOT_IMPLEMENTED; - } if (flags & ~BCRYPT_BLOCK_PADDING) { FIXME( "flags %08x not implemented\n", flags ); return STATUS_NOT_IMPLEMENTED; }
+ if (key->mode == MODE_ID_GCM) + { + BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO *auth_info = padding; + + if (!auth_info) return STATUS_INVALID_PARAMETER; + if (!auth_info->pbNonce) return STATUS_INVALID_PARAMETER; + if (!auth_info->pbTag) return STATUS_INVALID_PARAMETER; + if (auth_info->cbTag < 12 || auth_info->cbTag > 16) return STATUS_INVALID_PARAMETER; + if (auth_info->dwFlags & BCRYPT_AUTH_MODE_CHAIN_CALLS_FLAG) + FIXME( "call chaining not implemented\n" ); + + if ((status = key_set_params( key, auth_info->pbNonce, auth_info->cbNonce ))) + return status; + + *ret_len = input_len; + if (flags & BCRYPT_BLOCK_PADDING) return STATUS_INVALID_PARAMETER; + if (!output) return STATUS_SUCCESS; + if (output_len < *ret_len) return STATUS_BUFFER_TOO_SMALL; + + if ((status = key_encrypt( key, input, input_len, output, output_len ))) + return status; + + return STATUS_SUCCESS; + } + if ((status = key_set_params( key, iv, iv_len ))) return status;
*ret_len = input_len; diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c index ba2011f..1875fb3 100644 --- a/dlls/bcrypt/tests/bcrypt.c +++ b/dlls/bcrypt/tests/bcrypt.c @@ -751,12 +751,12 @@ static void test_BCryptEncrypt(void) memset(ciphertext, 0xff, sizeof(ciphertext)); memset(tag, 0xff, sizeof(tag)); ret = pBCryptEncrypt(key, data2, 32, &auth_info, ivbuf, 16, ciphertext, 32, &size, 0); - todo_wine ok(ret == STATUS_SUCCESS, "got %08x\n", ret); - todo_wine ok(size == 32, "got %u\n", size); - todo_wine ok(!memcmp(ciphertext, expected4, sizeof(expected4)), "wrong data\n"); + 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"); for (i = 0; i < 32; i++) - todo_wine ok(ciphertext[i] == expected4[i], "%u: %02x != %02x\n", i, ciphertext[i], expected4[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]);
@@ -766,12 +766,12 @@ static void test_BCryptEncrypt(void) memset(ciphertext, 0xff, sizeof(ciphertext)); memset(tag, 0xff, sizeof(tag)); ret = pBCryptEncrypt(key, data2, 24, &auth_info, ivbuf, 16, ciphertext, 24, &size, 0); - todo_wine ok(ret == STATUS_SUCCESS, "got %08x\n", ret); - todo_wine ok(size == 24, "got %u\n", size); - todo_wine ok(!memcmp(ciphertext, expected4, 24), "wrong data\n"); + 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"); for (i = 0; i < 24; i++) - todo_wine ok(ciphertext[i] == expected4[i], "%u: %02x != %02x\n", i, ciphertext[i], expected4[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]);
@@ -784,7 +784,7 @@ static void test_BCryptEncrypt(void) memcpy(ivbuf, iv, sizeof(iv)); memset(ciphertext, 0, sizeof(ciphertext)); ret = pBCryptEncrypt(key, data2, 32, &auth_info, ivbuf, 16, ciphertext, 48, &size, BCRYPT_BLOCK_PADDING); - todo_wine ok(ret == STATUS_INVALID_PARAMETER, "got %08x\n", ret); + ok(ret == STATUS_INVALID_PARAMETER, "got %08x\n", ret);
ret = pBCryptDestroyKey(key); ok(ret == STATUS_SUCCESS, "got %08x\n", ret);