[2/2] crypt32: Implement PKCS_RSA_PRIVATE_KEY decoding.

Vincent Povirk madewokherd at gmail.com
Thu Feb 26 15:00:17 CST 2015


-------------- next part --------------
From 397978657b6dc56115662766b067c81bf83cc9df Mon Sep 17 00:00:00 2001
From: Vincent Povirk <vincent at codeweavers.com>
Date: Thu, 26 Feb 2015 14:48:05 -0600
Subject: [PATCH 2/2] crypt32: Implement PKCS_RSA_PRIVATE_KEY decoding.

---
 dlls/crypt32/decode.c       | 144 ++++++++++++++++++++++++++++++++++++++++++++
 dlls/crypt32/tests/encode.c |   4 +-
 2 files changed, 146 insertions(+), 2 deletions(-)

diff --git a/dlls/crypt32/decode.c b/dlls/crypt32/decode.c
index e5f8baf..92dfba2 100644
--- a/dlls/crypt32/decode.c
+++ b/dlls/crypt32/decode.c
@@ -3936,6 +3936,147 @@ static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
     return ret;
 }
 
+#define RSA2_MAGIC 0x32415352
+
+struct DECODED_RSA_PRIV_KEY
+{
+    DWORD              version;
+    DWORD              pubexp;
+    CRYPT_INTEGER_BLOB modulus;
+    CRYPT_INTEGER_BLOB privexp;
+    CRYPT_INTEGER_BLOB prime1;
+    CRYPT_INTEGER_BLOB prime2;
+    CRYPT_INTEGER_BLOB exponent1;
+    CRYPT_INTEGER_BLOB exponent2;
+    CRYPT_INTEGER_BLOB coefficient;
+};
+
+static BOOL WINAPI CRYPT_AsnDecodeRsaPrivKey(DWORD dwCertEncodingType,
+ LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
+ PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
+{
+    BOOL ret;
+    DWORD halflen;
+
+    __TRY
+    {
+        struct AsnDecodeSequenceItem items[] = {
+         { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, version),
+           CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
+         { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, modulus),
+           CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
+           FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, modulus.pbData),
+           0 },
+         { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, pubexp),
+           CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
+         { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, privexp),
+           CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
+           FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, privexp.pbData),
+           0 },
+         { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, prime1),
+           CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
+           FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, prime1.pbData),
+           0 },
+         { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, prime2),
+           CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
+           FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, prime2.pbData),
+           0 },
+         { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, exponent1),
+           CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
+           FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, exponent1.pbData),
+           0 },
+         { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, exponent2),
+           CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
+           FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, exponent2.pbData),
+           0 },
+         { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, coefficient),
+           CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
+           FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, coefficient.pbData),
+           0 },
+        };
+        struct DECODED_RSA_PRIV_KEY *decodedKey = NULL;
+        DWORD size = 0;
+
+        ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+         pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey,
+         &size, NULL, NULL);
+        if (ret)
+        {
+            halflen = decodedKey->modulus.cbData / 2;
+            if ((decodedKey->modulus.cbData != halflen * 2) ||
+                (decodedKey->prime1.cbData != halflen) ||
+                (decodedKey->prime2.cbData != halflen) ||
+                (decodedKey->exponent1.cbData != halflen) ||
+                (decodedKey->exponent2.cbData != halflen) ||
+                (decodedKey->coefficient.cbData != halflen) ||
+                (decodedKey->privexp.cbData != halflen * 2))
+            {
+                ret = FALSE;
+                SetLastError(CRYPT_E_BAD_ENCODE);
+            }
+            
+            if (ret)
+            {
+                DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
+                 (halflen * 9);
+
+                if (!pvStructInfo)
+                {
+                    *pcbStructInfo = bytesNeeded;
+                    ret = TRUE;
+                }
+                else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
+                 pvStructInfo, pcbStructInfo, bytesNeeded)))
+                {
+                    BLOBHEADER *hdr;
+                    RSAPUBKEY *rsaPubKey;
+                    BYTE *vardata;
+
+                    if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
+                        pvStructInfo = *(BYTE **)pvStructInfo;
+
+                    hdr = pvStructInfo;
+                    hdr->bType = PRIVATEKEYBLOB;
+                    hdr->bVersion = CUR_BLOB_VERSION;
+                    hdr->reserved = 0;
+                    hdr->aiKeyAlg = CALG_RSA_KEYX;
+
+                    rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
+                     sizeof(BLOBHEADER));
+                    rsaPubKey->magic = RSA2_MAGIC;
+                    rsaPubKey->pubexp = decodedKey->pubexp;
+                    rsaPubKey->bitlen = halflen * 16;
+
+                    vardata = (BYTE*)(rsaPubKey + 1);
+                    memcpy(vardata,
+                     decodedKey->modulus.pbData, halflen * 2);
+                    memcpy(vardata + halflen * 2,
+                     decodedKey->prime1.pbData, halflen);
+                    memcpy(vardata + halflen * 3,
+                     decodedKey->prime2.pbData, halflen);
+                    memcpy(vardata + halflen * 4,
+                     decodedKey->exponent1.pbData, halflen);
+                    memcpy(vardata + halflen * 5,
+                     decodedKey->exponent2.pbData, halflen);
+                    memcpy(vardata + halflen * 6,
+                     decodedKey->coefficient.pbData, halflen);
+                    memcpy(vardata + halflen * 7,
+                     decodedKey->privexp.pbData, halflen * 2);
+                }
+            }
+            
+            LocalFree(decodedKey);
+        }
+    }
+    __EXCEPT_PAGE_FAULT
+    {
+        SetLastError(STATUS_ACCESS_VIOLATION);
+        ret = FALSE;
+    }
+    __ENDTRY
+    return ret;
+}
+
 static BOOL CRYPT_AsnDecodeOctetsInternal(const BYTE *pbEncoded,
  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
  DWORD *pcbDecoded)
@@ -5798,6 +5939,9 @@ static CryptDecodeObjectExFunc CRYPT_GetBuiltinDecoder(DWORD dwCertEncodingType,
         case LOWORD(RSA_CSP_PUBLICKEYBLOB):
             decodeFunc = CRYPT_AsnDecodeRsaPubKey;
             break;
+        case LOWORD(PKCS_RSA_PRIVATE_KEY):
+            decodeFunc = CRYPT_AsnDecodeRsaPrivKey;
+            break;
         case LOWORD(X509_UNICODE_NAME):
             decodeFunc = CRYPT_AsnDecodeUnicodeName;
             break;
diff --git a/dlls/crypt32/tests/encode.c b/dlls/crypt32/tests/encode.c
index 3240a84..b45b5f2 100644
--- a/dlls/crypt32/tests/encode.c
+++ b/dlls/crypt32/tests/encode.c
@@ -8101,7 +8101,7 @@ static void test_decodeRsaPrivateKey(DWORD dwEncoding)
     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_RSA_PRIVATE_KEY,
      rsaPrivKeyDer, sizeof(rsaPrivKeyDer)-10,
      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
-    todo_wine ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD),
+    ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD),
      "Expected CRYPT_E_ASN1_EOD, got %08x\n",
      GetLastError());
 
@@ -8110,7 +8110,7 @@ static void test_decodeRsaPrivateKey(DWORD dwEncoding)
     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_RSA_PRIVATE_KEY,
      rsaPrivKeyDer, sizeof(rsaPrivKeyDer),
      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
-    todo_wine ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
+    ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
 
     if (ret)
     {
-- 
2.1.0



More information about the wine-patches mailing list