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 char cspName[] = "WineCryptTemp";
90 static void verifySig(HCRYPTPROV csp, const BYTE *toSign, size_t toSignLen,
91 const BYTE *sig, size_t 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() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
190 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
192 ret = pCryptVerifyCertificateSignatureEx(csp, 0, 0, NULL, 0, NULL, 0, NULL);
193 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
194 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
196 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING, 0, NULL, 0,
198 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
199 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
202 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
203 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, NULL, 0, NULL, 0, NULL);
206 info.ToBeSigned.cbData = toBeSigned->cbData;
207 info.ToBeSigned.pbData = toBeSigned->pbData;
208 info.SignatureAlgorithm.pszObjId = (LPSTR)sigOID;
209 info.SignatureAlgorithm.Parameters.cbData = 0;
210 info.Signature.cbData = sigLen;
211 info.Signature.pbData = (BYTE *)sig;
212 info.Signature.cUnusedBits = 0;
213 ret = CryptEncodeObjectEx(X509_ASN_ENCODING, X509_CERT, &info,
214 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&cert, &size);
215 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
218 CRYPT_DATA_BLOB certBlob = { 0, NULL };
219 PCERT_PUBLIC_KEY_INFO pubKeyInfo = NULL;
221 if(pCryptVerifyCertificateSignatureEx) {
222 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
223 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
224 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
225 "Expected CRYPT_E_ASN1_EOD, got %08lx\n", GetLastError());
227 certBlob.pbData = (void *)0xdeadbeef;
228 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
229 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
230 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
231 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
232 certBlob.cbData = size;
233 certBlob.pbData = cert;
234 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
235 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
236 ok(!ret && GetLastError() ==
237 HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
238 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
240 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
241 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
242 CRYPT_VERIFY_CERT_SIGN_ISSUER_NULL, NULL, 0, NULL);
243 ok(!ret && GetLastError() ==
244 HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
245 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
248 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
249 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
250 CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY, NULL, 0, NULL);
253 CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
254 (LPSTR)sigOID, 0, NULL, NULL, &size);
255 pubKeyInfo = HeapAlloc(GetProcessHeap(), 0, size);
258 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
259 X509_ASN_ENCODING, (LPSTR)sigOID, 0, NULL, pubKeyInfo, &size);
260 ok(ret, "CryptExportKey failed: %08lx\n", GetLastError());
261 if (ret && pCryptVerifyCertificateSignatureEx)
263 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
264 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
265 CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY, pubKeyInfo, 0, NULL);
266 ok(ret, "CryptVerifyCertificateSignatureEx failed: %08lx\n",
269 HeapFree(GetProcessHeap(), 0, pubKeyInfo);
275 static const BYTE emptyCert[] = { 0x30, 0x00 };
277 static void testCertSigs(void)
280 CRYPT_DATA_BLOB toBeSigned = { sizeof(emptyCert), (LPBYTE)emptyCert };
284 DWORD sigSize = sizeof(sig);
286 /* Just in case a previous run failed, delete this thing */
287 CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
289 ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
291 ok(ret, "CryptAcquireContext failed: %08lx\n", GetLastError());
293 testSignCert(csp, &toBeSigned, szOID_RSA_SHA1RSA, &key, sig, &sigSize);
294 testVerifyCertSig(csp, &toBeSigned, szOID_RSA_SHA1RSA, sig, sigSize);
296 CryptDestroyKey(key);
297 CryptReleaseContext(csp, 0);
298 ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
302 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
303 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
304 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
305 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
306 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
307 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
308 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
309 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
310 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
311 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
313 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
314 szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
316 static const BYTE certWithUsage[] = { 0x30, 0x81, 0x93, 0x02, 0x01, 0x01, 0x30,
317 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04,
318 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00,
319 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
320 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
321 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31,
322 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61,
323 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00,
324 0x03, 0x01, 0x00, 0xa3, 0x2f, 0x30, 0x2d, 0x30, 0x2b, 0x06, 0x03, 0x55, 0x1d,
325 0x25, 0x01, 0x01, 0xff, 0x04, 0x21, 0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01,
326 0x05, 0x05, 0x07, 0x03, 0x03, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
327 0x03, 0x02, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
329 static void testKeyUsage(void)
332 PCCERT_CONTEXT context;
335 /* Test base cases */
336 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, NULL);
337 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
338 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
340 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, &size);
341 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
342 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
344 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, &size);
345 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
346 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
348 ret = CertSetEnhancedKeyUsage(NULL, NULL);
349 usage.cUsageIdentifier = 0;
350 ret = CertSetEnhancedKeyUsage(NULL, &usage);
352 /* Test with a cert with no enhanced key usage extension */
353 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
355 ok(context != NULL, "CertCreateCertificateContext failed: %08lx\n",
359 static const char oid[] = "1.2.3.4";
360 BYTE buf[sizeof(CERT_ENHKEY_USAGE) + 2 * (sizeof(LPSTR) + sizeof(oid))];
361 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
363 ret = CertGetEnhancedKeyUsage(context, 0, NULL, NULL);
364 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
365 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
367 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &size);
370 /* Windows 2000, ME, or later: even though it succeeded, we expect
371 * CRYPT_E_NOT_FOUND, which indicates there is no enhanced key
372 * usage set for this cert (which implies it's valid for all uses.)
374 ok(GetLastError() == CRYPT_E_NOT_FOUND,
375 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
376 ok(size == sizeof(CERT_ENHKEY_USAGE), "Expected size %d, got %ld\n",
377 sizeof(CERT_ENHKEY_USAGE), size);
378 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
379 ok(ret, "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
380 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %ld\n",
381 pUsage->cUsageIdentifier);
385 /* Windows NT, 95, or 98: it fails, and the last error is
388 ok(GetLastError() == CRYPT_E_NOT_FOUND,
389 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
391 /* I can add a usage identifier when no key usage has been set */
392 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
393 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08lx\n",
396 ret = CertGetEnhancedKeyUsage(context,
397 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
398 ok(ret && GetLastError() == 0,
399 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
400 ok(pUsage->cUsageIdentifier == 1, "Expected 1 usage, got %ld\n",
401 pUsage->cUsageIdentifier);
402 if (pUsage->cUsageIdentifier)
403 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
404 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
405 /* Now set an empty key usage */
406 pUsage->cUsageIdentifier = 0;
407 ret = CertSetEnhancedKeyUsage(context, pUsage);
408 ok(ret, "CertSetEnhancedKeyUsage failed: %08lx\n", GetLastError());
409 /* Shouldn't find it in the cert */
411 ret = CertGetEnhancedKeyUsage(context,
412 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
413 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
414 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
415 /* Should find it as an extended property */
416 ret = CertGetEnhancedKeyUsage(context,
417 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
418 ok(ret && GetLastError() == 0,
419 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
420 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %ld\n",
421 pUsage->cUsageIdentifier);
422 /* Should find it as either */
423 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
424 ok(ret && GetLastError() == 0,
425 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
426 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %ld\n",
427 pUsage->cUsageIdentifier);
428 /* Add a usage identifier */
429 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
430 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08lx\n",
433 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
434 ok(ret && GetLastError() == 0,
435 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
436 ok(pUsage->cUsageIdentifier == 1, "Expected 1 identifier, got %ld\n",
437 pUsage->cUsageIdentifier);
438 if (pUsage->cUsageIdentifier)
439 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
440 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
441 /* Yep, I can re-add the same usage identifier */
442 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
443 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08lx\n",
446 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
447 ok(ret && GetLastError() == 0,
448 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
449 ok(pUsage->cUsageIdentifier == 2, "Expected 2 identifiers, got %ld\n",
450 pUsage->cUsageIdentifier);
451 if (pUsage->cUsageIdentifier)
452 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
453 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
454 if (pUsage->cUsageIdentifier >= 2)
455 ok(!strcmp(pUsage->rgpszUsageIdentifier[1], oid),
456 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[1]);
457 /* Now set a NULL extended property--this deletes the property. */
458 ret = CertSetEnhancedKeyUsage(context, NULL);
459 ok(ret, "CertSetEnhancedKeyUsage failed: %08lx\n", GetLastError());
460 SetLastError(0xbaadcafe);
462 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
463 ok(GetLastError() == CRYPT_E_NOT_FOUND,
464 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
466 CertFreeCertificateContext(context);
468 /* Now test with a cert with an enhanced key usage extension */
469 context = CertCreateCertificateContext(X509_ASN_ENCODING, certWithUsage,
470 sizeof(certWithUsage));
471 ok(context != NULL, "CertCreateCertificateContext failed: %08lx\n",
476 DWORD bufSize = 0, i;
478 /* The size may depend on what flags are used to query it, so I
479 * realloc the buffer for each test.
481 ret = CertGetEnhancedKeyUsage(context,
482 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, NULL, &bufSize);
483 ok(ret, "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
484 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
487 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
489 /* Should find it in the cert */
491 ret = CertGetEnhancedKeyUsage(context,
492 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
493 ok(ret && GetLastError() == 0,
494 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
495 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %ld\n",
496 pUsage->cUsageIdentifier);
497 for (i = 0; i < pUsage->cUsageIdentifier; i++)
498 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
499 "Expected %s, got %s\n", keyUsages[i],
500 pUsage->rgpszUsageIdentifier[i]);
501 HeapFree(GetProcessHeap(), 0, buf);
503 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
504 ok(ret, "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
505 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
508 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
510 /* Should find it as either */
512 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
513 /* In Windows, GetLastError returns CRYPT_E_NOT_FOUND not found
514 * here, even though the return is successful and the usage id
515 * count is positive. I don't enforce that here.
518 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
519 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %ld\n",
520 pUsage->cUsageIdentifier);
521 for (i = 0; i < pUsage->cUsageIdentifier; i++)
522 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
523 "Expected %s, got %s\n", keyUsages[i],
524 pUsage->rgpszUsageIdentifier[i]);
525 HeapFree(GetProcessHeap(), 0, buf);
527 /* Shouldn't find it as an extended property */
528 ret = CertGetEnhancedKeyUsage(context,
529 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, NULL, &size);
530 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
531 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
532 /* Adding a usage identifier overrides the cert's usage!? */
533 ret = CertAddEnhancedKeyUsageIdentifier(context, szOID_RSA_RSA);
534 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08lx\n",
536 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
537 ok(ret, "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
538 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
541 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
543 /* Should find it as either */
545 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
547 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
548 ok(pUsage->cUsageIdentifier == 1, "Expected 1 usage, got %ld\n",
549 pUsage->cUsageIdentifier);
550 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], szOID_RSA_RSA),
551 "Expected %s, got %s\n", szOID_RSA_RSA,
552 pUsage->rgpszUsageIdentifier[0]);
553 HeapFree(GetProcessHeap(), 0, buf);
555 /* But querying the cert directly returns its usage */
556 ret = CertGetEnhancedKeyUsage(context,
557 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, NULL, &bufSize);
558 ok(ret, "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
559 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
562 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
565 ret = CertGetEnhancedKeyUsage(context,
566 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
568 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
569 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %ld\n",
570 pUsage->cUsageIdentifier);
571 for (i = 0; i < pUsage->cUsageIdentifier; i++)
572 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
573 "Expected %s, got %s\n", keyUsages[i],
574 pUsage->rgpszUsageIdentifier[i]);
575 HeapFree(GetProcessHeap(), 0, buf);
577 /* And removing the only usage identifier in the extended property
578 * results in the cert's key usage being found.
580 ret = CertRemoveEnhancedKeyUsageIdentifier(context, szOID_RSA_RSA);
581 ok(ret, "CertRemoveEnhancedKeyUsage failed: %08lx\n", GetLastError());
582 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
583 ok(ret, "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
584 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
587 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
589 /* Should find it as either */
591 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
593 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
594 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %ld\n",
595 pUsage->cUsageIdentifier);
596 for (i = 0; i < pUsage->cUsageIdentifier; i++)
597 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
598 "Expected %s, got %s\n", keyUsages[i],
599 pUsage->rgpszUsageIdentifier[i]);
600 HeapFree(GetProcessHeap(), 0, buf);
603 CertFreeCertificateContext(context);
609 init_function_pointers();