From cafd79af01f3b6568fd9d552137c11179d6a66a3 Mon Sep 17 00:00:00 2001
From: Charles Davis <cdavis5x@gmail.com>
Date: Sun, 1 Sep 2013 23:39:41 -0600
Subject: [PATCH] crypt32: Skip unknown item when decoding a CMS certificate.
Reply-To: Wine Developer's List <wine-devel@winehq.org>

I ran into this while trying to run Star Citizen under Wine.
---
 dlls/crypt32/decode.c       |  2 ++
 dlls/crypt32/tests/encode.c | 77 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 79 insertions(+)

diff --git a/dlls/crypt32/decode.c b/dlls/crypt32/decode.c
index e5f8baf..0917924 100644
--- a/dlls/crypt32/decode.c
+++ b/dlls/crypt32/decode.c
@@ -5502,6 +5502,8 @@ static BOOL CRYPT_AsnDecodeCMSSignerInfoInternal(const BYTE *pbEncoded,
        offsetof(CMSG_CMS_SIGNER_INFO, AuthAttrs),
        CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
        TRUE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
+     /* Unknown item; doesn't seem important */
+     { ASN_CONSTRUCTOR | ASN_UNIVERSAL | 0x11, 0, NULL, 0, TRUE, FALSE, 0, 0 },
      { ASN_SEQUENCEOF, offsetof(CMSG_CMS_SIGNER_INFO, HashEncryptionAlgorithm),
        CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
        FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO,
diff --git a/dlls/crypt32/tests/encode.c b/dlls/crypt32/tests/encode.c
index 5d9e76b..ba3715f 100644
--- a/dlls/crypt32/tests/encode.c
+++ b/dlls/crypt32/tests/encode.c
@@ -6421,6 +6421,17 @@ static const BYTE PKCSSignerWithHashAndEncryptionAlgo[] = {
  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
  0x06,0x05,0x00,0x04,0x00 };
+static const BYTE PKCSSignerWithUnknownItem31[] = {
+ 0x30,0x82,0x00,0x92,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,
+ 0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
+ 0x67,0x02,0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x31,0x60,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00,0x04,0x00 };
 static const BYTE PKCSSignerWithHash[] = {
  0x30,0x40,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
@@ -6435,6 +6446,21 @@ static const BYTE PKCSSignerWithAuthAttr[] = {
 0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,
 0x06,0x06,0x02,0x2d,0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,
 0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
+static const BYTE PKCSSignerWithAuthAttrAndUnknownItem31[] = {
+0x30,0x82,0x00,0xc4,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,
+0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
+0x67,0x02,0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0xa0,0x20,0x30,
+0x1e,0x06,0x03,0x55,0x04,0x03,0x31,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
+0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
+0x00,0x31,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x06,0x06,0x02,0x2d,0x06,
+0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,
+0x0b,0x0c,0x0d,0x0e,0x0f };
 
 static void test_encodePKCSSignerInfo(DWORD dwEncoding)
 {
@@ -6727,6 +6753,27 @@ static void test_decodePKCSSignerInfo(DWORD dwEncoding)
          encodedCommonName, sizeof(encodedCommonName)), "Unexpected value\n");
         LocalFree(buf);
     }
+    ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
+     PKCSSignerWithAuthAttrAndUnknownItem31,
+     sizeof(PKCSSignerWithAuthAttrAndUnknownItem31),
+     CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
+    if (ret)
+    {
+        info = (CMSG_SIGNER_INFO *)buf;
+        ok(info->AuthAttrs.cAttr == 1, "Expected 1 attribute, got %d\n",
+         info->AuthAttrs.cAttr);
+        ok(!strcmp(info->AuthAttrs.rgAttr[0].pszObjId, szOID_COMMON_NAME),
+         "Expected %s, got %s\n", szOID_COMMON_NAME,
+         info->AuthAttrs.rgAttr[0].pszObjId);
+        ok(info->AuthAttrs.rgAttr[0].cValue == 1, "Expected 1 value, got %d\n",
+         info->AuthAttrs.rgAttr[0].cValue);
+        ok(info->AuthAttrs.rgAttr[0].rgValue[0].cbData ==
+         sizeof(encodedCommonName), "Unexpected size %d\n",
+         info->AuthAttrs.rgAttr[0].rgValue[0].cbData);
+        ok(!memcmp(info->AuthAttrs.rgAttr[0].rgValue[0].pbData,
+         encodedCommonName, sizeof(encodedCommonName)), "Unexpected value\n");
+        LocalFree(buf);
+    }
 }
 
 static const BYTE CMSSignerWithKeyId[] = {
@@ -7010,6 +7057,36 @@ static void test_decodeCMSSignerInfo(DWORD dwEncoding)
         LocalFree(buf);
     }
     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
+     PKCSSignerWithUnknownItem31, sizeof(PKCSSignerWithUnknownItem31),
+     CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
+    ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
+    if (ret)
+    {
+        info = (CMSG_CMS_SIGNER_INFO *)buf;
+        ok(info->dwVersion == 0, "Expected version 0, got %d\n",
+         info->dwVersion);
+        ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
+         "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
+         info->SignerId.dwIdChoice);
+        ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
+         sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
+         U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
+        ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
+         encodedCommonNameNoNull,
+         U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
+         "Unexpected value\n");
+        ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
+         sizeof(serialNum), "Unexpected size %d\n",
+         U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
+        ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
+         serialNum, sizeof(serialNum)), "Unexpected value\n");
+        ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
+         "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
+        ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
+         "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
+        LocalFree(buf);
+    }
+    ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
      PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
-- 
1.7.12.4

