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