diff --git a/patches/crypt32-ECDSA_Cert_Chains/0001-bcrypt-Preparation-for-asymmetric-keys.patch b/patches/bcrypt-Improvements/0030-bcrypt-Preparation-for-asymmetric-keys.patch similarity index 100% rename from patches/crypt32-ECDSA_Cert_Chains/0001-bcrypt-Preparation-for-asymmetric-keys.patch rename to patches/bcrypt-Improvements/0030-bcrypt-Preparation-for-asymmetric-keys.patch diff --git a/patches/crypt32-ECDSA_Cert_Chains/0002-include-Add-ecdsa-and-asymmetric-key-related-bcrypt-.patch b/patches/bcrypt-Improvements/0031-include-Add-ecdsa-and-asymmetric-key-related-bcrypt-.patch similarity index 100% rename from patches/crypt32-ECDSA_Cert_Chains/0002-include-Add-ecdsa-and-asymmetric-key-related-bcrypt-.patch rename to patches/bcrypt-Improvements/0031-include-Add-ecdsa-and-asymmetric-key-related-bcrypt-.patch diff --git a/patches/crypt32-ECDSA_Cert_Chains/0003-bcrypt-tests-Add-basic-test-for-ecdsa.patch b/patches/bcrypt-Improvements/0032-bcrypt-tests-Add-basic-test-for-ecdsa.patch similarity index 100% rename from patches/crypt32-ECDSA_Cert_Chains/0003-bcrypt-tests-Add-basic-test-for-ecdsa.patch rename to patches/bcrypt-Improvements/0032-bcrypt-tests-Add-basic-test-for-ecdsa.patch diff --git a/patches/crypt32-ECDSA_Cert_Chains/0004-bcrypt-Implement-importing-of-ecdsa-keys.patch b/patches/bcrypt-Improvements/0033-bcrypt-Implement-importing-of-ecdsa-keys.patch similarity index 100% rename from patches/crypt32-ECDSA_Cert_Chains/0004-bcrypt-Implement-importing-of-ecdsa-keys.patch rename to patches/bcrypt-Improvements/0033-bcrypt-Implement-importing-of-ecdsa-keys.patch diff --git a/patches/crypt32-ECDSA_Cert_Chains/0005-bcrypt-Implement-BCryptVerifySignature-for-ecdsa-sig.patch b/patches/bcrypt-Improvements/0034-bcrypt-Implement-BCryptVerifySignature-for-ecdsa-sig.patch similarity index 100% rename from patches/crypt32-ECDSA_Cert_Chains/0005-bcrypt-Implement-BCryptVerifySignature-for-ecdsa-sig.patch rename to patches/bcrypt-Improvements/0034-bcrypt-Implement-BCryptVerifySignature-for-ecdsa-sig.patch diff --git a/patches/bcrypt-Improvements/0035-bcrypt-Initial-implementation-for-RSA-key-import-and.patch b/patches/bcrypt-Improvements/0035-bcrypt-Initial-implementation-for-RSA-key-import-and.patch new file mode 100644 index 00000000..a7a3009e --- /dev/null +++ b/patches/bcrypt-Improvements/0035-bcrypt-Initial-implementation-for-RSA-key-import-and.patch @@ -0,0 +1,296 @@ +From 72f7ded1f27e7d14b7efb7200b43e320f3e245d4 Mon Sep 17 00:00:00 2001 +From: Kimmo Myllyvirta +Date: Tue, 10 Oct 2017 16:40:41 +0300 +Subject: bcrypt: Initial implementation for RSA key import and signature + verification. + +--- + dlls/bcrypt/bcrypt_main.c | 128 ++++++++++++++++++++++++++++++++++++++++++---- + include/bcrypt.h | 17 ++++++ + 2 files changed, 135 insertions(+), 10 deletions(-) + +diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c +index 881f6f7eb0c..3356364a6dc 100644 +--- a/dlls/bcrypt/bcrypt_main.c ++++ b/dlls/bcrypt/bcrypt_main.c +@@ -71,6 +71,9 @@ static int (*pgnutls_pubkey_verify_hash2)(gnutls_pubkey_t key, gnutls_sign_algor + unsigned int flags, const gnutls_datum_t *hash, + const gnutls_datum_t *signature); + ++/* Not present in gnutls version < 2.11.0 */ ++static int (*pgnutls_pubkey_import_rsa_raw)(gnutls_pubkey_t key, const gnutls_datum_t *m, const gnutls_datum_t *e); ++ + static void *libgnutls_handle; + #define MAKE_FUNCPTR(f) static typeof(f) * p##f + MAKE_FUNCPTR(gnutls_cipher_decrypt2); +@@ -121,6 +124,11 @@ static int compat_gnutls_pubkey_verify_hash2(gnutls_pubkey_t key, gnutls_sign_al + return GNUTLS_E_UNKNOWN_CIPHER_TYPE; + } + ++static int compat_gnutls_pubkey_import_rsa_raw(gnutls_pubkey_t key, const gnutls_datum_t *m, const gnutls_datum_t *e) ++{ ++ return GNUTLS_E_UNKNOWN_CIPHER_TYPE; ++} ++ + static void gnutls_log( int level, const char *msg ) + { + TRACE( "<%d> %s", level, msg ); +@@ -181,6 +189,11 @@ static BOOL gnutls_initialize(void) + WARN("gnutls_pubkey_verify_hash2 not found\n"); + pgnutls_pubkey_verify_hash2 = compat_gnutls_pubkey_verify_hash2; + } ++ if (!(pgnutls_pubkey_import_rsa_raw = wine_dlsym( libgnutls_handle, "gnutls_pubkey_import_rsa_raw", NULL, 0 ))) ++ { ++ WARN("gnutls_pubkey_import_rsa_raw not found\n"); ++ pgnutls_pubkey_import_rsa_raw = compat_gnutls_pubkey_import_rsa_raw; ++ } + + if ((ret = pgnutls_global_init()) != GNUTLS_E_SUCCESS) + { +@@ -234,6 +247,7 @@ enum alg_id + ALG_ID_AES, + ALG_ID_MD5, + ALG_ID_RNG, ++ ALG_ID_RSA, + ALG_ID_SHA1, + ALG_ID_SHA256, + ALG_ID_SHA384, +@@ -262,6 +276,7 @@ static const struct { + /* ALG_ID_AES */ { 654, 0, 0, BCRYPT_AES_ALGORITHM, TRUE }, + /* ALG_ID_MD5 */ { 274, 16, 512, BCRYPT_MD5_ALGORITHM, FALSE }, + /* ALG_ID_RNG */ { 0, 0, 0, BCRYPT_RNG_ALGORITHM, FALSE }, ++ /* ALG_ID_RSA */ { 0, 0, 0, BCRYPT_RSA_ALGORITHM, FALSE }, + /* 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 }, +@@ -340,6 +355,7 @@ NTSTATUS WINAPI BCryptOpenAlgorithmProvider( BCRYPT_ALG_HANDLE *handle, LPCWSTR + if (!strcmpW( id, BCRYPT_AES_ALGORITHM )) alg_id = ALG_ID_AES; + else if (!strcmpW( id, BCRYPT_MD5_ALGORITHM )) alg_id = ALG_ID_MD5; + else if (!strcmpW( id, BCRYPT_RNG_ALGORITHM )) alg_id = ALG_ID_RNG; ++ else if (!strcmpW( id, BCRYPT_RSA_ALGORITHM )) alg_id = ALG_ID_RSA; + else if (!strcmpW( id, BCRYPT_SHA1_ALGORITHM )) alg_id = ALG_ID_SHA1; + else if (!strcmpW( id, BCRYPT_SHA256_ALGORITHM )) alg_id = ALG_ID_SHA256; + else if (!strcmpW( id, BCRYPT_SHA384_ALGORITHM )) alg_id = ALG_ID_SHA384; +@@ -950,6 +966,7 @@ static NTSTATUS key_asymmetric_init( struct key *key, struct algorithm *alg, con + { + case ALG_ID_ECDSA_P256: + case ALG_ID_ECDSA_P384: ++ case ALG_ID_RSA: + break; + + default: +@@ -1326,6 +1343,34 @@ static NTSTATUS import_gnutls_pubkey_ecc( struct key *key, gnutls_pubkey_t *gnut + return STATUS_SUCCESS; + } + ++static NTSTATUS import_gnutls_pubkey_rsa( struct key *key, gnutls_pubkey_t *gnutls_key ) ++{ ++ BCRYPT_RSAKEY_BLOB *rsa_blob; ++ gnutls_datum_t m, e; ++ int ret; ++ ++ if ((ret = pgnutls_pubkey_init( gnutls_key ))) ++ { ++ pgnutls_perror( ret ); ++ return STATUS_INTERNAL_ERROR; ++ } ++ ++ rsa_blob = (BCRYPT_RSAKEY_BLOB *)key->u.a.pubkey; ++ e.data = key->u.a.pubkey + sizeof(*rsa_blob); ++ e.size = rsa_blob->cbPublicExp; ++ m.data = key->u.a.pubkey + sizeof(*rsa_blob) + rsa_blob->cbPublicExp; ++ m.size = rsa_blob->cbModulus; ++ ++ if ((ret = pgnutls_pubkey_import_rsa_raw( *gnutls_key, &m, &e ))) ++ { ++ pgnutls_perror( ret ); ++ pgnutls_pubkey_deinit( *gnutls_key ); ++ return STATUS_INTERNAL_ERROR; ++ } ++ ++ return STATUS_SUCCESS; ++} ++ + static NTSTATUS import_gnutls_pubkey( struct key *key, gnutls_pubkey_t *gnutls_key) + { + switch (key->alg_id) +@@ -1333,6 +1378,8 @@ static NTSTATUS import_gnutls_pubkey( struct key *key, gnutls_pubkey_t *gnutls_ + case ALG_ID_ECDSA_P256: + case ALG_ID_ECDSA_P384: + return import_gnutls_pubkey_ecc( key, gnutls_key ); ++ case ALG_ID_RSA: ++ return import_gnutls_pubkey_rsa( key, gnutls_key ); + + default: + FIXME("Algorithm %d not yet supported\n", key->alg_id); +@@ -1362,6 +1409,14 @@ static NTSTATUS prepare_gnutls_signature_ecc( struct key *key, UCHAR *signature, + return STATUS_SUCCESS; + } + ++static NTSTATUS prepare_gnutls_signature_rsa( struct key *key, UCHAR *signature, ULONG signature_len, ++ gnutls_datum_t *gnutls_signature ) ++{ ++ gnutls_signature->data = signature; ++ gnutls_signature->size = signature_len; ++ return STATUS_SUCCESS; ++} ++ + static NTSTATUS prepare_gnutls_signature( struct key *key, UCHAR *signature, ULONG signature_len, + gnutls_datum_t *gnutls_signature ) + { +@@ -1370,6 +1425,8 @@ static NTSTATUS prepare_gnutls_signature( struct key *key, UCHAR *signature, ULO + case ALG_ID_ECDSA_P256: + case ALG_ID_ECDSA_P384: + return prepare_gnutls_signature_ecc( key, signature, signature_len, gnutls_signature ); ++ case ALG_ID_RSA: ++ return prepare_gnutls_signature_rsa( key, signature, signature_len, gnutls_signature ); + + default: + FIXME( "Algorithm %d not yet supported\n", key->alg_id ); +@@ -1388,18 +1445,38 @@ static NTSTATUS key_asymmetric_verify( struct key *key, void *padding, UCHAR *ha + NTSTATUS status; + int ret; + +- if (flags) +- FIXME( "Flags %08x not supported\n", flags ); ++ if (key->alg_id == ALG_ID_RSA) ++ { ++ BCRYPT_PKCS1_PADDING_INFO *pinfo = (BCRYPT_PKCS1_PADDING_INFO *)padding; + +- /* only the hash size must match, not the actual hash function */ +- switch (hash_len) ++ if (!(flags & BCRYPT_PAD_PKCS1) || !pinfo) return STATUS_INVALID_PARAMETER; ++ if (!pinfo->pszAlgId) return STATUS_INVALID_SIGNATURE; ++ ++ if (!strcmpW( pinfo->pszAlgId, BCRYPT_SHA1_ALGORITHM )) hash_algo = GNUTLS_DIG_SHA1; ++ else if (!strcmpW( pinfo->pszAlgId, BCRYPT_SHA256_ALGORITHM )) hash_algo = GNUTLS_DIG_SHA256; ++ else if (!strcmpW( pinfo->pszAlgId, BCRYPT_SHA384_ALGORITHM )) hash_algo = GNUTLS_DIG_SHA384; ++ else if (!strcmpW( pinfo->pszAlgId, BCRYPT_SHA512_ALGORITHM )) hash_algo = GNUTLS_DIG_SHA512; ++ else ++ { ++ FIXME( "Hash algorithm %s not supported\n", debugstr_w(pinfo->pszAlgId) ); ++ return STATUS_NOT_SUPPORTED; ++ } ++ } ++ else + { +- case 32: hash_algo = GNUTLS_DIG_SHA256; break; +- case 48: hash_algo = GNUTLS_DIG_SHA384; break; ++ if (flags) ++ FIXME( "Flags %08x not supported\n", flags ); + +- default: +- FIXME( "Hash size %u not yet supported\n", hash_len ); +- return STATUS_INVALID_SIGNATURE; ++ /* only the hash size must match, not the actual hash function */ ++ switch (hash_len) ++ { ++ case 32: hash_algo = GNUTLS_DIG_SHA256; break; ++ case 48: hash_algo = GNUTLS_DIG_SHA384; break; ++ ++ default: ++ FIXME( "Hash size %u not yet supported\n", hash_len ); ++ return STATUS_INVALID_SIGNATURE; ++ } + } + + switch (key->alg_id) +@@ -1408,6 +1485,9 @@ static NTSTATUS key_asymmetric_verify( struct key *key, void *padding, UCHAR *ha + case ALG_ID_ECDSA_P384: + pk_algo = GNUTLS_PK_ECC; + break; ++ case ALG_ID_RSA: ++ pk_algo = GNUTLS_PK_RSA; ++ break; + + default: + FIXME( "Algorithm %d not yet supported\n", key->alg_id ); +@@ -1433,7 +1513,8 @@ static NTSTATUS key_asymmetric_verify( struct key *key, void *padding, UCHAR *ha + gnutls_hash.size = hash_len; + ret = pgnutls_pubkey_verify_hash2( gnutls_key, sign_algo, 0, &gnutls_hash, &gnutls_signature ); + +- HeapFree( GetProcessHeap(), 0, gnutls_signature.data ); ++ if (gnutls_signature.data != signature) ++ HeapFree( GetProcessHeap(), 0, gnutls_signature.data ); + pgnutls_pubkey_deinit( gnutls_key ); + return (ret < 0) ? STATUS_INVALID_SIGNATURE : STATUS_SUCCESS; + } +@@ -1774,6 +1855,33 @@ NTSTATUS WINAPI BCryptImportKeyPair( BCRYPT_ALG_HANDLE algorithm, BCRYPT_KEY_HAN + *ret_key = key; + return STATUS_SUCCESS; + } ++ else if (!strcmpW( type, BCRYPT_RSAPUBLIC_BLOB )) ++ { ++ BCRYPT_RSAKEY_BLOB *rsa_blob = (BCRYPT_RSAKEY_BLOB *)input; ++ ++ if (input_len < sizeof(*rsa_blob)) ++ return STATUS_INVALID_PARAMETER; ++ ++ if (alg->id != ALG_ID_RSA) ++ return STATUS_NOT_SUPPORTED; ++ ++ if (rsa_blob->Magic != BCRYPT_RSAPUBLIC_MAGIC) ++ return STATUS_NOT_SUPPORTED; ++ ++ if (!(key = HeapAlloc( GetProcessHeap(), 0, sizeof(*key) ))) ++ return STATUS_NO_MEMORY; ++ ++ key->hdr.magic = MAGIC_KEY; ++ if ((status = key_asymmetric_init( key, alg, (BYTE *)rsa_blob, ++ sizeof(*rsa_blob) + rsa_blob->cbPublicExp + rsa_blob->cbModulus ))) ++ { ++ HeapFree( GetProcessHeap(), 0, key ); ++ return status; ++ } ++ ++ *ret_key = key; ++ return STATUS_SUCCESS; ++ } + + FIXME( "unsupported key type %s\n", debugstr_w(type) ); + return STATUS_NOT_SUPPORTED; +diff --git a/include/bcrypt.h b/include/bcrypt.h +index 3dcc953e9ed..944796024bf 100644 +--- a/include/bcrypt.h ++++ b/include/bcrypt.h +@@ -63,6 +63,8 @@ typedef LONG NTSTATUS; + #define BCRYPT_AES_WRAP_KEY_BLOB (const WCHAR []){'R','f','c','3','5','6','5','K','e','y','W','r','a','p','B','l','o','b',0} + #define BCRYPT_ECCPUBLIC_BLOB (const WCHAR []){'E','C','C','P','U','B','L','I','C','B','L','O','B',0} + #define BCRYPT_ECCPRIVATE_BLOB (const WCHAR []){'E','C','C','P','R','I','V','A','T','E','B','L','O','B',0} ++#define BCRYPT_RSAPUBLIC_BLOB (const WCHAR []){'R','S','A','P','U','B','L','I','C','B','L','O','B',0} ++#define BCRYPT_RSAPRIVATE_BLOB (const WCHAR []){'R','S','A','P','R','I','V','A','T','E','B','L','O','B',0} + + #define MS_PRIMITIVE_PROVIDER (const WCHAR [])\ + {'M','i','c','r','o','s','o','f','t',' ','P','r','i','m','i','t','i','v','e',' ','P','r','o','v','i','d','e','r',0} +@@ -72,6 +74,7 @@ typedef LONG NTSTATUS; + #define BCRYPT_AES_ALGORITHM (const WCHAR []){'A','E','S',0} + #define BCRYPT_MD5_ALGORITHM (const WCHAR []){'M','D','5',0} + #define BCRYPT_RNG_ALGORITHM (const WCHAR []){'R','N','G',0} ++#define BCRYPT_RSA_ALGORITHM (const WCHAR []){'R','S','A',0} + #define BCRYPT_SHA1_ALGORITHM (const WCHAR []){'S','H','A','1',0} + #define BCRYPT_SHA256_ALGORITHM (const WCHAR []){'S','H','A','2','5','6',0} + #define BCRYPT_SHA384_ALGORITHM (const WCHAR []){'S','H','A','3','8','4',0} +@@ -138,6 +141,20 @@ typedef struct _BCRYPT_ECCKEY_BLOB + ULONG cbKey; + } BCRYPT_ECCKEY_BLOB, *PBCRYPT_ECCKEY_BLOB; + ++#define BCRYPT_RSAPUBLIC_MAGIC 0x31415352 ++#define BCRYPT_RSAPRIVATE_MAGIC 0x32415352 ++#define BCRYPT_RSAFULLPRIVATE_MAGIC 0x33415352 ++ ++typedef struct _BCRYPT_RSAKEY_BLOB ++{ ++ ULONG Magic; ++ ULONG BitLength; ++ ULONG cbPublicExp; ++ ULONG cbModulus; ++ ULONG cbPrime1; ++ ULONG cbPrime2; ++} BCRYPT_RSAKEY_BLOB; ++ + typedef struct _BCRYPT_PKCS1_PADDING_INFO + { + LPCWSTR pszAlgId; +-- +2.14.1 + diff --git a/patches/bcrypt-Improvements/0036-bcrypt-tests-Add-simple-test-for-RSA.patch b/patches/bcrypt-Improvements/0036-bcrypt-tests-Add-simple-test-for-RSA.patch new file mode 100644 index 00000000..11107900 --- /dev/null +++ b/patches/bcrypt-Improvements/0036-bcrypt-tests-Add-simple-test-for-RSA.patch @@ -0,0 +1,129 @@ +From 1ac61b565db2204b247603ee7ad1124ad79bf50f Mon Sep 17 00:00:00 2001 +From: Kimmo Myllyvirta +Date: Tue, 10 Oct 2017 16:41:09 +0300 +Subject: bcrypt/tests: Add simple test for RSA. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Based on patch from Bernhard Übelacker. +--- + dlls/bcrypt/tests/bcrypt.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 95 insertions(+) + +diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c +index 73bd4d69a5b..56e3440b545 100644 +--- a/dlls/bcrypt/tests/bcrypt.c ++++ b/dlls/bcrypt/tests/bcrypt.c +@@ -1697,6 +1697,100 @@ static void test_ECDSA(void) + pBCryptCloseAlgorithmProvider(alg, 0); + } + ++static UCHAR rsaPublicBlob[] = ++{ ++ 0x52, 0x53, 0x41, 0x31, 0x00, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0xad, 0x41, 0x09, 0xa2, 0x56, ++ 0x3a, 0x7b, 0x75, 0x4b, 0x72, 0x9b, 0x28, 0x72, 0x3b, 0xae, 0x9f, 0xd8, 0xa8, 0x25, 0x4a, 0x4c, ++ 0x19, 0xf5, 0xa6, 0xd0, 0x05, 0x1c, 0x59, 0x8f, 0xe3, 0xf3, 0x2d, 0x29, 0x47, 0xf8, 0x80, 0x25, ++ 0x25, 0x21, 0x58, 0xc2, 0xac, 0xa1, 0x9e, 0x93, 0x8e, 0x82, 0x6d, 0xd7, 0xf3, 0xe7, 0x8f, 0x0b, ++ 0xc0, 0x41, 0x85, 0x29, 0x3c, 0xf1, 0x0b, 0x2c, 0x5d, 0x49, 0xed, 0xb4, 0x30, 0x6e, 0x02, 0x15, ++ 0x4b, 0x9a, 0x08, 0x0d, 0xe1, 0x6f, 0xa8, 0xd3, 0x12, 0xab, 0x66, 0x48, 0x4d, 0xd9, 0x28, 0x03, ++ 0x6c, 0x9d, 0x44, 0x7a, 0xed, 0xc9, 0x43, 0x4f, 0x9d, 0x4e, 0x3c, 0x7d, 0x0e, 0xff, 0x07, 0x87, ++ 0xeb, 0xca, 0xca, 0x65, 0x6d, 0xbe, 0xc5, 0x31, 0x8b, 0xcc, 0x7e, 0x0a, 0x71, 0x4a, 0x4d, 0x9d, ++ 0x3d, 0xfd, 0x7a, 0x56, 0x32, 0x8a, 0x6c, 0x6d, 0x9d, 0x2a, 0xd9, 0x8e, 0x68, 0x89, 0x63, 0xc6, ++ 0x4f, 0x24, 0xd1, 0x2a, 0x72, 0x69, 0x08, 0x77, 0xa0, 0x7f, 0xfe, 0xc6, 0x33, 0x8d, 0xb4, 0x7d, ++ 0x73, 0x91, 0x13, 0x9c, 0x47, 0x53, 0x6a, 0x13, 0xdf, 0x19, 0xc7, 0xed, 0x48, 0x81, 0xed, 0xd8, ++ 0x1f, 0x11, 0x11, 0xbb, 0x41, 0x15, 0x5b, 0xa4, 0xf5, 0xc9, 0x2b, 0x48, 0x5e, 0xd8, 0x4b, 0x52, ++ 0x1f, 0xf7, 0x87, 0xf2, 0x68, 0x25, 0x28, 0x79, 0xee, 0x39, 0x41, 0xc9, 0x0e, 0xc8, 0xf9, 0xf2, ++ 0xd8, 0x24, 0x09, 0xb4, 0xd4, 0xb7, 0x90, 0xba, 0x26, 0xe8, 0x1d, 0xb4, 0xd7, 0x09, 0x00, 0xc4, ++ 0xa0, 0xb6, 0x14, 0xe8, 0x4c, 0x29, 0x60, 0x54, 0x2e, 0x01, 0xde, 0x54, 0x66, 0x40, 0x22, 0x50, ++ 0x27, 0xf1, 0xe7, 0x62, 0xa9, 0x00, 0x5a, 0x61, 0x2e, 0xfa, 0xfe, 0x16, 0xd8, 0xe0, 0xe7, 0x66, ++ 0x17, 0xda, 0xb8, 0x0c, 0xa6, 0x04, 0x8d, 0xf8, 0x21, 0x68, 0x39 ++}; ++ ++static UCHAR rsaHash[] = ++{ ++ 0x96, 0x1f, 0xa6, 0x49, 0x58, 0x81, 0x8f, 0x76, 0x77, 0x07, 0x07, 0x27, 0x55, 0xd7, 0x01, 0x8d, ++ 0xcd, 0x27, 0x8e, 0x94 ++}; ++ ++static UCHAR rsaSignature[] = ++{ ++ 0xa8, 0x3a, 0x9d, 0xaf, 0x92, 0x94, 0xa4, 0x4d, 0x34, 0xba, 0x41, 0x0c, 0xc1, 0x23, 0x91, 0xc7, ++ 0x91, 0xa8, 0xf8, 0xfc, 0x94, 0x87, 0x4d, 0x05, 0x85, 0x63, 0xe8, 0x7d, 0xea, 0x7f, 0x6b, 0x8d, ++ 0xbb, 0x9a, 0xd4, 0x46, 0xa6, 0xc0, 0xd6, 0xdc, 0x91, 0xba, 0xd3, 0x1a, 0xbf, 0xf4, 0x52, 0xa0, ++ 0xc7, 0x15, 0x87, 0xe9, 0x1e, 0x60, 0x49, 0x9c, 0xee, 0x5a, 0x9c, 0x6c, 0xbd, 0x7a, 0x3e, 0xc3, ++ 0x48, 0xb3, 0xee, 0xca, 0x68, 0x40, 0x9b, 0xa1, 0x4c, 0x6e, 0x20, 0xd6, 0xca, 0x6c, 0x72, 0xaf, ++ 0x2b, 0x6b, 0x62, 0x7c, 0x78, 0x06, 0x94, 0x4c, 0x02, 0xf3, 0x8d, 0x49, 0xe0, 0x11, 0xc4, 0x9b, ++ 0x62, 0x5b, 0xc2, 0xfd, 0x68, 0xf4, 0x07, 0x15, 0x71, 0x11, 0x4c, 0x35, 0x97, 0x5d, 0xc0, 0xe6, ++ 0x22, 0xc9, 0x8a, 0x7b, 0x96, 0xc9, 0xc3, 0xe4, 0x2b, 0x1e, 0x88, 0x17, 0x4f, 0x98, 0x9b, 0xf3, ++ 0x42, 0x23, 0x0c, 0xa0, 0xfa, 0x19, 0x03, 0x2a, 0xf7, 0x13, 0x2d, 0x27, 0xac, 0x9f, 0xaf, 0x2d, ++ 0xa3, 0xce, 0xf7, 0x63, 0xbb, 0x39, 0x9f, 0x72, 0x80, 0xdd, 0x6c, 0x73, 0x00, 0x85, 0x70, 0xf2, ++ 0xed, 0x50, 0xed, 0xa0, 0x74, 0x42, 0xd7, 0x22, 0x46, 0x24, 0xee, 0x67, 0xdf, 0xb5, 0x45, 0xe8, ++ 0x49, 0xf4, 0x9c, 0xe4, 0x00, 0x83, 0xf2, 0x27, 0x8e, 0xa2, 0xb1, 0xc3, 0xc2, 0x01, 0xd7, 0x59, ++ 0x2e, 0x4d, 0xac, 0x49, 0xa2, 0xc1, 0x8d, 0x88, 0x4b, 0xfe, 0x28, 0xe5, 0xac, 0xa6, 0x85, 0xc4, ++ 0x1f, 0xf8, 0xc5, 0xc5, 0x14, 0x4e, 0xa3, 0xcb, 0x17, 0xb7, 0x64, 0xb3, 0xc2, 0x12, 0xf8, 0xf8, ++ 0x36, 0x99, 0x1c, 0x91, 0x9b, 0xbd, 0xed, 0x55, 0x0f, 0xfd, 0x49, 0x85, 0xbb, 0x32, 0xad, 0x78, ++ 0xc1, 0x74, 0xe6, 0x7c, 0x18, 0x0f, 0x2b, 0x3b, 0xaa, 0xd1, 0x9d, 0x40, 0x71, 0x1d, 0x19, 0x53 ++}; ++ ++static void test_RSA(void) ++{ ++ BCRYPT_PKCS1_PADDING_INFO pad; ++ BCRYPT_ALG_HANDLE alg = NULL; ++ BCRYPT_KEY_HANDLE key = NULL; ++ NTSTATUS ret; ++ ++ ret = pBCryptOpenAlgorithmProvider(&alg, BCRYPT_RSA_ALGORITHM, NULL, 0); ++ if (ret) ++ { ++ win_skip("Failed to open RSA provider: %08x, skipping test\n", ret); ++ return; ++ } ++ ++ ret = pBCryptImportKeyPair(alg, NULL, BCRYPT_RSAPUBLIC_BLOB, &key, rsaPublicBlob, sizeof(rsaPublicBlob), 0); ++ ok(!ret, "pBCryptImportKeyPair failed: %08x\n", ret); ++ ++ pad.pszAlgId = BCRYPT_SHA1_ALGORITHM; ++ ret = pBCryptVerifySignature(key, &pad, rsaHash, sizeof(rsaHash), rsaSignature, sizeof(rsaSignature), BCRYPT_PAD_PKCS1); ++ ok(!ret, "pBCryptVerifySignature failed: %08x\n", ret); ++ ++ ret = pBCryptVerifySignature(key, NULL, rsaHash, sizeof(rsaHash), rsaSignature, sizeof(rsaSignature), BCRYPT_PAD_PKCS1); ++ ok(ret == STATUS_INVALID_PARAMETER, "Expected STATUS_INVALID_PARAMETER, got %08x\n", ret); ++ ++ pad.pszAlgId = BCRYPT_SHA1_ALGORITHM; ++ ret = pBCryptVerifySignature(key, &pad, rsaHash, sizeof(rsaHash), rsaSignature, sizeof(rsaSignature), 0); ++ ok(ret == STATUS_INVALID_PARAMETER, "Expected STATUS_INVALID_PARAMETER, got %08x\n", ret); ++ ++ ret = pBCryptVerifySignature(key, NULL, rsaHash, sizeof(rsaHash), rsaSignature, sizeof(rsaSignature), 0); ++ ok(ret == STATUS_INVALID_PARAMETER, "Expected STATUS_INVALID_PARAMETER, got %08x\n", ret); ++ ++ pad.pszAlgId = BCRYPT_AES_ALGORITHM; ++ ret = pBCryptVerifySignature(key, &pad, rsaHash, sizeof(rsaHash), rsaSignature, sizeof(rsaSignature), BCRYPT_PAD_PKCS1); ++ ok(ret == STATUS_NOT_SUPPORTED, "Expected STATUS_NOT_SUPPORTED, got %08x\n", ret); ++ ++ pad.pszAlgId = NULL; ++ ret = pBCryptVerifySignature(key, &pad, rsaHash, sizeof(rsaHash), rsaSignature, sizeof(rsaSignature), BCRYPT_PAD_PKCS1); ++ ok(ret == STATUS_INVALID_SIGNATURE, "Expected STATUS_INVALID_SIGNATURE, got %08x\n", ret); ++ ++ ret = pBCryptDestroyKey(key); ++ ok(!ret, "pBCryptDestroyKey failed: %08x\n", ret); ++ ++ ret = pBCryptCloseAlgorithmProvider(alg, 0); ++ ok(!ret, "pBCryptCloseAlgorithmProvider failed: %08x\n", ret); ++} ++ + START_TEST(bcrypt) + { + HMODULE module; +@@ -1744,6 +1838,7 @@ START_TEST(bcrypt) + test_BCryptDecrypt(); + test_key_import_export(); + test_ECDSA(); ++ test_RSA(); + + if (pBCryptHash) /* >= Win 10 */ + test_BcryptHash(); +-- +2.14.1 + diff --git a/patches/bcrypt-Improvements/0037-bcrypt-Store-full-ECCKEY_BLOB-struct-in-BCryptImport.patch b/patches/bcrypt-Improvements/0037-bcrypt-Store-full-ECCKEY_BLOB-struct-in-BCryptImport.patch new file mode 100644 index 00000000..bdeae79b --- /dev/null +++ b/patches/bcrypt-Improvements/0037-bcrypt-Store-full-ECCKEY_BLOB-struct-in-BCryptImport.patch @@ -0,0 +1,49 @@ +From 3714e6bcd413355a60a691d38f487f321be93b2a Mon Sep 17 00:00:00 2001 +From: Sebastian Lackner +Date: Sat, 14 Oct 2017 22:44:13 +0200 +Subject: bcrypt: Store full ECCKEY_BLOB struct in BCryptImportKeyPair. + +--- + dlls/bcrypt/bcrypt_main.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c +index 3356364a6dc..2aecfb9a227 100644 +--- a/dlls/bcrypt/bcrypt_main.c ++++ b/dlls/bcrypt/bcrypt_main.c +@@ -1308,6 +1308,7 @@ static void buffer_append_asn1_r_s( struct buffer *buffer, BYTE *r, DWORD r_len, + + static NTSTATUS import_gnutls_pubkey_ecc( struct key *key, gnutls_pubkey_t *gnutls_key ) + { ++ BCRYPT_ECCKEY_BLOB *ecc_blob; + gnutls_ecc_curve_t curve; + gnutls_datum_t x, y; + int ret; +@@ -1328,10 +1329,11 @@ static NTSTATUS import_gnutls_pubkey_ecc( struct key *key, gnutls_pubkey_t *gnut + return STATUS_INTERNAL_ERROR; + } + +- x.data = key->u.a.pubkey; +- x.size = key->u.a.pubkey_len / 2; +- y.data = key->u.a.pubkey + x.size; +- y.size = x.size; ++ ecc_blob = (BCRYPT_ECCKEY_BLOB *)key->u.a.pubkey; ++ x.data = key->u.a.pubkey + sizeof(*ecc_blob); ++ x.size = ecc_blob->cbKey; ++ y.data = key->u.a.pubkey + sizeof(*ecc_blob) + ecc_blob->cbKey; ++ y.size = ecc_blob->cbKey; + + if ((ret = pgnutls_pubkey_import_ecc_raw( *gnutls_key, curve, &x, &y ))) + { +@@ -1846,7 +1848,7 @@ NTSTATUS WINAPI BCryptImportKeyPair( BCRYPT_ALG_HANDLE algorithm, BCRYPT_KEY_HAN + return STATUS_NO_MEMORY; + + key->hdr.magic = MAGIC_KEY; +- if ((status = key_asymmetric_init( key, alg, (BYTE *)(ecc_blob + 1), ecc_blob->cbKey * 2 ))) ++ if ((status = key_asymmetric_init( key, alg, (BYTE *)ecc_blob, sizeof(*ecc_blob) + ecc_blob->cbKey * 2 ))) + { + HeapFree( GetProcessHeap(), 0, key ); + return status; +-- +2.14.1 + diff --git a/patches/bcrypt-Improvements/definition b/patches/bcrypt-Improvements/definition index 2fbda0ff..7e310c30 100644 --- a/patches/bcrypt-Improvements/definition +++ b/patches/bcrypt-Improvements/definition @@ -1,3 +1,4 @@ Fixes: [40418] Implement BCrypt AES provider Fixes: [42553] Implement BCrypt ECB chaining mode +Fixes: [39582] Implement BCrypt RSA provider Fixes: Implement BCryptImportKey and BCryptExportKey diff --git a/patches/patchinstall.sh b/patches/patchinstall.sh index 024ce1f9..803d0007 100755 --- a/patches/patchinstall.sh +++ b/patches/patchinstall.sh @@ -3575,6 +3575,7 @@ fi # | This patchset fixes the following Wine bugs: # | * [#40418] Implement BCrypt AES provider # | * [#42553] Implement BCrypt ECB chaining mode +# | * [#39582] Implement BCrypt RSA provider # | # | Modified files: # | * dlls/bcrypt/bcrypt.spec, dlls/bcrypt/bcrypt_main.c, dlls/bcrypt/tests/bcrypt.c, dlls/ncrypt/ncrypt.spec, @@ -3602,6 +3603,14 @@ if test "$enable_bcrypt_Improvements" -eq 1; then patch_apply bcrypt-Improvements/0027-bcrypt-Fix-BCryptEncrypt-with-AES_GCM-and-no-input-a.patch patch_apply bcrypt-Improvements/0028-bcrypt-Partial-implementation-of-BCryptImportKey-and.patch patch_apply bcrypt-Improvements/0029-bcrypt-Add-support-for-192-and-256-bit-aes-keys.patch + patch_apply bcrypt-Improvements/0030-bcrypt-Preparation-for-asymmetric-keys.patch + patch_apply bcrypt-Improvements/0031-include-Add-ecdsa-and-asymmetric-key-related-bcrypt-.patch + patch_apply bcrypt-Improvements/0032-bcrypt-tests-Add-basic-test-for-ecdsa.patch + patch_apply bcrypt-Improvements/0033-bcrypt-Implement-importing-of-ecdsa-keys.patch + patch_apply bcrypt-Improvements/0034-bcrypt-Implement-BCryptVerifySignature-for-ecdsa-sig.patch + patch_apply bcrypt-Improvements/0035-bcrypt-Initial-implementation-for-RSA-key-import-and.patch + patch_apply bcrypt-Improvements/0036-bcrypt-tests-Add-simple-test-for-RSA.patch + patch_apply bcrypt-Improvements/0037-bcrypt-Store-full-ECCKEY_BLOB-struct-in-BCryptImport.patch ( printf '%s\n' '+ { "Hans Leidekker", "include: Add missing BCRYPT_CHAIN_MODE definitions.", 1 },'; printf '%s\n' '+ { "Sebastian Lackner", "bcrypt/tests: Add test for bugs in BCryptGetProperty.", 1 },'; @@ -3624,6 +3633,14 @@ if test "$enable_bcrypt_Improvements" -eq 1; then printf '%s\n' '+ { "Andrew Wesie", "bcrypt: Fix BCryptEncrypt with AES_GCM and no input and no output.", 1 },'; printf '%s\n' '+ { "Michael Müller", "bcrypt: Partial implementation of BCryptImportKey and BCryptExportKey.", 1 },'; printf '%s\n' '+ { "Michael Müller", "bcrypt: Add support for 192 and 256 bit aes keys.", 1 },'; + printf '%s\n' '+ { "Michael Müller", "bcrypt: Preparation for asymmetric keys.", 1 },'; + printf '%s\n' '+ { "Michael Müller", "include: Add ecdsa and asymmetric key related bcrypt definitions.", 1 },'; + printf '%s\n' '+ { "Michael Müller", "bcrypt/tests: Add basic test for ecdsa.", 1 },'; + printf '%s\n' '+ { "Michael Müller", "bcrypt: Implement importing of ecdsa keys.", 1 },'; + printf '%s\n' '+ { "Michael Müller", "bcrypt: Implement BCryptVerifySignature for ecdsa signatures.", 1 },'; + printf '%s\n' '+ { "Kimmo Myllyvirta", "bcrypt: Initial implementation for RSA key import and signature verification.", 1 },'; + printf '%s\n' '+ { "Kimmo Myllyvirta", "bcrypt/tests: Add simple test for RSA.", 1 },'; + printf '%s\n' '+ { "Sebastian Lackner", "bcrypt: Store full ECCKEY_BLOB struct in BCryptImportKeyPair.", 1 },'; ) >> "$patchlist" fi @@ -3780,17 +3797,11 @@ fi # | * [#35902] Implement support for validating ECDSA certificate chains # | # | Modified files: -# | * dlls/bcrypt/bcrypt.spec, dlls/bcrypt/bcrypt_main.c, dlls/bcrypt/tests/bcrypt.c, dlls/crypt32/Makefile.in, -# | dlls/crypt32/cert.c, dlls/crypt32/chain.c, dlls/crypt32/crypt32_private.h, dlls/crypt32/decode.c, dlls/crypt32/oid.c, -# | dlls/crypt32/tests/chain.c, dlls/crypt32/tests/encode.c, dlls/crypt32/tests/oid.c, include/bcrypt.h, include/ntstatus.h, -# | include/wincrypt.h +# | * dlls/crypt32/Makefile.in, dlls/crypt32/cert.c, dlls/crypt32/chain.c, dlls/crypt32/crypt32_private.h, +# | dlls/crypt32/decode.c, dlls/crypt32/oid.c, dlls/crypt32/tests/chain.c, dlls/crypt32/tests/encode.c, +# | dlls/crypt32/tests/oid.c, include/wincrypt.h # | if test "$enable_crypt32_ECDSA_Cert_Chains" -eq 1; then - patch_apply crypt32-ECDSA_Cert_Chains/0001-bcrypt-Preparation-for-asymmetric-keys.patch - patch_apply crypt32-ECDSA_Cert_Chains/0002-include-Add-ecdsa-and-asymmetric-key-related-bcrypt-.patch - patch_apply crypt32-ECDSA_Cert_Chains/0003-bcrypt-tests-Add-basic-test-for-ecdsa.patch - patch_apply crypt32-ECDSA_Cert_Chains/0004-bcrypt-Implement-importing-of-ecdsa-keys.patch - patch_apply crypt32-ECDSA_Cert_Chains/0005-bcrypt-Implement-BCryptVerifySignature-for-ecdsa-sig.patch patch_apply crypt32-ECDSA_Cert_Chains/0006-crypt32-tests-Basic-tests-for-decoding-ECDSA-signed-.patch patch_apply crypt32-ECDSA_Cert_Chains/0007-crypt32-Implement-decoding-of-X509_OBJECT_IDENTIFIER.patch patch_apply crypt32-ECDSA_Cert_Chains/0008-crypt32-Implement-decoding-of-X509_ECC_SIGNATURE.patch @@ -3800,11 +3811,6 @@ if test "$enable_crypt32_ECDSA_Cert_Chains" -eq 1; then patch_apply crypt32-ECDSA_Cert_Chains/0012-crypt32-tets-Add-test-for-verifying-an-ecdsa-chain.patch patch_apply crypt32-ECDSA_Cert_Chains/0013-crypt32-Implement-verification-of-ECDSA-signatures.patch ( - printf '%s\n' '+ { "Michael Müller", "bcrypt: Preparation for asymmetric keys.", 1 },'; - printf '%s\n' '+ { "Michael Müller", "include: Add ecdsa and asymmetric key related bcrypt definitions.", 1 },'; - printf '%s\n' '+ { "Michael Müller", "bcrypt/tests: Add basic test for ecdsa.", 1 },'; - printf '%s\n' '+ { "Michael Müller", "bcrypt: Implement importing of ecdsa keys.", 1 },'; - printf '%s\n' '+ { "Michael Müller", "bcrypt: Implement BCryptVerifySignature for ecdsa signatures.", 1 },'; printf '%s\n' '+ { "Michael Müller", "crypt32/tests: Basic tests for decoding ECDSA signed certificate.", 1 },'; printf '%s\n' '+ { "Michael Müller", "crypt32: Implement decoding of X509_OBJECT_IDENTIFIER.", 1 },'; printf '%s\n' '+ { "Michael Müller", "crypt32: Implement decoding of X509_ECC_SIGNATURE.", 1 },';