dbghelp: Dwarf abbrev table is now a sparse array.
[wine] / dlls / crypt32 / tests / cert.c
1 /*
2  * crypt32 cert functions tests
3  *
4  * Copyright 2005-2006 Juan Lang
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #include <assert.h>
22 #include <stdio.h>
23 #include <stdarg.h>
24 #include <windef.h>
25 #include <winbase.h>
26 #include <winreg.h>
27 #include <winerror.h>
28 #include <wincrypt.h>
29
30 #include "wine/test.h"
31
32 static BOOL (WINAPI * pCryptVerifyCertificateSignatureEx)
33                         (HCRYPTPROV, DWORD, DWORD, void *, DWORD, void *, DWORD, void *);
34
35 #define CRYPT_GET_PROC(func)                                       \
36     p ## func = (void *)GetProcAddress(hCrypt32, #func);           \
37     if(!p ## func)                                                 \
38         trace("GetProcAddress(hCrypt32, \"%s\") failed\n", #func); \
39
40 static void init_function_pointers(void)
41 {
42     HMODULE hCrypt32;
43
44     pCryptVerifyCertificateSignatureEx = NULL;
45
46     hCrypt32 = GetModuleHandleA("crypt32.dll");
47     assert(hCrypt32);
48
49     CRYPT_GET_PROC(CryptVerifyCertificateSignatureEx);
50 }
51
52 static void testCryptHashCert(void)
53 {
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,
56      0x09 };
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,
59      0xa2 };
60     static const BYTE toHash[] = "abcdefghijklmnopqrstuvwxyz0123456789.,;!?:";
61     BOOL ret;
62     BYTE hash[20];
63     DWORD hashLen = sizeof(hash);
64
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);
69      */
70     /* Test empty hash */
71     ret = CryptHashCertificate(0, 0, 0, toHash, sizeof(toHash), NULL,
72      &hashLen);
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,
82      &hashLen);
83     ok(ret, "CryptHashCertificate failed: %08lx\n", GetLastError());
84     ok(!memcmp(hash, knownHash, sizeof(knownHash)), "Unexpected hash\n");
85 }
86
87 static const WCHAR cspNameW[] = { 'W','i','n','e','C','r','y','p','t','T','e',
88  'm','p',0 };
89
90 static void verifySig(HCRYPTPROV csp, const BYTE *toSign, size_t toSignLen,
91  const BYTE *sig, unsigned int sigLen)
92 {
93     HCRYPTHASH hash;
94     BOOL ret = CryptCreateHash(csp, CALG_SHA1, 0, 0, &hash);
95
96     ok(ret, "CryptCreateHash failed: %08lx\n", GetLastError());
97     if (ret)
98     {
99         BYTE mySig[64];
100         DWORD mySigSize = sizeof(mySig);
101
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());
107         if (ret)
108         {
109             ok(mySigSize == sigLen, "Expected sig length %d, got %ld\n",
110              sigLen, mySigSize);
111             ok(!memcmp(mySig, sig, sigLen), "Unexpected signature\n");
112         }
113         CryptDestroyHash(hash);
114     }
115 }
116
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
121  * at least 64 bytes.
122  */
123 static void testSignCert(HCRYPTPROV csp, const CRYPT_DATA_BLOB *toBeSigned,
124  LPCSTR sigOID, HCRYPTKEY *key, BYTE *sig, DWORD *sigLen)
125 {
126     BOOL ret;
127     DWORD size = 0;
128     CRYPT_ALGORITHM_IDENTIFIER algoID = { NULL, { 0, NULL } };
129
130     /* These all crash
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);
135      */
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());
149
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",
155      GetLastError());
156     ret = CryptGenKey(csp, AT_SIGNATURE, 0, key);
157     ok(ret, "CryptGenKey failed: %08lx\n", GetLastError());
158     if (ret)
159     {
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);
164         if (ret)
165         {
166             ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
167              toBeSigned->cbData, &algoID, NULL, sig, &size);
168             ok(ret, "CryptSignCertificate failed: %08lx\n", GetLastError());
169             if (ret)
170             {
171                 *sigLen = size;
172                 verifySig(csp, toBeSigned->pbData, toBeSigned->cbData, sig,
173                  size);
174             }
175         }
176     }
177 }
178
179 static void testVerifyCertSig(HCRYPTPROV csp, const CRYPT_DATA_BLOB *toBeSigned,
180  LPCSTR sigOID, const BYTE *sig, DWORD sigLen)
181 {
182     CERT_SIGNED_CONTENT_INFO info;
183     LPBYTE cert = NULL;
184     DWORD size = 0;
185     BOOL ret;
186
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,
195          NULL, 0, NULL);
196         ok(!ret && GetLastError() == E_INVALIDARG,
197          "Expected E_INVALIDARG, got %08lx\n", GetLastError());
198         /* This crashes
199         ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
200          CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, NULL, 0, NULL, 0, NULL);
201          */
202     }
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());
213     if (cert)
214     {
215         CRYPT_DATA_BLOB certBlob = { 0, NULL };
216         PCERT_PUBLIC_KEY_INFO pubKeyInfo = NULL;
217
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());
223             certBlob.cbData = 1;
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());
240             /* This crashes
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);
244              */
245         }
246         CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
247          (LPSTR)sigOID, 0, NULL, NULL, &size);
248         pubKeyInfo = HeapAlloc(GetProcessHeap(), 0, size);
249         if (pubKeyInfo)
250         {
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)
255             {
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",
260                  GetLastError());
261             }
262             HeapFree(GetProcessHeap(), 0, pubKeyInfo);
263         }
264         LocalFree(cert);
265     }
266 }
267
268 static const BYTE emptyCert[] = { 0x30, 0x00 };
269
270 static void testCertSigs(void)
271 {
272     HCRYPTPROV csp;
273     CRYPT_DATA_BLOB toBeSigned = { sizeof(emptyCert), (LPBYTE)emptyCert };
274     BOOL ret;
275     HCRYPTKEY key;
276     BYTE sig[64];
277     DWORD sigSize = sizeof(sig);
278
279     /* Just in case a previous run failed, delete this thing */
280     CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
281      CRYPT_DELETEKEYSET);
282     ret = CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
283      CRYPT_NEWKEYSET);
284     ok(ret, "CryptAcquireContext failed: %08lx\n", GetLastError());
285
286     testSignCert(csp, &toBeSigned, szOID_RSA_SHA1RSA, &key, sig, &sigSize);
287     testVerifyCertSig(csp, &toBeSigned, szOID_RSA_SHA1RSA, sig, sigSize);
288
289     CryptDestroyKey(key);
290     CryptReleaseContext(csp, 0);
291     ret = CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
292      CRYPT_DELETEKEYSET);
293 }
294
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,
297  0x6e, 0x67, 0x00 };
298
299 static void testCreateSelfSignCert(void)
300 {
301     PCCERT_CONTEXT context;
302     CERT_NAME_BLOB name = { sizeof(subjectName), (LPBYTE)subjectName };
303     HCRYPTPROV csp;
304     BOOL ret;
305     HCRYPTKEY key;
306
307     /* This crashes:
308     context = CertCreateSelfSignCertificate(0, NULL, 0, NULL, NULL, NULL, NULL,
309      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
312      * name is a GUID.
313     context = CertCreateSelfSignCertificate(0, &name, 0, NULL, NULL, NULL, NULL,
314      NULL);
315      */
316
317     /* Acquire a CSP */
318     CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
319      CRYPT_DELETEKEYSET);
320     ret = CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
321      CRYPT_NEWKEYSET);
322     ok(ret, "CryptAcquireContext failed: %08lx\n", GetLastError());
323
324     context = CertCreateSelfSignCertificate(csp, &name, 0, NULL, NULL, NULL,
325      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());
330     if (ret)
331     {
332         context = CertCreateSelfSignCertificate(csp, &name, 0, NULL, NULL, NULL,
333          NULL, NULL);
334         ok(context != NULL, "CertCreateSelfSignCertificate failed: %08lx\n",
335          GetLastError());
336         if (context)
337         {
338             DWORD size = 0;
339             PCRYPT_KEY_PROV_INFO info;
340
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");
345             if (size)
346             {
347                 info = HeapAlloc(GetProcessHeap(), 0, size);
348                 if (info)
349                 {
350                     ret = CertGetCertificateContextProperty(context,
351                      CERT_KEY_PROV_INFO_PROP_ID, info, &size);
352                     ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
353                      GetLastError());
354                     if (ret)
355                     {
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);
363                     }
364                     HeapFree(GetProcessHeap(), 0, info);
365                 }
366             }
367
368             CertFreeCertificateContext(context);
369         }
370
371         CryptDestroyKey(key);
372     }
373
374     CryptReleaseContext(csp, 0);
375     ret = CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
376      CRYPT_DELETEKEYSET);
377 }
378
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 };
389
390 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
391  szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
392
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 };
405
406 static void testKeyUsage(void)
407 {
408     BOOL ret;
409     PCCERT_CONTEXT context;
410     DWORD size;
411
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());
416     size = 1;
417     ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, &size);
418     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
419      "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
420     size = 0;
421     ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, &size);
422     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
423      "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
424     /* These crash
425     ret = CertSetEnhancedKeyUsage(NULL, NULL);
426     usage.cUsageIdentifier = 0;
427     ret = CertSetEnhancedKeyUsage(NULL, &usage);
428      */
429     /* Test with a cert with no enhanced key usage extension */
430     context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
431      sizeof(bigCert));
432     ok(context != NULL, "CertCreateCertificateContext failed: %08lx\n",
433      GetLastError());
434     if (context)
435     {
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;
439
440         ret = CertGetEnhancedKeyUsage(context, 0, NULL, NULL);
441         ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
442          "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
443         size = 1;
444         ret = CertGetEnhancedKeyUsage(context, 0, NULL, &size);
445         if (ret)
446         {
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.)
450              */
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);
458         }
459         else
460         {
461             /* Windows NT, 95, or 98: it fails, and the last error is
462              * CRYPT_E_NOT_FOUND.
463              */
464             ok(GetLastError() == CRYPT_E_NOT_FOUND,
465              "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
466         }
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",
470          GetLastError());
471         size = sizeof(buf);
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 */
486         size = sizeof(buf);
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",
507          GetLastError());
508         size = sizeof(buf);
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",
520          GetLastError());
521         size = sizeof(buf);
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);
537         size = sizeof(buf);
538         ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
539         ok(GetLastError() == CRYPT_E_NOT_FOUND,
540          "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
541
542         CertFreeCertificateContext(context);
543     }
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",
548      GetLastError());
549     if (context)
550     {
551         LPBYTE buf = NULL;
552         DWORD bufSize = 0, i;
553
554         /* The size may depend on what flags are used to query it, so I
555          * realloc the buffer for each test.
556          */
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);
561         if (buf)
562         {
563             PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
564
565             /* Should find it in the cert */
566             size = bufSize;
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);
578         }
579         ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
580         ok(ret, "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
581         buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
582         if (buf)
583         {
584             PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
585
586             /* Should find it as either */
587             size = bufSize;
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.
592              */
593             ok(ret,
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);
602         }
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",
611          GetLastError());
612         ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
613         ok(ret, "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
614         buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
615         if (buf)
616         {
617             PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
618
619             /* Should find it as either */
620             size = bufSize;
621             ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
622             ok(ret,
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);
630         }
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);
636         if (buf)
637         {
638             PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
639
640             size = bufSize;
641             ret = CertGetEnhancedKeyUsage(context,
642              CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
643             ok(ret,
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);
652         }
653         /* And removing the only usage identifier in the extended property
654          * results in the cert's key usage being found.
655          */
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);
661         if (buf)
662         {
663             PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
664
665             /* Should find it as either */
666             size = bufSize;
667             ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
668             ok(ret,
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);
677         }
678
679         CertFreeCertificateContext(context);
680     }
681 }
682
683 static void testCompareCertName(void)
684 {
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 };
688     BOOL ret;
689     CERT_NAME_BLOB blob1, blob2;
690
691     /* crashes
692     ret = CertCompareCertificateName(0, NULL, NULL);
693      */
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");
714 }
715
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 };
723
724 struct IntBlobTest
725 {
726     CRYPT_INTEGER_BLOB blob1;
727     CRYPT_INTEGER_BLOB blob2;
728     BOOL areEqual;
729 } intBlobs[] = {
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 },
735 };
736
737 static void testCompareIntegerBlob(void)
738 {
739     DWORD i;
740     BOOL ret;
741
742     for (i = 0; i < sizeof(intBlobs) / sizeof(intBlobs[0]); i++)
743     {
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 ?
747          "to" : "not to");
748     }
749 }
750
751 static void testComparePublicKeyInfo(void)
752 {
753     BOOL ret;
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 };
761
762     /* crashes
763     ret = CertComparePublicKeyInfo(0, NULL, NULL);
764      */
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");
799 }
800
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,
803  0x6e, 0x67, 0x00 };
804
805 static const BYTE serialNum[] = { 1 };
806
807 void testCompareCert(void)
808 {
809     CERT_INFO info1 = { 0 }, info2 = { 0 };
810     BOOL ret;
811
812     /* Crashes
813     ret = CertCompareCertificate(X509_ASN_ENCODING, NULL, NULL);
814      */
815
816     /* Certs with the same issuer and serial number are equal, even if they
817      * differ in other respects (like subject).
818      */
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");
833
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");
838 }
839
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,
850  0x01, 0x01 };
851
852 static void testVerifySubjectCert(void)
853 {
854     BOOL ret;
855     DWORD flags;
856     PCCERT_CONTEXT context1, context2;
857
858     /* Crashes
859     ret = CertVerifySubjectCertificateContext(NULL, NULL, NULL);
860      */
861     flags = 0;
862     ret = CertVerifySubjectCertificateContext(NULL, NULL, &flags);
863     ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n",
864      GetLastError());
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());
869
870     flags = 0;
871     context1 = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
872      sizeof(bigCert));
873     ret = CertVerifySubjectCertificateContext(NULL, context1, &flags);
874     ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n",
875      GetLastError());
876     ret = CertVerifySubjectCertificateContext(context1, NULL, &flags);
877     ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n",
878      GetLastError());
879     ret = CertVerifySubjectCertificateContext(context1, context1, &flags);
880     ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n",
881      GetLastError());
882
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",
888      GetLastError());
889     flags = CERT_STORE_REVOCATION_FLAG;
890     ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
891     ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n",
892      GetLastError());
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",
895      flags);
896     flags = CERT_STORE_SIGNATURE_FLAG;
897     ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
898     ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n",
899      GetLastError());
900     ok(flags == CERT_STORE_SIGNATURE_FLAG,
901      "Expected CERT_STORE_SIGNATURE_FLAG, got %08lx\n", flags);
902     CertFreeCertificateContext(context2);
903
904     CertFreeCertificateContext(context1);
905 }
906
907 START_TEST(cert)
908 {
909     init_function_pointers();
910     testCryptHashCert();
911     testCertSigs();
912     testCreateSelfSignCert();
913     testKeyUsage();
914     testCompareCertName();
915     testCompareIntegerBlob();
916     testComparePublicKeyInfo();
917     testCompareCert();
918     testVerifySubjectCert();
919 }