bcrypt: Avoid recreating cipher handles when the initialization vector doesn't change.
Signed-off-by: Hans Leidekker <hans@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
5c708c857e
commit
f4d6df8947
|
@ -163,6 +163,8 @@ struct key_symmetric
|
|||
enum mode_id mode;
|
||||
ULONG block_size;
|
||||
gnutls_cipher_hd_t handle;
|
||||
UCHAR *vector;
|
||||
ULONG vector_len;
|
||||
UCHAR *secret;
|
||||
ULONG secret_len;
|
||||
};
|
||||
|
@ -192,6 +194,8 @@ struct key_symmetric
|
|||
ULONG block_size;
|
||||
CCCryptorRef ref_encrypt;
|
||||
CCCryptorRef ref_decrypt;
|
||||
UCHAR *vector;
|
||||
ULONG vector_len;
|
||||
UCHAR *secret;
|
||||
ULONG secret_len;
|
||||
};
|
||||
|
@ -234,7 +238,7 @@ NTSTATUS get_alg_property( const struct algorithm *, const WCHAR *, UCHAR *, ULO
|
|||
|
||||
NTSTATUS key_set_property( struct key *, const WCHAR *, UCHAR *, ULONG, ULONG ) DECLSPEC_HIDDEN;
|
||||
NTSTATUS key_symmetric_init( struct key *, struct algorithm *, const UCHAR *, ULONG ) DECLSPEC_HIDDEN;
|
||||
NTSTATUS key_symmetric_set_params( struct key *, UCHAR *, ULONG ) DECLSPEC_HIDDEN;
|
||||
NTSTATUS key_symmetric_set_vector( struct key *, UCHAR *, ULONG ) DECLSPEC_HIDDEN;
|
||||
NTSTATUS key_symmetric_set_auth_data( struct key *, UCHAR *, ULONG ) DECLSPEC_HIDDEN;
|
||||
NTSTATUS key_symmetric_encrypt( struct key *, const UCHAR *, ULONG, UCHAR *, ULONG ) DECLSPEC_HIDDEN;
|
||||
NTSTATUS key_symmetric_decrypt( struct key *, const UCHAR *, ULONG, UCHAR *, ULONG ) DECLSPEC_HIDDEN;
|
||||
|
@ -248,6 +252,9 @@ BOOL key_is_symmetric( struct key * ) DECLSPEC_HIDDEN;
|
|||
NTSTATUS key_export_ecc( struct key *, UCHAR *, ULONG, ULONG * ) DECLSPEC_HIDDEN;
|
||||
NTSTATUS key_import_ecc( struct key *, UCHAR *, ULONG ) DECLSPEC_HIDDEN;
|
||||
|
||||
BOOL is_zero_vector( const UCHAR *, ULONG ) DECLSPEC_HIDDEN;
|
||||
BOOL is_equal_vector( const UCHAR *, ULONG, const UCHAR *, ULONG ) DECLSPEC_HIDDEN;
|
||||
|
||||
BOOL gnutls_initialize(void) DECLSPEC_HIDDEN;
|
||||
void gnutls_uninitialize(void) DECLSPEC_HIDDEN;
|
||||
|
||||
|
|
|
@ -831,6 +831,21 @@ BOOL key_is_symmetric( struct key *key )
|
|||
return builtin_algorithms[key->alg_id].class == BCRYPT_CIPHER_INTERFACE;
|
||||
}
|
||||
|
||||
BOOL is_zero_vector( const UCHAR *vector, ULONG len )
|
||||
{
|
||||
ULONG i;
|
||||
if (!vector) return FALSE;
|
||||
for (i = 0; i < len; i++) if (vector[i]) return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL is_equal_vector( const UCHAR *vector, ULONG len, const UCHAR *vector2, ULONG len2 )
|
||||
{
|
||||
if (!vector && !vector2) return TRUE;
|
||||
if (len != len2) return FALSE;
|
||||
return !memcmp( vector, vector2, len );
|
||||
}
|
||||
|
||||
static NTSTATUS key_import( BCRYPT_ALG_HANDLE algorithm, const WCHAR *type, BCRYPT_KEY_HANDLE *key, UCHAR *object,
|
||||
ULONG object_len, UCHAR *input, ULONG input_len )
|
||||
{
|
||||
|
@ -965,7 +980,7 @@ static NTSTATUS key_encrypt( struct key *key, UCHAR *input, ULONG input_len, vo
|
|||
if (auth_info->dwFlags & BCRYPT_AUTH_MODE_CHAIN_CALLS_FLAG)
|
||||
FIXME( "call chaining not implemented\n" );
|
||||
|
||||
if ((status = key_symmetric_set_params( key, auth_info->pbNonce, auth_info->cbNonce )))
|
||||
if ((status = key_symmetric_set_vector( key, auth_info->pbNonce, auth_info->cbNonce )))
|
||||
return status;
|
||||
|
||||
*ret_len = input_len;
|
||||
|
@ -980,7 +995,6 @@ static NTSTATUS key_encrypt( struct key *key, UCHAR *input, ULONG input_len, vo
|
|||
return key_symmetric_get_tag( key, auth_info->pbTag, auth_info->cbTag );
|
||||
}
|
||||
|
||||
if ((status = key_symmetric_set_params( key, iv, iv_len ))) return status;
|
||||
*ret_len = input_len;
|
||||
|
||||
if (flags & BCRYPT_BLOCK_PADDING)
|
||||
|
@ -991,6 +1005,7 @@ static NTSTATUS key_encrypt( struct key *key, UCHAR *input, ULONG input_len, vo
|
|||
if (!output) return STATUS_SUCCESS;
|
||||
if (output_len < *ret_len) return STATUS_BUFFER_TOO_SMALL;
|
||||
if (key->u.s.mode == MODE_ID_ECB && iv) return STATUS_INVALID_PARAMETER;
|
||||
if ((status = key_symmetric_set_vector( key, iv, iv_len ))) return status;
|
||||
|
||||
src = input;
|
||||
dst = output;
|
||||
|
@ -998,7 +1013,7 @@ static NTSTATUS key_encrypt( struct key *key, UCHAR *input, ULONG input_len, vo
|
|||
{
|
||||
if ((status = key_symmetric_encrypt( key, src, key->u.s.block_size, dst, key->u.s.block_size )))
|
||||
return status;
|
||||
if (key->u.s.mode == MODE_ID_ECB && (status = key_symmetric_set_params( key, NULL, 0 ))) return status;
|
||||
if (key->u.s.mode == MODE_ID_ECB && (status = key_symmetric_set_vector( key, NULL, 0 ))) return status;
|
||||
bytes_left -= key->u.s.block_size;
|
||||
src += key->u.s.block_size;
|
||||
dst += key->u.s.block_size;
|
||||
|
@ -1033,7 +1048,7 @@ static NTSTATUS key_decrypt( struct key *key, UCHAR *input, ULONG input_len, voi
|
|||
if (!auth_info->pbTag) return STATUS_INVALID_PARAMETER;
|
||||
if (auth_info->cbTag < 12 || auth_info->cbTag > 16) return STATUS_INVALID_PARAMETER;
|
||||
|
||||
if ((status = key_symmetric_set_params( key, auth_info->pbNonce, auth_info->cbNonce )))
|
||||
if ((status = key_symmetric_set_vector( key, auth_info->pbNonce, auth_info->cbNonce )))
|
||||
return status;
|
||||
|
||||
*ret_len = input_len;
|
||||
|
@ -1051,8 +1066,6 @@ static NTSTATUS key_decrypt( struct key *key, UCHAR *input, ULONG input_len, voi
|
|||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if ((status = key_symmetric_set_params( key, iv, iv_len ))) return status;
|
||||
|
||||
*ret_len = input_len;
|
||||
|
||||
if (input_len & (key->u.s.block_size - 1)) return STATUS_INVALID_BUFFER_SIZE;
|
||||
|
@ -1066,6 +1079,7 @@ static NTSTATUS key_decrypt( struct key *key, UCHAR *input, ULONG input_len, voi
|
|||
else if (output_len < *ret_len) return STATUS_BUFFER_TOO_SMALL;
|
||||
|
||||
if (key->u.s.mode == MODE_ID_ECB && iv) return STATUS_INVALID_PARAMETER;
|
||||
if ((status = key_symmetric_set_vector( key, iv, iv_len ))) return status;
|
||||
|
||||
src = input;
|
||||
dst = output;
|
||||
|
@ -1073,7 +1087,7 @@ static NTSTATUS key_decrypt( struct key *key, UCHAR *input, ULONG input_len, voi
|
|||
{
|
||||
if ((status = key_symmetric_decrypt( key, src, key->u.s.block_size, dst, key->u.s.block_size )))
|
||||
return status;
|
||||
if (key->u.s.mode == MODE_ID_ECB && (status = key_symmetric_set_params( key, NULL, 0 ))) return status;
|
||||
if (key->u.s.mode == MODE_ID_ECB && (status = key_symmetric_set_vector( key, NULL, 0 ))) return status;
|
||||
bytes_left -= key->u.s.block_size;
|
||||
src += key->u.s.block_size;
|
||||
dst += key->u.s.block_size;
|
||||
|
|
|
@ -441,6 +441,8 @@ NTSTATUS key_symmetric_init( struct key *key, struct algorithm *alg, const UCHAR
|
|||
key->alg_id = alg->id;
|
||||
key->u.s.mode = alg->mode;
|
||||
key->u.s.handle = 0; /* initialized on first use */
|
||||
key->u.s.vector = NULL;
|
||||
key->u.s.vector_len = 0;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -475,30 +477,45 @@ static gnutls_cipher_algorithm_t get_gnutls_cipher( const struct key *key )
|
|||
}
|
||||
}
|
||||
|
||||
NTSTATUS key_symmetric_set_params( struct key *key, UCHAR *iv, ULONG iv_len )
|
||||
NTSTATUS key_symmetric_set_vector( struct key *key, UCHAR *vector, ULONG vector_len )
|
||||
{
|
||||
if (key->u.s.handle && (!is_zero_vector( vector, vector_len ) ||
|
||||
!is_equal_vector( key->u.s.vector, key->u.s.vector_len, vector, vector_len )))
|
||||
{
|
||||
TRACE( "invalidating cipher handle\n" );
|
||||
pgnutls_cipher_deinit( key->u.s.handle );
|
||||
key->u.s.handle = NULL;
|
||||
}
|
||||
|
||||
heap_free( key->u.s.vector );
|
||||
key->u.s.vector = NULL;
|
||||
key->u.s.vector_len = 0;
|
||||
if (vector)
|
||||
{
|
||||
if (!(key->u.s.vector = heap_alloc( vector_len ))) return STATUS_NO_MEMORY;
|
||||
memcpy( key->u.s.vector, vector, vector_len );
|
||||
key->u.s.vector_len = vector_len;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static NTSTATUS init_cipher_handle( struct key *key )
|
||||
{
|
||||
gnutls_cipher_algorithm_t cipher;
|
||||
gnutls_datum_t secret, vector;
|
||||
int ret;
|
||||
|
||||
if (key->u.s.handle)
|
||||
{
|
||||
pgnutls_cipher_deinit( key->u.s.handle );
|
||||
key->u.s.handle = NULL;
|
||||
}
|
||||
|
||||
if ((cipher = get_gnutls_cipher( key )) == GNUTLS_CIPHER_UNKNOWN)
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
if (key->u.s.handle) return STATUS_SUCCESS;
|
||||
if ((cipher = get_gnutls_cipher( key )) == GNUTLS_CIPHER_UNKNOWN) return STATUS_NOT_SUPPORTED;
|
||||
|
||||
secret.data = key->u.s.secret;
|
||||
secret.size = key->u.s.secret_len;
|
||||
if (iv)
|
||||
{
|
||||
vector.data = iv;
|
||||
vector.size = iv_len;
|
||||
}
|
||||
|
||||
if ((ret = pgnutls_cipher_init( &key->u.s.handle, cipher, &secret, iv ? &vector : NULL )))
|
||||
vector.data = key->u.s.vector;
|
||||
vector.size = key->u.s.vector_len;
|
||||
|
||||
if ((ret = pgnutls_cipher_init( &key->u.s.handle, cipher, &secret, key->u.s.vector ? &vector : NULL )))
|
||||
{
|
||||
pgnutls_perror( ret );
|
||||
return STATUS_INTERNAL_ERROR;
|
||||
|
@ -509,8 +526,12 @@ NTSTATUS key_symmetric_set_params( struct key *key, UCHAR *iv, ULONG iv_len )
|
|||
|
||||
NTSTATUS key_symmetric_set_auth_data( struct key *key, UCHAR *auth_data, ULONG len )
|
||||
{
|
||||
NTSTATUS status;
|
||||
int ret;
|
||||
|
||||
if (!auth_data) return STATUS_SUCCESS;
|
||||
if ((status = init_cipher_handle( key ))) return status;
|
||||
|
||||
if ((ret = pgnutls_cipher_add_auth( key->u.s.handle, auth_data, len )))
|
||||
{
|
||||
pgnutls_perror( ret );
|
||||
|
@ -521,7 +542,11 @@ NTSTATUS key_symmetric_set_auth_data( struct key *key, UCHAR *auth_data, ULONG l
|
|||
|
||||
NTSTATUS key_symmetric_encrypt( struct key *key, const UCHAR *input, ULONG input_len, UCHAR *output, ULONG output_len )
|
||||
{
|
||||
NTSTATUS status;
|
||||
int ret;
|
||||
|
||||
if ((status = init_cipher_handle( key ))) return status;
|
||||
|
||||
if ((ret = pgnutls_cipher_encrypt2( key->u.s.handle, input, input_len, output, output_len )))
|
||||
{
|
||||
pgnutls_perror( ret );
|
||||
|
@ -532,7 +557,11 @@ NTSTATUS key_symmetric_encrypt( struct key *key, const UCHAR *input, ULONG input
|
|||
|
||||
NTSTATUS key_symmetric_decrypt( struct key *key, const UCHAR *input, ULONG input_len, UCHAR *output, ULONG output_len )
|
||||
{
|
||||
NTSTATUS status;
|
||||
int ret;
|
||||
|
||||
if ((status = init_cipher_handle( key ))) return status;
|
||||
|
||||
if ((ret = pgnutls_cipher_decrypt2( key->u.s.handle, input, input_len, output, output_len )))
|
||||
{
|
||||
pgnutls_perror( ret );
|
||||
|
@ -543,7 +572,11 @@ NTSTATUS key_symmetric_decrypt( struct key *key, const UCHAR *input, ULONG input
|
|||
|
||||
NTSTATUS key_symmetric_get_tag( struct key *key, UCHAR *tag, ULONG len )
|
||||
{
|
||||
NTSTATUS status;
|
||||
int ret;
|
||||
|
||||
if ((status = init_cipher_handle( key ))) return status;
|
||||
|
||||
if ((ret = pgnutls_cipher_tag( key->u.s.handle, tag, len )))
|
||||
{
|
||||
pgnutls_perror( ret );
|
||||
|
@ -1128,6 +1161,7 @@ NTSTATUS key_destroy( struct key *key )
|
|||
if (key_is_symmetric( key ))
|
||||
{
|
||||
if (key->u.s.handle) pgnutls_cipher_deinit( key->u.s.handle );
|
||||
heap_free( key->u.s.vector );
|
||||
heap_free( key->u.s.secret );
|
||||
}
|
||||
else
|
||||
|
|
|
@ -106,6 +106,8 @@ NTSTATUS key_symmetric_init( struct key *key, struct algorithm *alg, const UCHAR
|
|||
key->u.s.mode = alg->mode;
|
||||
key->u.s.ref_encrypt = NULL; /* initialized on first use */
|
||||
key->u.s.ref_decrypt = NULL;
|
||||
key->u.s.vector = NULL;
|
||||
key->u.s.vector_len = 0;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -122,32 +124,50 @@ static CCMode get_cryptor_mode( struct key *key )
|
|||
}
|
||||
}
|
||||
|
||||
NTSTATUS key_symmetric_set_params( struct key *key, UCHAR *iv, ULONG iv_len )
|
||||
NTSTATUS key_symmetric_set_vector( struct key *key, UCHAR *vector, ULONG vector_len )
|
||||
{
|
||||
CCCryptorStatus status;
|
||||
CCMode mode;
|
||||
|
||||
if (!(mode = get_cryptor_mode( key ))) return STATUS_NOT_SUPPORTED;
|
||||
|
||||
if (key->u.s.ref_encrypt)
|
||||
if (key->u.s.ref_encrypt && (!is_zero_vector( vector, vector_len ) ||
|
||||
!is_equal_vector( key->u.s.vector, key->u.s.vector_len, vector, vector_len )))
|
||||
{
|
||||
TRACE( "invalidating cryptor handles\n" );
|
||||
CCCryptorRelease( key->u.s.ref_encrypt );
|
||||
key->u.s.ref_encrypt = NULL;
|
||||
}
|
||||
if (key->u.s.ref_decrypt)
|
||||
{
|
||||
|
||||
CCCryptorRelease( key->u.s.ref_decrypt );
|
||||
key->u.s.ref_decrypt = NULL;
|
||||
}
|
||||
|
||||
if ((status = CCCryptorCreateWithMode( kCCEncrypt, mode, kCCAlgorithmAES128, ccNoPadding, iv, key->u.s.secret,
|
||||
key->u.s.secret_len, NULL, 0, 0, 0, &key->u.s.ref_encrypt )) != kCCSuccess)
|
||||
heap_free( key->u.s.vector );
|
||||
key->u.s.vector = NULL;
|
||||
key->u.s.vector_len = 0;
|
||||
if (vector)
|
||||
{
|
||||
if (!(key->u.s.vector = heap_alloc( vector_len ))) return STATUS_NO_MEMORY;
|
||||
memcpy( key->u.s.vector, vector, vector_len );
|
||||
key->u.s.vector_len = vector_len;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static NTSTATUS init_cryptor_handles( struct key *key )
|
||||
{
|
||||
CCCryptorStatus status;
|
||||
CCMode mode;
|
||||
|
||||
if (key->u.s.ref_encrypt) return STATUS_SUCCESS;
|
||||
if (!(mode = get_cryptor_mode( key ))) return STATUS_NOT_SUPPORTED;
|
||||
|
||||
if ((status = CCCryptorCreateWithMode( kCCEncrypt, mode, kCCAlgorithmAES128, ccNoPadding, key->u.s.vector,
|
||||
key->u.s.secret, key->u.s.secret_len, NULL, 0, 0, 0,
|
||||
&key->u.s.ref_encrypt )) != kCCSuccess)
|
||||
{
|
||||
WARN( "CCCryptorCreateWithMode failed %d\n", status );
|
||||
return STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
if ((status = CCCryptorCreateWithMode( kCCDecrypt, mode, kCCAlgorithmAES128, ccNoPadding, iv, key->u.s.secret,
|
||||
key->u.s.secret_len, NULL, 0, 0, 0, &key->u.s.ref_decrypt )) != kCCSuccess)
|
||||
if ((status = CCCryptorCreateWithMode( kCCDecrypt, mode, kCCAlgorithmAES128, ccNoPadding, key->u.s.vector,
|
||||
key->u.s.secret, key->u.s.secret_len, NULL, 0, 0, 0,
|
||||
&key->u.s.ref_decrypt )) != kCCSuccess)
|
||||
{
|
||||
WARN( "CCCryptorCreateWithMode failed %d\n", status );
|
||||
CCCryptorRelease( key->u.s.ref_encrypt );
|
||||
|
@ -167,6 +187,10 @@ NTSTATUS key_symmetric_set_auth_data( struct key *key, UCHAR *auth_data, ULONG l
|
|||
NTSTATUS key_symmetric_encrypt( struct key *key, const UCHAR *input, ULONG input_len, UCHAR *output, ULONG output_len )
|
||||
{
|
||||
CCCryptorStatus status;
|
||||
NTSTATUS ret;
|
||||
|
||||
if ((ret = init_cryptor_handles( key ))) return ret;
|
||||
|
||||
if ((status = CCCryptorUpdate( key->u.s.ref_encrypt, input, input_len, output, output_len, NULL )) != kCCSuccess)
|
||||
{
|
||||
WARN( "CCCryptorUpdate failed %d\n", status );
|
||||
|
@ -178,6 +202,10 @@ NTSTATUS key_symmetric_encrypt( struct key *key, const UCHAR *input, ULONG input
|
|||
NTSTATUS key_symmetric_decrypt( struct key *key, const UCHAR *input, ULONG input_len, UCHAR *output, ULONG output_len )
|
||||
{
|
||||
CCCryptorStatus status;
|
||||
NTSTATUS ret;
|
||||
|
||||
if ((ret = init_cryptor_handles( key ))) return ret;
|
||||
|
||||
if ((status = CCCryptorUpdate( key->u.s.ref_decrypt, input, input_len, output, output_len, NULL )) != kCCSuccess)
|
||||
{
|
||||
WARN( "CCCryptorUpdate failed %d\n", status );
|
||||
|
@ -235,6 +263,7 @@ NTSTATUS key_destroy( struct key *key )
|
|||
{
|
||||
if (key->u.s.ref_encrypt) CCCryptorRelease( key->u.s.ref_encrypt );
|
||||
if (key->u.s.ref_decrypt) CCCryptorRelease( key->u.s.ref_decrypt );
|
||||
heap_free( key->u.s.vector );
|
||||
heap_free( key->u.s.secret );
|
||||
heap_free( key );
|
||||
return STATUS_SUCCESS;
|
||||
|
|
|
@ -2128,6 +2128,74 @@ static void test_BCryptEnumAlgorithms(void)
|
|||
pBCryptFreeBuffer( list );
|
||||
}
|
||||
|
||||
static void test_aes_vector(void)
|
||||
{
|
||||
static const UCHAR secret[] = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10};
|
||||
static const UCHAR expect[] = {0xb0,0xcb,0xf5,0x80,0xd4,0xe3,0x55,0x23,0x6e,0x19,0x5b,0xdb,0xfe,0xe0,0x6c,0xd3};
|
||||
static const UCHAR expect2[] = {0x06,0x0c,0x81,0xab,0xd4,0x28,0x80,0x42,0xce,0x30,0x56,0x17,0x15,0x00,0x9e,0xc1};
|
||||
static const UCHAR expect3[] = {0x3e,0x99,0xbf,0x02,0xf5,0xd3,0xb8,0x81,0x91,0x4d,0x93,0xea,0xd4,0x92,0x93,0x46};
|
||||
static UCHAR iv[16], input[] = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p'};
|
||||
UCHAR output[16];
|
||||
BCRYPT_ALG_HANDLE alg;
|
||||
BCRYPT_KEY_HANDLE key;
|
||||
UCHAR data[sizeof(BCRYPT_KEY_DATA_BLOB_HEADER) + sizeof(secret)];
|
||||
BCRYPT_KEY_DATA_BLOB_HEADER *blob = (BCRYPT_KEY_DATA_BLOB_HEADER *)data;
|
||||
ULONG size;
|
||||
NTSTATUS ret;
|
||||
|
||||
ret = pBCryptOpenAlgorithmProvider(&alg, BCRYPT_AES_ALGORITHM, NULL, 0);
|
||||
ok(!ret, "got %08x\n", ret);
|
||||
|
||||
size = sizeof(BCRYPT_CHAIN_MODE_CBC);
|
||||
ret = pBCryptSetProperty(alg, BCRYPT_CHAINING_MODE, (UCHAR *)BCRYPT_CHAIN_MODE_CBC, size, 0);
|
||||
ok(!ret, "got %08x\n", ret);
|
||||
|
||||
blob->dwMagic = BCRYPT_KEY_DATA_BLOB_MAGIC;
|
||||
blob->dwVersion = BCRYPT_KEY_DATA_BLOB_VERSION1;
|
||||
blob->cbKeyData = sizeof(secret);
|
||||
memcpy(data + sizeof(*blob), secret, sizeof(secret));
|
||||
size = sizeof(BCRYPT_KEY_DATA_BLOB_HEADER) + sizeof(secret);
|
||||
ret = pBCryptImportKey(alg, NULL, BCRYPT_KEY_DATA_BLOB, &key, NULL, 0, data, size, 0);
|
||||
ok(!ret || broken(ret == STATUS_INVALID_PARAMETER) /* vista */, "got %08x\n", ret);
|
||||
if (ret == STATUS_INVALID_PARAMETER)
|
||||
{
|
||||
win_skip("broken BCryptImportKey\n");
|
||||
pBCryptCloseAlgorithmProvider(alg, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
/* zero initialization vector */
|
||||
size = 0;
|
||||
memset(output, 0, sizeof(output));
|
||||
ret = pBCryptEncrypt(key, input, sizeof(input), NULL, iv, sizeof(iv), output, sizeof(output), &size, 0);
|
||||
ok(!ret, "got %08x\n", ret);
|
||||
ok(size == 16, "got %u\n", size);
|
||||
ok(!memcmp(output, expect, sizeof(expect)), "wrong cipher text\n");
|
||||
|
||||
/* same initialization vector */
|
||||
size = 0;
|
||||
memset(output, 0, sizeof(output));
|
||||
ret = pBCryptEncrypt(key, input, sizeof(input), NULL, iv, sizeof(iv), output, sizeof(output), &size, 0);
|
||||
ok(!ret, "got %08x\n", ret);
|
||||
ok(size == 16, "got %u\n", size);
|
||||
ok(!memcmp(output, expect2, sizeof(expect2)), "wrong cipher text\n");
|
||||
|
||||
/* different initialization vector */
|
||||
iv[0] = 0x1;
|
||||
size = 0;
|
||||
memset(output, 0, sizeof(output));
|
||||
ret = pBCryptEncrypt(key, input, sizeof(input), NULL, iv, sizeof(iv), output, sizeof(output), &size, 0);
|
||||
ok(!ret, "got %08x\n", ret);
|
||||
ok(size == 16, "got %u\n", size);
|
||||
todo_wine ok(!memcmp(output, expect3, sizeof(expect3)), "wrong cipher text\n");
|
||||
|
||||
ret = pBCryptDestroyKey(key);
|
||||
ok(!ret, "got %08x\n", ret);
|
||||
|
||||
ret = pBCryptCloseAlgorithmProvider(alg, 0);
|
||||
ok(!ret, "got %08x\n", ret);
|
||||
}
|
||||
|
||||
START_TEST(bcrypt)
|
||||
{
|
||||
HMODULE module;
|
||||
|
@ -2186,6 +2254,7 @@ START_TEST(bcrypt)
|
|||
test_BCryptEnumContextFunctions();
|
||||
test_BCryptSignHash();
|
||||
test_BCryptEnumAlgorithms();
|
||||
test_aes_vector();
|
||||
|
||||
FreeLibrary(module);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue