Commit dd61c563 authored by Santino Mazza's avatar Santino Mazza Committed by Alexandre Julliard

bcrypt: Initial RSA encryption implementation.

parent 4a395899
...@@ -237,6 +237,16 @@ struct key_asymmetric_decrypt_params ...@@ -237,6 +237,16 @@ struct key_asymmetric_decrypt_params
ULONG *ret_len; ULONG *ret_len;
}; };
struct key_asymmetric_encrypt_params
{
struct key *key;
UCHAR *input;
unsigned input_len;
UCHAR *output;
ULONG output_len;
ULONG *ret_len;
};
struct key_asymmetric_duplicate_params struct key_asymmetric_duplicate_params
{ {
struct key *key_orig; struct key *key_orig;
...@@ -298,6 +308,7 @@ enum key_funcs ...@@ -298,6 +308,7 @@ enum key_funcs
unix_key_symmetric_destroy, unix_key_symmetric_destroy,
unix_key_asymmetric_generate, unix_key_asymmetric_generate,
unix_key_asymmetric_decrypt, unix_key_asymmetric_decrypt,
unix_key_asymmetric_encrypt,
unix_key_asymmetric_duplicate, unix_key_asymmetric_duplicate,
unix_key_asymmetric_sign, unix_key_asymmetric_sign,
unix_key_asymmetric_verify, unix_key_asymmetric_verify,
......
...@@ -1880,26 +1880,41 @@ NTSTATUS WINAPI BCryptEncrypt( BCRYPT_KEY_HANDLE handle, UCHAR *input, ULONG inp ...@@ -1880,26 +1880,41 @@ NTSTATUS WINAPI BCryptEncrypt( BCRYPT_KEY_HANDLE handle, UCHAR *input, ULONG inp
ULONG iv_len, UCHAR *output, ULONG output_len, ULONG *ret_len, ULONG flags ) ULONG iv_len, UCHAR *output, ULONG output_len, ULONG *ret_len, ULONG flags )
{ {
struct key *key = handle; struct key *key = handle;
struct key_asymmetric_encrypt_params asymmetric_params;
NTSTATUS ret; NTSTATUS ret;
TRACE( "%p, %p, %lu, %p, %p, %lu, %p, %lu, %p, %#lx\n", handle, input, input_len, padding, iv, iv_len, output, TRACE( "%p, %p, %lu, %p, %p, %lu, %p, %lu, %p, %#lx\n", handle, input, input_len, padding, iv, iv_len, output,
output_len, ret_len, flags ); output_len, ret_len, flags );
if (!key || key->hdr.magic != MAGIC_KEY) return STATUS_INVALID_HANDLE; if (!key || key->hdr.magic != MAGIC_KEY) return STATUS_INVALID_HANDLE;
if (!key_is_symmetric( key ))
if (key_is_symmetric( key ))
{ {
FIXME( "encryption with asymmetric keys not yet supported\n" );
return STATUS_NOT_IMPLEMENTED;
}
if (flags & ~BCRYPT_BLOCK_PADDING) if (flags & ~BCRYPT_BLOCK_PADDING)
{ {
FIXME( "flags %#lx not implemented\n", flags ); FIXME( "flags %#lx not implemented\n", flags );
return STATUS_NOT_IMPLEMENTED; return STATUS_NOT_IMPLEMENTED;
} }
EnterCriticalSection( &key->u.s.cs ); EnterCriticalSection( &key->u.s.cs );
ret = key_symmetric_encrypt( key, input, input_len, padding, iv, iv_len, output, output_len, ret_len, flags ); ret = key_symmetric_encrypt( key, input, input_len, padding, iv, iv_len, output, output_len, ret_len, flags );
LeaveCriticalSection( &key->u.s.cs ); LeaveCriticalSection( &key->u.s.cs );
}
else
{
if (flags & BCRYPT_PAD_NONE || flags & BCRYPT_PAD_OAEP)
{
FIXME( "flags %#lx not implemented\n", flags );
return STATUS_NOT_IMPLEMENTED;
}
asymmetric_params.input = input;
asymmetric_params.input_len = input_len;
asymmetric_params.key = key;
asymmetric_params.output = output;
asymmetric_params.output_len = output_len;
asymmetric_params.ret_len = ret_len;
ret = UNIX_CALL(key_asymmetric_encrypt, &asymmetric_params);
}
return ret; return ret;
} }
......
...@@ -97,6 +97,8 @@ static int (*pgnutls_privkey_import_ecc_raw)(gnutls_privkey_t, gnutls_ecc_curve_ ...@@ -97,6 +97,8 @@ static int (*pgnutls_privkey_import_ecc_raw)(gnutls_privkey_t, gnutls_ecc_curve_
const gnutls_datum_t *, const gnutls_datum_t *); const gnutls_datum_t *, const gnutls_datum_t *);
static int (*pgnutls_pubkey_verify_hash2)(gnutls_pubkey_t, gnutls_sign_algorithm_t, unsigned int, static int (*pgnutls_pubkey_verify_hash2)(gnutls_pubkey_t, gnutls_sign_algorithm_t, unsigned int,
const gnutls_datum_t *, const gnutls_datum_t *); const gnutls_datum_t *, const gnutls_datum_t *);
static int (*pgnutls_pubkey_encrypt_data)(gnutls_pubkey_t, unsigned int flags, const gnutls_datum_t *,
gnutls_datum_t *);
/* Not present in gnutls version < 2.11.0 */ /* Not present in gnutls version < 2.11.0 */
static int (*pgnutls_pubkey_import_rsa_raw)(gnutls_pubkey_t, const gnutls_datum_t *, const gnutls_datum_t *); static int (*pgnutls_pubkey_import_rsa_raw)(gnutls_pubkey_t, const gnutls_datum_t *, const gnutls_datum_t *);
...@@ -105,6 +107,8 @@ static int (*pgnutls_pubkey_import_rsa_raw)(gnutls_pubkey_t, const gnutls_datum_ ...@@ -105,6 +107,8 @@ static int (*pgnutls_pubkey_import_rsa_raw)(gnutls_pubkey_t, const gnutls_datum_
static int (*pgnutls_pubkey_import_dsa_raw)(gnutls_pubkey_t, const gnutls_datum_t *, const gnutls_datum_t *, static int (*pgnutls_pubkey_import_dsa_raw)(gnutls_pubkey_t, const gnutls_datum_t *, const gnutls_datum_t *,
const gnutls_datum_t *, const gnutls_datum_t *); const gnutls_datum_t *, const gnutls_datum_t *);
static int (*pgnutls_pubkey_import_privkey)(gnutls_pubkey_t, gnutls_privkey_t, unsigned int, unsigned int); static int (*pgnutls_pubkey_import_privkey)(gnutls_pubkey_t, gnutls_privkey_t, unsigned int, unsigned int);
static int (*pgnutls_privkey_decrypt_data)(gnutls_privkey_t, unsigned int flags, const gnutls_datum_t *,
gnutls_datum_t *);
/* Not present in gnutls version < 3.3.0 */ /* Not present in gnutls version < 3.3.0 */
static int (*pgnutls_pubkey_export_dsa_raw)(gnutls_pubkey_t, gnutls_datum_t *, gnutls_datum_t *, gnutls_datum_t *, static int (*pgnutls_pubkey_export_dsa_raw)(gnutls_pubkey_t, gnutls_datum_t *, gnutls_datum_t *, gnutls_datum_t *,
...@@ -121,7 +125,6 @@ static int (*pgnutls_privkey_generate)(gnutls_privkey_t, gnutls_pk_algorithm_t, ...@@ -121,7 +125,6 @@ static int (*pgnutls_privkey_generate)(gnutls_privkey_t, gnutls_pk_algorithm_t,
static int (*pgnutls_privkey_import_rsa_raw)(gnutls_privkey_t, const gnutls_datum_t *, const gnutls_datum_t *, static int (*pgnutls_privkey_import_rsa_raw)(gnutls_privkey_t, const gnutls_datum_t *, const gnutls_datum_t *,
const gnutls_datum_t *, const gnutls_datum_t *, const gnutls_datum_t *, const gnutls_datum_t *, const gnutls_datum_t *, const gnutls_datum_t *,
const gnutls_datum_t *, const gnutls_datum_t *, const gnutls_datum_t *); const gnutls_datum_t *, const gnutls_datum_t *, const gnutls_datum_t *);
static int (*pgnutls_privkey_decrypt_data)(gnutls_privkey_t, unsigned int flags, const gnutls_datum_t *, gnutls_datum_t *);
/* Not present in gnutls version < 3.6.0 */ /* Not present in gnutls version < 3.6.0 */
static int (*pgnutls_decode_rs_value)(const gnutls_datum_t *, gnutls_datum_t *, gnutls_datum_t *); static int (*pgnutls_decode_rs_value)(const gnutls_datum_t *, gnutls_datum_t *, gnutls_datum_t *);
...@@ -143,6 +146,7 @@ MAKE_FUNCPTR(gnutls_privkey_import_dsa_raw); ...@@ -143,6 +146,7 @@ MAKE_FUNCPTR(gnutls_privkey_import_dsa_raw);
MAKE_FUNCPTR(gnutls_privkey_init); MAKE_FUNCPTR(gnutls_privkey_init);
MAKE_FUNCPTR(gnutls_privkey_sign_hash); MAKE_FUNCPTR(gnutls_privkey_sign_hash);
MAKE_FUNCPTR(gnutls_pubkey_deinit); MAKE_FUNCPTR(gnutls_pubkey_deinit);
MAKE_FUNCPTR(gnutls_pubkey_encrypt_data);
MAKE_FUNCPTR(gnutls_pubkey_import_privkey); MAKE_FUNCPTR(gnutls_pubkey_import_privkey);
MAKE_FUNCPTR(gnutls_pubkey_init); MAKE_FUNCPTR(gnutls_pubkey_init);
#undef MAKE_FUNCPTR #undef MAKE_FUNCPTR
...@@ -253,6 +257,12 @@ static int compat_gnutls_privkey_decrypt_data(gnutls_privkey_t key, unsigned int ...@@ -253,6 +257,12 @@ static int compat_gnutls_privkey_decrypt_data(gnutls_privkey_t key, unsigned int
return GNUTLS_E_UNKNOWN_PK_ALGORITHM; return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
} }
static int compat_gnutls_pubkey_encrypt_data(gnutls_pubkey_t key, unsigned int flags, const gnutls_datum_t *cipher_text,
gnutls_datum_t *plain_text)
{
return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
}
static void gnutls_log( int level, const char *msg ) static void gnutls_log( int level, const char *msg )
{ {
TRACE( "<%d> %s", level, msg ); TRACE( "<%d> %s", level, msg );
...@@ -329,6 +339,7 @@ static NTSTATUS gnutls_process_attach( void *args ) ...@@ -329,6 +339,7 @@ static NTSTATUS gnutls_process_attach( void *args )
LOAD_FUNCPTR_OPT(gnutls_decode_rs_value) LOAD_FUNCPTR_OPT(gnutls_decode_rs_value)
LOAD_FUNCPTR_OPT(gnutls_privkey_import_rsa_raw) LOAD_FUNCPTR_OPT(gnutls_privkey_import_rsa_raw)
LOAD_FUNCPTR_OPT(gnutls_privkey_decrypt_data) LOAD_FUNCPTR_OPT(gnutls_privkey_decrypt_data)
LOAD_FUNCPTR_OPT(gnutls_pubkey_encrypt_data)
#undef LOAD_FUNCPTR_OPT #undef LOAD_FUNCPTR_OPT
if ((ret = pgnutls_global_init()) != GNUTLS_E_SUCCESS) if ((ret = pgnutls_global_init()) != GNUTLS_E_SUCCESS)
...@@ -1927,6 +1938,30 @@ static NTSTATUS key_asymmetric_decrypt( void *args ) ...@@ -1927,6 +1938,30 @@ static NTSTATUS key_asymmetric_decrypt( void *args )
return status; return status;
} }
static NTSTATUS key_asymmetric_encrypt( void *args )
{
const struct key_asymmetric_encrypt_params *params = args;
gnutls_datum_t d, e = { 0 };
NTSTATUS status = STATUS_SUCCESS;
int ret;
d.data = params->input;
d.size = params->input_len;
if ((ret = pgnutls_pubkey_encrypt_data(key_data(params->key)->a.pubkey, 0, &d, &e)))
{
pgnutls_perror( ret );
return STATUS_INTERNAL_ERROR;
}
*params->ret_len = e.size;
if (params->output_len >= e.size) memcpy( params->output, e.data, *params->ret_len );
else if (params->output_len == 0) status = STATUS_SUCCESS;
else status = STATUS_BUFFER_TOO_SMALL;
free( e.data );
return status;
}
const unixlib_entry_t __wine_unix_call_funcs[] = const unixlib_entry_t __wine_unix_call_funcs[] =
{ {
gnutls_process_attach, gnutls_process_attach,
...@@ -1939,6 +1974,7 @@ const unixlib_entry_t __wine_unix_call_funcs[] = ...@@ -1939,6 +1974,7 @@ const unixlib_entry_t __wine_unix_call_funcs[] =
key_symmetric_destroy, key_symmetric_destroy,
key_asymmetric_generate, key_asymmetric_generate,
key_asymmetric_decrypt, key_asymmetric_decrypt,
key_asymmetric_encrypt,
key_asymmetric_duplicate, key_asymmetric_duplicate,
key_asymmetric_sign, key_asymmetric_sign,
key_asymmetric_verify, key_asymmetric_verify,
...@@ -2188,6 +2224,36 @@ static NTSTATUS wow64_key_asymmetric_decrypt( void *args ) ...@@ -2188,6 +2224,36 @@ static NTSTATUS wow64_key_asymmetric_decrypt( void *args )
return ret; return ret;
} }
static NTSTATUS wow64_key_asymmetric_encrypt( void *args )
{
struct
{
PTR32 key;
PTR32 input;
ULONG input_len;
PTR32 output;
ULONG output_len;
PTR32 ret_len;
} const *params32 = args;
NTSTATUS ret;
struct key key;
struct key32 *key32 = ULongToPtr( params32->key );
struct key_asymmetric_encrypt_params params =
{
get_asymmetric_key( key32, &key ),
ULongToPtr(params32->input),
params32->input_len,
ULongToPtr(params32->output),
params32->output_len,
ULongToPtr(params32->ret_len)
};
ret = key_asymmetric_encrypt( &params );
put_asymmetric_key32( &key, key32 );
return ret;
}
static NTSTATUS wow64_key_asymmetric_duplicate( void *args ) static NTSTATUS wow64_key_asymmetric_duplicate( void *args )
{ {
struct struct
...@@ -2369,6 +2435,7 @@ const unixlib_entry_t __wine_unix_call_wow64_funcs[] = ...@@ -2369,6 +2435,7 @@ const unixlib_entry_t __wine_unix_call_wow64_funcs[] =
wow64_key_symmetric_destroy, wow64_key_symmetric_destroy,
wow64_key_asymmetric_generate, wow64_key_asymmetric_generate,
wow64_key_asymmetric_decrypt, wow64_key_asymmetric_decrypt,
wow64_key_asymmetric_encrypt,
wow64_key_asymmetric_duplicate, wow64_key_asymmetric_duplicate,
wow64_key_asymmetric_sign, wow64_key_asymmetric_sign,
wow64_key_asymmetric_verify, wow64_key_asymmetric_verify,
......
...@@ -2075,6 +2075,7 @@ static void test_rsa_encrypt(void) ...@@ -2075,6 +2075,7 @@ static void test_rsa_encrypt(void)
BCryptDecrypt(key, encrypted_a, encrypted_size, NULL, NULL, 0, decrypted, decrypted_size, &decrypted_size, BCRYPT_PAD_NONE); BCryptDecrypt(key, encrypted_a, encrypted_size, NULL, NULL, 0, decrypted, decrypted_size, &decrypted_size, BCRYPT_PAD_NONE);
ok(!memcmp(decrypted, input_no_padding, sizeof(input_no_padding)), "Decrypted output it's not what expected\n"); ok(!memcmp(decrypted, input_no_padding, sizeof(input_no_padding)), "Decrypted output it's not what expected\n");
free(decrypted); free(decrypted);
}
encrypted_size = 60; encrypted_size = 60;
/* PKCS1 Padding */ /* PKCS1 Padding */
...@@ -2093,6 +2094,7 @@ static void test_rsa_encrypt(void) ...@@ -2093,6 +2094,7 @@ static void test_rsa_encrypt(void)
ok(ret == STATUS_SUCCESS, "got %lx\n", ret); ok(ret == STATUS_SUCCESS, "got %lx\n", ret);
ok(memcmp(encrypted_a, encrypted_b, encrypted_size), "Both outputs are the same\n"); ok(memcmp(encrypted_a, encrypted_b, encrypted_size), "Both outputs are the same\n");
todo_wine {
BCryptDecrypt(key, encrypted_a, encrypted_size, NULL, NULL, 0, NULL, 0, &decrypted_size, BCRYPT_PAD_PKCS1); BCryptDecrypt(key, encrypted_a, encrypted_size, NULL, NULL, 0, NULL, 0, &decrypted_size, BCRYPT_PAD_PKCS1);
decrypted = malloc(decrypted_size); decrypted = malloc(decrypted_size);
BCryptDecrypt(key, encrypted_a, encrypted_size, NULL, NULL, 0, decrypted, decrypted_size, &decrypted_size, BCRYPT_PAD_PKCS1); BCryptDecrypt(key, encrypted_a, encrypted_size, NULL, NULL, 0, decrypted, decrypted_size, &decrypted_size, BCRYPT_PAD_PKCS1);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment