Module: wine Branch: master Commit: 4f11b1af28abb2bf8089422cc935ea22b40586c7 URL: http://source.winehq.org/git/?p=wine.git;a=commit;h=4f11b1af28abb2bf8089422c...
Author: Juan Lang juan_lang@yahoo.com Date: Wed Sep 27 23:07:26 2006 -0700
crypt32: Implement CertGetPublicKeyLength.
---
dlls/crypt32/cert.c | 39 +++++++++++++++++++++++ dlls/crypt32/crypt32.spec | 2 + dlls/crypt32/tests/cert.c | 77 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 117 insertions(+), 1 deletions(-)
diff --git a/dlls/crypt32/cert.c b/dlls/crypt32/cert.c index b131f11..185f133 100644 --- a/dlls/crypt32/cert.c +++ b/dlls/crypt32/cert.c @@ -772,6 +772,45 @@ BOOL WINAPI CertComparePublicKeyInfo(DWO return ret; }
+DWORD WINAPI CertGetPublicKeyLength(DWORD dwCertEncodingType, + PCERT_PUBLIC_KEY_INFO pPublicKey) +{ + DWORD len = 0; + + TRACE("(%08lx, %p)\n", dwCertEncodingType, pPublicKey); + + if (dwCertEncodingType != X509_ASN_ENCODING) + { + SetLastError(ERROR_FILE_NOT_FOUND); + return 0; + } + if (pPublicKey->Algorithm.pszObjId && + !strcmp(pPublicKey->Algorithm.pszObjId, szOID_RSA_DH)) + { + FIXME("unimplemented for DH public keys\n"); + SetLastError(CRYPT_E_ASN1_BADTAG); + } + else + { + DWORD size; + PBYTE buf; + BOOL ret = CryptDecodeObjectEx(dwCertEncodingType, + RSA_CSP_PUBLICKEYBLOB, pPublicKey->PublicKey.pbData, + pPublicKey->PublicKey.cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, + &size); + + if (ret) + { + RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)((LPBYTE)buf + + sizeof(BLOBHEADER)); + + len = rsaPubKey->bitlen; + LocalFree(buf); + } + } + return len; +} + typedef BOOL (*CertCompareFunc)(PCCERT_CONTEXT pCertContext, DWORD dwType, DWORD dwFlags, const void *pvPara);
diff --git a/dlls/crypt32/crypt32.spec b/dlls/crypt32/crypt32.spec index ab2c947..8da0dad 100644 --- a/dlls/crypt32/crypt32.spec +++ b/dlls/crypt32/crypt32.spec @@ -57,7 +57,7 @@ @ stdcall CertGetIssuerCertificateFromStore(long ptr ptr ptr) @ stdcall CertGetNameStringA(ptr long long ptr ptr long) @ stdcall CertGetNameStringW(ptr long long ptr ptr long) -@ stub CertGetPublicKeyLength +@ stdcall CertGetPublicKeyLength(long ptr) @ stdcall CertGetSubjectCertificateFromStore(ptr long ptr) @ stdcall CertGetValidUsages(long ptr ptr ptr ptr) @ stub CertIsRDNAttrsInCertificateName diff --git a/dlls/crypt32/tests/cert.c b/dlls/crypt32/tests/cert.c index f1bec9f..398ef15 100644 --- a/dlls/crypt32/tests/cert.c +++ b/dlls/crypt32/tests/cert.c @@ -1903,6 +1903,82 @@ static void testAcquireCertPrivateKey(vo CertFreeCertificateContext(cert); }
+static void testGetPublicKeyLength(void) +{ + static char oid_rsa_rsa[] = szOID_RSA_RSA; + static char oid_rsa_dh[] = szOID_RSA_DH; + static char bogusOID[] = "1.2.3"; + DWORD ret; + CERT_PUBLIC_KEY_INFO info = { { 0 } }; + BYTE bogusKey[] = { 1, 2, 3, 4, 5, 6, 7, 8 }; + BYTE key[] = { 0x30,0x0f,0x02,0x08,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x02,0x03,0x01,0x00,0x01 }; + + /* Crashes + ret = CertGetPublicKeyLength(0, NULL); + */ + /* With an empty public key info */ + SetLastError(0xdeadbeef); + ret = CertGetPublicKeyLength(0, &info); + ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND, + "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %ld, %08lx\n", + ret, GetLastError()); + SetLastError(0xdeadbeef); + ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info); + ok(ret == 0 && GetLastError() == CRYPT_E_ASN1_EOD, + "Expected length 0 and CRYPT_E_ASN1_EOD, got length %ld, %08lx\n", + ret, GetLastError()); + /* With a nearly-empty public key info */ + info.Algorithm.pszObjId = oid_rsa_rsa; + SetLastError(0xdeadbeef); + ret = CertGetPublicKeyLength(0, &info); + ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND, + "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %ld, %08lx\n", + ret, GetLastError()); + SetLastError(0xdeadbeef); + ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info); + ok(ret == 0 && GetLastError() == CRYPT_E_ASN1_EOD, + "Expected length 0 and CRYPT_E_ASN1_EOD, got length %ld, %08lx\n", + ret, GetLastError()); + /* With a bogus key */ + info.PublicKey.cbData = sizeof(bogusKey); + info.PublicKey.pbData = bogusKey; + SetLastError(0xdeadbeef); + ret = CertGetPublicKeyLength(0, &info); + ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND, + "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %ld, %08lx\n", + ret, GetLastError()); + SetLastError(0xdeadbeef); + ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info); + ok(ret == 0 && GetLastError() == CRYPT_E_ASN1_BADTAG, + "Expected length 0 and CRYPT_E_ASN1_BADTAGTAG, got length %ld, %08lx\n", + ret, GetLastError()); + /* With a believable RSA key but a bogus OID */ + info.Algorithm.pszObjId = bogusOID; + info.PublicKey.cbData = sizeof(key); + info.PublicKey.pbData = key; + SetLastError(0xdeadbeef); + ret = CertGetPublicKeyLength(0, &info); + ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND, + "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %ld, %08lx\n", + ret, GetLastError()); + SetLastError(0xdeadbeef); + ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info); + ok(ret == 56, "Expected length 56, got %ld\n", ret); + /* An RSA key with the DH OID */ + info.Algorithm.pszObjId = oid_rsa_dh; + SetLastError(0xdeadbeef); + ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info); + ok(ret == 0 && GetLastError() == CRYPT_E_ASN1_BADTAG, + "Expected length 0 and CRYPT_E_ASN1_BADTAG, got length %ld, %08lx\n", + ret, GetLastError()); + /* With the RSA OID */ + info.Algorithm.pszObjId = oid_rsa_rsa; + SetLastError(0xdeadbeef); + ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info); + ok(ret == 56, "Expected length 56, got %ld\n", ret); +} + START_TEST(cert) { init_function_pointers(); @@ -1925,4 +2001,5 @@ START_TEST(cert) testCompareCert(); testVerifySubjectCert(); testAcquireCertPrivateKey(); + testGetPublicKeyLength(); }