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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
191 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
193 ret = pCryptVerifyCertificateSignatureEx(csp, 0, 0, NULL, 0, NULL, 0, NULL);
194 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
195 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
197 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING, 0, NULL, 0,
199 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
200 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
203 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
204 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, NULL, 0, NULL, 0, NULL);
207 info.ToBeSigned.cbData = toBeSigned->cbData;
208 info.ToBeSigned.pbData = toBeSigned->pbData;
209 info.SignatureAlgorithm.pszObjId = (LPSTR)sigOID;
210 info.SignatureAlgorithm.Parameters.cbData = 0;
211 info.Signature.cbData = sigLen;
212 info.Signature.pbData = (BYTE *)sig;
213 info.Signature.cUnusedBits = 0;
214 ret = CryptEncodeObjectEx(X509_ASN_ENCODING, X509_CERT, &info,
215 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&cert, &size);
216 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
219 CRYPT_DATA_BLOB certBlob = { 0, NULL };
220 PCERT_PUBLIC_KEY_INFO pubKeyInfo = NULL;
222 if(pCryptVerifyCertificateSignatureEx) {
223 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
224 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
225 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
226 "Expected CRYPT_E_ASN1_EOD, got %08lx\n", GetLastError());
228 certBlob.pbData = (void *)0xdeadbeef;
229 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
230 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
231 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
232 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
233 certBlob.cbData = size;
234 certBlob.pbData = cert;
235 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
236 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
237 ok(!ret && GetLastError() ==
238 HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
239 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
241 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
242 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
243 CRYPT_VERIFY_CERT_SIGN_ISSUER_NULL, NULL, 0, NULL);
244 ok(!ret && GetLastError() ==
245 HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
246 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
249 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
250 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
251 CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY, NULL, 0, NULL);
254 CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
255 (LPSTR)sigOID, 0, NULL, NULL, &size);
256 pubKeyInfo = HeapAlloc(GetProcessHeap(), 0, size);
259 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
260 X509_ASN_ENCODING, (LPSTR)sigOID, 0, NULL, pubKeyInfo, &size);
261 ok(ret, "CryptExportKey failed: %08lx\n", GetLastError());
262 if (ret && pCryptVerifyCertificateSignatureEx)
264 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
265 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
266 CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY, pubKeyInfo, 0, NULL);
267 ok(ret, "CryptVerifyCertificateSignatureEx failed: %08lx\n",
270 HeapFree(GetProcessHeap(), 0, pubKeyInfo);
276 static const BYTE emptyCert[] = { 0x30, 0x00 };
278 static void testCertSigs(void)
281 CRYPT_DATA_BLOB toBeSigned = { sizeof(emptyCert), (LPBYTE)emptyCert };
285 DWORD sigSize = sizeof(sig);
287 /* Just in case a previous run failed, delete this thing */
288 CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
290 ret = CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
292 ok(ret, "CryptAcquireContext failed: %08lx\n", GetLastError());
294 testSignCert(csp, &toBeSigned, szOID_RSA_SHA1RSA, &key, sig, &sigSize);
295 testVerifyCertSig(csp, &toBeSigned, szOID_RSA_SHA1RSA, sig, sigSize);
297 CryptDestroyKey(key);
298 CryptReleaseContext(csp, 0);
299 ret = CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
303 static const BYTE subjectName[] = { 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
304 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
307 static void testCreateSelfSignCert(void)
309 PCCERT_CONTEXT context;
310 CERT_NAME_BLOB name = { sizeof(subjectName), (LPBYTE)subjectName };
316 context = CertCreateSelfSignCertificate(0, NULL, 0, NULL, NULL, NULL, NULL,
318 * Calling this with no first parameter creates a new key container, which
319 * lasts beyond the test, so I don't test that. Nb: the generated key
321 context = CertCreateSelfSignCertificate(0, &name, 0, NULL, NULL, NULL, NULL,
326 CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
328 ret = CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
330 ok(ret, "CryptAcquireContext failed: %08lx\n", GetLastError());
332 context = CertCreateSelfSignCertificate(csp, &name, 0, NULL, NULL, NULL,
334 ok(!context && GetLastError() == NTE_NO_KEY,
335 "Expected NTE_NO_KEY, got %08lx\n", GetLastError());
336 ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
337 ok(ret, "CryptGenKey failed: %08lx\n", GetLastError());
340 context = CertCreateSelfSignCertificate(csp, &name, 0, NULL, NULL, NULL,
342 ok(context != NULL, "CertCreateSelfSignCertificate failed: %08lx\n",
347 PCRYPT_KEY_PROV_INFO info;
349 /* The context must have a key provider info property */
350 ret = CertGetCertificateContextProperty(context,
351 CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
352 ok(ret && size, "Expected non-zero key provider info\n");
355 info = HeapAlloc(GetProcessHeap(), 0, size);
358 ret = CertGetCertificateContextProperty(context,
359 CERT_KEY_PROV_INFO_PROP_ID, info, &size);
360 ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
364 /* Sanity-check the key provider */
365 ok(!lstrcmpW(info->pwszContainerName, cspNameW),
366 "Unexpected key container\n");
367 ok(!lstrcmpW(info->pwszProvName, MS_DEF_PROV_W),
368 "Unexpected provider\n");
369 ok(info->dwKeySpec == AT_SIGNATURE,
370 "Expected AT_SIGNATURE, got %ld\n", info->dwKeySpec);
372 HeapFree(GetProcessHeap(), 0, info);
376 CertFreeCertificateContext(context);
379 CryptDestroyKey(key);
382 CryptReleaseContext(csp, 0);
383 ret = CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
387 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
388 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
389 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
390 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
391 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
392 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
393 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
394 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
395 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
396 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
398 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
399 szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
401 static const BYTE certWithUsage[] = { 0x30, 0x81, 0x93, 0x02, 0x01, 0x01, 0x30,
402 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04,
403 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00,
404 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
405 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
406 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31,
407 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61,
408 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00,
409 0x03, 0x01, 0x00, 0xa3, 0x2f, 0x30, 0x2d, 0x30, 0x2b, 0x06, 0x03, 0x55, 0x1d,
410 0x25, 0x01, 0x01, 0xff, 0x04, 0x21, 0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01,
411 0x05, 0x05, 0x07, 0x03, 0x03, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
412 0x03, 0x02, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
414 static void testKeyUsage(void)
417 PCCERT_CONTEXT context;
420 /* Test base cases */
421 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, NULL);
422 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
423 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
425 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, &size);
426 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
427 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
429 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, &size);
430 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
431 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
433 ret = CertSetEnhancedKeyUsage(NULL, NULL);
434 usage.cUsageIdentifier = 0;
435 ret = CertSetEnhancedKeyUsage(NULL, &usage);
437 /* Test with a cert with no enhanced key usage extension */
438 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
440 ok(context != NULL, "CertCreateCertificateContext failed: %08lx\n",
444 static const char oid[] = "1.2.3.4";
445 BYTE buf[sizeof(CERT_ENHKEY_USAGE) + 2 * (sizeof(LPSTR) + sizeof(oid))];
446 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
448 ret = CertGetEnhancedKeyUsage(context, 0, NULL, NULL);
449 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
450 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
452 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &size);
455 /* Windows 2000, ME, or later: even though it succeeded, we expect
456 * CRYPT_E_NOT_FOUND, which indicates there is no enhanced key
457 * usage set for this cert (which implies it's valid for all uses.)
459 ok(GetLastError() == CRYPT_E_NOT_FOUND,
460 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
461 ok(size == sizeof(CERT_ENHKEY_USAGE), "Expected size %d, got %ld\n",
462 sizeof(CERT_ENHKEY_USAGE), size);
463 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
464 ok(ret, "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
465 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %ld\n",
466 pUsage->cUsageIdentifier);
470 /* Windows NT, 95, or 98: it fails, and the last error is
473 ok(GetLastError() == CRYPT_E_NOT_FOUND,
474 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
476 /* I can add a usage identifier when no key usage has been set */
477 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
478 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08lx\n",
481 ret = CertGetEnhancedKeyUsage(context,
482 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
483 ok(ret && GetLastError() == 0,
484 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
485 ok(pUsage->cUsageIdentifier == 1, "Expected 1 usage, got %ld\n",
486 pUsage->cUsageIdentifier);
487 if (pUsage->cUsageIdentifier)
488 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
489 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
490 /* Now set an empty key usage */
491 pUsage->cUsageIdentifier = 0;
492 ret = CertSetEnhancedKeyUsage(context, pUsage);
493 ok(ret, "CertSetEnhancedKeyUsage failed: %08lx\n", GetLastError());
494 /* Shouldn't find it in the cert */
496 ret = CertGetEnhancedKeyUsage(context,
497 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
498 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
499 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
500 /* Should find it as an extended property */
501 ret = CertGetEnhancedKeyUsage(context,
502 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
503 ok(ret && GetLastError() == 0,
504 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
505 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %ld\n",
506 pUsage->cUsageIdentifier);
507 /* Should find it as either */
508 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
509 ok(ret && GetLastError() == 0,
510 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
511 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %ld\n",
512 pUsage->cUsageIdentifier);
513 /* Add a usage identifier */
514 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
515 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08lx\n",
518 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
519 ok(ret && GetLastError() == 0,
520 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
521 ok(pUsage->cUsageIdentifier == 1, "Expected 1 identifier, got %ld\n",
522 pUsage->cUsageIdentifier);
523 if (pUsage->cUsageIdentifier)
524 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
525 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
526 /* Yep, I can re-add the same usage identifier */
527 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
528 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08lx\n",
531 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
532 ok(ret && GetLastError() == 0,
533 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
534 ok(pUsage->cUsageIdentifier == 2, "Expected 2 identifiers, got %ld\n",
535 pUsage->cUsageIdentifier);
536 if (pUsage->cUsageIdentifier)
537 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
538 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
539 if (pUsage->cUsageIdentifier >= 2)
540 ok(!strcmp(pUsage->rgpszUsageIdentifier[1], oid),
541 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[1]);
542 /* Now set a NULL extended property--this deletes the property. */
543 ret = CertSetEnhancedKeyUsage(context, NULL);
544 ok(ret, "CertSetEnhancedKeyUsage failed: %08lx\n", GetLastError());
545 SetLastError(0xbaadcafe);
547 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
548 ok(GetLastError() == CRYPT_E_NOT_FOUND,
549 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
551 CertFreeCertificateContext(context);
553 /* Now test with a cert with an enhanced key usage extension */
554 context = CertCreateCertificateContext(X509_ASN_ENCODING, certWithUsage,
555 sizeof(certWithUsage));
556 ok(context != NULL, "CertCreateCertificateContext failed: %08lx\n",
561 DWORD bufSize = 0, i;
563 /* The size may depend on what flags are used to query it, so I
564 * realloc the buffer for each test.
566 ret = CertGetEnhancedKeyUsage(context,
567 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, NULL, &bufSize);
568 ok(ret, "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
569 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
572 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
574 /* Should find it in the cert */
576 ret = CertGetEnhancedKeyUsage(context,
577 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
578 ok(ret && GetLastError() == 0,
579 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
580 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %ld\n",
581 pUsage->cUsageIdentifier);
582 for (i = 0; i < pUsage->cUsageIdentifier; i++)
583 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
584 "Expected %s, got %s\n", keyUsages[i],
585 pUsage->rgpszUsageIdentifier[i]);
586 HeapFree(GetProcessHeap(), 0, buf);
588 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
589 ok(ret, "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
590 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
593 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
595 /* Should find it as either */
597 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
598 /* In Windows, GetLastError returns CRYPT_E_NOT_FOUND not found
599 * here, even though the return is successful and the usage id
600 * count is positive. I don't enforce that here.
603 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
604 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %ld\n",
605 pUsage->cUsageIdentifier);
606 for (i = 0; i < pUsage->cUsageIdentifier; i++)
607 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
608 "Expected %s, got %s\n", keyUsages[i],
609 pUsage->rgpszUsageIdentifier[i]);
610 HeapFree(GetProcessHeap(), 0, buf);
612 /* Shouldn't find it as an extended property */
613 ret = CertGetEnhancedKeyUsage(context,
614 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, NULL, &size);
615 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
616 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
617 /* Adding a usage identifier overrides the cert's usage!? */
618 ret = CertAddEnhancedKeyUsageIdentifier(context, szOID_RSA_RSA);
619 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08lx\n",
621 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
622 ok(ret, "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
623 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
626 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
628 /* Should find it as either */
630 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
632 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
633 ok(pUsage->cUsageIdentifier == 1, "Expected 1 usage, got %ld\n",
634 pUsage->cUsageIdentifier);
635 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], szOID_RSA_RSA),
636 "Expected %s, got %s\n", szOID_RSA_RSA,
637 pUsage->rgpszUsageIdentifier[0]);
638 HeapFree(GetProcessHeap(), 0, buf);
640 /* But querying the cert directly returns its usage */
641 ret = CertGetEnhancedKeyUsage(context,
642 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, NULL, &bufSize);
643 ok(ret, "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
644 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
647 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
650 ret = CertGetEnhancedKeyUsage(context,
651 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
653 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
654 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %ld\n",
655 pUsage->cUsageIdentifier);
656 for (i = 0; i < pUsage->cUsageIdentifier; i++)
657 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
658 "Expected %s, got %s\n", keyUsages[i],
659 pUsage->rgpszUsageIdentifier[i]);
660 HeapFree(GetProcessHeap(), 0, buf);
662 /* And removing the only usage identifier in the extended property
663 * results in the cert's key usage being found.
665 ret = CertRemoveEnhancedKeyUsageIdentifier(context, szOID_RSA_RSA);
666 ok(ret, "CertRemoveEnhancedKeyUsage failed: %08lx\n", GetLastError());
667 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
668 ok(ret, "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
669 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
672 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
674 /* Should find it as either */
676 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
678 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
679 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %ld\n",
680 pUsage->cUsageIdentifier);
681 for (i = 0; i < pUsage->cUsageIdentifier; i++)
682 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
683 "Expected %s, got %s\n", keyUsages[i],
684 pUsage->rgpszUsageIdentifier[i]);
685 HeapFree(GetProcessHeap(), 0, buf);
688 CertFreeCertificateContext(context);
694 init_function_pointers();
697 testCreateSelfSignCert();