2 * crypt32 cert functions tests
4 * Copyright 2005-2006 Juan Lang
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
30 #include "wine/test.h"
32 static BOOL (WINAPI * pCryptVerifyCertificateSignatureEx)
33 (HCRYPTPROV, DWORD, DWORD, void *, DWORD, void *, DWORD, void *);
35 #define CRYPT_GET_PROC(func) \
36 p ## func = (void *)GetProcAddress(hCrypt32, #func); \
38 trace("GetProcAddress(hCrypt32, \"%s\") failed\n", #func); \
40 static void init_function_pointers(void)
44 pCryptVerifyCertificateSignatureEx = NULL;
46 hCrypt32 = GetModuleHandleA("crypt32.dll");
49 CRYPT_GET_PROC(CryptVerifyCertificateSignatureEx);
52 static void testCryptHashCert(void)
54 static const BYTE emptyHash[] = { 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b,
55 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07,
57 static const BYTE knownHash[] = { 0xae, 0x9d, 0xbf, 0x6d, 0xf5, 0x46, 0xee,
58 0x8b, 0xc5, 0x7a, 0x13, 0xba, 0xc2, 0xb1, 0x04, 0xf2, 0xbf, 0x52, 0xa8,
60 static const BYTE toHash[] = "abcdefghijklmnopqrstuvwxyz0123456789.,;!?:";
63 DWORD hashLen = sizeof(hash);
65 /* NULL buffer and nonzero length crashes
66 ret = CryptHashCertificate(0, 0, 0, NULL, size, hash, &hashLen);
67 empty hash length also crashes
68 ret = CryptHashCertificate(0, 0, 0, buf, size, hash, NULL);
71 ret = CryptHashCertificate(0, 0, 0, toHash, sizeof(toHash), NULL,
73 ok(ret, "CryptHashCertificate failed: %08lx\n", GetLastError());
74 ok(hashLen == sizeof(hash),
75 "Got unexpected size of hash %ld, expected %d\n", hashLen, sizeof(hash));
76 /* Test with empty buffer */
77 ret = CryptHashCertificate(0, 0, 0, NULL, 0, hash, &hashLen);
78 ok(ret, "CryptHashCertificate failed: %08lx\n", GetLastError());
79 ok(!memcmp(hash, emptyHash, sizeof(emptyHash)),
80 "Unexpected hash of nothing\n");
81 /* Test a known value */
82 ret = CryptHashCertificate(0, 0, 0, toHash, sizeof(toHash), hash,
84 ok(ret, "CryptHashCertificate failed: %08lx\n", GetLastError());
85 ok(!memcmp(hash, knownHash, sizeof(knownHash)), "Unexpected hash\n");
88 static const WCHAR cspNameW[] = { 'W','i','n','e','C','r','y','p','t','T','e',
91 static void verifySig(HCRYPTPROV csp, const BYTE *toSign, size_t toSignLen,
92 const BYTE *sig, size_t sigLen)
95 BOOL ret = CryptCreateHash(csp, CALG_SHA1, 0, 0, &hash);
97 ok(ret, "CryptCreateHash failed: %08lx\n", GetLastError());
101 DWORD mySigSize = sizeof(mySig);
103 ret = CryptHashData(hash, toSign, toSignLen, 0);
104 ok(ret, "CryptHashData failed: %08lx\n", GetLastError());
105 /* use the A variant so the test can run on Win9x */
106 ret = CryptSignHashA(hash, AT_SIGNATURE, NULL, 0, mySig, &mySigSize);
107 ok(ret, "CryptSignHash failed: %08lx\n", GetLastError());
110 ok(mySigSize == sigLen, "Expected sig length %d, got %ld\n",
112 ok(!memcmp(mySig, sig, sigLen), "Unexpected signature\n");
114 CryptDestroyHash(hash);
118 /* Tests signing the certificate described by toBeSigned with the CSP passed in,
119 * using the algorithm with OID sigOID. The CSP is assumed to be empty, and a
120 * keyset named AT_SIGNATURE will be added to it. The signing key will be
121 * stored in *key, and the signature will be stored in sig. sigLen should be
124 static void testSignCert(HCRYPTPROV csp, const CRYPT_DATA_BLOB *toBeSigned,
125 LPCSTR sigOID, HCRYPTKEY *key, BYTE *sig, DWORD *sigLen)
129 CRYPT_ALGORITHM_IDENTIFIER algoID = { NULL, { 0, NULL } };
132 ret = CryptSignCertificate(0, 0, 0, NULL, 0, NULL, NULL, NULL, NULL);
133 ret = CryptSignCertificate(0, 0, 0, NULL, 0, NULL, NULL, NULL, &size);
134 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
135 NULL, NULL, NULL, &size);
137 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
138 &algoID, NULL, NULL, &size);
139 ok(!ret && GetLastError() == NTE_BAD_ALGID,
140 "Expected NTE_BAD_ALGID, got %08lx\n", GetLastError());
141 algoID.pszObjId = (LPSTR)sigOID;
142 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
143 &algoID, NULL, NULL, &size);
144 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
145 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
146 ret = CryptSignCertificate(0, AT_SIGNATURE, 0, toBeSigned->pbData,
147 toBeSigned->cbData, &algoID, NULL, NULL, &size);
148 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
149 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
151 /* No keys exist in the new CSP yet.. */
152 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
153 toBeSigned->cbData, &algoID, NULL, NULL, &size);
154 ok(!ret && (GetLastError() == NTE_BAD_KEYSET || GetLastError() ==
155 NTE_NO_KEY), "Expected NTE_BAD_KEYSET or NTE_NO_KEY, got %08lx\n",
157 ret = CryptGenKey(csp, AT_SIGNATURE, 0, key);
158 ok(ret, "CryptGenKey failed: %08lx\n", GetLastError());
161 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
162 toBeSigned->cbData, &algoID, NULL, NULL, &size);
163 ok(ret, "CryptSignCertificate failed: %08lx\n", GetLastError());
164 ok(size <= *sigLen, "Expected size <= %ld, got %ld\n", *sigLen, size);
167 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
168 toBeSigned->cbData, &algoID, NULL, sig, &size);
169 ok(ret, "CryptSignCertificate failed: %08lx\n", GetLastError());
173 verifySig(csp, toBeSigned->pbData, toBeSigned->cbData, sig,
180 static void testVerifyCertSig(HCRYPTPROV csp, const CRYPT_DATA_BLOB *toBeSigned,
181 LPCSTR sigOID, const BYTE *sig, DWORD sigLen)
183 CERT_SIGNED_CONTENT_INFO info;
188 if(pCryptVerifyCertificateSignatureEx) {
189 ret = pCryptVerifyCertificateSignatureEx(0, 0, 0, NULL, 0, NULL, 0, NULL);
190 ok(!ret && GetLastError() == E_INVALIDARG,
191 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
192 ret = pCryptVerifyCertificateSignatureEx(csp, 0, 0, NULL, 0, NULL, 0, NULL);
193 ok(!ret && GetLastError() == E_INVALIDARG,
194 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
195 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING, 0, NULL, 0,
197 ok(!ret && GetLastError() == E_INVALIDARG,
198 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
200 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
201 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, NULL, 0, NULL, 0, NULL);
204 info.ToBeSigned.cbData = toBeSigned->cbData;
205 info.ToBeSigned.pbData = toBeSigned->pbData;
206 info.SignatureAlgorithm.pszObjId = (LPSTR)sigOID;
207 info.SignatureAlgorithm.Parameters.cbData = 0;
208 info.Signature.cbData = sigLen;
209 info.Signature.pbData = (BYTE *)sig;
210 info.Signature.cUnusedBits = 0;
211 ret = CryptEncodeObjectEx(X509_ASN_ENCODING, X509_CERT, &info,
212 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&cert, &size);
213 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
216 CRYPT_DATA_BLOB certBlob = { 0, NULL };
217 PCERT_PUBLIC_KEY_INFO pubKeyInfo = NULL;
219 if(pCryptVerifyCertificateSignatureEx) {
220 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
221 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
222 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
223 "Expected CRYPT_E_ASN1_EOD, got %08lx\n", GetLastError());
225 certBlob.pbData = (void *)0xdeadbeef;
226 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
227 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
228 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
229 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
230 certBlob.cbData = size;
231 certBlob.pbData = cert;
232 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
233 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
234 ok(!ret && GetLastError() == E_INVALIDARG,
235 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
236 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
237 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
238 CRYPT_VERIFY_CERT_SIGN_ISSUER_NULL, NULL, 0, NULL);
239 ok(!ret && GetLastError() == E_INVALIDARG,
240 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
242 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
243 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
244 CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY, NULL, 0, NULL);
247 CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
248 (LPSTR)sigOID, 0, NULL, NULL, &size);
249 pubKeyInfo = HeapAlloc(GetProcessHeap(), 0, size);
252 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
253 X509_ASN_ENCODING, (LPSTR)sigOID, 0, NULL, pubKeyInfo, &size);
254 ok(ret, "CryptExportKey failed: %08lx\n", GetLastError());
255 if (ret && pCryptVerifyCertificateSignatureEx)
257 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
258 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
259 CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY, pubKeyInfo, 0, NULL);
260 ok(ret, "CryptVerifyCertificateSignatureEx failed: %08lx\n",
263 HeapFree(GetProcessHeap(), 0, pubKeyInfo);
269 static const BYTE emptyCert[] = { 0x30, 0x00 };
271 static void testCertSigs(void)
274 CRYPT_DATA_BLOB toBeSigned = { sizeof(emptyCert), (LPBYTE)emptyCert };
278 DWORD sigSize = sizeof(sig);
280 /* Just in case a previous run failed, delete this thing */
281 CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
283 ret = CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
285 ok(ret, "CryptAcquireContext failed: %08lx\n", GetLastError());
287 testSignCert(csp, &toBeSigned, szOID_RSA_SHA1RSA, &key, sig, &sigSize);
288 testVerifyCertSig(csp, &toBeSigned, szOID_RSA_SHA1RSA, sig, sigSize);
290 CryptDestroyKey(key);
291 CryptReleaseContext(csp, 0);
292 ret = CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
296 static const BYTE subjectName[] = { 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
297 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
300 static void testCreateSelfSignCert(void)
302 PCCERT_CONTEXT context;
303 CERT_NAME_BLOB name = { sizeof(subjectName), (LPBYTE)subjectName };
309 context = CertCreateSelfSignCertificate(0, NULL, 0, NULL, NULL, NULL, NULL,
311 * Calling this with no first parameter creates a new key container, which
312 * lasts beyond the test, so I don't test that. Nb: the generated key
314 context = CertCreateSelfSignCertificate(0, &name, 0, NULL, NULL, NULL, NULL,
319 CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
321 ret = CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
323 ok(ret, "CryptAcquireContext failed: %08lx\n", GetLastError());
325 context = CertCreateSelfSignCertificate(csp, &name, 0, NULL, NULL, NULL,
327 ok(!context && GetLastError() == NTE_NO_KEY,
328 "Expected NTE_NO_KEY, got %08lx\n", GetLastError());
329 ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
330 ok(ret, "CryptGenKey failed: %08lx\n", GetLastError());
333 context = CertCreateSelfSignCertificate(csp, &name, 0, NULL, NULL, NULL,
335 ok(context != NULL, "CertCreateSelfSignCertificate failed: %08lx\n",
340 PCRYPT_KEY_PROV_INFO info;
342 /* The context must have a key provider info property */
343 ret = CertGetCertificateContextProperty(context,
344 CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
345 ok(ret && size, "Expected non-zero key provider info\n");
348 info = HeapAlloc(GetProcessHeap(), 0, size);
351 ret = CertGetCertificateContextProperty(context,
352 CERT_KEY_PROV_INFO_PROP_ID, info, &size);
353 ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
357 /* Sanity-check the key provider */
358 ok(!lstrcmpW(info->pwszContainerName, cspNameW),
359 "Unexpected key container\n");
360 ok(!lstrcmpW(info->pwszProvName, MS_DEF_PROV_W),
361 "Unexpected provider\n");
362 ok(info->dwKeySpec == AT_SIGNATURE,
363 "Expected AT_SIGNATURE, got %ld\n", info->dwKeySpec);
365 HeapFree(GetProcessHeap(), 0, info);
369 CertFreeCertificateContext(context);
372 CryptDestroyKey(key);
375 CryptReleaseContext(csp, 0);
376 ret = CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
380 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
381 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
382 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
383 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
384 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
385 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
386 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
387 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
388 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
389 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
391 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
392 szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
394 static const BYTE certWithUsage[] = { 0x30, 0x81, 0x93, 0x02, 0x01, 0x01, 0x30,
395 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04,
396 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00,
397 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
398 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
399 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31,
400 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61,
401 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00,
402 0x03, 0x01, 0x00, 0xa3, 0x2f, 0x30, 0x2d, 0x30, 0x2b, 0x06, 0x03, 0x55, 0x1d,
403 0x25, 0x01, 0x01, 0xff, 0x04, 0x21, 0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01,
404 0x05, 0x05, 0x07, 0x03, 0x03, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
405 0x03, 0x02, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
407 static void testKeyUsage(void)
410 PCCERT_CONTEXT context;
413 /* Test base cases */
414 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, NULL);
415 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
416 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
418 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, &size);
419 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
420 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
422 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, &size);
423 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
424 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
426 ret = CertSetEnhancedKeyUsage(NULL, NULL);
427 usage.cUsageIdentifier = 0;
428 ret = CertSetEnhancedKeyUsage(NULL, &usage);
430 /* Test with a cert with no enhanced key usage extension */
431 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
433 ok(context != NULL, "CertCreateCertificateContext failed: %08lx\n",
437 static const char oid[] = "1.2.3.4";
438 BYTE buf[sizeof(CERT_ENHKEY_USAGE) + 2 * (sizeof(LPSTR) + sizeof(oid))];
439 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
441 ret = CertGetEnhancedKeyUsage(context, 0, NULL, NULL);
442 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
443 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
445 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &size);
448 /* Windows 2000, ME, or later: even though it succeeded, we expect
449 * CRYPT_E_NOT_FOUND, which indicates there is no enhanced key
450 * usage set for this cert (which implies it's valid for all uses.)
452 ok(GetLastError() == CRYPT_E_NOT_FOUND,
453 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
454 ok(size == sizeof(CERT_ENHKEY_USAGE), "Expected size %d, got %ld\n",
455 sizeof(CERT_ENHKEY_USAGE), size);
456 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
457 ok(ret, "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
458 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %ld\n",
459 pUsage->cUsageIdentifier);
463 /* Windows NT, 95, or 98: it fails, and the last error is
466 ok(GetLastError() == CRYPT_E_NOT_FOUND,
467 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
469 /* I can add a usage identifier when no key usage has been set */
470 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
471 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08lx\n",
474 ret = CertGetEnhancedKeyUsage(context,
475 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
476 ok(ret && GetLastError() == 0,
477 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
478 ok(pUsage->cUsageIdentifier == 1, "Expected 1 usage, got %ld\n",
479 pUsage->cUsageIdentifier);
480 if (pUsage->cUsageIdentifier)
481 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
482 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
483 /* Now set an empty key usage */
484 pUsage->cUsageIdentifier = 0;
485 ret = CertSetEnhancedKeyUsage(context, pUsage);
486 ok(ret, "CertSetEnhancedKeyUsage failed: %08lx\n", GetLastError());
487 /* Shouldn't find it in the cert */
489 ret = CertGetEnhancedKeyUsage(context,
490 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
491 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
492 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
493 /* Should find it as an extended property */
494 ret = CertGetEnhancedKeyUsage(context,
495 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
496 ok(ret && GetLastError() == 0,
497 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
498 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %ld\n",
499 pUsage->cUsageIdentifier);
500 /* Should find it as either */
501 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
502 ok(ret && GetLastError() == 0,
503 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
504 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %ld\n",
505 pUsage->cUsageIdentifier);
506 /* Add a usage identifier */
507 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
508 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08lx\n",
511 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
512 ok(ret && GetLastError() == 0,
513 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
514 ok(pUsage->cUsageIdentifier == 1, "Expected 1 identifier, got %ld\n",
515 pUsage->cUsageIdentifier);
516 if (pUsage->cUsageIdentifier)
517 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
518 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
519 /* Yep, I can re-add the same usage identifier */
520 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
521 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08lx\n",
524 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
525 ok(ret && GetLastError() == 0,
526 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
527 ok(pUsage->cUsageIdentifier == 2, "Expected 2 identifiers, got %ld\n",
528 pUsage->cUsageIdentifier);
529 if (pUsage->cUsageIdentifier)
530 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
531 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
532 if (pUsage->cUsageIdentifier >= 2)
533 ok(!strcmp(pUsage->rgpszUsageIdentifier[1], oid),
534 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[1]);
535 /* Now set a NULL extended property--this deletes the property. */
536 ret = CertSetEnhancedKeyUsage(context, NULL);
537 ok(ret, "CertSetEnhancedKeyUsage failed: %08lx\n", GetLastError());
538 SetLastError(0xbaadcafe);
540 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
541 ok(GetLastError() == CRYPT_E_NOT_FOUND,
542 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
544 CertFreeCertificateContext(context);
546 /* Now test with a cert with an enhanced key usage extension */
547 context = CertCreateCertificateContext(X509_ASN_ENCODING, certWithUsage,
548 sizeof(certWithUsage));
549 ok(context != NULL, "CertCreateCertificateContext failed: %08lx\n",
554 DWORD bufSize = 0, i;
556 /* The size may depend on what flags are used to query it, so I
557 * realloc the buffer for each test.
559 ret = CertGetEnhancedKeyUsage(context,
560 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, NULL, &bufSize);
561 ok(ret, "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
562 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
565 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
567 /* Should find it in the cert */
569 ret = CertGetEnhancedKeyUsage(context,
570 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
571 ok(ret && GetLastError() == 0,
572 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
573 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %ld\n",
574 pUsage->cUsageIdentifier);
575 for (i = 0; i < pUsage->cUsageIdentifier; i++)
576 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
577 "Expected %s, got %s\n", keyUsages[i],
578 pUsage->rgpszUsageIdentifier[i]);
579 HeapFree(GetProcessHeap(), 0, buf);
581 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
582 ok(ret, "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
583 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
586 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
588 /* Should find it as either */
590 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
591 /* In Windows, GetLastError returns CRYPT_E_NOT_FOUND not found
592 * here, even though the return is successful and the usage id
593 * count is positive. I don't enforce that here.
596 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
597 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %ld\n",
598 pUsage->cUsageIdentifier);
599 for (i = 0; i < pUsage->cUsageIdentifier; i++)
600 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
601 "Expected %s, got %s\n", keyUsages[i],
602 pUsage->rgpszUsageIdentifier[i]);
603 HeapFree(GetProcessHeap(), 0, buf);
605 /* Shouldn't find it as an extended property */
606 ret = CertGetEnhancedKeyUsage(context,
607 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, NULL, &size);
608 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
609 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
610 /* Adding a usage identifier overrides the cert's usage!? */
611 ret = CertAddEnhancedKeyUsageIdentifier(context, szOID_RSA_RSA);
612 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08lx\n",
614 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
615 ok(ret, "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
616 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
619 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
621 /* Should find it as either */
623 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
625 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
626 ok(pUsage->cUsageIdentifier == 1, "Expected 1 usage, got %ld\n",
627 pUsage->cUsageIdentifier);
628 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], szOID_RSA_RSA),
629 "Expected %s, got %s\n", szOID_RSA_RSA,
630 pUsage->rgpszUsageIdentifier[0]);
631 HeapFree(GetProcessHeap(), 0, buf);
633 /* But querying the cert directly returns its usage */
634 ret = CertGetEnhancedKeyUsage(context,
635 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, NULL, &bufSize);
636 ok(ret, "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
637 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
640 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
643 ret = CertGetEnhancedKeyUsage(context,
644 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
646 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
647 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %ld\n",
648 pUsage->cUsageIdentifier);
649 for (i = 0; i < pUsage->cUsageIdentifier; i++)
650 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
651 "Expected %s, got %s\n", keyUsages[i],
652 pUsage->rgpszUsageIdentifier[i]);
653 HeapFree(GetProcessHeap(), 0, buf);
655 /* And removing the only usage identifier in the extended property
656 * results in the cert's key usage being found.
658 ret = CertRemoveEnhancedKeyUsageIdentifier(context, szOID_RSA_RSA);
659 ok(ret, "CertRemoveEnhancedKeyUsage failed: %08lx\n", GetLastError());
660 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
661 ok(ret, "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
662 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
665 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
667 /* Should find it as either */
669 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
671 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
672 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %ld\n",
673 pUsage->cUsageIdentifier);
674 for (i = 0; i < pUsage->cUsageIdentifier; i++)
675 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
676 "Expected %s, got %s\n", keyUsages[i],
677 pUsage->rgpszUsageIdentifier[i]);
678 HeapFree(GetProcessHeap(), 0, buf);
681 CertFreeCertificateContext(context);
685 static void testCompareCertName(void)
687 static const BYTE bogus[] = { 1, 2, 3, 4 };
688 static const BYTE bogusPrime[] = { 0, 1, 2, 3, 4 };
689 static const BYTE emptyPrime[] = { 0x30, 0x00, 0x01 };
691 CERT_NAME_BLOB blob1, blob2;
694 ret = CertCompareCertificateName(0, NULL, NULL);
696 /* An empty name checks against itself.. */
697 blob1.pbData = (LPBYTE)emptyCert;
698 blob1.cbData = sizeof(emptyCert);
699 ret = CertCompareCertificateName(0, &blob1, &blob1);
700 ok(ret, "CertCompareCertificateName failed: %08lx\n", GetLastError());
701 /* It doesn't have to be a valid encoded name.. */
702 blob1.pbData = (LPBYTE)bogus;
703 blob1.cbData = sizeof(bogus);
704 ret = CertCompareCertificateName(0, &blob1, &blob1);
705 ok(ret, "CertCompareCertificateName failed: %08lx\n", GetLastError());
706 /* Leading zeroes matter.. */
707 blob2.pbData = (LPBYTE)bogusPrime;
708 blob2.cbData = sizeof(bogusPrime);
709 ret = CertCompareCertificateName(0, &blob1, &blob2);
710 ok(!ret, "Expected failure\n");
711 /* As do trailing extra bytes. */
712 blob2.pbData = (LPBYTE)emptyPrime;
713 blob2.cbData = sizeof(emptyPrime);
714 ret = CertCompareCertificateName(0, &blob1, &blob2);
715 ok(!ret, "Expected failure\n");
718 static const BYTE int1[] = { 0x88, 0xff, 0xff, 0xff };
719 static const BYTE int2[] = { 0x88, 0xff };
720 static const BYTE int3[] = { 0x23, 0xff };
721 static const BYTE int4[] = { 0x7f, 0x00 };
722 static const BYTE int5[] = { 0x7f };
723 static const BYTE int6[] = { 0x80, 0x00, 0x00, 0x00 };
724 static const BYTE int7[] = { 0x80, 0x00 };
728 CRYPT_INTEGER_BLOB blob1;
729 CRYPT_INTEGER_BLOB blob2;
732 { { sizeof(int1), (LPBYTE)int1 }, { sizeof(int2), (LPBYTE)int2 }, TRUE },
733 { { sizeof(int3), (LPBYTE)int3 }, { sizeof(int3), (LPBYTE)int3 }, TRUE },
734 { { sizeof(int4), (LPBYTE)int4 }, { sizeof(int5), (LPBYTE)int5 }, TRUE },
735 { { sizeof(int6), (LPBYTE)int6 }, { sizeof(int7), (LPBYTE)int7 }, TRUE },
736 { { sizeof(int1), (LPBYTE)int1 }, { sizeof(int7), (LPBYTE)int7 }, FALSE },
739 static void testCompareIntegerBlob(void)
744 for (i = 0; i < sizeof(intBlobs) / sizeof(intBlobs[0]); i++)
746 ret = CertCompareIntegerBlob(&intBlobs[i].blob1, &intBlobs[i].blob2);
747 ok(ret == intBlobs[i].areEqual,
748 "%ld: expected blobs %s compare\n", i, intBlobs[i].areEqual ?
753 static void testComparePublicKeyInfo(void)
756 CERT_PUBLIC_KEY_INFO info1 = { { 0 } }, info2 = { { 0 } };
757 static CHAR oid_rsa_rsa[] = szOID_RSA_RSA;
758 static CHAR oid_rsa_sha1rsa[] = szOID_RSA_SHA1RSA;
759 static CHAR oid_x957_dsa[] = szOID_X957_DSA;
760 static const BYTE bits1[] = { 1, 0 };
761 static const BYTE bits2[] = { 0 };
762 static const BYTE bits3[] = { 1 };
765 ret = CertComparePublicKeyInfo(0, NULL, NULL);
767 /* Empty public keys compare */
768 ret = CertComparePublicKeyInfo(0, &info1, &info2);
769 ok(ret, "CertComparePublicKeyInfo failed: %08lx\n", GetLastError());
770 /* Different OIDs appear to compare */
771 info1.Algorithm.pszObjId = oid_rsa_rsa;
772 info2.Algorithm.pszObjId = oid_rsa_sha1rsa;
773 ret = CertComparePublicKeyInfo(0, &info1, &info2);
774 ok(ret, "CertComparePublicKeyInfo failed: %08lx\n", GetLastError());
775 info2.Algorithm.pszObjId = oid_x957_dsa;
776 ret = CertComparePublicKeyInfo(0, &info1, &info2);
777 ok(ret, "CertComparePublicKeyInfo failed: %08lx\n", GetLastError());
778 info1.PublicKey.cbData = sizeof(bits1);
779 info1.PublicKey.pbData = (LPBYTE)bits1;
780 info1.PublicKey.cUnusedBits = 0;
781 info2.PublicKey.cbData = sizeof(bits1);
782 info2.PublicKey.pbData = (LPBYTE)bits1;
783 info2.PublicKey.cUnusedBits = 0;
784 ret = CertComparePublicKeyInfo(0, &info1, &info2);
785 ok(ret, "CertComparePublicKeyInfo failed: %08lx\n", GetLastError());
786 /* Even though they compare in their used bits, these do not compare */
787 info1.PublicKey.cbData = sizeof(bits2);
788 info1.PublicKey.pbData = (LPBYTE)bits2;
789 info1.PublicKey.cUnusedBits = 0;
790 info2.PublicKey.cbData = sizeof(bits3);
791 info2.PublicKey.pbData = (LPBYTE)bits3;
792 info2.PublicKey.cUnusedBits = 1;
793 ret = CertComparePublicKeyInfo(0, &info1, &info2);
794 /* Simple (non-comparing) case */
795 ok(!ret, "Expected keys not to compare\n");
796 info2.PublicKey.cbData = sizeof(bits1);
797 info2.PublicKey.pbData = (LPBYTE)bits1;
798 info2.PublicKey.cUnusedBits = 0;
799 ret = CertComparePublicKeyInfo(0, &info1, &info2);
800 ok(!ret, "Expected keys not to compare\n");
803 static const BYTE subjectName2[] = { 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
804 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61,
807 static const BYTE serialNum[] = { 1 };
809 void testCompareCert(void)
811 CERT_INFO info1 = { 0 }, info2 = { 0 };
815 ret = CertCompareCertificate(X509_ASN_ENCODING, NULL, NULL);
818 /* Certs with the same issuer and serial number are equal, even if they
819 * differ in other respects (like subject).
821 info1.SerialNumber.pbData = (LPBYTE)serialNum;
822 info1.SerialNumber.cbData = sizeof(serialNum);
823 info1.Issuer.pbData = (LPBYTE)subjectName;
824 info1.Issuer.cbData = sizeof(subjectName);
825 info1.Subject.pbData = (LPBYTE)subjectName2;
826 info1.Subject.cbData = sizeof(subjectName2);
827 info2.SerialNumber.pbData = (LPBYTE)serialNum;
828 info2.SerialNumber.cbData = sizeof(serialNum);
829 info2.Issuer.pbData = (LPBYTE)subjectName;
830 info2.Issuer.cbData = sizeof(subjectName);
831 info2.Subject.pbData = (LPBYTE)subjectName;
832 info2.Subject.cbData = sizeof(subjectName);
833 ret = CertCompareCertificate(X509_ASN_ENCODING, &info1, &info2);
834 ok(ret, "Expected certs to be equal\n");
836 info2.Issuer.pbData = (LPBYTE)subjectName2;
837 info2.Issuer.cbData = sizeof(subjectName2);
838 ret = CertCompareCertificate(X509_ASN_ENCODING, &info1, &info2);
839 ok(!ret, "Expected certs not to be equal\n");
842 static const BYTE bigCertWithDifferentSubject[] = { 0x30, 0x7a, 0x02, 0x01, 0x02,
843 0x30, 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
844 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67,
845 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31,
846 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
847 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15,
848 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c,
849 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06,
850 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55,
851 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02,
854 static void testVerifySubjectCert(void)
858 PCCERT_CONTEXT context1, context2;
861 ret = CertVerifySubjectCertificateContext(NULL, NULL, NULL);
864 ret = CertVerifySubjectCertificateContext(NULL, NULL, &flags);
865 ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n",
867 flags = CERT_STORE_NO_CRL_FLAG;
868 ret = CertVerifySubjectCertificateContext(NULL, NULL, &flags);
869 ok(!ret && GetLastError() == E_INVALIDARG,
870 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
873 context1 = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
875 ret = CertVerifySubjectCertificateContext(NULL, context1, &flags);
876 ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n",
878 ret = CertVerifySubjectCertificateContext(context1, NULL, &flags);
879 ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n",
881 ret = CertVerifySubjectCertificateContext(context1, context1, &flags);
882 ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n",
885 context2 = CertCreateCertificateContext(X509_ASN_ENCODING,
886 bigCertWithDifferentSubject, sizeof(bigCertWithDifferentSubject));
887 SetLastError(0xdeadbeef);
888 ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
889 ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n",
891 flags = CERT_STORE_REVOCATION_FLAG;
892 ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
893 ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n",
895 ok(flags == (CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG),
896 "Expected CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG, got %08lx\n",
898 flags = CERT_STORE_SIGNATURE_FLAG;
899 ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
900 ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n",
902 ok(flags == CERT_STORE_SIGNATURE_FLAG,
903 "Expected CERT_STORE_SIGNATURE_FLAG, got %08lx\n", flags);
904 CertFreeCertificateContext(context2);
906 CertFreeCertificateContext(context1);
911 init_function_pointers();
914 testCreateSelfSignCert();
916 testCompareCertName();
917 testCompareIntegerBlob();
918 testComparePublicKeyInfo();
920 testVerifySubjectCert();