[PATCH 5/5] dssenh: Implement CPGenKey.

Hans Leidekker hans at codeweavers.com
Wed Oct 14 04:03:57 CDT 2020


Signed-off-by: Hans Leidekker <hans at codeweavers.com>
---
 dlls/dssenh/main.c         | 143 ++++++++++++++++++++++++++++---------
 dlls/dssenh/tests/dssenh.c | 109 ++++++++++++++--------------
 2 files changed, 164 insertions(+), 88 deletions(-)

diff --git a/dlls/dssenh/main.c b/dlls/dssenh/main.c
index 752189d15bb..5ad0ef1505d 100644
--- a/dlls/dssenh/main.c
+++ b/dlls/dssenh/main.c
@@ -19,6 +19,8 @@
 
 #include <stdarg.h>
 
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
 #include "windef.h"
 #include "winbase.h"
 #include "wincrypt.h"
@@ -309,27 +311,6 @@ BOOL WINAPI CPGetProvParam( HCRYPTPROV hprov, DWORD param, BYTE *data, DWORD *le
     return FALSE;
 }
 
-BOOL WINAPI CPGenKey( HCRYPTPROV hprov, ALG_ID algid, DWORD flags, HCRYPTKEY *ret_key )
-{
-    return FALSE;
-}
-
-BOOL WINAPI CPDestroyKey( HCRYPTPROV hprov, HCRYPTKEY hkey )
-{
-    struct key *key = (struct key *)hkey;
-
-    TRACE( "%p, %p\n", (void *)hprov, (void *)hkey );
-
-    if (key->magic != MAGIC_KEY)
-    {
-        SetLastError( NTE_BAD_KEY );
-        return FALSE;
-    }
-
-    destroy_key( key );
-    return TRUE;
-}
-
 static BOOL store_key_pair( struct key *key, HKEY hkey, DWORD keyspec, DWORD flags )
 {
     const WCHAR *value;
@@ -378,6 +359,112 @@ static BOOL store_key_container_keys( struct container *container )
     return ret;
 }
 
+static struct key *duplicate_key( const struct key *key )
+{
+    struct key *ret;
+
+    if (!(ret = create_key( key->algid, key->flags ))) return NULL;
+
+    if (BCryptDuplicateKey( key->handle, &ret->handle, NULL, 0, 0 ))
+    {
+        heap_free( ret );
+        return NULL;
+    }
+    return ret;
+}
+
+static BOOL generate_key( struct container *container, ALG_ID algid, DWORD bitlen, DWORD flags, HCRYPTKEY *ret_key )
+{
+    struct key *key, *sign_key;
+    NTSTATUS status;
+
+    if (!(key = create_key( algid, flags ))) return FALSE;
+
+    if ((status = BCryptGenerateKeyPair( key->alg_handle, &key->handle, bitlen, 0 )))
+    {
+        ERR( "failed to generate key %08x\n", status );
+        destroy_key( key );
+        return FALSE;
+    }
+    if ((status = BCryptFinalizeKeyPair( key->handle, 0 )))
+    {
+        ERR( "failed to finalize key %08x\n", status );
+        destroy_key( key );
+        return FALSE;
+    }
+
+    switch (algid)
+    {
+    case AT_SIGNATURE:
+    case CALG_DSS_SIGN:
+        if (!(sign_key = duplicate_key( key )))
+        {
+            destroy_key( key );
+            return FALSE;
+        }
+        destroy_key( container->sign_key );
+        container->sign_key = sign_key;
+        break;
+
+    default:
+        FIXME( "unhandled algorithm %08x\n", algid );
+        return FALSE;
+    }
+
+    if (!store_key_container_keys( container ))
+    {
+        destroy_key( key );
+        return FALSE;
+    }
+
+    *ret_key = (HCRYPTKEY)key;
+    return TRUE;
+}
+
+BOOL WINAPI CPGenKey( HCRYPTPROV hprov, ALG_ID algid, DWORD flags, HCRYPTKEY *ret_key )
+{
+    static const unsigned int supported_key_lengths[] = { 512, 768, 1024 };
+    struct container *container = (struct container *)hprov;
+    ULONG i, bitlen = HIWORD(flags) ? HIWORD(flags) : 1024;
+
+    TRACE( "%p, %08x, %08x, %p\n", (void *)hprov, algid, flags, ret_key );
+
+    if (container->magic != MAGIC_CONTAINER) return FALSE;
+
+    if (bitlen % 2)
+    {
+        SetLastError( STATUS_INVALID_PARAMETER );
+        return FALSE;
+    }
+    for (i = 0; i < ARRAY_SIZE(supported_key_lengths); i++)
+    {
+        if (bitlen == supported_key_lengths[i]) break;
+    }
+    if (i >= ARRAY_SIZE(supported_key_lengths))
+    {
+        SetLastError( NTE_BAD_FLAGS );
+        return FALSE;
+    }
+
+    return generate_key( container, algid, bitlen, LOWORD(flags), ret_key );
+}
+
+BOOL WINAPI CPDestroyKey( HCRYPTPROV hprov, HCRYPTKEY hkey )
+{
+    struct key *key = (struct key *)hkey;
+
+    TRACE( "%p, %p\n", (void *)hprov, (void *)hkey );
+
+    if (key->magic != MAGIC_KEY)
+    {
+        SetLastError( NTE_BAD_KEY );
+        return FALSE;
+    }
+
+    destroy_key( key );
+    return TRUE;
+}
+
 #define MAGIC_DSS1 ('D' | ('S' << 8) | ('S' << 16) | ('1' << 24))
 #define MAGIC_DSS2 ('D' | ('S' << 8) | ('S' << 16) | ('2' << 24))
 
@@ -493,20 +580,6 @@ BOOL WINAPI CPExportKey( HCRYPTPROV hprov, HCRYPTKEY hkey, HCRYPTKEY hexpkey, DW
     return !BCryptExportKey( key->handle, NULL, LEGACY_DSA_V2_PUBLIC_BLOB, data, *len, len, 0 );
 }
 
-static struct key *duplicate_key( const struct key *key )
-{
-    struct key *ret;
-
-    if (!(ret = create_key( key->algid, key->flags ))) return NULL;
-
-    if (BCryptDuplicateKey( key->handle, &ret->handle, NULL, 0, 0 ))
-    {
-        heap_free( ret );
-        return NULL;
-    }
-    return ret;
-}
-
 BOOL WINAPI CPDuplicateKey( HCRYPTPROV hprov, HCRYPTKEY hkey, DWORD *reserved, DWORD flags, HCRYPTKEY *ret_key )
 {
     struct key *key = (struct key *)hkey, *ret;
diff --git a/dlls/dssenh/tests/dssenh.c b/dlls/dssenh/tests/dssenh.c
index c2ab37d288b..4f401254f52 100644
--- a/dlls/dssenh/tests/dssenh.c
+++ b/dlls/dssenh/tests/dssenh.c
@@ -184,14 +184,16 @@ struct keylength_test {
     BOOL expectedResult;
     DWORD expectedError;
     DWORD brokenError;
+    int todo_result;
+    int todo_error;
 };
 
 static const struct keylength_test baseDSS_keylength[] = {
     /* AT_KEYEXCHANGE is not supported by the base DSS provider */
-    {AT_KEYEXCHANGE, 448 << 16, FALSE, NTE_BAD_ALGID},
-    {AT_KEYEXCHANGE, 512 << 16, FALSE, NTE_BAD_ALGID},
-    {AT_KEYEXCHANGE, 1024 << 16, FALSE, NTE_BAD_ALGID},
-    {AT_KEYEXCHANGE, 1088 << 16, FALSE, NTE_BAD_ALGID},
+    {AT_KEYEXCHANGE, 448 << 16, FALSE, NTE_BAD_ALGID, 0, 0, 1},
+    {AT_KEYEXCHANGE, 512 << 16, FALSE, NTE_BAD_ALGID, 0, 0, 1},
+    {AT_KEYEXCHANGE, 1024 << 16, FALSE, NTE_BAD_ALGID, 0, 0, 1},
+    {AT_KEYEXCHANGE, 1088 << 16, FALSE, NTE_BAD_ALGID, 0, 0, 1},
     /* min 512 max 1024 increment by 64 */
     {AT_SIGNATURE, 448 << 16, FALSE, NTE_BAD_FLAGS},
     {AT_SIGNATURE, 512 << 16, TRUE},
@@ -200,15 +202,15 @@ static const struct keylength_test baseDSS_keylength[] = {
     {AT_SIGNATURE, 1024 << 16, TRUE},
     {AT_SIGNATURE, 1088 << 16, FALSE, NTE_BAD_FLAGS},
     /* CALG_DH_EPHEM is not supported by the base DSS provider */
-    {CALG_DH_EPHEM, 448 << 16, FALSE, NTE_BAD_ALGID},
-    {CALG_DH_EPHEM, 512 << 16, FALSE, NTE_BAD_ALGID},
-    {CALG_DH_EPHEM, 1024 << 16, FALSE, NTE_BAD_ALGID},
-    {CALG_DH_EPHEM, 1088 << 16, FALSE, NTE_BAD_ALGID},
+    {CALG_DH_EPHEM, 448 << 16, FALSE, NTE_BAD_ALGID, 0, 0, 1},
+    {CALG_DH_EPHEM, 512 << 16, FALSE, NTE_BAD_ALGID, 0, 0, 1},
+    {CALG_DH_EPHEM, 1024 << 16, FALSE, NTE_BAD_ALGID, 0, 0, 1},
+    {CALG_DH_EPHEM, 1088 << 16, FALSE, NTE_BAD_ALGID, 0, 0, 1},
     /* CALG_DH_SF is not supported by the base DSS provider */
-    {CALG_DH_SF, 448 << 16, FALSE, NTE_BAD_ALGID},
-    {CALG_DH_SF, 512 << 16, FALSE, NTE_BAD_ALGID},
-    {CALG_DH_SF, 1024 << 16, FALSE, NTE_BAD_ALGID},
-    {CALG_DH_SF, 1088 << 16, FALSE, NTE_BAD_ALGID},
+    {CALG_DH_SF, 448 << 16, FALSE, NTE_BAD_ALGID, 0, 0, 1},
+    {CALG_DH_SF, 512 << 16, FALSE, NTE_BAD_ALGID, 0, 0, 1},
+    {CALG_DH_SF, 1024 << 16, FALSE, NTE_BAD_ALGID, 0, 0, 1},
+    {CALG_DH_SF, 1088 << 16, FALSE, NTE_BAD_ALGID, 0, 0, 1},
     /* min 512 max 1024, increment by 64 */
     {CALG_DSS_SIGN, 448 << 16, FALSE, NTE_BAD_FLAGS},
     {CALG_DSS_SIGN, 512 << 16, TRUE},
@@ -221,10 +223,10 @@ static const struct keylength_test baseDSS_keylength[] = {
 static const struct keylength_test dssDH_keylength[] = {
     /* min 512 max 1024, increment by 64 */
     {AT_KEYEXCHANGE, 448 << 16, FALSE, NTE_BAD_FLAGS},
-    {AT_KEYEXCHANGE, 512 << 16, TRUE},
-    {AT_KEYEXCHANGE, 513 << 16, FALSE, NTE_BAD_FLAGS},
-    {AT_KEYEXCHANGE, 768 << 16, TRUE},
-    {AT_KEYEXCHANGE, 1024 << 16, TRUE},
+    {AT_KEYEXCHANGE, 512 << 16, TRUE, 0, 0, 1},
+    {AT_KEYEXCHANGE, 513 << 16, FALSE, NTE_BAD_FLAGS, 0, 0, 1},
+    {AT_KEYEXCHANGE, 768 << 16, TRUE, 0, 0, 1},
+    {AT_KEYEXCHANGE, 1024 << 16, TRUE, 0, 0, 1},
     {AT_KEYEXCHANGE, 1088 << 16, FALSE, NTE_BAD_FLAGS},
     {AT_SIGNATURE, 448 << 16, FALSE, NTE_BAD_FLAGS},
     {AT_SIGNATURE, 512 << 16, TRUE},
@@ -233,16 +235,16 @@ static const struct keylength_test dssDH_keylength[] = {
     {AT_SIGNATURE, 1024 << 16, TRUE},
     {AT_SIGNATURE, 1088 << 16, FALSE, NTE_BAD_FLAGS},
     {CALG_DH_EPHEM, 448 << 16, FALSE, NTE_BAD_FLAGS},
-    {CALG_DH_EPHEM, 512 << 16, TRUE},
-    {CALG_DH_EPHEM, 513 << 16, FALSE, NTE_BAD_FLAGS},
-    {CALG_DH_EPHEM, 768 << 16, TRUE},
-    {CALG_DH_EPHEM, 1024 << 16, TRUE},
+    {CALG_DH_EPHEM, 512 << 16, TRUE, 0, 0, 1},
+    {CALG_DH_EPHEM, 513 << 16, FALSE, NTE_BAD_FLAGS, 0, 0, 1},
+    {CALG_DH_EPHEM, 768 << 16, TRUE, 0, 0, 1},
+    {CALG_DH_EPHEM, 1024 << 16, TRUE, 0, 0, 1},
     {CALG_DH_EPHEM, 1088 << 16, FALSE, NTE_BAD_FLAGS},
     {CALG_DH_SF, 448 << 16, FALSE, NTE_BAD_FLAGS},
-    {CALG_DH_SF, 512 << 16, TRUE},
-    {CALG_DH_SF, 513 << 16, FALSE, NTE_BAD_FLAGS},
-    {CALG_DH_SF, 768 << 16, TRUE},
-    {CALG_DH_SF, 1024 << 16, TRUE},
+    {CALG_DH_SF, 512 << 16, TRUE, 0, 0, 1},
+    {CALG_DH_SF, 513 << 16, FALSE, NTE_BAD_FLAGS, 0, 0, 1},
+    {CALG_DH_SF, 768 << 16, TRUE, 0, 0, 1},
+    {CALG_DH_SF, 1024 << 16, TRUE, 0, 0, 1},
     {CALG_DH_SF, 1088 << 16, FALSE, NTE_BAD_FLAGS},
     {CALG_DSS_SIGN, 448 << 16, FALSE, NTE_BAD_FLAGS},
     {CALG_DSS_SIGN, 512 << 16, TRUE},
@@ -255,12 +257,12 @@ static const struct keylength_test dssDH_keylength[] = {
 static const struct keylength_test dssENH_keylength[] = {
     /* min 512 max 1024 (AT_KEYEXCHANGE, CALG_DH_EPHEM, CALG_DH_SF max 4096), increment by 64*/
     {AT_KEYEXCHANGE, 448 << 16, FALSE, NTE_BAD_FLAGS},
-    {AT_KEYEXCHANGE, 512 << 16, TRUE},
-    {AT_KEYEXCHANGE, 513 << 16, FALSE, NTE_BAD_FLAGS},
-    {AT_KEYEXCHANGE, 768 << 16, TRUE},
-    {AT_KEYEXCHANGE, 1024 << 16, TRUE},
-    {AT_KEYEXCHANGE, 1088 << 16, TRUE},
-    {AT_KEYEXCHANGE, 2048 << 16, TRUE},
+    {AT_KEYEXCHANGE, 512 << 16, TRUE, 0, 0, 1},
+    {AT_KEYEXCHANGE, 513 << 16, FALSE, NTE_BAD_FLAGS, 0, 0, 1},
+    {AT_KEYEXCHANGE, 768 << 16, TRUE, 0, 0, 1},
+    {AT_KEYEXCHANGE, 1024 << 16, TRUE, 0, 0, 1},
+    {AT_KEYEXCHANGE, 1088 << 16, TRUE, 0, 0, 1},
+    {AT_KEYEXCHANGE, 2048 << 16, TRUE, 0, 0, 1},
     /* Keylength too large - test bot timeout.
     {AT_KEYEXCHANGE, 3072 << 16, TRUE},
     {AT_KEYEXCHANGE, 4096 << 16, TRUE}, */
@@ -272,20 +274,20 @@ static const struct keylength_test dssENH_keylength[] = {
     {AT_SIGNATURE, 1024 << 16, TRUE},
     {AT_SIGNATURE, 1032 << 16, FALSE, NTE_BAD_FLAGS},
     {CALG_DH_EPHEM, 448 << 16, FALSE, NTE_BAD_FLAGS},
-    {CALG_DH_EPHEM, 512 << 16, TRUE},
-    {CALG_DH_EPHEM, 513 << 16, FALSE, NTE_BAD_FLAGS},
-    {CALG_DH_EPHEM, 768 << 16, TRUE},
-    {CALG_DH_EPHEM, 1024 << 16, TRUE},
+    {CALG_DH_EPHEM, 512 << 16, TRUE, 0, 0, 1},
+    {CALG_DH_EPHEM, 513 << 16, FALSE, NTE_BAD_FLAGS, 0, 0, 1},
+    {CALG_DH_EPHEM, 768 << 16, TRUE, 0, 0, 1},
+    {CALG_DH_EPHEM, 1024 << 16, TRUE, 0, 0, 1},
     {CALG_DH_EPHEM, 1040 << 16, FALSE, NTE_BAD_FLAGS},
-    {CALG_DH_EPHEM, 1088 << 16, TRUE},
+    {CALG_DH_EPHEM, 1088 << 16, TRUE, 0, 0, 1},
     {CALG_DH_EPHEM, 4160 << 16, FALSE, NTE_BAD_FLAGS},
     {CALG_DH_SF, 448 << 16, FALSE, NTE_BAD_FLAGS},
-    {CALG_DH_SF, 512 << 16, TRUE},
-    {CALG_DH_SF, 513 << 16, FALSE, NTE_BAD_FLAGS},
-    {CALG_DH_SF, 768 << 16, TRUE},
-    {CALG_DH_SF, 1024 << 16, TRUE},
+    {CALG_DH_SF, 512 << 16, TRUE, 0, 0, 1},
+    {CALG_DH_SF, 513 << 16, FALSE, NTE_BAD_FLAGS, 0, 0, 1},
+    {CALG_DH_SF, 768 << 16, TRUE, 0, 0, 1},
+    {CALG_DH_SF, 1024 << 16, TRUE, 0, 0, 1},
     {CALG_DH_SF, 1032 << 16, FALSE, NTE_BAD_FLAGS},
-    {CALG_DH_SF, 1088 << 16, TRUE},
+    {CALG_DH_SF, 1088 << 16, TRUE, 0, 0, 1},
     {CALG_DH_SF, 4160 << 16, FALSE, NTE_BAD_FLAGS},
     {CALG_DSS_SIGN, 448 << 16, FALSE, NTE_BAD_FLAGS},
     {CALG_DSS_SIGN, 512 << 16, TRUE},
@@ -307,16 +309,22 @@ static void test_keylength_array(HCRYPTPROV hProv,const struct keylength_test *t
         result = CryptGenKey(hProv, tests[i].algid, tests[i].flags, &key);
 
         /* success */
-        if(tests[i].expectedResult)
+        if (tests[i].expectedResult)
         {
-            ok(result, "%d: Expected a key, got %08x\n", i, GetLastError());
-            result = CryptDestroyKey(key);
-            ok(result, "Expected no errors.\n");
+            todo_wine_if (tests[i].todo_result) ok(result, "%d: got %08x\n", i, GetLastError());
+            if (result)
+            {
+                result = CryptDestroyKey(key);
+                ok(result, "%d: got %08x\n", i, GetLastError());
+            }
         }
         else
-            ok(!result && (GetLastError() == tests[i].expectedError ||
-                           broken(GetLastError() == tests[i].brokenError)),
-               "%d: got %x.\n", i, GetLastError());
+        {
+            todo_wine_if (tests[i].todo_result) ok(!result, "%d: got %x\n", i, GetLastError());
+            todo_wine_if (tests[i].todo_error)
+                ok(GetLastError() == tests[i].expectedError ||
+                   broken(GetLastError() == tests[i].brokenError), "%d: got %08x\n", i, GetLastError());
+        }
     }
 }
 
@@ -337,12 +345,7 @@ static void test_keylength(void)
     ok(result, "Expected no errors.\n");
 
     result = CryptGenKey(hProv, AT_SIGNATURE, 0, &key);
-    todo_wine ok(result, "Expected no errors.\n");
-    if (!result)
-    {
-        skip("skipping key length tests\n");
-        return;
-    }
+    ok(result, "Expected no errors.\n");
 
     result = CryptDestroyKey(key);
     ok(result, "Expected no errors.\n");
-- 
2.28.0




More information about the wine-devel mailing list