[PATCH 2/6] bcrypt: Implement importing of ecdsa keys.
Alistair Leslie-Hughes
leslie_alistair at hotmail.com
Sun Mar 25 21:35:07 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.spec | 4 +-
dlls/bcrypt/bcrypt_main.c | 160 +++++++++++++++++++++++++++++++++++++++++++--
dlls/bcrypt/tests/bcrypt.c | 4 +-
include/bcrypt.h | 2 +
4 files changed, 161 insertions(+), 9 deletions(-)
diff --git a/dlls/bcrypt/bcrypt.spec b/dlls/bcrypt/bcrypt.spec
index 28c2394..78824d7 100644
--- a/dlls/bcrypt/bcrypt.spec
+++ b/dlls/bcrypt/bcrypt.spec
@@ -32,7 +32,7 @@
@ stdcall BCryptHash(ptr ptr long ptr long ptr long)
@ stdcall BCryptHashData(ptr ptr long long)
@ stdcall BCryptImportKey(ptr ptr wstr ptr ptr long ptr long long)
-@ stub BCryptImportKeyPair
+@ stdcall BCryptImportKeyPair(ptr ptr wstr ptr ptr long long)
@ stdcall BCryptOpenAlgorithmProvider(ptr wstr wstr long)
@ stub BCryptQueryContextConfiguration
@ stub BCryptQueryContextFunctionConfiguration
@@ -50,7 +50,7 @@
@ stub BCryptSignHash
@ stub BCryptUnregisterConfigChangeNotify
@ stdcall BCryptUnregisterProvider(wstr)
-@ stub BCryptVerifySignature
+@ stdcall BCryptVerifySignature(ptr ptr ptr long ptr long long)
@ stub GetAsymmetricEncryptionInterface
@ stub GetCipherInterface
@ stub GetHashInterface
diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c
index 3d31e76..afa8f2a 100644
--- a/dlls/bcrypt/bcrypt_main.c
+++ b/dlls/bcrypt/bcrypt_main.c
@@ -220,7 +220,9 @@ enum alg_id
ALG_ID_SHA1,
ALG_ID_SHA256,
ALG_ID_SHA384,
- ALG_ID_SHA512
+ ALG_ID_SHA512,
+ ALG_ID_ECDSA_P256,
+ ALG_ID_ECDSA_P384,
};
enum mode_id
@@ -248,7 +250,9 @@ static const struct {
/* ALG_ID_SHA1 */ { 278, 20, 512, BCRYPT_SHA1_ALGORITHM, FALSE },
/* ALG_ID_SHA256 */ { 286, 32, 512, BCRYPT_SHA256_ALGORITHM, FALSE },
/* ALG_ID_SHA384 */ { 382, 48, 1024, BCRYPT_SHA384_ALGORITHM, FALSE },
- /* ALG_ID_SHA512 */ { 382, 64, 1024, BCRYPT_SHA512_ALGORITHM, FALSE }
+ /* ALG_ID_SHA512 */ { 382, 64, 1024, BCRYPT_SHA512_ALGORITHM, FALSE },
+ /* ALG_ID_ECDSA_P256 */ { 0, 0, 0, BCRYPT_ECDSA_P256_ALGORITHM, FALSE },
+ /* ALG_ID_ECDSA_P384 */ { 0, 0, 0, BCRYPT_ECDSA_P384_ALGORITHM, FALSE },
};
struct algorithm
@@ -324,6 +328,8 @@ NTSTATUS WINAPI BCryptOpenAlgorithmProvider( BCRYPT_ALG_HANDLE *handle, LPCWSTR
else if (!strcmpW( id, BCRYPT_SHA256_ALGORITHM )) alg_id = ALG_ID_SHA256;
else if (!strcmpW( id, BCRYPT_SHA384_ALGORITHM )) alg_id = ALG_ID_SHA384;
else if (!strcmpW( id, BCRYPT_SHA512_ALGORITHM )) alg_id = ALG_ID_SHA512;
+ else if (!strcmpW( id, BCRYPT_ECDSA_P256_ALGORITHM )) alg_id = ALG_ID_ECDSA_P256;
+ else if (!strcmpW( id, BCRYPT_ECDSA_P384_ALGORITHM )) alg_id = ALG_ID_ECDSA_P384;
else
{
FIXME( "algorithm %s not supported\n", debugstr_w(id) );
@@ -866,6 +872,12 @@ struct key_symmetric
ULONG secret_len;
};
+struct key_asymmetric
+{
+ UCHAR *pubkey;
+ ULONG pubkey_len;
+};
+
struct key
{
struct object hdr;
@@ -873,6 +885,7 @@ struct key
union
{
struct key_symmetric s;
+ struct key_asymmetric a;
} u;
};
@@ -887,6 +900,12 @@ struct key_symmetric
ULONG secret_len;
};
+struct key_asymmetric
+{
+ UCHAR *pubkey;
+ ULONG pubkey_len;
+};
+
struct key
{
struct object hdr;
@@ -894,6 +913,7 @@ struct key
union
{
struct key_symmetric s;
+ struct key_asymmetric a;
} u;
};
#else
@@ -986,11 +1006,42 @@ static NTSTATUS key_duplicate( struct key *key_orig, struct key *key_copy )
}
else
{
- return STATUS_NOT_IMPLEMENTED;
+ if (!(buffer = heap_alloc( key_orig->u.a.pubkey_len ))) return STATUS_NO_MEMORY;
+ memcpy( buffer, key_orig->u.a.pubkey, key_orig->u.a.pubkey_len );
+
+ key_copy->u.a.pubkey = buffer;
+ key_copy->u.a.pubkey_len = key_orig->u.a.pubkey_len;
}
return STATUS_SUCCESS;
}
+
+static NTSTATUS key_asymmetric_init( struct key *key, struct algorithm *alg, const UCHAR *pubkey, ULONG pubkey_len )
+{
+ UCHAR *buffer;
+
+ if (!libgnutls_handle) return STATUS_INTERNAL_ERROR;
+
+ switch (alg->id)
+ {
+ case ALG_ID_ECDSA_P256:
+ case ALG_ID_ECDSA_P384:
+ break;
+
+ default:
+ FIXME( "algorithm %u not supported\n", alg->id );
+ return STATUS_NOT_SUPPORTED;
+ }
+
+ if (!(buffer = heap_alloc( pubkey_len ))) return STATUS_NO_MEMORY;
+ memcpy( buffer, pubkey, pubkey_len );
+
+ key->alg_id = alg->id;
+ key->u.a.pubkey = buffer;
+ key->u.a.pubkey_len = pubkey_len;
+
+ return STATUS_SUCCESS;
+}
#endif
#if defined(HAVE_GNUTLS_CIPHER_INIT) && !defined(HAVE_COMMONCRYPTO_COMMONCRYPTOR_H)
@@ -1170,8 +1221,13 @@ static NTSTATUS key_get_tag( struct key *key, UCHAR *tag, ULONG len )
static NTSTATUS key_destroy( struct key *key )
{
- if (key->u.s.handle) pgnutls_cipher_deinit( key->u.s.handle );
- heap_free( key->u.s.secret );
+ if(key_is_symmetric(key))
+ {
+ if (key->u.s.handle) pgnutls_cipher_deinit( key->u.s.handle );
+ heap_free( key->u.s.secret );
+ }
+ else
+ heap_free( key->u.a.pubkey );
heap_free( key );
return STATUS_SUCCESS;
}
@@ -1341,6 +1397,12 @@ static NTSTATUS key_symmetric_init( struct key *key, struct algorithm *alg, cons
return STATUS_NOT_IMPLEMENTED;
}
+static NTSTATUS key_asymmetric_init( struct key *key, struct algorithm *alg, const UCHAR *pubkey, ULONG pubkey_len )
+{
+ FIXME( "not implemented on Mac\n" );
+ return STATUS_NOT_IMPLEMENTED;
+}
+
static NTSTATUS set_key_property( struct key *key, const WCHAR *prop, UCHAR *value, ULONG size, ULONG flags )
{
ERR( "support for keys not available at build time\n" );
@@ -1403,6 +1465,12 @@ static inline BOOL key_is_symmetric( struct key *key )
return FALSE;
}
+static inline BOOL key_is_asymmetric( struct key *key )
+{
+ ERR( "support for keys not available at build time\n" );
+ return FALSE;
+}
+
static NTSTATUS key_symmetric_get_mode( struct key *key, enum mode_id *mode )
{
*mode = key->u.s.mode;
@@ -1529,6 +1597,88 @@ NTSTATUS WINAPI BCryptDuplicateKey( BCRYPT_KEY_HANDLE handle, BCRYPT_KEY_HANDLE
return STATUS_SUCCESS;
}
+NTSTATUS WINAPI BCryptImportKeyPair( BCRYPT_ALG_HANDLE algorithm, BCRYPT_KEY_HANDLE decrypt_key, const WCHAR *type,
+ BCRYPT_KEY_HANDLE *ret_key, UCHAR *input, ULONG input_len, ULONG flags )
+{
+ struct algorithm *alg = algorithm;
+ NTSTATUS status;
+ struct key *key;
+
+ TRACE( "%p, %p, %s, %p, %p, %u, %u\n", algorithm, decrypt_key, debugstr_w(type), ret_key, input, input_len, flags );
+
+ if (!alg || alg->hdr.magic != MAGIC_ALG) return STATUS_INVALID_HANDLE;
+ if (!ret_key || !type || !input) return STATUS_INVALID_PARAMETER;
+
+ *ret_key = NULL;
+
+ if (decrypt_key)
+ {
+ FIXME( "decrypting of key not yet supported\n" );
+ return STATUS_NOT_IMPLEMENTED;
+ }
+
+ if (!strcmpW( type, BCRYPT_ECCPUBLIC_BLOB ))
+ {
+ BCRYPT_ECCKEY_BLOB *ecc_blob = (BCRYPT_ECCKEY_BLOB *)input;
+ DWORD key_size, magic;
+
+ if (input_len < sizeof(*ecc_blob))
+ return STATUS_INVALID_PARAMETER;
+
+ switch (alg->id)
+ {
+ case ALG_ID_ECDSA_P256:
+ key_size = 32;
+ magic = BCRYPT_ECDSA_PUBLIC_P256_MAGIC;
+ break;
+ case ALG_ID_ECDSA_P384:
+ key_size = 48;
+ magic = BCRYPT_ECDSA_PUBLIC_P384_MAGIC;
+ break;
+
+ default:
+ FIXME("Algorithm %d does not yet support importing blob of type: %s\n", alg->id, debugstr_w(type));
+ return STATUS_NOT_SUPPORTED;
+ }
+
+ if (ecc_blob->dwMagic != magic)
+ return STATUS_NOT_SUPPORTED;
+
+ if (ecc_blob->cbKey != key_size)
+ return STATUS_INVALID_PARAMETER;
+
+ if (!(key = heap_alloc( sizeof(*key) )))
+ return STATUS_NO_MEMORY;
+
+ key->hdr.magic = MAGIC_KEY;
+ if ((status = key_asymmetric_init( key, alg, (BYTE *)(ecc_blob + 1), ecc_blob->cbKey * 2 )))
+ {
+ heap_free( key );
+ return status;
+ }
+
+ *ret_key = key;
+ return STATUS_SUCCESS;
+ }
+
+ FIXME( "unsupported key type %s\n", debugstr_w(type) );
+ return STATUS_NOT_SUPPORTED;
+}
+
+NTSTATUS WINAPI BCryptVerifySignature( BCRYPT_KEY_HANDLE handle, void *padding, UCHAR *hash, ULONG hash_len,
+ UCHAR *signature, ULONG signature_len, ULONG flags )
+{
+ struct key *key = handle;
+
+ FIXME( "%p, %p, %p, %u, %p, %u, %08x: stub!\n", handle, padding, hash,
+ hash_len, signature, signature_len, flags );
+
+ if (!key || key->hdr.magic != MAGIC_KEY) return STATUS_INVALID_HANDLE;
+ if (!key_is_asymmetric(key)) return STATUS_NOT_SUPPORTED;
+
+ return STATUS_NOT_IMPLEMENTED;
+}
+
NTSTATUS WINAPI BCryptDestroyKey( BCRYPT_KEY_HANDLE handle )
{
struct key *key = handle;
diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c
index 57d0488..fa244d1 100644
--- a/dlls/bcrypt/tests/bcrypt.c
+++ b/dlls/bcrypt/tests/bcrypt.c
@@ -1486,10 +1486,10 @@ static void test_ECDSA(void)
ok(!status, "BCryptImportKeyPair failed: %08x\n", status);
status = pBCryptVerifySignature(key, NULL, certHash, sizeof(certHash) - 1, certSignature, sizeof(certSignature), 0);
- ok(status == STATUS_INVALID_SIGNATURE, "Expected STATUS_INVALID_SIGNATURE, got %08x\n", status);
+ todo_wine ok(status == STATUS_INVALID_SIGNATURE, "Expected STATUS_INVALID_SIGNATURE, got %08x\n", status);
status = pBCryptVerifySignature(key, NULL, certHash, sizeof(certHash), certSignature, sizeof(certSignature), 0);
- ok(!status, "BCryptVerifySignature failed: %08x\n", status);
+ todo_wine ok(!status, "BCryptVerifySignature failed: %08x\n", status);
pBCryptDestroyKey(key);
pBCryptCloseAlgorithmProvider(alg, 0);
diff --git a/include/bcrypt.h b/include/bcrypt.h
index 717d77c..f28b0d3 100644
--- a/include/bcrypt.h
+++ b/include/bcrypt.h
@@ -211,8 +211,10 @@ NTSTATUS WINAPI BCryptGetFipsAlgorithmMode(BOOLEAN *);
NTSTATUS WINAPI BCryptGetProperty(BCRYPT_HANDLE, LPCWSTR, PUCHAR, ULONG, ULONG *, ULONG);
NTSTATUS WINAPI BCryptHash(BCRYPT_ALG_HANDLE, PUCHAR, ULONG, PUCHAR, ULONG, PUCHAR, ULONG);
NTSTATUS WINAPI BCryptHashData(BCRYPT_HASH_HANDLE, PUCHAR, ULONG, ULONG);
+NTSTATUS WINAPI BCryptImportKeyPair(BCRYPT_ALG_HANDLE, BCRYPT_KEY_HANDLE, LPCWSTR, BCRYPT_KEY_HANDLE *, UCHAR *, ULONG, ULONG);
NTSTATUS WINAPI BCryptOpenAlgorithmProvider(BCRYPT_ALG_HANDLE *, LPCWSTR, LPCWSTR, ULONG);
NTSTATUS WINAPI BCryptSetProperty(BCRYPT_HANDLE, LPCWSTR, PUCHAR, ULONG, ULONG);
NTSTATUS WINAPI BCryptDuplicateHash(BCRYPT_HASH_HANDLE, BCRYPT_HASH_HANDLE *, UCHAR *, ULONG, ULONG);
+NTSTATUS WINAPI BCryptVerifySignature(BCRYPT_KEY_HANDLE, void *, UCHAR *, ULONG, UCHAR *, ULONG, ULONG);
#endif /* __WINE_BCRYPT_H */
--
1.9.1
More information about the wine-devel
mailing list