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), "Got unexpected size of hash %ld\n", hashLen);
75 /* Test with empty buffer */
76 ret = CryptHashCertificate(0, 0, 0, NULL, 0, hash, &hashLen);
77 ok(ret, "CryptHashCertificate failed: %08lx\n", GetLastError());
78 ok(!memcmp(hash, emptyHash, sizeof(emptyHash)),
79 "Unexpected hash of nothing\n");
80 /* Test a known value */
81 ret = CryptHashCertificate(0, 0, 0, toHash, sizeof(toHash), hash,
83 ok(ret, "CryptHashCertificate failed: %08lx\n", GetLastError());
84 ok(!memcmp(hash, knownHash, sizeof(knownHash)), "Unexpected hash\n");
87 static const WCHAR cspNameW[] = { 'W','i','n','e','C','r','y','p','t','T','e',
90 static void verifySig(HCRYPTPROV csp, const BYTE *toSign, size_t toSignLen,
91 const BYTE *sig, unsigned int sigLen)
94 BOOL ret = CryptCreateHash(csp, CALG_SHA1, 0, 0, &hash);
96 ok(ret, "CryptCreateHash failed: %08lx\n", GetLastError());
100 DWORD mySigSize = sizeof(mySig);
102 ret = CryptHashData(hash, toSign, toSignLen, 0);
103 ok(ret, "CryptHashData failed: %08lx\n", GetLastError());
104 /* use the A variant so the test can run on Win9x */
105 ret = CryptSignHashA(hash, AT_SIGNATURE, NULL, 0, mySig, &mySigSize);
106 ok(ret, "CryptSignHash failed: %08lx\n", GetLastError());
109 ok(mySigSize == sigLen, "Expected sig length %d, got %ld\n",
111 ok(!memcmp(mySig, sig, sigLen), "Unexpected signature\n");
113 CryptDestroyHash(hash);
117 /* Tests signing the certificate described by toBeSigned with the CSP passed in,
118 * using the algorithm with OID sigOID. The CSP is assumed to be empty, and a
119 * keyset named AT_SIGNATURE will be added to it. The signing key will be
120 * stored in *key, and the signature will be stored in sig. sigLen should be
123 static void testSignCert(HCRYPTPROV csp, const CRYPT_DATA_BLOB *toBeSigned,
124 LPCSTR sigOID, HCRYPTKEY *key, BYTE *sig, DWORD *sigLen)
128 CRYPT_ALGORITHM_IDENTIFIER algoID = { NULL, { 0, NULL } };
131 ret = CryptSignCertificate(0, 0, 0, NULL, 0, NULL, NULL, NULL, NULL);
132 ret = CryptSignCertificate(0, 0, 0, NULL, 0, NULL, NULL, NULL, &size);
133 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
134 NULL, NULL, NULL, &size);
136 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
137 &algoID, NULL, NULL, &size);
138 ok(!ret && GetLastError() == NTE_BAD_ALGID,
139 "Expected NTE_BAD_ALGID, got %08lx\n", GetLastError());
140 algoID.pszObjId = (LPSTR)sigOID;
141 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
142 &algoID, NULL, NULL, &size);
143 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
144 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
145 ret = CryptSignCertificate(0, AT_SIGNATURE, 0, toBeSigned->pbData,
146 toBeSigned->cbData, &algoID, NULL, NULL, &size);
147 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
148 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
150 /* No keys exist in the new CSP yet.. */
151 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
152 toBeSigned->cbData, &algoID, NULL, NULL, &size);
153 ok(!ret && (GetLastError() == NTE_BAD_KEYSET || GetLastError() ==
154 NTE_NO_KEY), "Expected NTE_BAD_KEYSET or NTE_NO_KEY, got %08lx\n",
156 ret = CryptGenKey(csp, AT_SIGNATURE, 0, key);
157 ok(ret, "CryptGenKey failed: %08lx\n", GetLastError());
160 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
161 toBeSigned->cbData, &algoID, NULL, NULL, &size);
162 ok(ret, "CryptSignCertificate failed: %08lx\n", GetLastError());
163 ok(size <= *sigLen, "Expected size <= %ld, got %ld\n", *sigLen, size);
166 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
167 toBeSigned->cbData, &algoID, NULL, sig, &size);
168 ok(ret, "CryptSignCertificate failed: %08lx\n", GetLastError());
172 verifySig(csp, toBeSigned->pbData, toBeSigned->cbData, sig,
179 static void testVerifyCertSig(HCRYPTPROV csp, const CRYPT_DATA_BLOB *toBeSigned,
180 LPCSTR sigOID, const BYTE *sig, DWORD sigLen)
182 CERT_SIGNED_CONTENT_INFO info;
187 if(pCryptVerifyCertificateSignatureEx) {
188 ret = pCryptVerifyCertificateSignatureEx(0, 0, 0, NULL, 0, NULL, 0, NULL);
189 ok(!ret && GetLastError() == E_INVALIDARG,
190 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
191 ret = pCryptVerifyCertificateSignatureEx(csp, 0, 0, NULL, 0, NULL, 0, NULL);
192 ok(!ret && GetLastError() == E_INVALIDARG,
193 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
194 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING, 0, NULL, 0,
196 ok(!ret && GetLastError() == E_INVALIDARG,
197 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
199 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
200 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, NULL, 0, NULL, 0, NULL);
203 info.ToBeSigned.cbData = toBeSigned->cbData;
204 info.ToBeSigned.pbData = toBeSigned->pbData;
205 info.SignatureAlgorithm.pszObjId = (LPSTR)sigOID;
206 info.SignatureAlgorithm.Parameters.cbData = 0;
207 info.Signature.cbData = sigLen;
208 info.Signature.pbData = (BYTE *)sig;
209 info.Signature.cUnusedBits = 0;
210 ret = CryptEncodeObjectEx(X509_ASN_ENCODING, X509_CERT, &info,
211 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&cert, &size);
212 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
215 CRYPT_DATA_BLOB certBlob = { 0, NULL };
216 PCERT_PUBLIC_KEY_INFO pubKeyInfo = NULL;
218 if(pCryptVerifyCertificateSignatureEx) {
219 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
220 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
221 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
222 "Expected CRYPT_E_ASN1_EOD, got %08lx\n", GetLastError());
224 certBlob.pbData = (void *)0xdeadbeef;
225 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
226 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
227 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
228 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
229 certBlob.cbData = size;
230 certBlob.pbData = cert;
231 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
232 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
233 ok(!ret && GetLastError() == E_INVALIDARG,
234 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
235 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
236 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
237 CRYPT_VERIFY_CERT_SIGN_ISSUER_NULL, NULL, 0, NULL);
238 ok(!ret && GetLastError() == E_INVALIDARG,
239 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
241 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
242 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
243 CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY, NULL, 0, NULL);
246 CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
247 (LPSTR)sigOID, 0, NULL, NULL, &size);
248 pubKeyInfo = HeapAlloc(GetProcessHeap(), 0, size);
251 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
252 X509_ASN_ENCODING, (LPSTR)sigOID, 0, NULL, pubKeyInfo, &size);
253 ok(ret, "CryptExportKey failed: %08lx\n", GetLastError());
254 if (ret && pCryptVerifyCertificateSignatureEx)
256 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
257 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
258 CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY, pubKeyInfo, 0, NULL);
259 ok(ret, "CryptVerifyCertificateSignatureEx failed: %08lx\n",
262 HeapFree(GetProcessHeap(), 0, pubKeyInfo);
268 static const BYTE emptyCert[] = { 0x30, 0x00 };
270 static void testCertSigs(void)
273 CRYPT_DATA_BLOB toBeSigned = { sizeof(emptyCert), (LPBYTE)emptyCert };
277 DWORD sigSize = sizeof(sig);
279 /* Just in case a previous run failed, delete this thing */
280 CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
282 ret = CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
284 ok(ret, "CryptAcquireContext failed: %08lx\n", GetLastError());
286 testSignCert(csp, &toBeSigned, szOID_RSA_SHA1RSA, &key, sig, &sigSize);
287 testVerifyCertSig(csp, &toBeSigned, szOID_RSA_SHA1RSA, sig, sigSize);
289 CryptDestroyKey(key);
290 CryptReleaseContext(csp, 0);
291 ret = CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
295 static const BYTE subjectName[] = { 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
296 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
299 static void testCreateSelfSignCert(void)
301 PCCERT_CONTEXT context;
302 CERT_NAME_BLOB name = { sizeof(subjectName), (LPBYTE)subjectName };
308 context = CertCreateSelfSignCertificate(0, NULL, 0, NULL, NULL, NULL, NULL,
310 * Calling this with no first parameter creates a new key container, which
311 * lasts beyond the test, so I don't test that. Nb: the generated key
313 context = CertCreateSelfSignCertificate(0, &name, 0, NULL, NULL, NULL, NULL,
318 CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
320 ret = CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
322 ok(ret, "CryptAcquireContext failed: %08lx\n", GetLastError());
324 context = CertCreateSelfSignCertificate(csp, &name, 0, NULL, NULL, NULL,
326 ok(!context && GetLastError() == NTE_NO_KEY,
327 "Expected NTE_NO_KEY, got %08lx\n", GetLastError());
328 ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
329 ok(ret, "CryptGenKey failed: %08lx\n", GetLastError());
332 context = CertCreateSelfSignCertificate(csp, &name, 0, NULL, NULL, NULL,
334 ok(context != NULL, "CertCreateSelfSignCertificate failed: %08lx\n",
339 PCRYPT_KEY_PROV_INFO info;
341 /* The context must have a key provider info property */
342 ret = CertGetCertificateContextProperty(context,
343 CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
344 ok(ret && size, "Expected non-zero key provider info\n");
347 info = HeapAlloc(GetProcessHeap(), 0, size);
350 ret = CertGetCertificateContextProperty(context,
351 CERT_KEY_PROV_INFO_PROP_ID, info, &size);
352 ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
356 /* Sanity-check the key provider */
357 ok(!lstrcmpW(info->pwszContainerName, cspNameW),
358 "Unexpected key container\n");
359 ok(!lstrcmpW(info->pwszProvName, MS_DEF_PROV_W),
360 "Unexpected provider\n");
361 ok(info->dwKeySpec == AT_SIGNATURE,
362 "Expected AT_SIGNATURE, got %ld\n", info->dwKeySpec);
364 HeapFree(GetProcessHeap(), 0, info);
368 CertFreeCertificateContext(context);
371 CryptDestroyKey(key);
374 CryptReleaseContext(csp, 0);
375 ret = CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
379 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
380 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
381 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
382 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
383 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
384 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
385 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
386 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
387 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
388 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
390 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
391 szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
393 static const BYTE certWithUsage[] = { 0x30, 0x81, 0x93, 0x02, 0x01, 0x01, 0x30,
394 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04,
395 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00,
396 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
397 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
398 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31,
399 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61,
400 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00,
401 0x03, 0x01, 0x00, 0xa3, 0x2f, 0x30, 0x2d, 0x30, 0x2b, 0x06, 0x03, 0x55, 0x1d,
402 0x25, 0x01, 0x01, 0xff, 0x04, 0x21, 0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01,
403 0x05, 0x05, 0x07, 0x03, 0x03, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
404 0x03, 0x02, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
406 static void testKeyUsage(void)
409 PCCERT_CONTEXT context;
412 /* Test base cases */
413 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, NULL);
414 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
415 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
417 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, &size);
418 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
419 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
421 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, &size);
422 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
423 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
425 ret = CertSetEnhancedKeyUsage(NULL, NULL);
426 usage.cUsageIdentifier = 0;
427 ret = CertSetEnhancedKeyUsage(NULL, &usage);
429 /* Test with a cert with no enhanced key usage extension */
430 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
432 ok(context != NULL, "CertCreateCertificateContext failed: %08lx\n",
436 static const char oid[] = "1.2.3.4";
437 BYTE buf[sizeof(CERT_ENHKEY_USAGE) + 2 * (sizeof(LPSTR) + sizeof(oid))];
438 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
440 ret = CertGetEnhancedKeyUsage(context, 0, NULL, NULL);
441 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
442 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
444 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &size);
447 /* Windows 2000, ME, or later: even though it succeeded, we expect
448 * CRYPT_E_NOT_FOUND, which indicates there is no enhanced key
449 * usage set for this cert (which implies it's valid for all uses.)
451 ok(GetLastError() == CRYPT_E_NOT_FOUND,
452 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
453 ok(size == sizeof(CERT_ENHKEY_USAGE), "Wrong size %ld\n", size);
454 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
455 ok(ret, "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
456 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %ld\n",
457 pUsage->cUsageIdentifier);
461 /* Windows NT, 95, or 98: it fails, and the last error is
464 ok(GetLastError() == CRYPT_E_NOT_FOUND,
465 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
467 /* I can add a usage identifier when no key usage has been set */
468 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
469 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08lx\n",
472 ret = CertGetEnhancedKeyUsage(context,
473 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
474 ok(ret && GetLastError() == 0,
475 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
476 ok(pUsage->cUsageIdentifier == 1, "Expected 1 usage, got %ld\n",
477 pUsage->cUsageIdentifier);
478 if (pUsage->cUsageIdentifier)
479 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
480 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
481 /* Now set an empty key usage */
482 pUsage->cUsageIdentifier = 0;
483 ret = CertSetEnhancedKeyUsage(context, pUsage);
484 ok(ret, "CertSetEnhancedKeyUsage failed: %08lx\n", GetLastError());
485 /* Shouldn't find it in the cert */
487 ret = CertGetEnhancedKeyUsage(context,
488 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
489 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
490 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
491 /* Should find it as an extended property */
492 ret = CertGetEnhancedKeyUsage(context,
493 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
494 ok(ret && GetLastError() == 0,
495 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
496 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %ld\n",
497 pUsage->cUsageIdentifier);
498 /* Should find it as either */
499 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
500 ok(ret && GetLastError() == 0,
501 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
502 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %ld\n",
503 pUsage->cUsageIdentifier);
504 /* Add a usage identifier */
505 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
506 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08lx\n",
509 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
510 ok(ret && GetLastError() == 0,
511 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
512 ok(pUsage->cUsageIdentifier == 1, "Expected 1 identifier, got %ld\n",
513 pUsage->cUsageIdentifier);
514 if (pUsage->cUsageIdentifier)
515 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
516 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
517 /* Yep, I can re-add the same usage identifier */
518 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
519 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08lx\n",
522 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
523 ok(ret && GetLastError() == 0,
524 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
525 ok(pUsage->cUsageIdentifier == 2, "Expected 2 identifiers, got %ld\n",
526 pUsage->cUsageIdentifier);
527 if (pUsage->cUsageIdentifier)
528 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
529 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
530 if (pUsage->cUsageIdentifier >= 2)
531 ok(!strcmp(pUsage->rgpszUsageIdentifier[1], oid),
532 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[1]);
533 /* Now set a NULL extended property--this deletes the property. */
534 ret = CertSetEnhancedKeyUsage(context, NULL);
535 ok(ret, "CertSetEnhancedKeyUsage failed: %08lx\n", GetLastError());
536 SetLastError(0xbaadcafe);
538 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
539 ok(GetLastError() == CRYPT_E_NOT_FOUND,
540 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
542 CertFreeCertificateContext(context);
544 /* Now test with a cert with an enhanced key usage extension */
545 context = CertCreateCertificateContext(X509_ASN_ENCODING, certWithUsage,
546 sizeof(certWithUsage));
547 ok(context != NULL, "CertCreateCertificateContext failed: %08lx\n",
552 DWORD bufSize = 0, i;
554 /* The size may depend on what flags are used to query it, so I
555 * realloc the buffer for each test.
557 ret = CertGetEnhancedKeyUsage(context,
558 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, NULL, &bufSize);
559 ok(ret, "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
560 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
563 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
565 /* Should find it in the cert */
567 ret = CertGetEnhancedKeyUsage(context,
568 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
569 ok(ret && GetLastError() == 0,
570 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
571 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %ld\n",
572 pUsage->cUsageIdentifier);
573 for (i = 0; i < pUsage->cUsageIdentifier; i++)
574 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
575 "Expected %s, got %s\n", keyUsages[i],
576 pUsage->rgpszUsageIdentifier[i]);
577 HeapFree(GetProcessHeap(), 0, buf);
579 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
580 ok(ret, "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
581 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
584 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
586 /* Should find it as either */
588 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
589 /* In Windows, GetLastError returns CRYPT_E_NOT_FOUND not found
590 * here, even though the return is successful and the usage id
591 * count is positive. I don't enforce that here.
594 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
595 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %ld\n",
596 pUsage->cUsageIdentifier);
597 for (i = 0; i < pUsage->cUsageIdentifier; i++)
598 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
599 "Expected %s, got %s\n", keyUsages[i],
600 pUsage->rgpszUsageIdentifier[i]);
601 HeapFree(GetProcessHeap(), 0, buf);
603 /* Shouldn't find it as an extended property */
604 ret = CertGetEnhancedKeyUsage(context,
605 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, NULL, &size);
606 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
607 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
608 /* Adding a usage identifier overrides the cert's usage!? */
609 ret = CertAddEnhancedKeyUsageIdentifier(context, szOID_RSA_RSA);
610 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08lx\n",
612 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
613 ok(ret, "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
614 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
617 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
619 /* Should find it as either */
621 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
623 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
624 ok(pUsage->cUsageIdentifier == 1, "Expected 1 usage, got %ld\n",
625 pUsage->cUsageIdentifier);
626 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], szOID_RSA_RSA),
627 "Expected %s, got %s\n", szOID_RSA_RSA,
628 pUsage->rgpszUsageIdentifier[0]);
629 HeapFree(GetProcessHeap(), 0, buf);
631 /* But querying the cert directly returns its usage */
632 ret = CertGetEnhancedKeyUsage(context,
633 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, NULL, &bufSize);
634 ok(ret, "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
635 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
638 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
641 ret = CertGetEnhancedKeyUsage(context,
642 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
644 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
645 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %ld\n",
646 pUsage->cUsageIdentifier);
647 for (i = 0; i < pUsage->cUsageIdentifier; i++)
648 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
649 "Expected %s, got %s\n", keyUsages[i],
650 pUsage->rgpszUsageIdentifier[i]);
651 HeapFree(GetProcessHeap(), 0, buf);
653 /* And removing the only usage identifier in the extended property
654 * results in the cert's key usage being found.
656 ret = CertRemoveEnhancedKeyUsageIdentifier(context, szOID_RSA_RSA);
657 ok(ret, "CertRemoveEnhancedKeyUsage failed: %08lx\n", GetLastError());
658 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
659 ok(ret, "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
660 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
663 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
665 /* Should find it as either */
667 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
669 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
670 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %ld\n",
671 pUsage->cUsageIdentifier);
672 for (i = 0; i < pUsage->cUsageIdentifier; i++)
673 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
674 "Expected %s, got %s\n", keyUsages[i],
675 pUsage->rgpszUsageIdentifier[i]);
676 HeapFree(GetProcessHeap(), 0, buf);
679 CertFreeCertificateContext(context);
683 static void testCompareCertName(void)
685 static const BYTE bogus[] = { 1, 2, 3, 4 };
686 static const BYTE bogusPrime[] = { 0, 1, 2, 3, 4 };
687 static const BYTE emptyPrime[] = { 0x30, 0x00, 0x01 };
689 CERT_NAME_BLOB blob1, blob2;
692 ret = CertCompareCertificateName(0, NULL, NULL);
694 /* An empty name checks against itself.. */
695 blob1.pbData = (LPBYTE)emptyCert;
696 blob1.cbData = sizeof(emptyCert);
697 ret = CertCompareCertificateName(0, &blob1, &blob1);
698 ok(ret, "CertCompareCertificateName failed: %08lx\n", GetLastError());
699 /* It doesn't have to be a valid encoded name.. */
700 blob1.pbData = (LPBYTE)bogus;
701 blob1.cbData = sizeof(bogus);
702 ret = CertCompareCertificateName(0, &blob1, &blob1);
703 ok(ret, "CertCompareCertificateName failed: %08lx\n", GetLastError());
704 /* Leading zeroes matter.. */
705 blob2.pbData = (LPBYTE)bogusPrime;
706 blob2.cbData = sizeof(bogusPrime);
707 ret = CertCompareCertificateName(0, &blob1, &blob2);
708 ok(!ret, "Expected failure\n");
709 /* As do trailing extra bytes. */
710 blob2.pbData = (LPBYTE)emptyPrime;
711 blob2.cbData = sizeof(emptyPrime);
712 ret = CertCompareCertificateName(0, &blob1, &blob2);
713 ok(!ret, "Expected failure\n");
716 static const BYTE int1[] = { 0x88, 0xff, 0xff, 0xff };
717 static const BYTE int2[] = { 0x88, 0xff };
718 static const BYTE int3[] = { 0x23, 0xff };
719 static const BYTE int4[] = { 0x7f, 0x00 };
720 static const BYTE int5[] = { 0x7f };
721 static const BYTE int6[] = { 0x80, 0x00, 0x00, 0x00 };
722 static const BYTE int7[] = { 0x80, 0x00 };
726 CRYPT_INTEGER_BLOB blob1;
727 CRYPT_INTEGER_BLOB blob2;
730 { { sizeof(int1), (LPBYTE)int1 }, { sizeof(int2), (LPBYTE)int2 }, TRUE },
731 { { sizeof(int3), (LPBYTE)int3 }, { sizeof(int3), (LPBYTE)int3 }, TRUE },
732 { { sizeof(int4), (LPBYTE)int4 }, { sizeof(int5), (LPBYTE)int5 }, TRUE },
733 { { sizeof(int6), (LPBYTE)int6 }, { sizeof(int7), (LPBYTE)int7 }, TRUE },
734 { { sizeof(int1), (LPBYTE)int1 }, { sizeof(int7), (LPBYTE)int7 }, FALSE },
737 static void testCompareIntegerBlob(void)
742 for (i = 0; i < sizeof(intBlobs) / sizeof(intBlobs[0]); i++)
744 ret = CertCompareIntegerBlob(&intBlobs[i].blob1, &intBlobs[i].blob2);
745 ok(ret == intBlobs[i].areEqual,
746 "%ld: expected blobs %s compare\n", i, intBlobs[i].areEqual ?
751 static void testComparePublicKeyInfo(void)
754 CERT_PUBLIC_KEY_INFO info1 = { { 0 } }, info2 = { { 0 } };
755 static CHAR oid_rsa_rsa[] = szOID_RSA_RSA;
756 static CHAR oid_rsa_sha1rsa[] = szOID_RSA_SHA1RSA;
757 static CHAR oid_x957_dsa[] = szOID_X957_DSA;
758 static const BYTE bits1[] = { 1, 0 };
759 static const BYTE bits2[] = { 0 };
760 static const BYTE bits3[] = { 1 };
763 ret = CertComparePublicKeyInfo(0, NULL, NULL);
765 /* Empty public keys compare */
766 ret = CertComparePublicKeyInfo(0, &info1, &info2);
767 ok(ret, "CertComparePublicKeyInfo failed: %08lx\n", GetLastError());
768 /* Different OIDs appear to compare */
769 info1.Algorithm.pszObjId = oid_rsa_rsa;
770 info2.Algorithm.pszObjId = oid_rsa_sha1rsa;
771 ret = CertComparePublicKeyInfo(0, &info1, &info2);
772 ok(ret, "CertComparePublicKeyInfo failed: %08lx\n", GetLastError());
773 info2.Algorithm.pszObjId = oid_x957_dsa;
774 ret = CertComparePublicKeyInfo(0, &info1, &info2);
775 ok(ret, "CertComparePublicKeyInfo failed: %08lx\n", GetLastError());
776 info1.PublicKey.cbData = sizeof(bits1);
777 info1.PublicKey.pbData = (LPBYTE)bits1;
778 info1.PublicKey.cUnusedBits = 0;
779 info2.PublicKey.cbData = sizeof(bits1);
780 info2.PublicKey.pbData = (LPBYTE)bits1;
781 info2.PublicKey.cUnusedBits = 0;
782 ret = CertComparePublicKeyInfo(0, &info1, &info2);
783 ok(ret, "CertComparePublicKeyInfo failed: %08lx\n", GetLastError());
784 /* Even though they compare in their used bits, these do not compare */
785 info1.PublicKey.cbData = sizeof(bits2);
786 info1.PublicKey.pbData = (LPBYTE)bits2;
787 info1.PublicKey.cUnusedBits = 0;
788 info2.PublicKey.cbData = sizeof(bits3);
789 info2.PublicKey.pbData = (LPBYTE)bits3;
790 info2.PublicKey.cUnusedBits = 1;
791 ret = CertComparePublicKeyInfo(0, &info1, &info2);
792 /* Simple (non-comparing) case */
793 ok(!ret, "Expected keys not to compare\n");
794 info2.PublicKey.cbData = sizeof(bits1);
795 info2.PublicKey.pbData = (LPBYTE)bits1;
796 info2.PublicKey.cUnusedBits = 0;
797 ret = CertComparePublicKeyInfo(0, &info1, &info2);
798 ok(!ret, "Expected keys not to compare\n");
801 static const BYTE subjectName2[] = { 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
802 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61,
805 static const BYTE serialNum[] = { 1 };
807 void testCompareCert(void)
809 CERT_INFO info1 = { 0 }, info2 = { 0 };
813 ret = CertCompareCertificate(X509_ASN_ENCODING, NULL, NULL);
816 /* Certs with the same issuer and serial number are equal, even if they
817 * differ in other respects (like subject).
819 info1.SerialNumber.pbData = (LPBYTE)serialNum;
820 info1.SerialNumber.cbData = sizeof(serialNum);
821 info1.Issuer.pbData = (LPBYTE)subjectName;
822 info1.Issuer.cbData = sizeof(subjectName);
823 info1.Subject.pbData = (LPBYTE)subjectName2;
824 info1.Subject.cbData = sizeof(subjectName2);
825 info2.SerialNumber.pbData = (LPBYTE)serialNum;
826 info2.SerialNumber.cbData = sizeof(serialNum);
827 info2.Issuer.pbData = (LPBYTE)subjectName;
828 info2.Issuer.cbData = sizeof(subjectName);
829 info2.Subject.pbData = (LPBYTE)subjectName;
830 info2.Subject.cbData = sizeof(subjectName);
831 ret = CertCompareCertificate(X509_ASN_ENCODING, &info1, &info2);
832 ok(ret, "Expected certs to be equal\n");
834 info2.Issuer.pbData = (LPBYTE)subjectName2;
835 info2.Issuer.cbData = sizeof(subjectName2);
836 ret = CertCompareCertificate(X509_ASN_ENCODING, &info1, &info2);
837 ok(!ret, "Expected certs not to be equal\n");
840 static const BYTE bigCertWithDifferentSubject[] = { 0x30, 0x7a, 0x02, 0x01, 0x02,
841 0x30, 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
842 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67,
843 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31,
844 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
845 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15,
846 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c,
847 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06,
848 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55,
849 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02,
852 static void testVerifySubjectCert(void)
856 PCCERT_CONTEXT context1, context2;
859 ret = CertVerifySubjectCertificateContext(NULL, NULL, NULL);
862 ret = CertVerifySubjectCertificateContext(NULL, NULL, &flags);
863 ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n",
865 flags = CERT_STORE_NO_CRL_FLAG;
866 ret = CertVerifySubjectCertificateContext(NULL, NULL, &flags);
867 ok(!ret && GetLastError() == E_INVALIDARG,
868 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
871 context1 = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
873 ret = CertVerifySubjectCertificateContext(NULL, context1, &flags);
874 ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n",
876 ret = CertVerifySubjectCertificateContext(context1, NULL, &flags);
877 ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n",
879 ret = CertVerifySubjectCertificateContext(context1, context1, &flags);
880 ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n",
883 context2 = CertCreateCertificateContext(X509_ASN_ENCODING,
884 bigCertWithDifferentSubject, sizeof(bigCertWithDifferentSubject));
885 SetLastError(0xdeadbeef);
886 ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
887 ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n",
889 flags = CERT_STORE_REVOCATION_FLAG;
890 ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
891 ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n",
893 ok(flags == (CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG),
894 "Expected CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG, got %08lx\n",
896 flags = CERT_STORE_SIGNATURE_FLAG;
897 ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
898 ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n",
900 ok(flags == CERT_STORE_SIGNATURE_FLAG,
901 "Expected CERT_STORE_SIGNATURE_FLAG, got %08lx\n", flags);
902 CertFreeCertificateContext(context2);
904 CertFreeCertificateContext(context1);
909 init_function_pointers();
912 testCreateSelfSignCert();
914 testCompareCertName();
915 testCompareIntegerBlob();
916 testComparePublicKeyInfo();
918 testVerifySubjectCert();