Juan Lang : rsaenh: Support setting the effective key length of RC2 keys.

Alexandre Julliard julliard at wine.codeweavers.com
Tue Sep 11 07:28:46 CDT 2007


Module: wine
Branch: master
Commit: 41d057837cd7c22ba2db55690add4761865e0e24
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=41d057837cd7c22ba2db55690add4761865e0e24

Author: Juan Lang <juan.lang at gmail.com>
Date:   Mon Sep 10 15:05:24 2007 -0700

rsaenh: Support setting the effective key length of RC2 keys.

---

 dlls/rsaenh/implglue.c     |    7 ++--
 dlls/rsaenh/implglue.h     |    4 +-
 dlls/rsaenh/rsaenh.c       |   37 ++++++++++++++++++++++++-
 dlls/rsaenh/tests/rsaenh.c |   66 ++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 108 insertions(+), 6 deletions(-)

diff --git a/dlls/rsaenh/implglue.c b/dlls/rsaenh/implglue.c
index 6953161..d31f615 100644
--- a/dlls/rsaenh/implglue.c
+++ b/dlls/rsaenh/implglue.c
@@ -166,8 +166,8 @@ BOOL free_key_impl(ALG_ID aiAlgid, KEY_CONTEXT *pKeyContext)
     return TRUE;
 }
 
-BOOL setup_key_impl(ALG_ID aiAlgid, KEY_CONTEXT *pKeyContext, DWORD dwKeyLen, DWORD dwSaltLen, 
-                    BYTE *abKeyValue) 
+BOOL setup_key_impl(ALG_ID aiAlgid, KEY_CONTEXT *pKeyContext, DWORD dwKeyLen,
+                    DWORD dwEffectiveKeyLen, DWORD dwSaltLen, BYTE *abKeyValue)
 {
     switch (aiAlgid) 
     {
@@ -178,7 +178,8 @@ BOOL setup_key_impl(ALG_ID aiAlgid, KEY_CONTEXT *pKeyContext, DWORD dwKeyLen, DW
             break;
         
         case CALG_RC2:
-            rc2_setup(abKeyValue, dwKeyLen + dwSaltLen, dwKeyLen << 3, 0, &pKeyContext->rc2);
+            rc2_setup(abKeyValue, dwKeyLen + dwSaltLen, dwEffectiveKeyLen ?
+                      dwEffectiveKeyLen : dwKeyLen << 3, 0, &pKeyContext->rc2);
             break;
         
         case CALG_3DES:
diff --git a/dlls/rsaenh/implglue.h b/dlls/rsaenh/implglue.h
index 597ca1e..d421c3d 100644
--- a/dlls/rsaenh/implglue.h
+++ b/dlls/rsaenh/implglue.h
@@ -76,8 +76,8 @@ BOOL duplicate_hash_impl(ALG_ID aiAlgid, CONST HASH_CONTEXT *pSrcHashContext,
 
 BOOL new_key_impl(ALG_ID aiAlgid, KEY_CONTEXT *pKeyContext, DWORD dwKeyLen);
 BOOL free_key_impl(ALG_ID aiAlgid, KEY_CONTEXT *pKeyContext);
-BOOL setup_key_impl(ALG_ID aiAlgid, KEY_CONTEXT *pKeyContext, DWORD dwKeyLen, DWORD dwSaltLen, 
-                    BYTE *abKeyValue);
+BOOL setup_key_impl(ALG_ID aiAlgid, KEY_CONTEXT *pKeyContext, DWORD dwKeyLen,
+                    DWORD dwEffectiveKeyLen, DWORD dwSaltLen, BYTE *abKeyValue);
 BOOL duplicate_key_impl(ALG_ID aiAlgid, CONST KEY_CONTEXT *pSrcKeyContext, 
                         KEY_CONTEXT *pDestKeyContext);
 
diff --git a/dlls/rsaenh/rsaenh.c b/dlls/rsaenh/rsaenh.c
index ce15b4e..4002f27 100644
--- a/dlls/rsaenh/rsaenh.c
+++ b/dlls/rsaenh/rsaenh.c
@@ -93,6 +93,7 @@ typedef struct tagCRYPTKEY
     DWORD       dwModeBits;
     DWORD       dwPermissions;
     DWORD       dwKeyLen;
+    DWORD       dwEffectiveKeyLen;
     DWORD       dwSaltLen;
     DWORD       dwBlockLen;
     DWORD       dwState;
@@ -718,7 +719,8 @@ static inline void setup_key(CRYPTKEY *pCryptKey) {
     pCryptKey->dwState = RSAENH_KEYSTATE_IDLE;
     memcpy(pCryptKey->abChainVector, pCryptKey->abInitVector, sizeof(pCryptKey->abChainVector));
     setup_key_impl(pCryptKey->aiAlgid, &pCryptKey->context, pCryptKey->dwKeyLen, 
-                   pCryptKey->dwSaltLen, pCryptKey->abKeyValue);
+                   pCryptKey->dwEffectiveKeyLen, pCryptKey->dwSaltLen,
+                   pCryptKey->abKeyValue);
 }
 
 /******************************************************************************
@@ -813,6 +815,7 @@ static HCRYPTKEY new_key(HCRYPTPROV hProv, ALG_ID aiAlgid, DWORD dwFlags, CRYPTK
         pCryptKey->dwPermissions = CRYPT_ENCRYPT | CRYPT_DECRYPT | CRYPT_READ | CRYPT_WRITE | 
                                    CRYPT_MAC;
         pCryptKey->dwKeyLen = dwKeyLen >> 3;
+        pCryptKey->dwEffectiveKeyLen = 0;
         if ((dwFlags & CRYPT_CREATE_SALT) || (dwKeyLen == 40 && !(dwFlags & CRYPT_NO_SALT))) 
             pCryptKey->dwSaltLen = 16 /*FIXME*/ - pCryptKey->dwKeyLen;
         else
@@ -2710,6 +2713,31 @@ BOOL WINAPI RSAENH_CPSetKeyParam(HCRYPTPROV hProv, HCRYPTKEY hKey, DWORD dwParam
             setup_key(pCryptKey);
             return TRUE;
 
+        case KP_EFFECTIVE_KEYLEN:
+            switch (pCryptKey->aiAlgid) {
+                case CALG_RC2:
+                    if (!pbData)
+                    {
+                        SetLastError(ERROR_INVALID_PARAMETER);
+                        return FALSE;
+                    }
+                    else if (!*(DWORD *)pbData || *(DWORD *)pbData > 1024)
+                    {
+                        SetLastError(NTE_BAD_DATA);
+                        return FALSE;
+                    }
+                    else
+                    {
+                        pCryptKey->dwEffectiveKeyLen = *(DWORD *)pbData;
+                        setup_key(pCryptKey);
+                    }
+                    break;
+                default:
+                    SetLastError(NTE_BAD_TYPE);
+                    return FALSE;
+            }
+            return TRUE;
+
         case KP_SCHANNEL_ALG:
             switch (((PSCHANNEL_ALG)pbData)->dwUse) {
                 case SCHANNEL_ENC_KEY:
@@ -2807,6 +2835,13 @@ BOOL WINAPI RSAENH_CPGetKeyParam(HCRYPTPROV hProv, HCRYPTKEY hKey, DWORD dwParam
             dwBitLen = pCryptKey->dwKeyLen << 3;
             return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwBitLen, sizeof(DWORD));
         
+        case KP_EFFECTIVE_KEYLEN:
+            if (pCryptKey->dwEffectiveKeyLen)
+                dwBitLen = pCryptKey->dwEffectiveKeyLen;
+            else
+                dwBitLen = pCryptKey->dwKeyLen << 3;
+            return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwBitLen, sizeof(DWORD));
+
         case KP_BLOCKLEN:
             dwBitLen = pCryptKey->dwBlockLen << 3;
             return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwBitLen, sizeof(DWORD));
diff --git a/dlls/rsaenh/tests/rsaenh.c b/dlls/rsaenh/tests/rsaenh.c
index 2a397e7..163aa5e 100644
--- a/dlls/rsaenh/tests/rsaenh.c
+++ b/dlls/rsaenh/tests/rsaenh.c
@@ -498,6 +498,9 @@ static void test_rc2(void)
     static const BYTE rc2encrypted[16] = { 
         0x02, 0x34, 0x7d, 0xf6, 0x1d, 0xc5, 0x9b, 0x8b, 
         0x2e, 0x0d, 0x63, 0x80, 0x72, 0xc1, 0xc2, 0xb1 };
+    static const BYTE rc2_128_encrypted[] = {
+        0x82,0x81,0xf7,0xff,0xdd,0xd7,0x88,0x8c,0x2a,0x2a,0xc0,0xce,0x4c,0x89,
+        0xb6,0x66 };
     HCRYPTHASH hHash;
     HCRYPTKEY hKey;
     BOOL result;
@@ -579,6 +582,69 @@ static void test_rc2(void)
         result = CryptDestroyKey(hKey);
         ok(result, "%08x\n", GetLastError());
     }
+
+    /* Again, but test setting the effective key len */
+    for (i=0; i<2000; i++) pbData[i] = (unsigned char)i;
+
+    result = CryptCreateHash(hProv, CALG_MD2, 0, 0, &hHash);
+    if (!result) {
+        ok(GetLastError()==NTE_BAD_ALGID, "%08x\n", GetLastError());
+    } else {
+        result = CryptHashData(hHash, (BYTE*)pbData, sizeof(pbData), 0);
+        ok(result, "%08x\n", GetLastError());
+
+        dwLen = 16;
+        result = CryptGetHashParam(hHash, HP_HASHVAL, pbHashValue, &dwLen, 0);
+        ok(result, "%08x\n", GetLastError());
+
+        result = CryptDeriveKey(hProv, CALG_RC2, hHash, 56 << 16, &hKey);
+        ok(result, "%08x\n", GetLastError());
+
+        SetLastError(0xdeadbeef);
+        result = CryptSetKeyParam(hKey, KP_EFFECTIVE_KEYLEN, NULL, 0);
+        ok(!result && GetLastError()==ERROR_INVALID_PARAMETER, "%08x\n", GetLastError());
+        dwKeyLen = 0;
+        SetLastError(0xdeadbeef);
+        result = CryptSetKeyParam(hKey, KP_EFFECTIVE_KEYLEN, (LPBYTE)&dwKeyLen, 0);
+        ok(!result && GetLastError()==NTE_BAD_DATA, "%08x\n", GetLastError());
+        dwKeyLen = 1025;
+        SetLastError(0xdeadbeef);
+        result = CryptSetKeyParam(hKey, KP_EFFECTIVE_KEYLEN, (LPBYTE)&dwKeyLen, 0);
+
+        dwLen = sizeof(dwKeyLen);
+        CryptGetKeyParam(hKey, KP_KEYLEN, (BYTE *)&dwKeyLen, &dwLen, 0);
+        ok(dwKeyLen == 56, "%d (%08x)\n", dwKeyLen, GetLastError());
+        CryptGetKeyParam(hKey, KP_EFFECTIVE_KEYLEN, (BYTE *)&dwKeyLen, &dwLen, 0);
+        ok(dwKeyLen == 56, "%d (%08x)\n", dwKeyLen, GetLastError());
+
+        dwKeyLen = 128;
+        result = CryptSetKeyParam(hKey, KP_EFFECTIVE_KEYLEN, (LPBYTE)&dwKeyLen, 0);
+        ok(result, "%d\n", GetLastError());
+
+        dwLen = sizeof(dwKeyLen);
+        CryptGetKeyParam(hKey, KP_KEYLEN, (BYTE *)&dwKeyLen, &dwLen, 0);
+        ok(dwKeyLen == 56, "%d (%08x)\n", dwKeyLen, GetLastError());
+        CryptGetKeyParam(hKey, KP_EFFECTIVE_KEYLEN, (BYTE *)&dwKeyLen, &dwLen, 0);
+        ok(dwKeyLen == 128, "%d (%08x)\n", dwKeyLen, GetLastError());
+
+        result = CryptDestroyHash(hHash);
+        ok(result, "%08x\n", GetLastError());
+
+        dwDataLen = 13;
+        result = CryptEncrypt(hKey, (HCRYPTHASH)NULL, TRUE, 0, pbData, &dwDataLen, 24);
+        ok(result, "%08x\n", GetLastError());
+
+        ok(!memcmp(pbData, rc2_128_encrypted, sizeof(rc2_128_encrypted)),
+                "RC2 encryption failed!\n");
+
+        /* Oddly enough this succeeds, though it should have no effect */
+        dwKeyLen = 40;
+        result = CryptSetKeyParam(hKey, KP_EFFECTIVE_KEYLEN, (LPBYTE)&dwKeyLen, 0);
+        ok(result, "%d\n", GetLastError());
+
+        result = CryptDestroyKey(hKey);
+        ok(result, "%08x\n", GetLastError());
+    }
 }
 
 static void test_rc4(void)




More information about the wine-cvs mailing list