Michael Karcher : crypt32: ComparePublicKeyInfo must ignore the leading zero.

Alexandre Julliard julliard at winehq.org
Mon Jun 30 08:27:52 CDT 2008


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

Author: Michael Karcher <wine at mkarcher.dialup.fu-berlin.de>
Date:   Sun Jun 29 12:33:48 2008 +0200

crypt32: ComparePublicKeyInfo must ignore the leading zero.

---

 dlls/crypt32/cert.c       |   61 +++++++++++++++++++++++++++++++++++++++------
 dlls/crypt32/tests/cert.c |   32 +++++++++++++++++++++++
 2 files changed, 85 insertions(+), 8 deletions(-)

diff --git a/dlls/crypt32/cert.c b/dlls/crypt32/cert.c
index b916ce3..2ab147a 100644
--- a/dlls/crypt32/cert.c
+++ b/dlls/crypt32/cert.c
@@ -788,17 +788,62 @@ BOOL WINAPI CertComparePublicKeyInfo(DWORD dwCertEncodingType,
 
     TRACE("(%08x, %p, %p)\n", dwCertEncodingType, pPublicKey1, pPublicKey2);
 
-    if (pPublicKey1->PublicKey.cbData == pPublicKey2->PublicKey.cbData &&
-     pPublicKey1->PublicKey.cUnusedBits == pPublicKey2->PublicKey.cUnusedBits)
+    switch (GET_CERT_ENCODING_TYPE(dwCertEncodingType))
     {
-        if (pPublicKey2->PublicKey.cbData)
-            ret = !memcmp(pPublicKey1->PublicKey.pbData,
-             pPublicKey2->PublicKey.pbData, pPublicKey1->PublicKey.cbData);
+    case 0:	/* Seems to mean "raw binary bits" */
+        if (pPublicKey1->PublicKey.cbData == pPublicKey2->PublicKey.cbData &&
+         pPublicKey1->PublicKey.cUnusedBits == pPublicKey2->PublicKey.cUnusedBits)
+        {
+          if (pPublicKey2->PublicKey.cbData)
+              ret = !memcmp(pPublicKey1->PublicKey.pbData,
+               pPublicKey2->PublicKey.pbData, pPublicKey1->PublicKey.cbData);
+          else
+              ret = TRUE;
+        }
         else
-            ret = TRUE;
-    }
-    else
+            ret = FALSE;
+        break;
+    default:
+        WARN("Unknown encoding type %08x\n", dwCertEncodingType);
+        /* FALLTHROUGH */
+    case X509_ASN_ENCODING:
+    {
+        BLOBHEADER *pblob1, *pblob2;
+        DWORD length;
         ret = FALSE;
+        if (CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
+                    pPublicKey1->PublicKey.pbData, pPublicKey1->PublicKey.cbData,
+                    0, NULL, &length))
+        {
+            pblob1 = CryptMemAlloc(length);
+            if (CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
+                    pPublicKey1->PublicKey.pbData, pPublicKey1->PublicKey.cbData,
+                    0, pblob1, &length))
+            {
+                if (CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
+                            pPublicKey2->PublicKey.pbData, pPublicKey2->PublicKey.cbData,
+                            0, NULL, &length))
+                {
+                    pblob2 = CryptMemAlloc(length);
+                    if (CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
+                            pPublicKey2->PublicKey.pbData, pPublicKey2->PublicKey.cbData,
+                            0, pblob2, &length))
+                    {
+                        /* The RSAPUBKEY structure directly follows the BLOBHEADER */
+                        RSAPUBKEY *pk1 = (LPVOID)(pblob1 + 1),
+                                  *pk2 = (LPVOID)(pblob2 + 1);
+                        ret = (pk1->bitlen == pk2->bitlen) && (pk1->pubexp == pk2->pubexp)
+                                 && !memcmp(pk1 + 1, pk2 + 1, pk1->bitlen/8);
+                    }
+                    CryptMemFree(pblob2);
+                }
+            }
+            CryptMemFree(pblob1);
+        }
+
+        break;
+    }
+    }
     return ret;
 }
 
diff --git a/dlls/crypt32/tests/cert.c b/dlls/crypt32/tests/cert.c
index 64aba83..37cea10 100644
--- a/dlls/crypt32/tests/cert.c
+++ b/dlls/crypt32/tests/cert.c
@@ -2437,6 +2437,9 @@ static void testComparePublicKeyInfo(void)
     static BYTE bits1[] = { 1, 0 };
     static BYTE bits2[] = { 0 };
     static BYTE bits3[] = { 1 };
+    static BYTE bits4[] = { 0x30,8, 2,1,0x81, 2,3,1,0,1 };
+    static BYTE bits5[] = { 0x30,9, 2,2,0,0x81, 2,3,1,0,1 };
+    static BYTE bits6[] = { 0x30,9, 2,2,0,0x82, 2,3,1,0,1 };
 
     /* crashes
     ret = CertComparePublicKeyInfo(0, NULL, NULL);
@@ -2460,6 +2463,26 @@ static void testComparePublicKeyInfo(void)
     info2.PublicKey.cUnusedBits = 0;
     ret = CertComparePublicKeyInfo(0, &info1, &info2);
     ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
+    info2.Algorithm.pszObjId = oid_rsa_rsa;
+    info1.PublicKey.cbData = sizeof(bits4);
+    info1.PublicKey.pbData = bits4;
+    info1.PublicKey.cUnusedBits = 0;
+    info2.PublicKey.cbData = sizeof(bits5);
+    info2.PublicKey.pbData = bits5;
+    info2.PublicKey.cUnusedBits = 0;
+    ret = CertComparePublicKeyInfo(0, &info1, &info2);
+    ok(!ret, "CertComparePublicKeyInfo: as raw binary: keys should be unequal\n");
+    ret = CertComparePublicKeyInfo(X509_ASN_ENCODING, &info1, &info2);
+    ok(ret, "CertComparePublicKeyInfo: as ASN.1 encoded: keys should be equal\n");
+    info1.PublicKey.cUnusedBits = 1;
+    info2.PublicKey.cUnusedBits = 5;
+    ret = CertComparePublicKeyInfo(X509_ASN_ENCODING, &info1, &info2);
+    ok(ret, "CertComparePublicKeyInfo: ASN.1 encoding should ignore cUnusedBits\n");
+    info1.PublicKey.cUnusedBits = 0;
+    info2.PublicKey.cUnusedBits = 0;
+    info1.PublicKey.cbData--; /* kill one byte, make ASN.1 encoded data invalid */
+    ret = CertComparePublicKeyInfo(X509_ASN_ENCODING, &info1, &info2);
+    ok(!ret, "CertComparePublicKeyInfo: comparing bad ASN.1 encoded key should fail\n");
     /* Even though they compare in their used bits, these do not compare */
     info1.PublicKey.cbData = sizeof(bits2);
     info1.PublicKey.pbData = bits2;
@@ -2475,6 +2498,15 @@ static void testComparePublicKeyInfo(void)
     info2.PublicKey.cUnusedBits = 0;
     ret = CertComparePublicKeyInfo(0, &info1, &info2);
     ok(!ret, "Expected keys not to compare\n");
+    /* ASN.1 encoded non-comparing case */
+    info1.PublicKey.cbData = sizeof(bits5);
+    info1.PublicKey.pbData = bits5;
+    info1.PublicKey.cUnusedBits = 0;
+    info2.PublicKey.cbData = sizeof(bits6);
+    info2.PublicKey.pbData = bits6;
+    info2.PublicKey.cUnusedBits = 0;
+    ret = CertComparePublicKeyInfo(X509_ASN_ENCODING, &info1, &info2);
+    ok(!ret, "CertComparePublicKeyInfo: different keys should be unequal\n");
 }
 
 static void testHashPublicKeyInfo(void)




More information about the wine-cvs mailing list