crypt32: Implement CertVerifyRevocation.
[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 static BOOL (WINAPI * pCryptAcquireContextW)
36                         (HCRYPTPROV *, LPCWSTR, LPCWSTR, DWORD, DWORD);
37
38 static void init_function_pointers(void)
39 {
40     HMODULE hCrypt32 = GetModuleHandleA("crypt32.dll");
41     HMODULE hAdvapi32 = GetModuleHandleA("advapi32.dll");
42
43 #define GET_PROC(dll, func) \
44     p ## func = (void *)GetProcAddress(dll, #func); \
45     if(!p ## func) \
46       trace("GetProcAddress(%s) failed\n", #func);
47
48     GET_PROC(hCrypt32, CryptVerifyCertificateSignatureEx)
49
50     GET_PROC(hAdvapi32, CryptAcquireContextW)
51
52 #undef GET_PROC
53 }
54
55 static BYTE subjectName[] = { 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
56  0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
57  0x6e, 0x67, 0x00 };
58 static BYTE serialNum[] = { 1 };
59 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
60  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
61  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
62  0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
63  0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
64  0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
65  0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
66  0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
67  0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
68  0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
69 static BYTE bigCertHash[] = { 0x6e, 0x30, 0x90, 0x71, 0x5f, 0xd9, 0x23,
70  0x56, 0xeb, 0xae, 0x25, 0x40, 0xe6, 0x22, 0xda, 0x19, 0x26, 0x02, 0xa6, 0x08 };
71
72 static const BYTE bigCertWithDifferentSubject[] = { 0x30, 0x7a, 0x02, 0x01, 0x02,
73  0x30, 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
74  0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67,
75  0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31,
76  0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
77  0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15,
78  0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c,
79  0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06,
80  0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55,
81  0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02,
82  0x01, 0x01 };
83 static const BYTE bigCertWithDifferentIssuer[] = { 0x30, 0x7a, 0x02, 0x01,
84  0x01, 0x30, 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
85  0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e,
86  0x67, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
87  0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30,
88  0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30,
89  0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
90  0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02,
91  0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03,
92  0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff,
93  0x02, 0x01, 0x01 };
94
95 static BYTE subjectName2[] = { 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
96  0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61,
97  0x6e, 0x67, 0x00 };
98 static const BYTE bigCert2[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
99  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
100  0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
101  0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
102  0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
103  0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
104  0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20,
105  0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
106  0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
107  0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
108 static const BYTE bigCert2WithDifferentSerial[] = { 0x30, 0x7a, 0x02, 0x01,
109  0x02, 0x30, 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
110  0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e,
111  0x67, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
112  0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30,
113  0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30,
114  0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41,
115  0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02,
116  0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03,
117  0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff,
118  0x02, 0x01, 0x01 };
119 static BYTE bigCert2Hash[] = { 0x4a, 0x7f, 0x32, 0x1f, 0xcf, 0x3b, 0xc0,
120  0x87, 0x48, 0x2b, 0xa1, 0x86, 0x54, 0x18, 0xe4, 0x3a, 0x0e, 0x53, 0x7e, 0x2b };
121
122 static const BYTE certWithUsage[] = { 0x30, 0x81, 0x93, 0x02, 0x01, 0x01, 0x30,
123  0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04,
124  0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00,
125  0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
126  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
127  0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31,
128  0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61,
129  0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00,
130  0x03, 0x01, 0x00, 0xa3, 0x2f, 0x30, 0x2d, 0x30, 0x2b, 0x06, 0x03, 0x55, 0x1d,
131  0x25, 0x01, 0x01, 0xff, 0x04, 0x21, 0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01,
132  0x05, 0x05, 0x07, 0x03, 0x03, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
133  0x03, 0x02, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
134
135 static void testAddCert(void)
136 {
137     HCERTSTORE store;
138     HCERTSTORE collection;
139     PCCERT_CONTEXT context;
140     PCCERT_CONTEXT copyContext;
141     BOOL ret;
142
143     store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
144      CERT_STORE_CREATE_NEW_FLAG, NULL);
145     ok(store != NULL, "CertOpenStore failed: %d\n", GetLastError());
146     if (!store)
147         return;
148
149     /* Weird--bad add disposition leads to an access violation in Windows.
150      */
151     ret = CertAddEncodedCertificateToStore(0, X509_ASN_ENCODING, bigCert,
152      sizeof(bigCert), 0, NULL);
153     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
154      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
155     ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
156      bigCert, sizeof(bigCert), 0, NULL);
157     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
158      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
159
160     /* Weird--can add a cert to the NULL store (does this have special
161      * meaning?)
162      */
163     context = NULL;
164     ret = CertAddEncodedCertificateToStore(0, X509_ASN_ENCODING, bigCert,
165      sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
166     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
167      GetLastError());
168     if (context)
169         CertFreeCertificateContext(context);
170
171     ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
172      bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
173     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
174      GetLastError());
175     ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
176      bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, NULL);
177     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
178      GetLastError());
179     /* This has the same name as bigCert, so finding isn't done by name */
180     ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
181      certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, &context);
182     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
183      GetLastError());
184     ok(context != NULL, "Expected a context\n");
185     if (context)
186     {
187         CRYPT_DATA_BLOB hash = { sizeof(bigCert2Hash), bigCert2Hash };
188
189         /* Duplicate (AddRef) the context so we can still use it after
190          * deleting it from the store.
191          */
192         CertDuplicateCertificateContext(context);
193         CertDeleteCertificateFromStore(context);
194         /* Set the same hash as bigCert2, and try to readd it */
195         ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID,
196          0, &hash);
197         ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
198          GetLastError());
199         ret = CertAddCertificateContextToStore(store, context,
200          CERT_STORE_ADD_NEW, NULL);
201         /* The failure is a bit odd (CRYPT_E_ASN1_BADTAG), so just check
202          * that it fails.
203          */
204         ok(!ret, "Expected failure\n");
205         CertFreeCertificateContext(context);
206     }
207     context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert2,
208      sizeof(bigCert2));
209     ok(context != NULL, "Expected a context\n");
210     if (context)
211     {
212         /* Try to readd bigCert2 to the store */
213         ret = CertAddCertificateContextToStore(store, context,
214          CERT_STORE_ADD_NEW, NULL);
215         ok(!ret && GetLastError() == CRYPT_E_EXISTS,
216          "Expected CRYPT_E_EXISTS, got %08x\n", GetLastError());
217         CertFreeCertificateContext(context);
218     }
219
220     /* Adding a cert with the same issuer name and serial number (but
221      * different subject) as an existing cert succeeds.
222      */
223     context = NULL;
224     ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
225      bigCert2WithDifferentSerial, sizeof(bigCert2WithDifferentSerial),
226      CERT_STORE_ADD_NEW, &context);
227     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
228      GetLastError());
229     if (context)
230         CertDeleteCertificateFromStore(context);
231
232     /* Adding a cert with the same subject name and serial number (but
233      * different issuer) as an existing cert succeeds.
234      */
235     context = NULL;
236     ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
237      bigCertWithDifferentSubject, sizeof(bigCertWithDifferentSubject),
238      CERT_STORE_ADD_NEW, &context);
239     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
240      GetLastError());
241     if (context)
242         CertDeleteCertificateFromStore(context);
243
244     /* Adding a cert with the same issuer name and serial number (but
245      * different otherwise) as an existing cert succeeds.
246      */
247     context = NULL;
248     ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
249      bigCertWithDifferentIssuer, sizeof(bigCertWithDifferentIssuer),
250      CERT_STORE_ADD_NEW, &context);
251     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
252      GetLastError());
253     if (context)
254         CertDeleteCertificateFromStore(context);
255
256     collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
257      CERT_STORE_CREATE_NEW_FLAG, NULL);
258     ok(collection != NULL, "CertOpenStore failed: %08x\n", GetLastError());
259     if (collection)
260     {
261         /* Add store to the collection, but disable updates */
262         CertAddStoreToCollection(collection, store, 0, 0);
263
264         context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert2,
265          sizeof(bigCert2));
266         ok(context != NULL, "Expected a context\n");
267         if (context)
268         {
269             /* Try to readd bigCert2 to the collection */
270             ret = CertAddCertificateContextToStore(collection, context,
271              CERT_STORE_ADD_NEW, NULL);
272             ok(!ret && GetLastError() == CRYPT_E_EXISTS,
273              "Expected CRYPT_E_EXISTS, got %08x\n", GetLastError());
274             /* Replacing an existing certificate context is allowed, even
275              * though updates to the collection aren't..
276              */
277             ret = CertAddCertificateContextToStore(collection, context,
278              CERT_STORE_ADD_REPLACE_EXISTING, NULL);
279             ok(ret, "CertAddCertificateContextToStore failed: %08x\n",
280              GetLastError());
281             /* use the existing certificate and ask for a copy of the context*/
282             copyContext = NULL;
283             ret = CertAddCertificateContextToStore(collection, context,
284              CERT_STORE_ADD_USE_EXISTING, &copyContext);
285             ok(ret, "CertAddCertificateContextToStore failed: %08x\n",
286              GetLastError());
287             ok(copyContext != NULL, "Expected on output a non NULL copyContext\n");
288             if (copyContext)
289                 CertFreeCertificateContext(copyContext);
290             /* but adding a new certificate isn't allowed. */
291             ret = CertAddCertificateContextToStore(collection, context,
292              CERT_STORE_ADD_ALWAYS, NULL);
293             ok(!ret && GetLastError() == E_ACCESSDENIED,
294              "Expected E_ACCESSDENIED, got %08x\n", GetLastError());
295             CertFreeCertificateContext(context);
296         }
297
298         CertCloseStore(collection, 0);
299     }
300
301     CertCloseStore(store, 0);
302 }
303
304 static void checkHash(const BYTE *data, DWORD dataLen, ALG_ID algID,
305  PCCERT_CONTEXT context, DWORD propID)
306 {
307     BYTE hash[20] = { 0 }, hashProperty[20];
308     BOOL ret;
309     DWORD size;
310     DWORD dwSizeWithNull;
311
312     memset(hash, 0, sizeof(hash));
313     memset(hashProperty, 0, sizeof(hashProperty));
314     size = sizeof(hash);
315     ret = CryptHashCertificate(0, algID, 0, data, dataLen, hash, &size);
316     ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
317     ret = CertGetCertificateContextProperty(context, propID, NULL,
318      &dwSizeWithNull);
319     ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
320      GetLastError());
321     ret = CertGetCertificateContextProperty(context, propID, hashProperty,
322      &size);
323     ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
324      GetLastError());
325     ok(!memcmp(hash, hashProperty, size), "Unexpected hash for property %d\n",
326      propID);
327     ok(size == dwSizeWithNull, "Unexpected length of hash for property: received %d instead of %d\n",
328      dwSizeWithNull,size);
329 }
330
331 static WCHAR cspNameW[] = { 'W','i','n','e','C','r','y','p','t','T','e','m','p',0 };
332 static const BYTE v1CertWithPubKey[] = {
333 0x30,0x81,0x95,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
334 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
335 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
336 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
337 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
338 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
339 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
340 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
341 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,
342 0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,
343 0x01,0x01 };
344 static const BYTE v1CertWithSubjectKeyId[] = {
345 0x30,0x7b,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
346 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
347 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
348 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
349 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
350 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
351 0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x17,0x30,0x15,0x30,
352 0x13,0x06,0x03,0x55,0x1d,0x0e,0x04,0x0c,0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,
353 0x4c,0x61,0x6e,0x67,0x00 };
354 static const BYTE subjectKeyId[] = {
355 0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
356
357 static void testCertProperties(void)
358 {
359     PCCERT_CONTEXT context = CertCreateCertificateContext(X509_ASN_ENCODING,
360      bigCert, sizeof(bigCert));
361     DWORD propID, numProps, access, size;
362     BOOL ret;
363     BYTE hash[20] = { 0 }, hashProperty[20];
364     CRYPT_DATA_BLOB blob;
365     CERT_KEY_CONTEXT keyContext;
366
367     ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
368      GetLastError());
369     if (!context)
370         return;
371
372     /* This crashes
373     propID = CertEnumCertificateContextProperties(NULL, 0);
374      */
375
376     propID = 0;
377     numProps = 0;
378     do {
379         propID = CertEnumCertificateContextProperties(context, propID);
380         if (propID)
381             numProps++;
382     } while (propID != 0);
383     ok(numProps == 0, "Expected 0 properties, got %d\n", numProps);
384
385     /* Tests with a NULL cert context.  Prop ID 0 fails.. */
386     ret = CertSetCertificateContextProperty(NULL, 0, 0, NULL);
387     ok(!ret && GetLastError() == E_INVALIDARG,
388      "Expected E_INVALIDARG, got %08x\n", GetLastError());
389     /* while this just crashes.
390     ret = CertSetCertificateContextProperty(NULL,
391      CERT_KEY_PROV_HANDLE_PROP_ID, 0, NULL);
392      */
393
394     ret = CertSetCertificateContextProperty(context, 0, 0, NULL);
395     ok(!ret && GetLastError() == E_INVALIDARG,
396      "Expected E_INVALIDARG, got %08x\n", GetLastError());
397     /* Can't set the cert property directly, this crashes.
398     ret = CertSetCertificateContextProperty(context,
399      CERT_CERT_PROP_ID, 0, bigCert2);
400      */
401
402     /* These all crash.
403     ret = CertGetCertificateContextProperty(context,
404      CERT_ACCESS_STATE_PROP_ID, 0, NULL);
405     ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID, 
406      NULL, NULL);
407     ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID, 
408      hashProperty, NULL);
409      */
410     /* A missing prop */
411     size = 0;
412     ret = CertGetCertificateContextProperty(context,
413      CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
414     ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
415      "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
416     /* And, an implicit property */
417     size = sizeof(access);
418     ret = CertGetCertificateContextProperty(context,
419      CERT_ACCESS_STATE_PROP_ID, &access, &size);
420     ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
421      GetLastError());
422     ok(!(access & CERT_ACCESS_STATE_WRITE_PERSIST_FLAG),
423      "Didn't expect a persisted cert\n");
424     /* Trying to set this "read only" property crashes.
425     access |= CERT_ACCESS_STATE_WRITE_PERSIST_FLAG;
426     ret = CertSetCertificateContextProperty(context,
427      CERT_ACCESS_STATE_PROP_ID, 0, &access);
428      */
429
430     /* Can I set the hash to an invalid hash? */
431     blob.pbData = hash;
432     blob.cbData = sizeof(hash);
433     ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID, 0,
434      &blob);
435     ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
436      GetLastError());
437     size = sizeof(hashProperty);
438     ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
439      hashProperty, &size);
440     ok(!memcmp(hashProperty, hash, sizeof(hash)), "Unexpected hash\n");
441     /* Delete the (bogus) hash, and get the real one */
442     ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID, 0,
443      NULL);
444     ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
445      GetLastError());
446     checkHash(bigCert, sizeof(bigCert), CALG_SHA1, context,
447      CERT_HASH_PROP_ID);
448
449     /* Now that the hash property is set, we should get one property when
450      * enumerating.
451      */
452     propID = 0;
453     numProps = 0;
454     do {
455         propID = CertEnumCertificateContextProperties(context, propID);
456         if (propID)
457             numProps++;
458     } while (propID != 0);
459     ok(numProps == 1, "Expected 1 properties, got %d\n", numProps);
460
461     /* Check a few other implicit properties */
462     checkHash(bigCert, sizeof(bigCert), CALG_MD5, context,
463      CERT_MD5_HASH_PROP_ID);
464     checkHash(
465      context->pCertInfo->Subject.pbData,
466      context->pCertInfo->Subject.cbData,
467      CALG_MD5, context, CERT_SUBJECT_NAME_MD5_HASH_PROP_ID);
468     checkHash(
469      context->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData,
470      context->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData,
471      CALG_MD5, context, CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID);
472
473     /* Test key contexts and handles and such */
474     size = 0;
475     ret = CertGetCertificateContextProperty(context, CERT_KEY_CONTEXT_PROP_ID,
476      NULL, &size);
477     ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
478      "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
479     size = sizeof(CERT_KEY_CONTEXT);
480     ret = CertGetCertificateContextProperty(context, CERT_KEY_CONTEXT_PROP_ID,
481      NULL, &size);
482     ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
483      "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
484     ret = CertGetCertificateContextProperty(context, CERT_KEY_CONTEXT_PROP_ID,
485      &keyContext, &size);
486     ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
487      "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
488     /* Key context with an invalid size */
489     keyContext.cbSize = 0;
490     ret = CertSetCertificateContextProperty(context, CERT_KEY_CONTEXT_PROP_ID,
491      0, &keyContext);
492     ok(!ret && GetLastError() == E_INVALIDARG,
493      "Expected E_INVALIDARG, got %08x\n", GetLastError());
494     size = sizeof(keyContext);
495     ret = CertGetCertificateContextProperty(context, CERT_KEY_CONTEXT_PROP_ID,
496      &keyContext, &size);
497     ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
498      "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
499     keyContext.cbSize = sizeof(keyContext);
500     keyContext.hCryptProv = 0;
501     keyContext.dwKeySpec = AT_SIGNATURE;
502     ret = CertSetCertificateContextProperty(context, CERT_KEY_CONTEXT_PROP_ID,
503      0, &keyContext);
504     ok(ret, "CertSetCertificateContextProperty failed: %08x\n", GetLastError());
505     /* Now that that's set, the key prov handle property is also gettable.
506      */
507     size = sizeof(DWORD);
508     ret = CertGetCertificateContextProperty(context,
509      CERT_KEY_PROV_HANDLE_PROP_ID, &keyContext.hCryptProv, &size);
510     ok(ret, "Expected to get the CERT_KEY_PROV_HANDLE_PROP_ID, got %08x\n",
511      GetLastError());
512     /* Remove the key prov handle property.. */
513     ret = CertSetCertificateContextProperty(context,
514      CERT_KEY_PROV_HANDLE_PROP_ID, 0, NULL);
515     ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
516      GetLastError());
517     /* and the key context's CSP is set to NULL. */
518     size = sizeof(keyContext);
519     ret = CertGetCertificateContextProperty(context,
520      CERT_KEY_CONTEXT_PROP_ID, &keyContext, &size);
521     ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
522      GetLastError());
523     ok(keyContext.hCryptProv == 0, "Expected no hCryptProv\n");
524
525     /* According to MSDN the subject key id can be stored as a property,
526      * as a subject key extension, or as the SHA1 hash of the public key,
527      * but this cert has none of them:
528      */
529     ret = CertGetCertificateContextProperty(context,
530      CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size);
531     ok(!ret && GetLastError() == ERROR_INVALID_DATA,
532      "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
533     CertFreeCertificateContext(context);
534     /* This cert does have a public key, but its subject key identifier still
535      * isn't available: */
536     context = CertCreateCertificateContext(X509_ASN_ENCODING,
537      v1CertWithPubKey, sizeof(v1CertWithPubKey));
538     ret = CertGetCertificateContextProperty(context,
539      CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size);
540     ok(!ret && GetLastError() == ERROR_INVALID_DATA,
541      "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
542     CertFreeCertificateContext(context);
543     /* This cert with a subject key extension can have its key identifier
544      * property retrieved:
545      */
546     context = CertCreateCertificateContext(X509_ASN_ENCODING,
547      v1CertWithSubjectKeyId, sizeof(v1CertWithSubjectKeyId));
548     ret = CertGetCertificateContextProperty(context,
549      CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size);
550     ok(ret, "CertGetCertificateContextProperty failed: %08x\n", GetLastError());
551     if (ret)
552     {
553         LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, size);
554
555         if (buf)
556         {
557             ret = CertGetCertificateContextProperty(context,
558              CERT_KEY_IDENTIFIER_PROP_ID, buf, &size);
559             ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
560              GetLastError());
561             ok(!memcmp(buf, subjectKeyId, size), "Unexpected subject key id\n");
562             HeapFree(GetProcessHeap(), 0, buf);
563         }
564     }
565     CertFreeCertificateContext(context);
566 }
567
568 static void testDupCert(void)
569 {
570     HCERTSTORE store;
571     PCCERT_CONTEXT context, dupContext;
572     BOOL ret;
573
574     store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
575      CERT_STORE_CREATE_NEW_FLAG, NULL);
576     ok(store != NULL, "CertOpenStore failed: %d\n", GetLastError());
577     if (!store)
578         return;
579
580     ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
581      bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
582     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
583      GetLastError());
584     ok(context != NULL, "Expected a valid cert context\n");
585     if (context)
586     {
587         ok(context->cbCertEncoded == sizeof(bigCert),
588          "Wrong cert size %d\n", context->cbCertEncoded);
589         ok(!memcmp(context->pbCertEncoded, bigCert, sizeof(bigCert)),
590          "Unexpected encoded cert in context\n");
591         ok(context->hCertStore == store, "Unexpected store\n");
592
593         dupContext = CertDuplicateCertificateContext(context);
594         ok(dupContext != NULL, "Expected valid duplicate\n");
595         /* Not only is it a duplicate, it's identical: the address is the
596          * same.
597          */
598         ok(dupContext == context, "Expected identical context addresses\n");
599         CertFreeCertificateContext(dupContext);
600         CertFreeCertificateContext(context);
601     }
602     CertCloseStore(store, 0);
603 }
604
605 static BYTE subjectName3[] = { 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
606  0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x52, 0x6f, 0x62, 0x20, 0x20, 0x4c, 0x61,
607  0x6e, 0x67, 0x00 };
608 static const BYTE iTunesCert0[] = {
609 0x30,0x82,0x03,0xc4,0x30,0x82,0x03,0x2d,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,
610 0x47,0xbf,0x19,0x95,0xdf,0x8d,0x52,0x46,0x43,0xf7,0xdb,0x6d,0x48,0x0d,0x31,
611 0xa4,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,
612 0x00,0x30,0x81,0x8b,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,
613 0x5a,0x41,0x31,0x15,0x30,0x13,0x06,0x03,0x55,0x04,0x08,0x13,0x0c,0x57,0x65,
614 0x73,0x74,0x65,0x72,0x6e,0x20,0x43,0x61,0x70,0x65,0x31,0x14,0x30,0x12,0x06,
615 0x03,0x55,0x04,0x07,0x13,0x0b,0x44,0x75,0x72,0x62,0x61,0x6e,0x76,0x69,0x6c,
616 0x6c,0x65,0x31,0x0f,0x30,0x0d,0x06,0x03,0x55,0x04,0x0a,0x13,0x06,0x54,0x68,
617 0x61,0x77,0x74,0x65,0x31,0x1d,0x30,0x1b,0x06,0x03,0x55,0x04,0x0b,0x13,0x14,
618 0x54,0x68,0x61,0x77,0x74,0x65,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,
619 0x61,0x74,0x69,0x6f,0x6e,0x31,0x1f,0x30,0x1d,0x06,0x03,0x55,0x04,0x03,0x13,
620 0x16,0x54,0x68,0x61,0x77,0x74,0x65,0x20,0x54,0x69,0x6d,0x65,0x73,0x74,0x61,
621 0x6d,0x70,0x69,0x6e,0x67,0x20,0x43,0x41,0x30,0x1e,0x17,0x0d,0x30,0x33,0x31,
622 0x32,0x30,0x34,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,0x31,0x33,0x31,
623 0x32,0x30,0x33,0x32,0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x53,0x31,0x0b,0x30,
624 0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x17,0x30,0x15,0x06,
625 0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x2c,
626 0x20,0x49,0x6e,0x63,0x2e,0x31,0x2b,0x30,0x29,0x06,0x03,0x55,0x04,0x03,0x13,
627 0x22,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x54,0x69,0x6d,0x65,0x20,
628 0x53,0x74,0x61,0x6d,0x70,0x69,0x6e,0x67,0x20,0x53,0x65,0x72,0x76,0x69,0x63,
629 0x65,0x73,0x20,0x43,0x41,0x30,0x82,0x01,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,
630 0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0f,0x00,0x30,
631 0x82,0x01,0x0a,0x02,0x82,0x01,0x01,0x00,0xa9,0xca,0xb2,0xa4,0xcc,0xcd,0x20,
632 0xaf,0x0a,0x7d,0x89,0xac,0x87,0x75,0xf0,0xb4,0x4e,0xf1,0xdf,0xc1,0x0f,0xbf,
633 0x67,0x61,0xbd,0xa3,0x64,0x1c,0xda,0xbb,0xf9,0xca,0x33,0xab,0x84,0x30,0x89,
634 0x58,0x7e,0x8c,0xdb,0x6b,0xdd,0x36,0x9e,0x0f,0xbf,0xd1,0xec,0x78,0xf2,0x77,
635 0xa6,0x7e,0x6f,0x3c,0xbf,0x93,0xaf,0x0d,0xba,0x68,0xf4,0x6c,0x94,0xca,0xbd,
636 0x52,0x2d,0xab,0x48,0x3d,0xf5,0xb6,0xd5,0x5d,0x5f,0x1b,0x02,0x9f,0xfa,0x2f,
637 0x6b,0x1e,0xa4,0xf7,0xa3,0x9a,0xa6,0x1a,0xc8,0x02,0xe1,0x7f,0x4c,0x52,0xe3,
638 0x0e,0x60,0xec,0x40,0x1c,0x7e,0xb9,0x0d,0xde,0x3f,0xc7,0xb4,0xdf,0x87,0xbd,
639 0x5f,0x7a,0x6a,0x31,0x2e,0x03,0x99,0x81,0x13,0xa8,0x47,0x20,0xce,0x31,0x73,
640 0x0d,0x57,0x2d,0xcd,0x78,0x34,0x33,0x95,0x12,0x99,0x12,0xb9,0xde,0x68,0x2f,
641 0xaa,0xe6,0xe3,0xc2,0x8a,0x8c,0x2a,0xc3,0x8b,0x21,0x87,0x66,0xbd,0x83,0x58,
642 0x57,0x6f,0x75,0xbf,0x3c,0xaa,0x26,0x87,0x5d,0xca,0x10,0x15,0x3c,0x9f,0x84,
643 0xea,0x54,0xc1,0x0a,0x6e,0xc4,0xfe,0xc5,0x4a,0xdd,0xb9,0x07,0x11,0x97,0x22,
644 0x7c,0xdb,0x3e,0x27,0xd1,0x1e,0x78,0xec,0x9f,0x31,0xc9,0xf1,0xe6,0x22,0x19,
645 0xdb,0xc4,0xb3,0x47,0x43,0x9a,0x1a,0x5f,0xa0,0x1e,0x90,0xe4,0x5e,0xf5,0xee,
646 0x7c,0xf1,0x7d,0xab,0x62,0x01,0x8f,0xf5,0x4d,0x0b,0xde,0xd0,0x22,0x56,0xa8,
647 0x95,0xcd,0xae,0x88,0x76,0xae,0xee,0xba,0x0d,0xf3,0xe4,0x4d,0xd9,0xa0,0xfb,
648 0x68,0xa0,0xae,0x14,0x3b,0xb3,0x87,0xc1,0xbb,0x02,0x03,0x01,0x00,0x01,0xa3,
649 0x81,0xdb,0x30,0x81,0xd8,0x30,0x34,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,
650 0x01,0x01,0x04,0x28,0x30,0x26,0x30,0x24,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,
651 0x07,0x30,0x01,0x86,0x18,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6f,0x63,0x73,
652 0x70,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x30,
653 0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,
654 0xff,0x02,0x01,0x00,0x30,0x41,0x06,0x03,0x55,0x1d,0x1f,0x04,0x3a,0x30,0x38,
655 0x30,0x36,0xa0,0x34,0xa0,0x32,0x86,0x30,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
656 0x63,0x72,0x6c,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,
657 0x6d,0x2f,0x54,0x68,0x61,0x77,0x74,0x65,0x54,0x69,0x6d,0x65,0x73,0x74,0x61,
658 0x6d,0x70,0x69,0x6e,0x67,0x43,0x41,0x2e,0x63,0x72,0x6c,0x30,0x13,0x06,0x03,
659 0x55,0x1d,0x25,0x04,0x0c,0x30,0x0a,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,
660 0x03,0x08,0x30,0x0e,0x06,0x03,0x55,0x1d,0x0f,0x01,0x01,0xff,0x04,0x04,0x03,
661 0x02,0x01,0x06,0x30,0x24,0x06,0x03,0x55,0x1d,0x11,0x04,0x1d,0x30,0x1b,0xa4,
662 0x19,0x30,0x17,0x31,0x15,0x30,0x13,0x06,0x03,0x55,0x04,0x03,0x13,0x0c,0x54,
663 0x53,0x41,0x32,0x30,0x34,0x38,0x2d,0x31,0x2d,0x35,0x33,0x30,0x0d,0x06,0x09,
664 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x03,0x81,0x81,0x00,
665 0x4a,0x6b,0xf9,0xea,0x58,0xc2,0x44,0x1c,0x31,0x89,0x79,0x99,0x2b,0x96,0xbf,
666 0x82,0xac,0x01,0xd6,0x1c,0x4c,0xcd,0xb0,0x8a,0x58,0x6e,0xdf,0x08,0x29,0xa3,
667 0x5e,0xc8,0xca,0x93,0x13,0xe7,0x04,0x52,0x0d,0xef,0x47,0x27,0x2f,0x00,0x38,
668 0xb0,0xe4,0xc9,0x93,0x4e,0x9a,0xd4,0x22,0x62,0x15,0xf7,0x3f,0x37,0x21,0x4f,
669 0x70,0x31,0x80,0xf1,0x8b,0x38,0x87,0xb3,0xe8,0xe8,0x97,0x00,0xfe,0xcf,0x55,
670 0x96,0x4e,0x24,0xd2,0xa9,0x27,0x4e,0x7a,0xae,0xb7,0x61,0x41,0xf3,0x2a,0xce,
671 0xe7,0xc9,0xd9,0x5e,0xdd,0xbb,0x2b,0x85,0x3e,0xb5,0x9d,0xb5,0xd9,0xe1,0x57,
672 0xff,0xbe,0xb4,0xc5,0x7e,0xf5,0xcf,0x0c,0x9e,0xf0,0x97,0xfe,0x2b,0xd3,0x3b,
673 0x52,0x1b,0x1b,0x38,0x27,0xf7,0x3f,0x4a };
674 static const BYTE iTunesCert1[] = {
675 0x30,0x82,0x03,0xff,0x30,0x82,0x02,0xe7,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,
676 0x0d,0xe9,0x2b,0xf0,0xd4,0xd8,0x29,0x88,0x18,0x32,0x05,0x09,0x5e,0x9a,0x76,
677 0x88,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,
678 0x00,0x30,0x53,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,
679 0x53,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,
680 0x69,0x53,0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x2b,0x30,0x29,
681 0x06,0x03,0x55,0x04,0x03,0x13,0x22,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,
682 0x20,0x54,0x69,0x6d,0x65,0x20,0x53,0x74,0x61,0x6d,0x70,0x69,0x6e,0x67,0x20,
683 0x53,0x65,0x72,0x76,0x69,0x63,0x65,0x73,0x20,0x43,0x41,0x30,0x1e,0x17,0x0d,
684 0x30,0x33,0x31,0x32,0x30,0x34,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,
685 0x30,0x38,0x31,0x32,0x30,0x33,0x32,0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x57,
686 0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x17,
687 0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,0x69,
688 0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x2f,0x30,0x2d,0x06,0x03,0x55,
689 0x04,0x03,0x13,0x26,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x54,0x69,
690 0x6d,0x65,0x20,0x53,0x74,0x61,0x6d,0x70,0x69,0x6e,0x67,0x20,0x53,0x65,0x72,
691 0x76,0x69,0x63,0x65,0x73,0x20,0x53,0x69,0x67,0x6e,0x65,0x72,0x30,0x82,0x01,
692 0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,
693 0x00,0x03,0x82,0x01,0x0f,0x00,0x30,0x82,0x01,0x0a,0x02,0x82,0x01,0x01,0x00,
694 0xb2,0x50,0x28,0x48,0xdd,0xd3,0x68,0x7a,0x84,0x18,0x44,0x66,0x75,0x5d,0x7e,
695 0xc4,0xb8,0x9f,0x63,0x26,0xff,0x3d,0x43,0x9c,0x7c,0x11,0x38,0x10,0x25,0x55,
696 0x73,0xd9,0x75,0x27,0x69,0xfd,0x4e,0xb9,0x20,0x5c,0xd3,0x0a,0xf9,0xa0,0x1b,
697 0x2a,0xed,0x55,0x56,0x21,0x61,0xd8,0x1e,0xdb,0xe4,0xbc,0x33,0x6b,0xc7,0xef,
698 0xdd,0xa3,0x37,0x65,0x8e,0x1b,0x93,0x0c,0xb6,0x53,0x1e,0x5c,0x7c,0x66,0x35,
699 0x5f,0x05,0x8a,0x45,0xfe,0x76,0x4e,0xdf,0x53,0x80,0xa2,0x81,0x20,0x9d,0xae,
700 0x88,0x5c,0xa2,0x08,0xf7,0xe5,0x30,0xf9,0xee,0x22,0x37,0x4c,0x42,0x0a,0xce,
701 0xdf,0xc6,0x1f,0xc4,0xd6,0x55,0xe9,0x81,0x3f,0xb5,0x52,0xa3,0x2c,0xaa,0x01,
702 0x7a,0xf2,0xa2,0xaa,0x8d,0x35,0xfe,0x9f,0xe6,0x5d,0x6a,0x05,0x9f,0x3d,0x6b,
703 0xe3,0xbf,0x96,0xc0,0xfe,0xcc,0x60,0xf9,0x40,0xe7,0x07,0xa0,0x44,0xeb,0x81,
704 0x51,0x6e,0xa5,0x2a,0xf2,0xb6,0x8a,0x10,0x28,0xed,0x8f,0xdc,0x06,0xa0,0x86,
705 0x50,0x9a,0x7b,0x4a,0x08,0x0d,0x30,0x1d,0xca,0x10,0x9e,0x6b,0xf7,0xe9,0x58,
706 0xae,0x04,0xa9,0x40,0x99,0xb2,0x28,0xe8,0x8f,0x16,0xac,0x3c,0xe3,0x53,0x6f,
707 0x4b,0xd3,0x35,0x9d,0xb5,0x6f,0x64,0x1d,0xb3,0x96,0x2c,0xbb,0x3d,0xe7,0x79,
708 0xeb,0x6d,0x7a,0xf9,0x16,0xe6,0x26,0xad,0xaf,0xef,0x99,0x53,0xb7,0x40,0x2c,
709 0x95,0xb8,0x79,0xaa,0xfe,0xd4,0x52,0xab,0x29,0x74,0x7e,0x42,0xec,0x39,0x1e,
710 0xa2,0x6a,0x16,0xe6,0x59,0xbb,0x24,0x68,0xd8,0x00,0x80,0x43,0x10,0x87,0x80,
711 0x6b,0x02,0x03,0x01,0x00,0x01,0xa3,0x81,0xca,0x30,0x81,0xc7,0x30,0x34,0x06,
712 0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x28,0x30,0x26,0x30,0x24,
713 0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x18,0x68,0x74,0x74,
714 0x70,0x3a,0x2f,0x2f,0x6f,0x63,0x73,0x70,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,
715 0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x30,0x0c,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
716 0xff,0x04,0x02,0x30,0x00,0x30,0x33,0x06,0x03,0x55,0x1d,0x1f,0x04,0x2c,0x30,
717 0x2a,0x30,0x28,0xa0,0x26,0xa0,0x24,0x86,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,
718 0x2f,0x63,0x72,0x6c,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,
719 0x6f,0x6d,0x2f,0x74,0x73,0x73,0x2d,0x63,0x61,0x2e,0x63,0x72,0x6c,0x30,0x16,
720 0x06,0x03,0x55,0x1d,0x25,0x01,0x01,0xff,0x04,0x0c,0x30,0x0a,0x06,0x08,0x2b,
721 0x06,0x01,0x05,0x05,0x07,0x03,0x08,0x30,0x0e,0x06,0x03,0x55,0x1d,0x0f,0x01,
722 0x01,0xff,0x04,0x04,0x03,0x02,0x06,0xc0,0x30,0x24,0x06,0x03,0x55,0x1d,0x11,
723 0x04,0x1d,0x30,0x1b,0xa4,0x19,0x30,0x17,0x31,0x15,0x30,0x13,0x06,0x03,0x55,
724 0x04,0x03,0x13,0x0c,0x54,0x53,0x41,0x32,0x30,0x34,0x38,0x2d,0x31,0x2d,0x35,
725 0x34,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,
726 0x00,0x03,0x82,0x01,0x01,0x00,0x87,0x78,0x70,0xda,0x4e,0x52,0x01,0x20,0x5b,
727 0xe0,0x79,0xc9,0x82,0x30,0xc4,0xfd,0xb9,0x19,0x96,0xbd,0x91,0x00,0xc3,0xbd,
728 0xcd,0xcd,0xc6,0xf4,0x0e,0xd8,0xff,0xf9,0x4d,0xc0,0x33,0x62,0x30,0x11,0xc5,
729 0xf5,0x74,0x1b,0xd4,0x92,0xde,0x5f,0x9c,0x20,0x13,0xb1,0x7c,0x45,0xbe,0x50,
730 0xcd,0x83,0xe7,0x80,0x17,0x83,0xa7,0x27,0x93,0x67,0x13,0x46,0xfb,0xca,0xb8,
731 0x98,0x41,0x03,0xcc,0x9b,0x51,0x5b,0x05,0x8b,0x7f,0xa8,0x6f,0xf3,0x1b,0x50,
732 0x1b,0x24,0x2e,0xf2,0x69,0x8d,0x6c,0x22,0xf7,0xbb,0xca,0x16,0x95,0xed,0x0c,
733 0x74,0xc0,0x68,0x77,0xd9,0xeb,0x99,0x62,0x87,0xc1,0x73,0x90,0xf8,0x89,0x74,
734 0x7a,0x23,0xab,0xa3,0x98,0x7b,0x97,0xb1,0xf7,0x8f,0x29,0x71,0x4d,0x2e,0x75,
735 0x1b,0x48,0x41,0xda,0xf0,0xb5,0x0d,0x20,0x54,0xd6,0x77,0xa0,0x97,0x82,0x63,
736 0x69,0xfd,0x09,0xcf,0x8a,0xf0,0x75,0xbb,0x09,0x9b,0xd9,0xf9,0x11,0x55,0x26,
737 0x9a,0x61,0x32,0xbe,0x7a,0x02,0xb0,0x7b,0x86,0xbe,0xa2,0xc3,0x8b,0x22,0x2c,
738 0x78,0xd1,0x35,0x76,0xbc,0x92,0x73,0x5c,0xf9,0xb9,0xe6,0x4c,0x15,0x0a,0x23,
739 0xcc,0xe4,0xd2,0xd4,0x34,0x2e,0x49,0x40,0x15,0x3c,0x0f,0x60,0x7a,0x24,0xc6,
740 0xa5,0x66,0xef,0x96,0xcf,0x70,0xeb,0x3e,0xe7,0xf4,0x0d,0x7e,0xdc,0xd1,0x7c,
741 0xa3,0x76,0x71,0x69,0xc1,0x9c,0x4f,0x47,0x30,0x35,0x21,0xb1,0xa2,0xaf,0x1a,
742 0x62,0x3c,0x2b,0xd9,0x8e,0xaa,0x2a,0x07,0x7b,0xd8,0x18,0xb3,0x5c,0x7b,0xe2,
743 0x9d,0xa5,0x6f,0xfe,0x3c,0x89,0xad };
744 static const BYTE iTunesCert2[] = {
745 0x30,0x82,0x04,0xbf,0x30,0x82,0x04,0x28,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,
746 0x41,0x91,0xa1,0x5a,0x39,0x78,0xdf,0xcf,0x49,0x65,0x66,0x38,0x1d,0x4c,0x75,
747 0xc2,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,
748 0x00,0x30,0x5f,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,
749 0x53,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,
750 0x69,0x53,0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x37,0x30,0x35,
751 0x06,0x03,0x55,0x04,0x0b,0x13,0x2e,0x43,0x6c,0x61,0x73,0x73,0x20,0x33,0x20,
752 0x50,0x75,0x62,0x6c,0x69,0x63,0x20,0x50,0x72,0x69,0x6d,0x61,0x72,0x79,0x20,
753 0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x41,
754 0x75,0x74,0x68,0x6f,0x72,0x69,0x74,0x79,0x30,0x1e,0x17,0x0d,0x30,0x34,0x30,
755 0x37,0x31,0x36,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,0x31,0x34,0x30,
756 0x37,0x31,0x35,0x32,0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x81,0xb4,0x31,0x0b,
757 0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x17,0x30,0x15,
758 0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,
759 0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x1f,0x30,0x1d,0x06,0x03,0x55,0x04,0x0b,
760 0x13,0x16,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x54,0x72,0x75,0x73,
761 0x74,0x20,0x4e,0x65,0x74,0x77,0x6f,0x72,0x6b,0x31,0x3b,0x30,0x39,0x06,0x03,
762 0x55,0x04,0x0b,0x13,0x32,0x54,0x65,0x72,0x6d,0x73,0x20,0x6f,0x66,0x20,0x75,
763 0x73,0x65,0x20,0x61,0x74,0x20,0x68,0x74,0x74,0x70,0x73,0x3a,0x2f,0x2f,0x77,
764 0x77,0x77,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,
765 0x2f,0x72,0x70,0x61,0x20,0x28,0x63,0x29,0x30,0x34,0x31,0x2e,0x30,0x2c,0x06,
766 0x03,0x55,0x04,0x03,0x13,0x25,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,
767 0x43,0x6c,0x61,0x73,0x73,0x20,0x33,0x20,0x43,0x6f,0x64,0x65,0x20,0x53,0x69,
768 0x67,0x6e,0x69,0x6e,0x67,0x20,0x32,0x30,0x30,0x34,0x20,0x43,0x41,0x30,0x82,
769 0x01,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,
770 0x05,0x00,0x03,0x82,0x01,0x0f,0x00,0x30,0x82,0x01,0x0a,0x02,0x82,0x01,0x01,
771 0x00,0xbe,0xbc,0xee,0xbc,0x7e,0xef,0x83,0xeb,0xe0,0x37,0x4f,0xfb,0x03,0x10,
772 0x38,0xbe,0x08,0xd2,0x8c,0x7d,0x9d,0xfa,0x92,0x7f,0x19,0x0c,0xc2,0x6b,0xee,
773 0x42,0x52,0x8c,0xde,0xd3,0x1c,0x48,0x13,0x25,0xea,0xc1,0x63,0x7a,0xf9,0x51,
774 0x65,0xee,0xd3,0xaa,0x3b,0xf5,0xf0,0x94,0x9c,0x2b,0xfb,0xf2,0x66,0xd4,0x24,
775 0xda,0xf7,0xf5,0x9f,0x6e,0x19,0x39,0x36,0xbc,0xd0,0xa3,0x76,0x08,0x1e,0x22,
776 0x27,0x24,0x6c,0x38,0x91,0x27,0xe2,0x84,0x49,0xae,0x1b,0x8a,0xa1,0xfd,0x25,
777 0x82,0x2c,0x10,0x30,0xe8,0x71,0xab,0x28,0xe8,0x77,0x4a,0x51,0xf1,0xec,0xcd,
778 0xf8,0xf0,0x54,0xd4,0x6f,0xc0,0xe3,0x6d,0x0a,0x8f,0xd9,0xd8,0x64,0x8d,0x63,
779 0xb2,0x2d,0x4e,0x27,0xf6,0x85,0x0e,0xfe,0x6d,0xe3,0x29,0x99,0xe2,0x85,0x47,
780 0x7c,0x2d,0x86,0x7f,0xe8,0x57,0x8f,0xad,0x67,0xc2,0x33,0x32,0x91,0x13,0x20,
781 0xfc,0xa9,0x23,0x14,0x9a,0x6d,0xc2,0x84,0x4b,0x76,0x68,0x04,0xd5,0x71,0x2c,
782 0x5d,0x21,0xfa,0x88,0x0d,0x26,0xfd,0x1f,0x2d,0x91,0x2b,0xe7,0x01,0x55,0x4d,
783 0xf2,0x6d,0x35,0x28,0x82,0xdf,0xd9,0x6b,0x5c,0xb6,0xd6,0xd9,0xaa,0x81,0xfd,
784 0x5f,0xcd,0x83,0xba,0x63,0x9d,0xd0,0x22,0xfc,0xa9,0x3b,0x42,0x69,0xb2,0x8e,
785 0x3a,0xb5,0xbc,0xb4,0x9e,0x0f,0x5e,0xc4,0xea,0x2c,0x82,0x8b,0x28,0xfd,0x53,
786 0x08,0x96,0xdd,0xb5,0x01,0x20,0xd1,0xf9,0xa5,0x18,0xe7,0xc0,0xee,0x51,0x70,
787 0x37,0xe1,0xb6,0x05,0x48,0x52,0x48,0x6f,0x38,0xea,0xc3,0xe8,0x6c,0x7b,0x44,
788 0x84,0xbb,0x02,0x03,0x01,0x00,0x01,0xa3,0x82,0x01,0xa0,0x30,0x82,0x01,0x9c,
789 0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,
790 0x01,0xff,0x02,0x01,0x00,0x30,0x44,0x06,0x03,0x55,0x1d,0x20,0x04,0x3d,0x30,
791 0x3b,0x30,0x39,0x06,0x0b,0x60,0x86,0x48,0x01,0x86,0xf8,0x45,0x01,0x07,0x17,
792 0x03,0x30,0x2a,0x30,0x28,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x02,0x01,
793 0x16,0x1c,0x68,0x74,0x74,0x70,0x73,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x76,
794 0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x2f,0x72,0x70,0x61,
795 0x30,0x31,0x06,0x03,0x55,0x1d,0x1f,0x04,0x2a,0x30,0x28,0x30,0x26,0xa0,0x24,
796 0xa0,0x22,0x86,0x20,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x63,0x72,0x6c,0x2e,
797 0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x2f,0x70,0x63,
798 0x61,0x33,0x2e,0x63,0x72,0x6c,0x30,0x1d,0x06,0x03,0x55,0x1d,0x25,0x04,0x16,
799 0x30,0x14,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x03,0x02,0x06,0x08,0x2b,
800 0x06,0x01,0x05,0x05,0x07,0x03,0x03,0x30,0x0e,0x06,0x03,0x55,0x1d,0x0f,0x01,
801 0x01,0xff,0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x11,0x06,0x09,0x60,0x86,0x48,
802 0x01,0x86,0xf8,0x42,0x01,0x01,0x04,0x04,0x03,0x02,0x00,0x01,0x30,0x29,0x06,
803 0x03,0x55,0x1d,0x11,0x04,0x22,0x30,0x20,0xa4,0x1e,0x30,0x1c,0x31,0x1a,0x30,
804 0x18,0x06,0x03,0x55,0x04,0x03,0x13,0x11,0x43,0x6c,0x61,0x73,0x73,0x33,0x43,
805 0x41,0x32,0x30,0x34,0x38,0x2d,0x31,0x2d,0x34,0x33,0x30,0x1d,0x06,0x03,0x55,
806 0x1d,0x0e,0x04,0x16,0x04,0x14,0x08,0xf5,0x51,0xe8,0xfb,0xfe,0x3d,0x3d,0x64,
807 0x36,0x7c,0x68,0xcf,0x5b,0x78,0xa8,0xdf,0xb9,0xc5,0x37,0x30,0x81,0x80,0x06,
808 0x03,0x55,0x1d,0x23,0x04,0x79,0x30,0x77,0xa1,0x63,0xa4,0x61,0x30,0x5f,0x31,
809 0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x17,0x30,
810 0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,0x69,0x67,
811 0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x37,0x30,0x35,0x06,0x03,0x55,0x04,
812 0x0b,0x13,0x2e,0x43,0x6c,0x61,0x73,0x73,0x20,0x33,0x20,0x50,0x75,0x62,0x6c,
813 0x69,0x63,0x20,0x50,0x72,0x69,0x6d,0x61,0x72,0x79,0x20,0x43,0x65,0x72,0x74,
814 0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x41,0x75,0x74,0x68,0x6f,
815 0x72,0x69,0x74,0x79,0x82,0x10,0x70,0xba,0xe4,0x1d,0x10,0xd9,0x29,0x34,0xb6,
816 0x38,0xca,0x7b,0x03,0xcc,0xba,0xbf,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,
817 0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x03,0x81,0x81,0x00,0xae,0x3a,0x17,0xb8,
818 0x4a,0x7b,0x55,0xfa,0x64,0x55,0xec,0x40,0xa4,0xed,0x49,0x41,0x90,0x99,0x9c,
819 0x89,0xbc,0xaf,0x2e,0x1d,0xca,0x78,0x23,0xf9,0x1c,0x19,0x0f,0x7f,0xeb,0x68,
820 0xbc,0x32,0xd9,0x88,0x38,0xde,0xdc,0x3f,0xd3,0x89,0xb4,0x3f,0xb1,0x82,0x96,
821 0xf1,0xa4,0x5a,0xba,0xed,0x2e,0x26,0xd3,0xde,0x7c,0x01,0x6e,0x00,0x0a,0x00,
822 0xa4,0x06,0x92,0x11,0x48,0x09,0x40,0xf9,0x1c,0x18,0x79,0x67,0x23,0x24,0xe0,
823 0xbb,0xd5,0xe1,0x50,0xae,0x1b,0xf5,0x0e,0xdd,0xe0,0x2e,0x81,0xcd,0x80,0xa3,
824 0x6c,0x52,0x4f,0x91,0x75,0x55,0x8a,0xba,0x22,0xf2,0xd2,0xea,0x41,0x75,0x88,
825 0x2f,0x63,0x55,0x7d,0x1e,0x54,0x5a,0x95,0x59,0xca,0xd9,0x34,0x81,0xc0,0x5f,
826 0x5e,0xf6,0x7a,0xb5 };
827 static const BYTE iTunesCert3[] = {
828 0x30,0x82,0x04,0xf1,0x30,0x82,0x03,0xd9,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,
829 0x0f,0x1a,0xa0,0xe0,0x9b,0x9b,0x61,0xa6,0xb6,0xfe,0x40,0xd2,0xdf,0x6a,0xf6,
830 0x8d,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,
831 0x00,0x30,0x81,0xb4,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,
832 0x55,0x53,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,
833 0x72,0x69,0x53,0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x1f,0x30,
834 0x1d,0x06,0x03,0x55,0x04,0x0b,0x13,0x16,0x56,0x65,0x72,0x69,0x53,0x69,0x67,
835 0x6e,0x20,0x54,0x72,0x75,0x73,0x74,0x20,0x4e,0x65,0x74,0x77,0x6f,0x72,0x6b,
836 0x31,0x3b,0x30,0x39,0x06,0x03,0x55,0x04,0x0b,0x13,0x32,0x54,0x65,0x72,0x6d,
837 0x73,0x20,0x6f,0x66,0x20,0x75,0x73,0x65,0x20,0x61,0x74,0x20,0x68,0x74,0x74,
838 0x70,0x73,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,
839 0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x2f,0x72,0x70,0x61,0x20,0x28,0x63,0x29,0x30,
840 0x34,0x31,0x2e,0x30,0x2c,0x06,0x03,0x55,0x04,0x03,0x13,0x25,0x56,0x65,0x72,
841 0x69,0x53,0x69,0x67,0x6e,0x20,0x43,0x6c,0x61,0x73,0x73,0x20,0x33,0x20,0x43,
842 0x6f,0x64,0x65,0x20,0x53,0x69,0x67,0x6e,0x69,0x6e,0x67,0x20,0x32,0x30,0x30,
843 0x34,0x20,0x43,0x41,0x30,0x1e,0x17,0x0d,0x30,0x36,0x30,0x31,0x31,0x37,0x30,
844 0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,0x30,0x38,0x30,0x31,0x32,0x32,0x32,
845 0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x81,0xb4,0x31,0x0b,0x30,0x09,0x06,0x03,
846 0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,
847 0x08,0x13,0x0a,0x43,0x61,0x6c,0x69,0x66,0x6f,0x72,0x6e,0x69,0x61,0x31,0x12,
848 0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x13,0x09,0x43,0x75,0x70,0x65,0x72,0x74,
849 0x69,0x6e,0x6f,0x31,0x1d,0x30,0x1b,0x06,0x03,0x55,0x04,0x0a,0x14,0x14,0x41,
850 0x70,0x70,0x6c,0x65,0x20,0x43,0x6f,0x6d,0x70,0x75,0x74,0x65,0x72,0x2c,0x20,
851 0x49,0x6e,0x63,0x2e,0x31,0x3e,0x30,0x3c,0x06,0x03,0x55,0x04,0x0b,0x13,0x35,
852 0x44,0x69,0x67,0x69,0x74,0x61,0x6c,0x20,0x49,0x44,0x20,0x43,0x6c,0x61,0x73,
853 0x73,0x20,0x33,0x20,0x2d,0x20,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,
854 0x20,0x53,0x6f,0x66,0x74,0x77,0x61,0x72,0x65,0x20,0x56,0x61,0x6c,0x69,0x64,
855 0x61,0x74,0x69,0x6f,0x6e,0x20,0x76,0x32,0x31,0x1d,0x30,0x1b,0x06,0x03,0x55,
856 0x04,0x03,0x14,0x14,0x41,0x70,0x70,0x6c,0x65,0x20,0x43,0x6f,0x6d,0x70,0x75,
857 0x74,0x65,0x72,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x30,0x81,0x9f,0x30,0x0d,0x06,
858 0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x81,0x8d,
859 0x00,0x30,0x81,0x89,0x02,0x81,0x81,0x00,0xd3,0xab,0x3b,0x7f,0xec,0x48,0x84,
860 0xce,0xa8,0x1a,0x12,0xf3,0x3c,0x87,0xcb,0x24,0x58,0x96,0x02,0x87,0x66,0x49,
861 0xeb,0x89,0xee,0x79,0x44,0x70,0x8d,0xe7,0xd4,0x1f,0x30,0x92,0xc0,0x9c,0x35,
862 0x78,0xc0,0xaf,0x1c,0xb6,0x28,0xd3,0xe0,0xe0,0x9d,0xd3,0x49,0x76,0x73,0x57,
863 0x19,0x4d,0x8d,0x70,0x85,0x64,0x4d,0x1d,0xc6,0x02,0x3e,0xe5,0x2c,0x66,0x07,
864 0xd2,0x27,0x4b,0xd6,0xc8,0x3c,0x93,0xb6,0x15,0x0c,0xde,0x5b,0xd7,0x93,0xdd,
865 0xbe,0x85,0x62,0x34,0x17,0x8a,0x05,0x60,0xf0,0x8a,0x1c,0x5a,0x40,0x21,0x8d,
866 0x51,0x6c,0xb0,0x62,0xd8,0xb5,0xd4,0xf9,0xb1,0xd0,0x58,0x7a,0x7a,0x82,0x55,
867 0xb3,0xf9,0x53,0x71,0xde,0xd2,0xc9,0x37,0x8c,0xf6,0x5a,0x1f,0x2d,0xcd,0x7c,
868 0x67,0x02,0x03,0x01,0x00,0x01,0xa3,0x82,0x01,0x7f,0x30,0x82,0x01,0x7b,0x30,
869 0x09,0x06,0x03,0x55,0x1d,0x13,0x04,0x02,0x30,0x00,0x30,0x0e,0x06,0x03,0x55,
870 0x1d,0x0f,0x01,0x01,0xff,0x04,0x04,0x03,0x02,0x07,0x80,0x30,0x40,0x06,0x03,
871 0x55,0x1d,0x1f,0x04,0x39,0x30,0x37,0x30,0x35,0xa0,0x33,0xa0,0x31,0x86,0x2f,
872 0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x43,0x53,0x43,0x33,0x2d,0x32,0x30,0x30,
873 0x34,0x2d,0x63,0x72,0x6c,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,
874 0x63,0x6f,0x6d,0x2f,0x43,0x53,0x43,0x33,0x2d,0x32,0x30,0x30,0x34,0x2e,0x63,
875 0x72,0x6c,0x30,0x44,0x06,0x03,0x55,0x1d,0x20,0x04,0x3d,0x30,0x3b,0x30,0x39,
876 0x06,0x0b,0x60,0x86,0x48,0x01,0x86,0xf8,0x45,0x01,0x07,0x17,0x03,0x30,0x2a,
877 0x30,0x28,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x1c,0x68,
878 0x74,0x74,0x70,0x73,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x76,0x65,0x72,0x69,
879 0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x2f,0x72,0x70,0x61,0x30,0x13,0x06,
880 0x03,0x55,0x1d,0x25,0x04,0x0c,0x30,0x0a,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,
881 0x07,0x03,0x03,0x30,0x75,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x01,0x01,
882 0x04,0x69,0x30,0x67,0x30,0x24,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,
883 0x01,0x86,0x18,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6f,0x63,0x73,0x70,0x2e,
884 0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x30,0x3f,0x06,
885 0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x33,0x68,0x74,0x74,0x70,
886 0x3a,0x2f,0x2f,0x43,0x53,0x43,0x33,0x2d,0x32,0x30,0x30,0x34,0x2d,0x61,0x69,
887 0x61,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x2f,
888 0x43,0x53,0x43,0x33,0x2d,0x32,0x30,0x30,0x34,0x2d,0x61,0x69,0x61,0x2e,0x63,
889 0x65,0x72,0x30,0x1f,0x06,0x03,0x55,0x1d,0x23,0x04,0x18,0x30,0x16,0x80,0x14,
890 0x08,0xf5,0x51,0xe8,0xfb,0xfe,0x3d,0x3d,0x64,0x36,0x7c,0x68,0xcf,0x5b,0x78,
891 0xa8,0xdf,0xb9,0xc5,0x37,0x30,0x11,0x06,0x09,0x60,0x86,0x48,0x01,0x86,0xf8,
892 0x42,0x01,0x01,0x04,0x04,0x03,0x02,0x04,0x10,0x30,0x16,0x06,0x0a,0x2b,0x06,
893 0x01,0x04,0x01,0x82,0x37,0x02,0x01,0x1b,0x04,0x08,0x30,0x06,0x01,0x01,0x00,
894 0x01,0x01,0xff,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,
895 0x05,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x6a,0xa6,0x06,0xd0,0x33,0x18,0x64,
896 0xe2,0x69,0x82,0xee,0x6e,0x36,0x9e,0x9d,0x9a,0x0e,0x18,0xa8,0xac,0x9d,0x10,
897 0xed,0x01,0x3c,0xb9,0x61,0x04,0x62,0xf3,0x85,0x8f,0xcc,0x4f,0x2c,0x66,0x35,
898 0x54,0x25,0x45,0x8d,0x95,0x1c,0xd2,0x33,0xbe,0x2e,0xdd,0x7f,0x74,0xaf,0x03,
899 0x7b,0x86,0x63,0xb0,0xc9,0xe6,0xbd,0xc7,0x8e,0xde,0x03,0x18,0x98,0x82,0xc3,
900 0xbb,0xf8,0x15,0x99,0x1a,0xa9,0xdd,0xb9,0x5d,0xb9,0xbd,0x53,0x95,0x25,0x76,
901 0xfb,0x5c,0x53,0x90,0xea,0x01,0x0a,0xa0,0xb1,0xbf,0x09,0x1b,0x97,0x8f,0x40,
902 0xfa,0x85,0x12,0x74,0x01,0xdb,0xf6,0xdb,0x09,0xd6,0x5f,0x4f,0xd7,0x17,0xb4,
903 0xbf,0x9e,0x2f,0x86,0x52,0x5d,0x70,0x24,0x52,0x32,0x1e,0xa5,0x1d,0x39,0x8b,
904 0x66,0xf6,0xba,0x9b,0x69,0x8e,0x12,0x60,0xdb,0xb6,0xcf,0xe6,0x0d,0xd6,0x1c,
905 0x8f,0xd4,0x5b,0x4b,0x00,0xde,0x21,0x93,0xfb,0x6e,0xc7,0x3d,0xb4,0x66,0x0d,
906 0x29,0x0c,0x4e,0xe9,0x3f,0x94,0xd6,0xd6,0xdc,0xec,0xf8,0x53,0x3b,0x62,0xd5,
907 0x97,0x50,0x53,0x84,0x17,0xfe,0xe2,0xed,0x4c,0x23,0x0a,0x49,0xce,0x5b,0xe9,
908 0x70,0x31,0xc1,0x04,0x02,0x02,0x6c,0xb8,0x52,0xcd,0xc7,0x4e,0x70,0xb4,0x13,
909 0xd7,0xe0,0x92,0xba,0x44,0x1a,0x10,0x4c,0x6e,0x45,0xc6,0x86,0x04,0xc6,0x64,
910 0xd3,0x9c,0x6e,0xc1,0x9c,0xac,0x74,0x3d,0x77,0x06,0x5e,0x28,0x28,0x5c,0xf5,
911 0xe0,0x9c,0x19,0xd8,0xba,0x74,0x81,0x2d,0x67,0x77,0x93,0x8d,0xbf,0xd2,0x52,
912 0x00,0xe6,0xa5,0x38,0x4e,0x2e,0x73,0x66,0x7a };
913 static BYTE iTunesIssuer[] = {
914 0x30,0x81,0xb4,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,
915 0x13,0x02,0x55,0x53,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,
916 0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x2c,
917 0x20,0x49,0x6e,0x63,0x2e,0x31,0x1f,0x30,0x1d,0x06,0x03,0x55,
918 0x04,0x0b,0x13,0x16,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,
919 0x20,0x54,0x72,0x75,0x73,0x74,0x20,0x4e,0x65,0x74,0x77,0x6f,
920 0x72,0x6b,0x31,0x3b,0x30,0x39,0x06,0x03,0x55,0x04,0x0b,0x13,
921 0x32,0x54,0x65,0x72,0x6d,0x73,0x20,0x6f,0x66,0x20,0x75,0x73,
922 0x65,0x20,0x61,0x74,0x20,0x68,0x74,0x74,0x70,0x73,0x3a,0x2f,
923 0x2f,0x77,0x77,0x77,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,
924 0x6e,0x2e,0x63,0x6f,0x6d,0x2f,0x72,0x70,0x61,0x20,0x28,0x63,
925 0x29,0x30,0x34,0x31,0x2e,0x30,0x2c,0x06,0x03,0x55,0x04,0x03,
926 0x13,0x25,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x43,
927 0x6c,0x61,0x73,0x73,0x20,0x33,0x20,0x43,0x6f,0x64,0x65,0x20,
928 0x53,0x69,0x67,0x6e,0x69,0x6e,0x67,0x20,0x32,0x30,0x30,0x34,
929 0x20,0x43,0x41 };
930 static BYTE iTunesSerialNum[] = {
931 0x8d,0xf6,0x6a,0xdf,0xd2,0x40,0xfe,0xb6,0xa6,0x61,0x9b,0x9b,
932 0xe0,0xa0,0x1a,0x0f };
933
934 static void testFindCert(void)
935 {
936     HCERTSTORE store;
937     PCCERT_CONTEXT context = NULL, subject;
938     BOOL ret;
939     CERT_INFO certInfo = { 0 };
940     CRYPT_HASH_BLOB blob;
941     BYTE otherSerialNumber[] = { 2 };
942
943     store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
944      CERT_STORE_CREATE_NEW_FLAG, NULL);
945     ok(store != NULL, "CertOpenStore failed: %d\n", GetLastError());
946     if (!store)
947         return;
948
949     ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
950      bigCert, sizeof(bigCert), CERT_STORE_ADD_NEW, NULL);
951     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
952      GetLastError());
953     ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
954      bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, NULL);
955     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
956      GetLastError());
957     /* This has the same name as bigCert */
958     ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
959      certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, NULL);
960     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
961      GetLastError());
962
963     /* Crashes
964     context = CertFindCertificateInStore(NULL, 0, 0, 0, NULL, NULL);
965      */
966
967     /* Check first cert's there, by issuer */
968     certInfo.Subject.pbData = subjectName;
969     certInfo.Subject.cbData = sizeof(subjectName);
970     certInfo.SerialNumber.pbData = serialNum;
971     certInfo.SerialNumber.cbData = sizeof(serialNum);
972     context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
973      CERT_FIND_ISSUER_NAME, &certInfo.Subject, NULL);
974     ok(context != NULL, "CertFindCertificateInStore failed: %08x\n",
975      GetLastError());
976     if (context)
977     {
978         context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
979          CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
980         ok(context != NULL, "Expected more than one cert\n");
981         if (context)
982         {
983             context = CertFindCertificateInStore(store, X509_ASN_ENCODING,
984              0, CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
985             ok(context == NULL, "Expected precisely two certs\n");
986         }
987     }
988
989     /* Check second cert's there as well, by subject name */
990     certInfo.Subject.pbData = subjectName2;
991     certInfo.Subject.cbData = sizeof(subjectName2);
992     context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
993      CERT_FIND_SUBJECT_NAME, &certInfo.Subject, NULL);
994     ok(context != NULL, "CertFindCertificateInStore failed: %08x\n",
995      GetLastError());
996     if (context)
997     {
998         context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
999          CERT_FIND_SUBJECT_NAME, &certInfo.Subject, context);
1000         ok(context == NULL, "Expected one cert only\n");
1001     }
1002
1003     /* Strange but true: searching for the subject cert requires you to set
1004      * the issuer, not the subject
1005      */
1006     context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1007      CERT_FIND_SUBJECT_CERT, &certInfo.Subject, NULL);
1008     ok(context == NULL, "Expected no certificate\n");
1009     certInfo.Subject.pbData = NULL;
1010     certInfo.Subject.cbData = 0;
1011     certInfo.Issuer.pbData = subjectName2;
1012     certInfo.Issuer.cbData = sizeof(subjectName2);
1013     context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1014      CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
1015     ok(context != NULL, "CertFindCertificateInStore failed: %08x\n",
1016      GetLastError());
1017     if (context)
1018     {
1019         context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1020          CERT_FIND_SUBJECT_CERT, &certInfo.Subject, context);
1021         ok(context == NULL, "Expected one cert only\n");
1022     }
1023     /* A non-matching serial number will not match. */
1024     certInfo.SerialNumber.pbData = otherSerialNumber;
1025     certInfo.SerialNumber.cbData = sizeof(otherSerialNumber);
1026     context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1027      CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
1028     ok(context == NULL, "Expected no match\n");
1029     /* No serial number will not match */
1030     certInfo.SerialNumber.cbData = 0;
1031     context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1032      CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
1033     ok(context == NULL, "Expected no match\n");
1034     /* A serial number still won't match if the name doesn't */
1035     certInfo.SerialNumber.pbData = serialNum;
1036     certInfo.SerialNumber.cbData = sizeof(serialNum);
1037     certInfo.Issuer.pbData = subjectName3;
1038     certInfo.Issuer.cbData = sizeof(subjectName3);
1039     context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1040      CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
1041     ok(context == NULL, "Expected no match\n");
1042
1043     /* The nice thing about hashes, they're unique */
1044     blob.pbData = bigCertHash;
1045     blob.cbData = sizeof(bigCertHash);
1046     context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1047      CERT_FIND_SHA1_HASH, &blob, NULL);
1048     ok(context != NULL, "CertFindCertificateInStore failed: %08x\n",
1049      GetLastError());
1050     if (context)
1051     {
1052         context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1053          CERT_FIND_SHA1_HASH, &certInfo.Subject, context);
1054         ok(context == NULL, "Expected one cert only\n");
1055     }
1056
1057     CertCloseStore(store, 0);
1058
1059     /* Another subject cert search, using iTunes's certs */
1060     store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1061      CERT_STORE_CREATE_NEW_FLAG, NULL);
1062     ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1063      iTunesCert0, sizeof(iTunesCert0), CERT_STORE_ADD_NEW, NULL);
1064     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1065      GetLastError());
1066     ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1067      iTunesCert1, sizeof(iTunesCert1), CERT_STORE_ADD_NEW, NULL);
1068     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1069      GetLastError());
1070     ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1071      iTunesCert2, sizeof(iTunesCert2), CERT_STORE_ADD_NEW, NULL);
1072     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1073      GetLastError());
1074     ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1075      iTunesCert3, sizeof(iTunesCert3), CERT_STORE_ADD_NEW, &subject);
1076     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1077      GetLastError());
1078
1079     /* The certInfo's issuer does not match any subject, but the serial
1080      * number does match a cert whose issuer matches certInfo's issuer.
1081      * This yields a match.
1082      */
1083     certInfo.SerialNumber.cbData = sizeof(iTunesSerialNum);
1084     certInfo.SerialNumber.pbData = iTunesSerialNum;
1085     certInfo.Issuer.cbData = sizeof(iTunesIssuer);
1086     certInfo.Issuer.pbData = iTunesIssuer;
1087     context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1088      CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
1089     ok(context != NULL, "Expected a match\n");
1090     if (context)
1091     {
1092         ret = CertCompareCertificateName(context->dwCertEncodingType,
1093          &certInfo.Issuer, &context->pCertInfo->Subject);
1094         ok(!ret, "Expected subject name not to match\n");
1095         ret = CertCompareCertificateName(context->dwCertEncodingType,
1096          &certInfo.Issuer, &context->pCertInfo->Issuer);
1097         ok(ret, "Expected issuer name to match\n");
1098         ret = CertCompareIntegerBlob(&certInfo.SerialNumber,
1099          &context->pCertInfo->SerialNumber);
1100         ok(ret, "Expected serial number to match\n");
1101         context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1102          CERT_FIND_SUBJECT_CERT, &certInfo, context);
1103         ok(context == NULL, "Expected one cert only\n");
1104     }
1105
1106     context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1107      CERT_FIND_ISSUER_OF, subject, NULL);
1108     ok(context != NULL, "Expected an issuer\n");
1109     if (context)
1110     {
1111         PCCERT_CONTEXT none = CertFindCertificateInStore(store,
1112          X509_ASN_ENCODING, 0, CERT_FIND_ISSUER_OF, context, NULL);
1113
1114         ok(!none, "Expected no parent of issuer\n");
1115         CertFreeCertificateContext(context);
1116     }
1117     CertFreeCertificateContext(subject);
1118     CertCloseStore(store, 0);
1119 }
1120
1121 static void testGetSubjectCert(void)
1122 {
1123     HCERTSTORE store;
1124     PCCERT_CONTEXT context1, context2;
1125     CERT_INFO info = { 0 };
1126     BOOL ret;
1127
1128     store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1129      CERT_STORE_CREATE_NEW_FLAG, NULL);
1130     ok(store != NULL, "CertOpenStore failed: %d\n", GetLastError());
1131     if (!store)
1132         return;
1133
1134     ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1135      bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
1136     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1137      GetLastError());
1138     ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1139      bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, &context1);
1140     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1141      GetLastError());
1142     ok(context1 != NULL, "Expected a context\n");
1143     ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1144      certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, NULL);
1145     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1146      GetLastError());
1147
1148     context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
1149      NULL);
1150     ok(!context2 && GetLastError() == E_INVALIDARG,
1151      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1152     context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
1153      &info);
1154     ok(!context2 && GetLastError() == CRYPT_E_NOT_FOUND,
1155      "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1156     info.SerialNumber.cbData = sizeof(serialNum);
1157     info.SerialNumber.pbData = serialNum;
1158     context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
1159      &info);
1160     ok(!context2 && GetLastError() == CRYPT_E_NOT_FOUND,
1161      "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1162     info.Issuer.cbData = sizeof(subjectName2);
1163     info.Issuer.pbData = subjectName2;
1164     context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
1165      &info);
1166     ok(context2 != NULL,
1167      "CertGetSubjectCertificateFromStore failed: %08x\n", GetLastError());
1168     /* Not only should this find a context, but it should be the same
1169      * (same address) as context1.
1170      */
1171     ok(context1 == context2, "Expected identical context addresses\n");
1172     CertFreeCertificateContext(context2);
1173
1174     CertFreeCertificateContext(context1);
1175     CertCloseStore(store, 0);
1176 }
1177
1178 /* This expires in 1970 or so */
1179 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
1180  0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
1181  0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
1182  0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
1183  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
1184  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
1185  0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
1186  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
1187  0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
1188  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
1189  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
1190  0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
1191  0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
1192  0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
1193  0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
1194  0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
1195  0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
1196  0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
1197  0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
1198  0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
1199  0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
1200  0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
1201  0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
1202  0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
1203  0x49, 0xe5, 0xf9, 0x65, 0xf3 };
1204
1205 /* This expires in 2036 or so */
1206 static const BYTE childOfExpired[] = { 0x30, 0x81, 0xcc, 0x30, 0x78, 0xa0,
1207  0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
1208  0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d,
1209  0x30, 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63,
1210  0x40, 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e,
1211  0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x35, 0x30, 0x35,
1212  0x31, 0x37, 0x31, 0x32, 0x34, 0x39, 0x5a, 0x17, 0x0d, 0x33, 0x36, 0x30, 0x35,
1213  0x30, 0x35, 0x31, 0x37, 0x31, 0x32, 0x34, 0x39, 0x5a, 0x30, 0x15, 0x31, 0x13,
1214  0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e,
1215  0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03,
1216  0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
1217  0x01, 0x05, 0x05, 0x00, 0x03, 0x41, 0x00, 0x20, 0x3b, 0xdb, 0x4d, 0x67, 0x50,
1218  0xec, 0x73, 0x9d, 0xf9, 0x85, 0x5d, 0x18, 0xe9, 0xb4, 0x98, 0xe3, 0x31, 0xb7,
1219  0x03, 0x0b, 0xc0, 0x39, 0x93, 0x56, 0x81, 0x0a, 0xfc, 0x78, 0xa8, 0x29, 0x42,
1220  0x5f, 0x69, 0xfb, 0xbc, 0x5b, 0xf2, 0xa6, 0x2a, 0xbe, 0x91, 0x2c, 0xfc, 0x89,
1221  0x69, 0x15, 0x18, 0x58, 0xe5, 0x02, 0x75, 0xf7, 0x2a, 0xb6, 0xa9, 0xfb, 0x47,
1222  0x6a, 0x6e, 0x0a, 0x9b, 0xe9, 0xdc };
1223 /* chain10_0 -+
1224  *            +-> chain7_1
1225  * chain10_1 -+
1226  * A chain with two issuers, only one of whose dates is valid.
1227  */
1228 static const BYTE chain10_0[] = {
1229 0x30,0x82,0x01,0x9b,0x30,0x82,0x01,0x08,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,
1230 0x4a,0x30,0x3a,0x42,0xa2,0x5a,0xb3,0x93,0x4d,0x94,0x06,0xad,0x6d,0x1c,0x34,
1231 0xe6,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x30,0x10,0x31,
1232 0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x03,0x13,0x05,0x43,0x65,0x72,0x74,0x31,
1233 0x30,0x1e,0x17,0x0d,0x30,0x36,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
1234 0x30,0x5a,0x17,0x0d,0x30,0x36,0x31,0x32,0x33,0x31,0x32,0x33,0x35,0x39,0x35,
1235 0x39,0x5a,0x30,0x10,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x03,0x13,0x05,
1236 0x43,0x65,0x72,0x74,0x31,0x30,0x81,0x9f,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
1237 0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x81,0x8d,0x00,0x30,0x81,0x89,
1238 0x02,0x81,0x81,0x00,0xad,0x7e,0xca,0xf3,0xe5,0x99,0xc2,0x2a,0xca,0x50,0x82,
1239 0x7c,0x2d,0xa4,0x81,0xcd,0x0d,0x0d,0x86,0xd7,0xd8,0xb2,0xde,0xc5,0xc3,0x34,
1240 0x9e,0x07,0x78,0x08,0x11,0x12,0x2d,0x21,0x0a,0x09,0x07,0x14,0x03,0x7a,0xe7,
1241 0x3b,0x58,0xf1,0xde,0x3e,0x01,0x25,0x93,0xab,0x8f,0xce,0x1f,0xc1,0x33,0x91,
1242 0xfe,0x59,0xb9,0x3b,0x9e,0x95,0x12,0x89,0x8e,0xc3,0x4b,0x98,0x1b,0x99,0xc5,
1243 0x07,0xe2,0xdf,0x15,0x4c,0x39,0x76,0x06,0xad,0xdb,0x16,0x06,0x49,0xba,0xcd,
1244 0x0f,0x07,0xd6,0xea,0x27,0xa6,0xfe,0x3d,0x88,0xe5,0x97,0x45,0x72,0xb6,0x1c,
1245 0xc0,0x1c,0xb1,0xa2,0x89,0xe8,0x37,0x9e,0xf6,0x2a,0xcf,0xd5,0x1f,0x2f,0x35,
1246 0x5e,0x8f,0x3a,0x9c,0x61,0xb1,0xf1,0x6c,0xff,0x8c,0xb2,0x2f,0x02,0x03,0x01,
1247 0x00,0x01,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x03,0x81,
1248 0x81,0x00,0x85,0x6e,0x35,0x2f,0x2c,0x51,0x4f,0xd6,0x2a,0xe4,0x9e,0xd0,0x4b,
1249 0xe6,0x90,0xfd,0xf7,0x20,0xad,0x76,0x3f,0x93,0xea,0x7f,0x0d,0x1f,0xb3,0x8e,
1250 0xfd,0xe0,0xe1,0xd6,0xd7,0x9c,0x7d,0x46,0x6b,0x15,0x5c,0xe6,0xc9,0x62,0x3b,
1251 0x70,0x4a,0x4b,0xb2,0x82,0xe3,0x55,0x0c,0xc4,0x90,0x44,0x06,0x6c,0x86,0x1c,
1252 0x6d,0x47,0x12,0xda,0x33,0x95,0x5d,0x98,0x43,0xcb,0x7c,0xfa,0x2b,0xee,0xc4,
1253 0x2d,0xc8,0x95,0x33,0x89,0x08,0x3f,0x9f,0x87,0xea,0x20,0x04,0xaf,0x58,0x4b,
1254 0x9d,0xc0,0x7c,0x0a,0x1b,0x05,0x31,0x3b,0xbb,0x13,0x58,0x2e,0x3f,0x61,0x6b,
1255 0x10,0xb4,0xeb,0xb9,0x1a,0x30,0xfd,0xea,0xca,0x29,0x99,0x5f,0x42,0x2b,0x00,
1256 0xb0,0x08,0xc3,0xf0,0xb6,0xd6,0x6b,0xf9,0x35,0x95 };
1257 static const BYTE chain10_1[] = {
1258 0x30,0x82,0x01,0x9b,0x30,0x82,0x01,0x08,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,
1259 0xbf,0x99,0x4f,0x14,0x03,0x77,0x44,0xb8,0x49,0x02,0x70,0xa1,0xb8,0x9c,0xa7,
1260 0x24,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x30,0x10,0x31,
1261 0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x03,0x13,0x05,0x43,0x65,0x72,0x74,0x31,
1262 0x30,0x1e,0x17,0x0d,0x30,0x37,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
1263 0x30,0x5a,0x17,0x0d,0x30,0x37,0x31,0x32,0x33,0x31,0x32,0x33,0x35,0x39,0x35,
1264 0x39,0x5a,0x30,0x10,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x03,0x13,0x05,
1265 0x43,0x65,0x72,0x74,0x31,0x30,0x81,0x9f,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
1266 0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x81,0x8d,0x00,0x30,0x81,0x89,
1267 0x02,0x81,0x81,0x00,0xad,0x7e,0xca,0xf3,0xe5,0x99,0xc2,0x2a,0xca,0x50,0x82,
1268 0x7c,0x2d,0xa4,0x81,0xcd,0x0d,0x0d,0x86,0xd7,0xd8,0xb2,0xde,0xc5,0xc3,0x34,
1269 0x9e,0x07,0x78,0x08,0x11,0x12,0x2d,0x21,0x0a,0x09,0x07,0x14,0x03,0x7a,0xe7,
1270 0x3b,0x58,0xf1,0xde,0x3e,0x01,0x25,0x93,0xab,0x8f,0xce,0x1f,0xc1,0x33,0x91,
1271 0xfe,0x59,0xb9,0x3b,0x9e,0x95,0x12,0x89,0x8e,0xc3,0x4b,0x98,0x1b,0x99,0xc5,
1272 0x07,0xe2,0xdf,0x15,0x4c,0x39,0x76,0x06,0xad,0xdb,0x16,0x06,0x49,0xba,0xcd,
1273 0x0f,0x07,0xd6,0xea,0x27,0xa6,0xfe,0x3d,0x88,0xe5,0x97,0x45,0x72,0xb6,0x1c,
1274 0xc0,0x1c,0xb1,0xa2,0x89,0xe8,0x37,0x9e,0xf6,0x2a,0xcf,0xd5,0x1f,0x2f,0x35,
1275 0x5e,0x8f,0x3a,0x9c,0x61,0xb1,0xf1,0x6c,0xff,0x8c,0xb2,0x2f,0x02,0x03,0x01,
1276 0x00,0x01,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x03,0x81,
1277 0x81,0x00,0xa8,0xec,0x8c,0x34,0xe7,0x2c,0xdf,0x75,0x87,0xc4,0xf7,0xda,0x71,
1278 0x72,0x29,0xb2,0x48,0xa8,0x2a,0xec,0x7b,0x7d,0x19,0xb9,0x5f,0x1d,0xd9,0x91,
1279 0x2b,0xc4,0x28,0x7e,0xd6,0xb5,0x91,0x69,0xa5,0x8a,0x1a,0x1f,0x97,0x98,0x46,
1280 0x9d,0xdf,0x12,0xf6,0x45,0x62,0xad,0x60,0xb6,0xba,0xb0,0xfd,0xf5,0x9f,0xc6,
1281 0x98,0x05,0x4f,0x4d,0x48,0xdc,0xee,0x69,0xbe,0xb8,0xc4,0xc4,0xd7,0x1b,0xb1,
1282 0x1f,0x64,0xd6,0x45,0xa7,0xdb,0xb3,0x87,0x63,0x0f,0x54,0xe1,0x3a,0x6b,0x57,
1283 0x36,0xd7,0x68,0x65,0xcf,0xda,0x57,0x8d,0xcd,0x84,0x75,0x47,0x26,0x2c,0xef,
1284 0x1e,0x8f,0xc7,0x3b,0xee,0x5d,0x03,0xa6,0xdf,0x3a,0x20,0xb2,0xcc,0xc9,0x09,
1285 0x2c,0xfe,0x2b,0x79,0xb0,0xca,0x2c,0x9a,0x81,0x6b };
1286 static const BYTE chain7_1[] = {
1287 0x30,0x82,0x01,0x93,0x30,0x81,0xfd,0xa0,0x03,0x02,0x01,0x02,0x02,0x01,0x01,
1288 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,
1289 0x30,0x10,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x03,0x13,0x05,0x43,0x65,
1290 0x72,0x74,0x31,0x30,0x1e,0x17,0x0d,0x30,0x37,0x30,0x31,0x30,0x31,0x30,0x30,
1291 0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,0x30,0x37,0x31,0x32,0x33,0x31,0x32,0x33,
1292 0x35,0x39,0x35,0x39,0x5a,0x30,0x10,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,
1293 0x03,0x13,0x05,0x43,0x65,0x72,0x74,0x32,0x30,0x81,0x9f,0x30,0x0d,0x06,0x09,
1294 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x81,0x8d,0x00,
1295 0x30,0x81,0x89,0x02,0x81,0x81,0x00,0xb8,0x52,0xda,0xc5,0x4b,0x3f,0xe5,0x33,
1296 0x0e,0x67,0x5f,0x48,0x21,0xdc,0x7e,0xef,0x37,0x33,0xba,0xff,0xb4,0xc6,0xdc,
1297 0xb6,0x17,0x8e,0x20,0x55,0x07,0x12,0xd2,0x7b,0x3c,0xce,0x30,0xc5,0xa7,0x48,
1298 0x9f,0x6e,0xfe,0xb8,0xbe,0xdb,0x9f,0x9b,0x17,0x60,0x16,0xde,0xc6,0x8b,0x47,
1299 0xd1,0x57,0x71,0x3c,0x93,0xfc,0xbd,0xec,0x44,0x32,0x3b,0xb9,0xcf,0x6b,0x05,
1300 0x72,0xa7,0x87,0x8e,0x7e,0xd4,0x9a,0x87,0x1c,0x2f,0xb7,0x82,0x40,0xfc,0x6a,
1301 0x80,0x83,0x68,0x28,0xce,0x84,0xf4,0x0b,0x2e,0x44,0xcb,0x53,0xac,0x85,0x85,
1302 0xb5,0x46,0x36,0x98,0x3c,0x10,0x02,0xaa,0x02,0xbc,0x8b,0xa2,0x23,0xb2,0xd3,
1303 0x51,0x9a,0x22,0x4a,0xe3,0xaa,0x4e,0x7c,0xda,0x38,0xcf,0x49,0x98,0x72,0xa3,
1304 0x02,0x03,0x01,0x00,0x01,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
1305 0x01,0x01,0x05,0x05,0x00,0x03,0x81,0x81,0x00,0x9f,0x69,0xfd,0x26,0xd5,0x4b,
1306 0xe0,0xab,0x12,0x21,0xb9,0xfc,0xf7,0xe0,0x0c,0x09,0x94,0xad,0x27,0xd7,0x9d,
1307 0xa3,0xcc,0x46,0x2a,0x25,0x9a,0x24,0xa7,0x31,0x58,0x78,0xf5,0xfc,0x30,0xe1,
1308 0x6d,0xfd,0x59,0xab,0xbe,0x69,0xa0,0xea,0xe3,0x7d,0x7a,0x7b,0xe5,0x85,0xeb,
1309 0x86,0x6a,0x84,0x3c,0x96,0x01,0x1a,0x70,0xa7,0xb8,0xcb,0xf2,0x11,0xe7,0x52,
1310 0x9c,0x58,0x2d,0xac,0x63,0xce,0x72,0x4b,0xad,0x62,0xa8,0x1d,0x75,0x96,0xe2,
1311 0x27,0xf5,0x6f,0xba,0x91,0xf8,0xf1,0xb0,0xbf,0x90,0x24,0x6d,0xba,0x5d,0xd7,
1312 0x39,0x63,0x3b,0x7c,0x04,0x5d,0x89,0x9d,0x1c,0xf2,0xf7,0xcc,0xdf,0x6e,0x8a,
1313 0x43,0xa9,0xdd,0x86,0x05,0xa2,0xf3,0x22,0x2d,0x1e,0x70,0xa1,0x59,0xd7,0xa5,
1314 0x94,0x7d };
1315
1316 static void testGetIssuerCert(void)
1317 {
1318     BOOL ret;
1319     PCCERT_CONTEXT parent, child, cert1, cert2;
1320     DWORD flags = 0xffffffff;
1321     HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1322      CERT_STORE_CREATE_NEW_FLAG, NULL);
1323
1324     ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1325
1326     ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1327      expiredCert, sizeof(expiredCert), CERT_STORE_ADD_ALWAYS, NULL);
1328     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1329      GetLastError());
1330
1331     ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1332      childOfExpired, sizeof(childOfExpired), CERT_STORE_ADD_ALWAYS, &child);
1333     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1334      GetLastError());
1335
1336     /* These crash:
1337     parent = CertGetIssuerCertificateFromStore(NULL, NULL, NULL, NULL);
1338     parent = CertGetIssuerCertificateFromStore(store, NULL, NULL, NULL);
1339      */
1340     parent = CertGetIssuerCertificateFromStore(NULL, NULL, NULL, &flags);
1341     ok(!parent && GetLastError() == E_INVALIDARG,
1342      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1343     parent = CertGetIssuerCertificateFromStore(store, NULL, NULL, &flags);
1344     ok(!parent && GetLastError() == E_INVALIDARG,
1345      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1346     parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1347     ok(!parent && GetLastError() == E_INVALIDARG,
1348      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1349     /* Confusing: the caller cannot set either of the
1350      * CERT_STORE_NO_*_FLAGs, as these are not checks,
1351      * they're results:
1352      */
1353     flags = CERT_STORE_NO_CRL_FLAG | CERT_STORE_NO_ISSUER_FLAG;
1354     parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1355     ok(!parent && GetLastError() == E_INVALIDARG,
1356      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1357     /* Perform no checks */
1358     flags = 0;
1359     parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1360     ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08x\n",
1361      GetLastError());
1362     if (parent)
1363         CertFreeCertificateContext(parent);
1364     /* Check revocation and signature only */
1365     flags = CERT_STORE_REVOCATION_FLAG | CERT_STORE_SIGNATURE_FLAG;
1366     parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1367     ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08x\n",
1368      GetLastError());
1369     /* Confusing: CERT_STORE_REVOCATION_FLAG succeeds when there is no CRL by
1370      * setting CERT_STORE_NO_CRL_FLAG.
1371      */
1372     ok(flags == (CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG),
1373      "Expected CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG, got %08x\n",
1374      flags);
1375     if (parent)
1376         CertFreeCertificateContext(parent);
1377     /* Now check just the time */
1378     flags = CERT_STORE_TIME_VALIDITY_FLAG;
1379     parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1380     ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08x\n",
1381      GetLastError());
1382     /* Oops: the child is not expired, so the time validity check actually
1383      * succeeds, even though the signing cert is expired.
1384      */
1385     ok(!flags, "Expected check to succeed, got %08x\n", flags);
1386     if (parent)
1387         CertFreeCertificateContext(parent);
1388
1389     CertFreeCertificateContext(child);
1390     CertCloseStore(store, 0);
1391
1392     flags = 0;
1393     store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1394      CERT_STORE_CREATE_NEW_FLAG, NULL);
1395     /* With only the child certificate, no issuer will be found */
1396     ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1397      chain7_1, sizeof(chain7_1), CERT_STORE_ADD_ALWAYS, &child);
1398     parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1399     ok(parent == NULL, "Expected no issuer\n");
1400     /* Adding an issuer allows one (and only one) issuer to be found */
1401     ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1402      chain10_1, sizeof(chain10_1), CERT_STORE_ADD_ALWAYS, &cert1);
1403     parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1404     ok(parent == cert1, "Expected cert1 to be the issuer\n");
1405     parent = CertGetIssuerCertificateFromStore(store, child, parent, &flags);
1406     ok(parent == NULL, "Expected only one issuer\n");
1407     /* Adding a second issuer allows two issuers to be found - and the second
1408      * issuer is found before the first, implying certs are added to the head
1409      * of a list.
1410      */
1411     ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1412      chain10_0, sizeof(chain10_0), CERT_STORE_ADD_ALWAYS, &cert2);
1413     parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1414     ok(parent == cert2, "Expected cert2 to be the first issuer\n");
1415     parent = CertGetIssuerCertificateFromStore(store, child, parent, &flags);
1416     ok(parent == cert1, "Expected cert1 to be the second issuer\n");
1417     parent = CertGetIssuerCertificateFromStore(store, child, parent, &flags);
1418     ok(parent == NULL, "Expected no more than two issuers\n");
1419     CertFreeCertificateContext(child);
1420     CertFreeCertificateContext(cert1);
1421     CertFreeCertificateContext(cert2);
1422     CertCloseStore(store, 0);
1423
1424     /* Repeat the test, reversing the order in which issuers are added,
1425      * to show it's order-dependent.
1426      */
1427     store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1428      CERT_STORE_CREATE_NEW_FLAG, NULL);
1429     /* With only the child certificate, no issuer will be found */
1430     ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1431      chain7_1, sizeof(chain7_1), CERT_STORE_ADD_ALWAYS, &child);
1432     parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1433     ok(parent == NULL, "Expected no issuer\n");
1434     /* Adding an issuer allows one (and only one) issuer to be found */
1435     ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1436      chain10_0, sizeof(chain10_0), CERT_STORE_ADD_ALWAYS, &cert1);
1437     parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1438     ok(parent == cert1, "Expected cert1 to be the issuer\n");
1439     parent = CertGetIssuerCertificateFromStore(store, child, parent, &flags);
1440     ok(parent == NULL, "Expected only one issuer\n");
1441     /* Adding a second issuer allows two issuers to be found - and the second
1442      * issuer is found before the first, implying certs are added to the head
1443      * of a list.
1444      */
1445     ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1446      chain10_1, sizeof(chain10_1), CERT_STORE_ADD_ALWAYS, &cert2);
1447     parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1448     ok(parent == cert2, "Expected cert2 to be the first issuer\n");
1449     parent = CertGetIssuerCertificateFromStore(store, child, parent, &flags);
1450     ok(parent == cert1, "Expected cert1 to be the second issuer\n");
1451     parent = CertGetIssuerCertificateFromStore(store, child, parent, &flags);
1452     ok(parent == NULL, "Expected no more than two issuers\n");
1453     CertFreeCertificateContext(child);
1454     CertFreeCertificateContext(cert1);
1455     CertFreeCertificateContext(cert2);
1456     CertCloseStore(store, 0);
1457 }
1458
1459 static void testCryptHashCert(void)
1460 {
1461     static const BYTE emptyHash[] = { 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b,
1462      0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07,
1463      0x09 };
1464     static const BYTE knownHash[] = { 0xae, 0x9d, 0xbf, 0x6d, 0xf5, 0x46, 0xee,
1465      0x8b, 0xc5, 0x7a, 0x13, 0xba, 0xc2, 0xb1, 0x04, 0xf2, 0xbf, 0x52, 0xa8,
1466      0xa2 };
1467     static const BYTE toHash[] = "abcdefghijklmnopqrstuvwxyz0123456789.,;!?:";
1468     BOOL ret;
1469     BYTE hash[20];
1470     DWORD hashLen = sizeof(hash);
1471
1472     /* NULL buffer and nonzero length crashes
1473     ret = CryptHashCertificate(0, 0, 0, NULL, size, hash, &hashLen);
1474        empty hash length also crashes
1475     ret = CryptHashCertificate(0, 0, 0, buf, size, hash, NULL);
1476      */
1477     /* Test empty hash */
1478     ret = CryptHashCertificate(0, 0, 0, toHash, sizeof(toHash), NULL,
1479      &hashLen);
1480     ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
1481     ok(hashLen == sizeof(hash), "Got unexpected size of hash %d\n", hashLen);
1482     /* Test with empty buffer */
1483     ret = CryptHashCertificate(0, 0, 0, NULL, 0, hash, &hashLen);
1484     ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
1485     ok(!memcmp(hash, emptyHash, sizeof(emptyHash)),
1486      "Unexpected hash of nothing\n");
1487     /* Test a known value */
1488     ret = CryptHashCertificate(0, 0, 0, toHash, sizeof(toHash), hash,
1489      &hashLen);
1490     ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
1491     ok(!memcmp(hash, knownHash, sizeof(knownHash)), "Unexpected hash\n");
1492 }
1493
1494 static void verifySig(HCRYPTPROV csp, const BYTE *toSign, size_t toSignLen,
1495  const BYTE *sig, unsigned int sigLen)
1496 {
1497     HCRYPTHASH hash;
1498     BOOL ret = CryptCreateHash(csp, CALG_SHA1, 0, 0, &hash);
1499
1500     ok(ret, "CryptCreateHash failed: %08x\n", GetLastError());
1501     if (ret)
1502     {
1503         BYTE mySig[64];
1504         DWORD mySigSize = sizeof(mySig);
1505
1506         ret = CryptHashData(hash, toSign, toSignLen, 0);
1507         ok(ret, "CryptHashData failed: %08x\n", GetLastError());
1508         /* use the A variant so the test can run on Win9x */
1509         ret = CryptSignHashA(hash, AT_SIGNATURE, NULL, 0, mySig, &mySigSize);
1510         ok(ret, "CryptSignHash failed: %08x\n", GetLastError());
1511         if (ret)
1512         {
1513             ok(mySigSize == sigLen, "Expected sig length %d, got %d\n",
1514              sigLen, mySigSize);
1515             ok(!memcmp(mySig, sig, sigLen), "Unexpected signature\n");
1516         }
1517         CryptDestroyHash(hash);
1518     }
1519 }
1520
1521 /* Tests signing the certificate described by toBeSigned with the CSP passed in,
1522  * using the algorithm with OID sigOID.  The CSP is assumed to be empty, and a
1523  * keyset named AT_SIGNATURE will be added to it.  The signing key will be
1524  * stored in *key, and the signature will be stored in sig.  sigLen should be
1525  * at least 64 bytes.
1526  */
1527 static void testSignCert(HCRYPTPROV csp, const CRYPT_DATA_BLOB *toBeSigned,
1528  LPCSTR sigOID, HCRYPTKEY *key, BYTE *sig, DWORD *sigLen)
1529 {
1530     BOOL ret;
1531     DWORD size = 0;
1532     CRYPT_ALGORITHM_IDENTIFIER algoID = { NULL, { 0, NULL } };
1533
1534     /* These all crash
1535     ret = CryptSignCertificate(0, 0, 0, NULL, 0, NULL, NULL, NULL, NULL);
1536     ret = CryptSignCertificate(0, 0, 0, NULL, 0, NULL, NULL, NULL, &size);
1537     ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
1538      NULL, NULL, NULL, &size);
1539      */
1540     ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
1541      &algoID, NULL, NULL, &size);
1542     ok(!ret && GetLastError() == NTE_BAD_ALGID, 
1543      "Expected NTE_BAD_ALGID, got %08x\n", GetLastError());
1544     algoID.pszObjId = (LPSTR)sigOID;
1545     ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
1546      &algoID, NULL, NULL, &size);
1547     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1548      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1549     ret = CryptSignCertificate(0, AT_SIGNATURE, 0, toBeSigned->pbData,
1550      toBeSigned->cbData, &algoID, NULL, NULL, &size);
1551     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1552      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1553
1554     /* No keys exist in the new CSP yet.. */
1555     ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
1556      toBeSigned->cbData, &algoID, NULL, NULL, &size);
1557     ok(!ret && (GetLastError() == NTE_BAD_KEYSET || GetLastError() ==
1558      NTE_NO_KEY), "Expected NTE_BAD_KEYSET or NTE_NO_KEY, got %08x\n",
1559      GetLastError());
1560     ret = CryptGenKey(csp, AT_SIGNATURE, 0, key);
1561     ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
1562     if (ret)
1563     {
1564         ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
1565          toBeSigned->cbData, &algoID, NULL, NULL, &size);
1566         ok(ret, "CryptSignCertificate failed: %08x\n", GetLastError());
1567         ok(size <= *sigLen, "Expected size <= %d, got %d\n", *sigLen, size);
1568         if (ret)
1569         {
1570             ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
1571              toBeSigned->cbData, &algoID, NULL, sig, &size);
1572             ok(ret, "CryptSignCertificate failed: %08x\n", GetLastError());
1573             if (ret)
1574             {
1575                 *sigLen = size;
1576                 verifySig(csp, toBeSigned->pbData, toBeSigned->cbData, sig,
1577                  size);
1578             }
1579         }
1580     }
1581 }
1582
1583 static void testVerifyCertSig(HCRYPTPROV csp, const CRYPT_DATA_BLOB *toBeSigned,
1584  LPCSTR sigOID, const BYTE *sig, DWORD sigLen)
1585 {
1586     CERT_SIGNED_CONTENT_INFO info;
1587     LPBYTE cert = NULL;
1588     DWORD size = 0;
1589     BOOL ret;
1590
1591     if (!pCryptVerifyCertificateSignatureEx)
1592     {
1593         skip("no CryptVerifyCertificateSignatureEx support\n");
1594         return;
1595     }
1596     ret = pCryptVerifyCertificateSignatureEx(0, 0, 0, NULL, 0, NULL, 0, NULL);
1597     ok(!ret && GetLastError() == E_INVALIDARG,
1598      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1599     ret = pCryptVerifyCertificateSignatureEx(csp, 0, 0, NULL, 0, NULL, 0, NULL);
1600     ok(!ret && GetLastError() == E_INVALIDARG,
1601      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1602     ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING, 0, NULL, 0,
1603      NULL, 0, NULL);
1604     ok(!ret && GetLastError() == E_INVALIDARG,
1605      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1606     /* This crashes
1607     ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1608      CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, NULL, 0, NULL, 0, NULL);
1609      */
1610     info.ToBeSigned.cbData = toBeSigned->cbData;
1611     info.ToBeSigned.pbData = toBeSigned->pbData;
1612     info.SignatureAlgorithm.pszObjId = (LPSTR)sigOID;
1613     info.SignatureAlgorithm.Parameters.cbData = 0;
1614     info.Signature.cbData = sigLen;
1615     info.Signature.pbData = (BYTE *)sig;
1616     info.Signature.cUnusedBits = 0;
1617     ret = CryptEncodeObjectEx(X509_ASN_ENCODING, X509_CERT, &info,
1618      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&cert, &size);
1619     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1620     if (cert)
1621     {
1622         CRYPT_DATA_BLOB certBlob = { 0, NULL };
1623         PCERT_PUBLIC_KEY_INFO pubKeyInfo = NULL;
1624
1625         ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1626          CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
1627         ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
1628          "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
1629         certBlob.cbData = 1;
1630         certBlob.pbData = (void *)0xdeadbeef;
1631         ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1632          CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
1633         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1634          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1635         certBlob.cbData = size;
1636         certBlob.pbData = cert;
1637         ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1638          CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
1639         ok(!ret && GetLastError() == E_INVALIDARG,
1640          "Expected E_INVALIDARG, got %08x\n", GetLastError());
1641         ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1642          CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
1643          CRYPT_VERIFY_CERT_SIGN_ISSUER_NULL, NULL, 0, NULL);
1644         ok(!ret && GetLastError() == E_INVALIDARG,
1645          "Expected E_INVALIDARG, got %08x\n", GetLastError());
1646         /* This crashes
1647         ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1648          CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
1649          CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY, NULL, 0, NULL);
1650          */
1651         CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
1652          (LPSTR)sigOID, 0, NULL, NULL, &size);
1653         pubKeyInfo = HeapAlloc(GetProcessHeap(), 0, size);
1654         if (pubKeyInfo)
1655         {
1656             ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
1657              X509_ASN_ENCODING, (LPSTR)sigOID, 0, NULL, pubKeyInfo, &size);
1658             ok(ret, "CryptExportKey failed: %08x\n", GetLastError());
1659             if (ret)
1660             {
1661                 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1662                  CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
1663                  CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY, pubKeyInfo, 0, NULL);
1664                 ok(ret, "CryptVerifyCertificateSignatureEx failed: %08x\n",
1665                  GetLastError());
1666             }
1667             HeapFree(GetProcessHeap(), 0, pubKeyInfo);
1668         }
1669         LocalFree(cert);
1670     }
1671 }
1672
1673 static BYTE emptyCert[] = { 0x30, 0x00 };
1674
1675 static void testCertSigs(void)
1676 {
1677     HCRYPTPROV csp;
1678     CRYPT_DATA_BLOB toBeSigned = { sizeof(emptyCert), emptyCert };
1679     BOOL ret;
1680     HCRYPTKEY key;
1681     BYTE sig[64];
1682     DWORD sigSize = sizeof(sig);
1683
1684     /* Just in case a previous run failed, delete this thing */
1685     pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1686      CRYPT_DELETEKEYSET);
1687     ret = pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1688      CRYPT_NEWKEYSET);
1689     ok(ret, "CryptAcquireContext failed: %08x\n", GetLastError());
1690
1691     testSignCert(csp, &toBeSigned, szOID_RSA_SHA1RSA, &key, sig, &sigSize);
1692     testVerifyCertSig(csp, &toBeSigned, szOID_RSA_SHA1RSA, sig, sigSize);
1693
1694     CryptDestroyKey(key);
1695     CryptReleaseContext(csp, 0);
1696     ret = pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1697      CRYPT_DELETEKEYSET);
1698 }
1699
1700 static const BYTE md5SignedEmptyCert[] = {
1701 0x30,0x56,0x30,0x33,0x02,0x00,0x30,0x02,0x06,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,
1702 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,
1703 0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x07,
1704 0x30,0x02,0x06,0x00,0x03,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,
1705 0x0d,0x02,0x05,0x05,0x00,0x03,0x11,0x00,0xfb,0x0f,0x66,0x82,0x66,0xd9,0xe5,0xf8,
1706 0xd8,0xa2,0x55,0x2b,0xe1,0xa5,0xd9,0x04 };
1707 static const BYTE md5SignedEmptyCertNoNull[] = {
1708 0x30,0x54,0x30,0x33,0x02,0x00,0x30,0x02,0x06,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,
1709 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,
1710 0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x07,
1711 0x30,0x02,0x06,0x00,0x03,0x01,0x00,0x30,0x0a,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,
1712 0x0d,0x02,0x05,0x03,0x11,0x00,0x04,0xd9,0xa5,0xe1,0x2b,0x55,0xa2,0xd8,0xf8,0xe5,
1713 0xd9,0x66,0x82,0x66,0x0f,0xfb };
1714
1715 static void testSignAndEncodeCert(void)
1716 {
1717     static char oid_rsa_md5rsa[] = szOID_RSA_MD5RSA;
1718     static char oid_rsa_md5[] = szOID_RSA_MD5;
1719     BOOL ret;
1720     DWORD size;
1721     CRYPT_ALGORITHM_IDENTIFIER algID = { 0 };
1722     CERT_INFO info = { 0 };
1723
1724     /* Crash
1725     ret = CryptSignAndEncodeCertificate(0, 0, 0, NULL, NULL, NULL, NULL, NULL,
1726      NULL);
1727     ret = CryptSignAndEncodeCertificate(0, 0, 0, NULL, NULL, NULL, NULL, NULL,
1728      &size);
1729      */
1730     ret = CryptSignAndEncodeCertificate(0, 0, 0, NULL, NULL, &algID, NULL, NULL,
1731      &size);
1732     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1733      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1734     ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING, NULL, NULL,
1735      &algID, NULL, NULL, &size);
1736     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1737      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1738     ret = CryptSignAndEncodeCertificate(0, 0, 0, X509_CERT_TO_BE_SIGNED, NULL,
1739      &algID, NULL, NULL, &size);
1740     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1741      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1742     ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1743      X509_CERT_TO_BE_SIGNED, NULL, &algID, NULL, NULL, &size);
1744     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1745      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1746     /* Crashes
1747     ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1748      X509_CERT_TO_BE_SIGNED, &info, NULL, NULL, NULL, &size);
1749      */
1750     ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1751      X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, NULL, &size);
1752     ok(!ret && GetLastError() == NTE_BAD_ALGID,
1753      "Expected NTE_BAD_ALGID, got %08x\n", GetLastError());
1754     algID.pszObjId = oid_rsa_md5rsa;
1755     ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1756      X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, NULL, &size);
1757     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1758      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1759     algID.pszObjId = oid_rsa_md5;
1760     ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1761      X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, NULL, &size);
1762     ok(ret, "CryptSignAndEncodeCertificate failed: %08x\n", GetLastError());
1763     if (ret)
1764     {
1765         LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, size);
1766
1767         if (buf)
1768         {
1769             ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1770              X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, buf, &size);
1771             ok(ret, "CryptSignAndEncodeCertificate failed: %08x\n",
1772              GetLastError());
1773             /* Tricky: because the NULL parameters may either be omitted or
1774              * included as an asn.1-encoded NULL (0x05,0x00), two different
1775              * values are allowed.
1776              */
1777             ok(size == sizeof(md5SignedEmptyCert) ||
1778              size == sizeof(md5SignedEmptyCertNoNull), "Unexpected size %d\n",
1779              size);
1780             if (size == sizeof(md5SignedEmptyCert))
1781                 ok(!memcmp(buf, md5SignedEmptyCert, size),
1782                  "Unexpected value\n");
1783             else if (size == sizeof(md5SignedEmptyCertNoNull))
1784                 ok(!memcmp(buf, md5SignedEmptyCertNoNull, size),
1785                  "Unexpected value\n");
1786             HeapFree(GetProcessHeap(), 0, buf);
1787         }
1788     }
1789 }
1790
1791 static void testCreateSelfSignCert(void)
1792 {
1793     PCCERT_CONTEXT context;
1794     CERT_NAME_BLOB name = { sizeof(subjectName), subjectName };
1795     HCRYPTPROV csp;
1796     BOOL ret;
1797     HCRYPTKEY key;
1798     CRYPT_KEY_PROV_INFO info;
1799
1800     /* This crashes:
1801     context = CertCreateSelfSignCertificate(0, NULL, 0, NULL, NULL, NULL, NULL,
1802      NULL);
1803      * Calling this with no first parameter creates a new key container, which
1804      * lasts beyond the test, so I don't test that.  Nb: the generated key
1805      * name is a GUID.
1806     context = CertCreateSelfSignCertificate(0, &name, 0, NULL, NULL, NULL, NULL,
1807      NULL);
1808      */
1809
1810     /* Acquire a CSP */
1811     pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1812      CRYPT_DELETEKEYSET);
1813     ret = pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1814      CRYPT_NEWKEYSET);
1815     ok(ret, "CryptAcquireContext failed: %08x\n", GetLastError());
1816
1817     context = CertCreateSelfSignCertificate(csp, &name, 0, NULL, NULL, NULL,
1818      NULL, NULL);
1819     ok(!context && GetLastError() == NTE_NO_KEY,
1820      "Expected NTE_NO_KEY, got %08x\n", GetLastError());
1821     ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
1822     ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
1823     if (ret)
1824     {
1825         context = CertCreateSelfSignCertificate(csp, &name, 0, NULL, NULL, NULL,
1826          NULL, NULL);
1827         ok(context != NULL, "CertCreateSelfSignCertificate failed: %08x\n",
1828          GetLastError());
1829         if (context)
1830         {
1831             DWORD size = 0;
1832             PCRYPT_KEY_PROV_INFO info;
1833
1834             /* The context must have a key provider info property */
1835             ret = CertGetCertificateContextProperty(context,
1836              CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
1837             ok(ret && size, "Expected non-zero key provider info\n");
1838             if (size)
1839             {
1840                 info = HeapAlloc(GetProcessHeap(), 0, size);
1841                 if (info)
1842                 {
1843                     ret = CertGetCertificateContextProperty(context,
1844                      CERT_KEY_PROV_INFO_PROP_ID, info, &size);
1845                     ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
1846                      GetLastError());
1847                     if (ret)
1848                     {
1849                         /* Sanity-check the key provider */
1850                         ok(!lstrcmpW(info->pwszContainerName, cspNameW),
1851                          "Unexpected key container\n");
1852                         ok(!lstrcmpW(info->pwszProvName, MS_DEF_PROV_W),
1853                          "Unexpected provider\n");
1854                         ok(info->dwKeySpec == AT_SIGNATURE,
1855                          "Expected AT_SIGNATURE, got %d\n", info->dwKeySpec);
1856                     }
1857                     HeapFree(GetProcessHeap(), 0, info);
1858                 }
1859             }
1860
1861             CertFreeCertificateContext(context);
1862         }
1863
1864         CryptDestroyKey(key);
1865     }
1866
1867     CryptReleaseContext(csp, 0);
1868     ret = pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1869      CRYPT_DELETEKEYSET);
1870
1871     /* do the same test with AT_KEYEXCHANGE  and key info*/
1872     memset(&info,0,sizeof(info));
1873     info.dwProvType = PROV_RSA_FULL;
1874     info.dwKeySpec = AT_KEYEXCHANGE;
1875     info.pwszProvName = (LPWSTR) MS_DEF_PROV_W;
1876     info.pwszContainerName = cspNameW;
1877     context = CertCreateSelfSignCertificate(0, &name, 0, &info, NULL, NULL,
1878         NULL, NULL);
1879     ok(context != NULL, "CertCreateSelfSignCertificate failed: %08x\n",
1880         GetLastError());
1881     if (context)
1882     {
1883         DWORD size = 0;
1884         PCRYPT_KEY_PROV_INFO info;
1885
1886         /* The context must have a key provider info property */
1887         ret = CertGetCertificateContextProperty(context,
1888             CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
1889         ok(ret && size, "Expected non-zero key provider info\n");
1890         if (size)
1891         {
1892             info = HeapAlloc(GetProcessHeap(), 0, size);
1893             if (info)
1894             {
1895                 ret = CertGetCertificateContextProperty(context,
1896                     CERT_KEY_PROV_INFO_PROP_ID, info, &size);
1897                 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
1898                     GetLastError());
1899                 if (ret)
1900                 {
1901                     /* Sanity-check the key provider */
1902                     ok(!lstrcmpW(info->pwszContainerName, cspNameW),
1903                         "Unexpected key container\n");
1904                     ok(!lstrcmpW(info->pwszProvName, MS_DEF_PROV_W),
1905                         "Unexpected provider\n");
1906                     ok(info->dwKeySpec == AT_KEYEXCHANGE,
1907                         "Expected AT_KEYEXCHANGE, got %d\n", info->dwKeySpec);
1908                 }
1909                 HeapFree(GetProcessHeap(), 0, info);
1910             }
1911         }
1912
1913         CertFreeCertificateContext(context);
1914     }
1915
1916     pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1917         CRYPT_DELETEKEYSET);
1918 }
1919
1920 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
1921  szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
1922
1923 static void testKeyUsage(void)
1924 {
1925     BOOL ret;
1926     PCCERT_CONTEXT context;
1927     DWORD size;
1928
1929     /* Test base cases */
1930     ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, NULL);
1931     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1932      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1933     size = 1;
1934     ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, &size);
1935     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1936      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1937     size = 0;
1938     ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, &size);
1939     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1940      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1941     /* These crash
1942     ret = CertSetEnhancedKeyUsage(NULL, NULL);
1943     usage.cUsageIdentifier = 0;
1944     ret = CertSetEnhancedKeyUsage(NULL, &usage);
1945      */
1946     /* Test with a cert with no enhanced key usage extension */
1947     context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
1948      sizeof(bigCert));
1949     ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
1950      GetLastError());
1951     if (context)
1952     {
1953         static const char oid[] = "1.2.3.4";
1954         BYTE buf[sizeof(CERT_ENHKEY_USAGE) + 2 * (sizeof(LPSTR) + sizeof(oid))];
1955         PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1956
1957         ret = CertGetEnhancedKeyUsage(context, 0, NULL, NULL);
1958         ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1959          "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1960         size = 1;
1961         ret = CertGetEnhancedKeyUsage(context, 0, NULL, &size);
1962         if (ret)
1963         {
1964             /* Windows 2000, ME, or later: even though it succeeded, we expect
1965              * CRYPT_E_NOT_FOUND, which indicates there is no enhanced key
1966              * usage set for this cert (which implies it's valid for all uses.)
1967              */
1968             ok(GetLastError() == CRYPT_E_NOT_FOUND,
1969              "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1970             ok(size == sizeof(CERT_ENHKEY_USAGE), "Wrong size %d\n", size);
1971             ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1972             ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1973             ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %d\n",
1974              pUsage->cUsageIdentifier);
1975         }
1976         else
1977         {
1978             /* Windows NT, 95, or 98: it fails, and the last error is
1979              * CRYPT_E_NOT_FOUND.
1980              */
1981             ok(GetLastError() == CRYPT_E_NOT_FOUND,
1982              "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1983         }
1984         /* I can add a usage identifier when no key usage has been set */
1985         ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
1986         ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
1987          GetLastError());
1988         size = sizeof(buf);
1989         ret = CertGetEnhancedKeyUsage(context,
1990          CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1991         ok(ret && GetLastError() == 0,
1992          "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1993         ok(pUsage->cUsageIdentifier == 1, "Expected 1 usage, got %d\n",
1994          pUsage->cUsageIdentifier);
1995         if (pUsage->cUsageIdentifier)
1996             ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
1997              "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
1998         /* Now set an empty key usage */
1999         pUsage->cUsageIdentifier = 0;
2000         ret = CertSetEnhancedKeyUsage(context, pUsage);
2001         ok(ret, "CertSetEnhancedKeyUsage failed: %08x\n", GetLastError());
2002         /* Shouldn't find it in the cert */
2003         size = sizeof(buf);
2004         ret = CertGetEnhancedKeyUsage(context,
2005          CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
2006         ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
2007          "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
2008         /* Should find it as an extended property */
2009         ret = CertGetEnhancedKeyUsage(context,
2010          CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
2011         ok(ret && GetLastError() == 0,
2012          "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2013         ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %d\n",
2014          pUsage->cUsageIdentifier);
2015         /* Should find it as either */
2016         ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2017         ok(ret && GetLastError() == 0,
2018          "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2019         ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %d\n",
2020          pUsage->cUsageIdentifier);
2021         /* Add a usage identifier */
2022         ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
2023         ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
2024          GetLastError());
2025         size = sizeof(buf);
2026         ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2027         ok(ret && GetLastError() == 0,
2028          "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2029         ok(pUsage->cUsageIdentifier == 1, "Expected 1 identifier, got %d\n",
2030          pUsage->cUsageIdentifier);
2031         if (pUsage->cUsageIdentifier)
2032             ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
2033              "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
2034         /* Yep, I can re-add the same usage identifier */
2035         ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
2036         ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
2037          GetLastError());
2038         size = sizeof(buf);
2039         ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2040         ok(ret && GetLastError() == 0,
2041          "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2042         ok(pUsage->cUsageIdentifier == 2, "Expected 2 identifiers, got %d\n",
2043          pUsage->cUsageIdentifier);
2044         if (pUsage->cUsageIdentifier)
2045             ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
2046              "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
2047         if (pUsage->cUsageIdentifier >= 2)
2048             ok(!strcmp(pUsage->rgpszUsageIdentifier[1], oid),
2049              "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[1]);
2050         /* Now set a NULL extended property--this deletes the property. */
2051         ret = CertSetEnhancedKeyUsage(context, NULL);
2052         ok(ret, "CertSetEnhancedKeyUsage failed: %08x\n", GetLastError());
2053         SetLastError(0xbaadcafe);
2054         size = sizeof(buf);
2055         ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2056         ok(GetLastError() == CRYPT_E_NOT_FOUND,
2057          "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
2058
2059         CertFreeCertificateContext(context);
2060     }
2061     /* Now test with a cert with an enhanced key usage extension */
2062     context = CertCreateCertificateContext(X509_ASN_ENCODING, certWithUsage,
2063      sizeof(certWithUsage));
2064     ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
2065      GetLastError());
2066     if (context)
2067     {
2068         LPBYTE buf = NULL;
2069         DWORD bufSize = 0, i;
2070
2071         /* The size may depend on what flags are used to query it, so I
2072          * realloc the buffer for each test.
2073          */
2074         ret = CertGetEnhancedKeyUsage(context,
2075          CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, NULL, &bufSize);
2076         ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2077         buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
2078         if (buf)
2079         {
2080             PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
2081
2082             /* Should find it in the cert */
2083             size = bufSize;
2084             ret = CertGetEnhancedKeyUsage(context,
2085              CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
2086             ok(ret && GetLastError() == 0,
2087              "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2088             ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
2089              pUsage->cUsageIdentifier);
2090             for (i = 0; i < pUsage->cUsageIdentifier; i++)
2091                 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
2092                  "Expected %s, got %s\n", keyUsages[i],
2093                  pUsage->rgpszUsageIdentifier[i]);
2094             HeapFree(GetProcessHeap(), 0, buf);
2095         }
2096         ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
2097         ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2098         buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
2099         if (buf)
2100         {
2101             PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
2102
2103             /* Should find it as either */
2104             size = bufSize;
2105             ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2106             /* In Windows, GetLastError returns CRYPT_E_NOT_FOUND not found
2107              * here, even though the return is successful and the usage id
2108              * count is positive.  I don't enforce that here.
2109              */
2110             ok(ret,
2111              "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2112             ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
2113              pUsage->cUsageIdentifier);
2114             for (i = 0; i < pUsage->cUsageIdentifier; i++)
2115                 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
2116                  "Expected %s, got %s\n", keyUsages[i],
2117                  pUsage->rgpszUsageIdentifier[i]);
2118             HeapFree(GetProcessHeap(), 0, buf);
2119         }
2120         /* Shouldn't find it as an extended property */
2121         ret = CertGetEnhancedKeyUsage(context,
2122          CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, NULL, &size);
2123         ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
2124          "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
2125         /* Adding a usage identifier overrides the cert's usage!? */
2126         ret = CertAddEnhancedKeyUsageIdentifier(context, szOID_RSA_RSA);
2127         ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
2128          GetLastError());
2129         ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
2130         ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2131         buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
2132         if (buf)
2133         {
2134             PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
2135
2136             /* Should find it as either */
2137             size = bufSize;
2138             ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2139             ok(ret,
2140              "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2141             ok(pUsage->cUsageIdentifier == 1, "Expected 1 usage, got %d\n",
2142              pUsage->cUsageIdentifier);
2143             ok(!strcmp(pUsage->rgpszUsageIdentifier[0], szOID_RSA_RSA),
2144              "Expected %s, got %s\n", szOID_RSA_RSA,
2145              pUsage->rgpszUsageIdentifier[0]);
2146             HeapFree(GetProcessHeap(), 0, buf);
2147         }
2148         /* But querying the cert directly returns its usage */
2149         ret = CertGetEnhancedKeyUsage(context,
2150          CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, NULL, &bufSize);
2151         ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2152         buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
2153         if (buf)
2154         {
2155             PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
2156
2157             size = bufSize;
2158             ret = CertGetEnhancedKeyUsage(context,
2159              CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
2160             ok(ret,
2161              "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2162             ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
2163              pUsage->cUsageIdentifier);
2164             for (i = 0; i < pUsage->cUsageIdentifier; i++)
2165                 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
2166                  "Expected %s, got %s\n", keyUsages[i],
2167                  pUsage->rgpszUsageIdentifier[i]);
2168             HeapFree(GetProcessHeap(), 0, buf);
2169         }
2170         /* And removing the only usage identifier in the extended property
2171          * results in the cert's key usage being found.
2172          */
2173         ret = CertRemoveEnhancedKeyUsageIdentifier(context, szOID_RSA_RSA);
2174         ok(ret, "CertRemoveEnhancedKeyUsage failed: %08x\n", GetLastError());
2175         ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
2176         ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2177         buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
2178         if (buf)
2179         {
2180             PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
2181
2182             /* Should find it as either */
2183             size = bufSize;
2184             ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2185             ok(ret,
2186              "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2187             ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
2188              pUsage->cUsageIdentifier);
2189             for (i = 0; i < pUsage->cUsageIdentifier; i++)
2190                 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
2191                  "Expected %s, got %s\n", keyUsages[i],
2192                  pUsage->rgpszUsageIdentifier[i]);
2193             HeapFree(GetProcessHeap(), 0, buf);
2194         }
2195
2196         CertFreeCertificateContext(context);
2197     }
2198 }
2199
2200 static const BYTE cert2WithUsage[] = {
2201 0x30,0x81,0x89,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2202 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2203 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2204 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2205 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2206 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2207 0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x25,0x30,0x23,
2208 0x30,0x21,0x06,0x03,0x55,0x1d,0x25,0x01,0x01,0xff,0x04,0x17,0x30,0x15,0x06,
2209 0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x03,0x02,0x06,0x09,0x2a,0x86,0x48,0x86,
2210 0xf7,0x0d,0x01,0x01,0x01 };
2211
2212 static void testGetValidUsages(void)
2213 {
2214     static const LPCSTR expectedOIDs[] = {
2215      "1.3.6.1.5.5.7.3.3",
2216      "1.3.6.1.5.5.7.3.2",
2217      "1.2.840.113549.1.1.1",
2218     };
2219     static const LPCSTR expectedOIDs2[] = {
2220      "1.3.6.1.5.5.7.3.2",
2221      "1.2.840.113549.1.1.1",
2222     };
2223     BOOL ret;
2224     int numOIDs;
2225     DWORD size;
2226     LPSTR *oids = NULL;
2227     PCCERT_CONTEXT contexts[3];
2228
2229     /* Crash
2230     ret = CertGetValidUsages(0, NULL, NULL, NULL, NULL);
2231     ret = CertGetValidUsages(0, NULL, NULL, NULL, &size);
2232      */
2233     contexts[0] = NULL;
2234     numOIDs = size = 0xdeadbeef;
2235     SetLastError(0xdeadbeef);
2236     ret = CertGetValidUsages(1, &contexts[0], &numOIDs, NULL, &size);
2237     ok(ret, "CertGetValidUsages failed: %d\n", GetLastError());
2238     ok(numOIDs == -1, "Expected -1, got %d\n", numOIDs);
2239     ok(size == 0, "Expected size 0, got %d\n", size);
2240     contexts[0] = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
2241      sizeof(bigCert));
2242     contexts[1] = CertCreateCertificateContext(X509_ASN_ENCODING, certWithUsage,
2243      sizeof(certWithUsage));
2244     contexts[2] = CertCreateCertificateContext(X509_ASN_ENCODING,
2245      cert2WithUsage, sizeof(cert2WithUsage));
2246     numOIDs = size = 0xdeadbeef;
2247     ret = CertGetValidUsages(0, NULL, &numOIDs, NULL, &size);
2248     ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2249     ok(numOIDs == -1, "Expected -1, got %d\n", numOIDs);
2250     ok(size == 0, "Expected size 0, got %d\n", size);
2251     numOIDs = size = 0xdeadbeef;
2252     ret = CertGetValidUsages(1, contexts, &numOIDs, NULL, &size);
2253     ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2254     ok(numOIDs == -1, "Expected -1, got %d\n", numOIDs);
2255     ok(size == 0, "Expected size 0, got %d\n", size);
2256     ret = CertGetValidUsages(1, &contexts[1], &numOIDs, NULL, &size);
2257     ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2258     ok(numOIDs == 3, "Expected 3, got %d\n", numOIDs);
2259     ok(size, "Expected non-zero size\n");
2260     oids = HeapAlloc(GetProcessHeap(), 0, size);
2261     if (oids)
2262     {
2263         int i;
2264         DWORD smallSize = 1;
2265
2266         SetLastError(0xdeadbeef);
2267         ret = CertGetValidUsages(1, &contexts[1], &numOIDs, oids, &smallSize);
2268         ok(!ret && GetLastError() == ERROR_MORE_DATA,
2269          "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
2270         ret = CertGetValidUsages(1, &contexts[1], &numOIDs, oids, &size);
2271         ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2272         for (i = 0; i < numOIDs; i++)
2273             ok(!lstrcmpA(oids[i], expectedOIDs[i]), "unexpected OID %s\n",
2274              oids[i]);
2275         HeapFree(GetProcessHeap(), 0, oids);
2276     }
2277     numOIDs = size = 0xdeadbeef;
2278     /* Oddly enough, this crashes when the number of contexts is not 1:
2279     ret = CertGetValidUsages(2, contexts, &numOIDs, NULL, &size);
2280      * but setting size to 0 allows it to succeed:
2281      */
2282     size = 0;
2283     ret = CertGetValidUsages(2, contexts, &numOIDs, NULL, &size);
2284     ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2285     ok(numOIDs == 3, "Expected 3, got %d\n", numOIDs);
2286     ok(size, "Expected non-zero size\n");
2287     oids = HeapAlloc(GetProcessHeap(), 0, size);
2288     if (oids)
2289     {
2290         int i;
2291
2292         ret = CertGetValidUsages(1, &contexts[1], &numOIDs, oids, &size);
2293         ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2294         for (i = 0; i < numOIDs; i++)
2295             ok(!lstrcmpA(oids[i], expectedOIDs[i]), "unexpected OID %s\n",
2296              oids[i]);
2297         HeapFree(GetProcessHeap(), 0, oids);
2298     }
2299     numOIDs = 0xdeadbeef;
2300     size = 0;
2301     ret = CertGetValidUsages(1, &contexts[2], &numOIDs, NULL, &size);
2302     ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2303     ok(numOIDs == 2, "Expected 2, got %d\n", numOIDs);
2304     ok(size, "Expected non-zero size\n");
2305     oids = HeapAlloc(GetProcessHeap(), 0, size);
2306     if (oids)
2307     {
2308         int i;
2309
2310         ret = CertGetValidUsages(1, &contexts[2], &numOIDs, oids, &size);
2311         ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2312         for (i = 0; i < numOIDs; i++)
2313             ok(!lstrcmpA(oids[i], expectedOIDs2[i]), "unexpected OID %s\n",
2314              oids[i]);
2315         HeapFree(GetProcessHeap(), 0, oids);
2316     }
2317     numOIDs = 0xdeadbeef;
2318     size = 0;
2319     ret = CertGetValidUsages(3, contexts, &numOIDs, NULL, &size);
2320     ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2321     ok(numOIDs == 2, "Expected 2, got %d\n", numOIDs);
2322     ok(size, "Expected non-zero size\n");
2323     oids = HeapAlloc(GetProcessHeap(), 0, size);
2324     if (oids)
2325     {
2326         int i;
2327
2328         ret = CertGetValidUsages(3, contexts, &numOIDs, oids, &size);
2329         ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2330         for (i = 0; i < numOIDs; i++)
2331             ok(!lstrcmpA(oids[i], expectedOIDs2[i]), "unexpected OID %s\n",
2332              oids[i]);
2333         HeapFree(GetProcessHeap(), 0, oids);
2334     }
2335     CertFreeCertificateContext(contexts[0]);
2336     CertFreeCertificateContext(contexts[1]);
2337     CertFreeCertificateContext(contexts[2]);
2338 }
2339
2340 static void testCompareCertName(void)
2341 {
2342     static BYTE bogus[] = { 1, 2, 3, 4 };
2343     static BYTE bogusPrime[] = { 0, 1, 2, 3, 4 };
2344     static BYTE emptyPrime[] = { 0x30, 0x00, 0x01 };
2345     BOOL ret;
2346     CERT_NAME_BLOB blob1, blob2;
2347
2348     /* crashes
2349     ret = CertCompareCertificateName(0, NULL, NULL);
2350      */
2351     /* An empty name checks against itself.. */
2352     blob1.pbData = emptyCert;
2353     blob1.cbData = sizeof(emptyCert);
2354     ret = CertCompareCertificateName(0, &blob1, &blob1);
2355     ok(ret, "CertCompareCertificateName failed: %08x\n", GetLastError());
2356     /* It doesn't have to be a valid encoded name.. */
2357     blob1.pbData = bogus;
2358     blob1.cbData = sizeof(bogus);
2359     ret = CertCompareCertificateName(0, &blob1, &blob1);
2360     ok(ret, "CertCompareCertificateName failed: %08x\n", GetLastError());
2361     /* Leading zeroes matter.. */
2362     blob2.pbData = bogusPrime;
2363     blob2.cbData = sizeof(bogusPrime);
2364     ret = CertCompareCertificateName(0, &blob1, &blob2);
2365     ok(!ret, "Expected failure\n");
2366     /* As do trailing extra bytes. */
2367     blob2.pbData = emptyPrime;
2368     blob2.cbData = sizeof(emptyPrime);
2369     ret = CertCompareCertificateName(0, &blob1, &blob2);
2370     ok(!ret, "Expected failure\n");
2371 }
2372
2373 static BYTE int1[] = { 0x88, 0xff, 0xff, 0xff };
2374 static BYTE int2[] = { 0x88, 0xff };
2375 static BYTE int3[] = { 0x23, 0xff };
2376 static BYTE int4[] = { 0x7f, 0x00 };
2377 static BYTE int5[] = { 0x7f };
2378 static BYTE int6[] = { 0x80, 0x00, 0x00, 0x00 };
2379 static BYTE int7[] = { 0x80, 0x00 };
2380
2381 static struct IntBlobTest
2382 {
2383     CRYPT_INTEGER_BLOB blob1;
2384     CRYPT_INTEGER_BLOB blob2;
2385     BOOL areEqual;
2386 } intBlobs[] = {
2387  { { sizeof(int1), int1 }, { sizeof(int2), int2 }, TRUE },
2388  { { sizeof(int3), int3 }, { sizeof(int3), int3 }, TRUE },
2389  { { sizeof(int4), int4 }, { sizeof(int5), int5 }, TRUE },
2390  { { sizeof(int6), int6 }, { sizeof(int7), int7 }, TRUE },
2391  { { sizeof(int1), int1 }, { sizeof(int7), int7 }, FALSE },
2392 };
2393
2394 static void testCompareIntegerBlob(void)
2395 {
2396     DWORD i;
2397     BOOL ret;
2398
2399     for (i = 0; i < sizeof(intBlobs) / sizeof(intBlobs[0]); i++)
2400     {
2401         ret = CertCompareIntegerBlob(&intBlobs[i].blob1, &intBlobs[i].blob2);
2402         ok(ret == intBlobs[i].areEqual,
2403          "%d: expected blobs %s compare\n", i, intBlobs[i].areEqual ?
2404          "to" : "not to");
2405     }
2406 }
2407
2408 static void testComparePublicKeyInfo(void)
2409 {
2410     BOOL ret;
2411     CERT_PUBLIC_KEY_INFO info1 = { { 0 } }, info2 = { { 0 } };
2412     static CHAR oid_rsa_rsa[]     = szOID_RSA_RSA;
2413     static CHAR oid_rsa_sha1rsa[] = szOID_RSA_SHA1RSA;
2414     static CHAR oid_x957_dsa[]    = szOID_X957_DSA;
2415     static BYTE bits1[] = { 1, 0 };
2416     static BYTE bits2[] = { 0 };
2417     static BYTE bits3[] = { 1 };
2418
2419     /* crashes
2420     ret = CertComparePublicKeyInfo(0, NULL, NULL);
2421      */
2422     /* Empty public keys compare */
2423     ret = CertComparePublicKeyInfo(0, &info1, &info2);
2424     ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
2425     /* Different OIDs appear to compare */
2426     info1.Algorithm.pszObjId = oid_rsa_rsa;
2427     info2.Algorithm.pszObjId = oid_rsa_sha1rsa;
2428     ret = CertComparePublicKeyInfo(0, &info1, &info2);
2429     ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
2430     info2.Algorithm.pszObjId = oid_x957_dsa;
2431     ret = CertComparePublicKeyInfo(0, &info1, &info2);
2432     ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
2433     info1.PublicKey.cbData = sizeof(bits1);
2434     info1.PublicKey.pbData = bits1;
2435     info1.PublicKey.cUnusedBits = 0;
2436     info2.PublicKey.cbData = sizeof(bits1);
2437     info2.PublicKey.pbData = bits1;
2438     info2.PublicKey.cUnusedBits = 0;
2439     ret = CertComparePublicKeyInfo(0, &info1, &info2);
2440     ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
2441     /* Even though they compare in their used bits, these do not compare */
2442     info1.PublicKey.cbData = sizeof(bits2);
2443     info1.PublicKey.pbData = bits2;
2444     info1.PublicKey.cUnusedBits = 0;
2445     info2.PublicKey.cbData = sizeof(bits3);
2446     info2.PublicKey.pbData = bits3;
2447     info2.PublicKey.cUnusedBits = 1;
2448     ret = CertComparePublicKeyInfo(0, &info1, &info2);
2449     /* Simple (non-comparing) case */
2450     ok(!ret, "Expected keys not to compare\n");
2451     info2.PublicKey.cbData = sizeof(bits1);
2452     info2.PublicKey.pbData = bits1;
2453     info2.PublicKey.cUnusedBits = 0;
2454     ret = CertComparePublicKeyInfo(0, &info1, &info2);
2455     ok(!ret, "Expected keys not to compare\n");
2456 }
2457
2458 static void testHashPublicKeyInfo(void)
2459 {
2460     BOOL ret;
2461     CERT_PUBLIC_KEY_INFO info = { { 0 } };
2462     DWORD len;
2463
2464     /* Crash
2465     ret = CryptHashPublicKeyInfo(0, 0, 0, 0, NULL, NULL, NULL);
2466     ret = CryptHashPublicKeyInfo(0, 0, 0, 0, &info, NULL, NULL);
2467      */
2468     ret = CryptHashPublicKeyInfo(0, 0, 0, 0, NULL, NULL, &len);
2469     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2470      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2471     ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, NULL, NULL, &len);
2472     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2473      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
2474     ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, &info, NULL, &len);
2475     ok(ret, "CryptHashPublicKeyInfo failed: %08x\n", GetLastError());
2476     ok(len == 16, "Expected hash size 16, got %d\n", len);
2477     if (len == 16)
2478     {
2479         static const BYTE emptyHash[] = { 0xb8,0x51,0x3a,0x31,0x0e,0x9f,0x40,
2480          0x36,0x9c,0x92,0x45,0x1b,0x9d,0xc8,0xf9,0xf6 };
2481         BYTE buf[16];
2482
2483         ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, &info, buf,
2484          &len);
2485         ok(ret, "CryptHashPublicKeyInfo failed: %08x\n", GetLastError());
2486         ok(!memcmp(buf, emptyHash, len), "Unexpected hash\n");
2487     }
2488 }
2489
2490 static void testCompareCert(void)
2491 {
2492     CERT_INFO info1 = { 0 }, info2 = { 0 };
2493     BOOL ret;
2494
2495     /* Crashes
2496     ret = CertCompareCertificate(X509_ASN_ENCODING, NULL, NULL);
2497      */
2498
2499     /* Certs with the same issuer and serial number are equal, even if they
2500      * differ in other respects (like subject).
2501      */
2502     info1.SerialNumber.pbData = serialNum;
2503     info1.SerialNumber.cbData = sizeof(serialNum);
2504     info1.Issuer.pbData = subjectName;
2505     info1.Issuer.cbData = sizeof(subjectName);
2506     info1.Subject.pbData = subjectName2;
2507     info1.Subject.cbData = sizeof(subjectName2);
2508     info2.SerialNumber.pbData = serialNum;
2509     info2.SerialNumber.cbData = sizeof(serialNum);
2510     info2.Issuer.pbData = subjectName;
2511     info2.Issuer.cbData = sizeof(subjectName);
2512     info2.Subject.pbData = subjectName;
2513     info2.Subject.cbData = sizeof(subjectName);
2514     ret = CertCompareCertificate(X509_ASN_ENCODING, &info1, &info2);
2515     ok(ret, "Expected certs to be equal\n");
2516
2517     info2.Issuer.pbData = subjectName2;
2518     info2.Issuer.cbData = sizeof(subjectName2);
2519     ret = CertCompareCertificate(X509_ASN_ENCODING, &info1, &info2);
2520     ok(!ret, "Expected certs not to be equal\n");
2521 }
2522
2523 static void testVerifySubjectCert(void)
2524 {
2525     BOOL ret;
2526     DWORD flags;
2527     PCCERT_CONTEXT context1, context2;
2528
2529     /* Crashes
2530     ret = CertVerifySubjectCertificateContext(NULL, NULL, NULL);
2531      */
2532     flags = 0;
2533     ret = CertVerifySubjectCertificateContext(NULL, NULL, &flags);
2534     ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
2535      GetLastError());
2536     flags = CERT_STORE_NO_CRL_FLAG;
2537     ret = CertVerifySubjectCertificateContext(NULL, NULL, &flags);
2538     ok(!ret && GetLastError() == E_INVALIDARG,
2539      "Expected E_INVALIDARG, got %08x\n", GetLastError());
2540
2541     flags = 0;
2542     context1 = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
2543      sizeof(bigCert));
2544     ret = CertVerifySubjectCertificateContext(NULL, context1, &flags);
2545     ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
2546      GetLastError());
2547     ret = CertVerifySubjectCertificateContext(context1, NULL, &flags);
2548     ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
2549      GetLastError());
2550     ret = CertVerifySubjectCertificateContext(context1, context1, &flags);
2551     ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
2552      GetLastError());
2553
2554     context2 = CertCreateCertificateContext(X509_ASN_ENCODING,
2555      bigCertWithDifferentSubject, sizeof(bigCertWithDifferentSubject));
2556     SetLastError(0xdeadbeef);
2557     ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
2558     ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
2559      GetLastError());
2560     flags = CERT_STORE_REVOCATION_FLAG;
2561     ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
2562     ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
2563      GetLastError());
2564     ok(flags == (CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG),
2565      "Expected CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG, got %08x\n",
2566      flags);
2567     flags = CERT_STORE_SIGNATURE_FLAG;
2568     ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
2569     ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
2570      GetLastError());
2571     ok(flags == CERT_STORE_SIGNATURE_FLAG,
2572      "Expected CERT_STORE_SIGNATURE_FLAG, got %08x\n", flags);
2573     CertFreeCertificateContext(context2);
2574
2575     CertFreeCertificateContext(context1);
2576 }
2577
2578 static void testVerifyRevocation(void)
2579 {
2580     BOOL ret;
2581     CERT_REVOCATION_STATUS status = { 0 };
2582     PCCERT_CONTEXT cert = CertCreateCertificateContext(X509_ASN_ENCODING,
2583      bigCert, sizeof(bigCert));
2584
2585     /* Crash
2586     ret = CertVerifyRevocation(0, 0, 0, NULL, 0, NULL, NULL);
2587      */
2588     SetLastError(0xdeadbeef);
2589     ret = CertVerifyRevocation(0, 0, 0, NULL, 0, NULL, &status);
2590     ok(!ret && GetLastError() == E_INVALIDARG,
2591      "Expected E_INVALIDARG, got %08x\n", GetLastError());
2592     status.cbSize = sizeof(status);
2593     ret = CertVerifyRevocation(0, 0, 0, NULL, 0, NULL, &status);
2594     ok(ret, "CertVerifyRevocation failed: %08x\n", GetLastError());
2595     ret = CertVerifyRevocation(0, 2, 0, NULL, 0, NULL, &status);
2596     ok(ret, "CertVerifyRevocation failed: %08x\n", GetLastError());
2597     ret = CertVerifyRevocation(2, 0, 0, NULL, 0, NULL, &status);
2598     ok(ret, "CertVerifyRevocation failed: %08x\n", GetLastError());
2599     SetLastError(0xdeadbeef);
2600     ret = CertVerifyRevocation(0, 0, 1, (void **)&cert, 0, NULL, &status);
2601     ok(!ret && GetLastError() == CRYPT_E_NO_REVOCATION_DLL,
2602      "Expected CRYPT_E_NO_REVOCATION_DLL, got %08x\n", GetLastError());
2603     SetLastError(0xdeadbeef);
2604     ret = CertVerifyRevocation(0, 2, 1, (void **)&cert, 0, NULL, &status);
2605     ok(!ret && GetLastError() == CRYPT_E_NO_REVOCATION_DLL,
2606      "Expected CRYPT_E_NO_REVOCATION_DLL, got %08x\n", GetLastError());
2607
2608     CertFreeCertificateContext(cert);
2609 }
2610
2611 static BYTE privKey[] = {
2612  0x07, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x52, 0x53, 0x41, 0x32, 0x00,
2613  0x02, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x79, 0x10, 0x1c, 0xd0, 0x6b, 0x10,
2614  0x18, 0x30, 0x94, 0x61, 0xdc, 0x0e, 0xcb, 0x96, 0x4e, 0x21, 0x3f, 0x79, 0xcd,
2615  0xa9, 0x17, 0x62, 0xbc, 0xbb, 0x61, 0x4c, 0xe0, 0x75, 0x38, 0x6c, 0xf3, 0xde,
2616  0x60, 0x86, 0x03, 0x97, 0x65, 0xeb, 0x1e, 0x6b, 0xdb, 0x53, 0x85, 0xad, 0x68,
2617  0x21, 0xf1, 0x5d, 0xe7, 0x1f, 0xe6, 0x53, 0xb4, 0xbb, 0x59, 0x3e, 0x14, 0x27,
2618  0xb1, 0x83, 0xa7, 0x3a, 0x54, 0xe2, 0x8f, 0x65, 0x8e, 0x6a, 0x4a, 0xcf, 0x3b,
2619  0x1f, 0x65, 0xff, 0xfe, 0xf1, 0x31, 0x3a, 0x37, 0x7a, 0x8b, 0xcb, 0xc6, 0xd4,
2620  0x98, 0x50, 0x36, 0x67, 0xe4, 0xa1, 0xe8, 0x7e, 0x8a, 0xc5, 0x23, 0xf2, 0x77,
2621  0xf5, 0x37, 0x61, 0x49, 0x72, 0x59, 0xe8, 0x3d, 0xf7, 0x60, 0xb2, 0x77, 0xca,
2622  0x78, 0x54, 0x6d, 0x65, 0x9e, 0x03, 0x97, 0x1b, 0x61, 0xbd, 0x0c, 0xd8, 0x06,
2623  0x63, 0xe2, 0xc5, 0x48, 0xef, 0xb3, 0xe2, 0x6e, 0x98, 0x7d, 0xbd, 0x4e, 0x72,
2624  0x91, 0xdb, 0x31, 0x57, 0xe3, 0x65, 0x3a, 0x49, 0xca, 0xec, 0xd2, 0x02, 0x4e,
2625  0x22, 0x7e, 0x72, 0x8e, 0xf9, 0x79, 0x84, 0x82, 0xdf, 0x7b, 0x92, 0x2d, 0xaf,
2626  0xc9, 0xe4, 0x33, 0xef, 0x89, 0x5c, 0x66, 0x99, 0xd8, 0x80, 0x81, 0x47, 0x2b,
2627  0xb1, 0x66, 0x02, 0x84, 0x59, 0x7b, 0xc3, 0xbe, 0x98, 0x45, 0x4a, 0x3d, 0xdd,
2628  0xea, 0x2b, 0xdf, 0x4e, 0xb4, 0x24, 0x6b, 0xec, 0xe7, 0xd9, 0x0c, 0x45, 0xb8,
2629  0xbe, 0xca, 0x69, 0x37, 0x92, 0x4c, 0x38, 0x6b, 0x96, 0x6d, 0xcd, 0x86, 0x67,
2630  0x5c, 0xea, 0x54, 0x94, 0xa4, 0xca, 0xa4, 0x02, 0xa5, 0x21, 0x4d, 0xae, 0x40,
2631  0x8f, 0x9d, 0x51, 0x83, 0xf2, 0x3f, 0x33, 0xc1, 0x72, 0xb4, 0x1d, 0x94, 0x6e,
2632  0x7d, 0xe4, 0x27, 0x3f, 0xea, 0xff, 0xe5, 0x9b, 0xa7, 0x5e, 0x55, 0x8e, 0x0d,
2633  0x69, 0x1c, 0x7a, 0xff, 0x81, 0x9d, 0x53, 0x52, 0x97, 0x9a, 0x76, 0x79, 0xda,
2634  0x93, 0x32, 0x16, 0xec, 0x69, 0x51, 0x1a, 0x4e, 0xc3, 0xf1, 0x72, 0x80, 0x78,
2635  0x5e, 0x66, 0x4a, 0x8d, 0x85, 0x2f, 0x3f, 0xb2, 0xa7 };
2636
2637 static const BYTE selfSignedCert[] = {
2638  0x30, 0x82, 0x01, 0x1f, 0x30, 0x81, 0xce, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
2639  0x10, 0xeb, 0x0d, 0x57, 0x2a, 0x9c, 0x09, 0xba, 0xa4, 0x4a, 0xb7, 0x25, 0x49,
2640  0xd9, 0x3e, 0xb5, 0x73, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d,
2641  0x05, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
2642  0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30,
2643  0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x36, 0x32, 0x39, 0x30, 0x35, 0x30, 0x30,
2644  0x34, 0x36, 0x5a, 0x17, 0x0d, 0x30, 0x37, 0x30, 0x36, 0x32, 0x39, 0x31, 0x31,
2645  0x30, 0x30, 0x34, 0x36, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
2646  0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e,
2647  0x67, 0x00, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
2648  0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
2649  0x00, 0xe2, 0x54, 0x3a, 0xa7, 0x83, 0xb1, 0x27, 0x14, 0x3e, 0x59, 0xbb, 0xb4,
2650  0x53, 0xe6, 0x1f, 0xe7, 0x5d, 0xf1, 0x21, 0x68, 0xad, 0x85, 0x53, 0xdb, 0x6b,
2651  0x1e, 0xeb, 0x65, 0x97, 0x03, 0x86, 0x60, 0xde, 0xf3, 0x6c, 0x38, 0x75, 0xe0,
2652  0x4c, 0x61, 0xbb, 0xbc, 0x62, 0x17, 0xa9, 0xcd, 0x79, 0x3f, 0x21, 0x4e, 0x96,
2653  0xcb, 0x0e, 0xdc, 0x61, 0x94, 0x30, 0x18, 0x10, 0x6b, 0xd0, 0x1c, 0x10, 0x79,
2654  0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
2655  0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x25, 0x90, 0x53, 0x34, 0xd9, 0x56, 0x41,
2656  0x5e, 0xdb, 0x7e, 0x01, 0x36, 0xec, 0x27, 0x61, 0x5e, 0xb7, 0x4d, 0x90, 0x66,
2657  0xa2, 0xe1, 0x9d, 0x58, 0x76, 0xd4, 0x9c, 0xba, 0x2c, 0x84, 0xc6, 0x83, 0x7a,
2658  0x22, 0x0d, 0x03, 0x69, 0x32, 0x1a, 0x6d, 0xcb, 0x0c, 0x15, 0xb3, 0x6b, 0xc7,
2659  0x0a, 0x8c, 0xb4, 0x5c, 0x34, 0x78, 0xe0, 0x3c, 0x9c, 0xe9, 0xf3, 0x30, 0x9f,
2660  0xa8, 0x76, 0x57, 0x92, 0x36 };
2661
2662 static const BYTE exportedPublicKeyBlob[] = {
2663 0x06,0x02,0x00,0x00,0x00,0xa4,0x00,0x00,0x52,0x53,0x41,0x31,0x00,0x02,0x00,0x00,
2664 0x01,0x00,0x01,0x00,0x79,0x10,0x1c,0xd0,0x6b,0x10,0x18,0x30,0x94,0x61,0xdc,0x0e,
2665 0xcb,0x96,0x4e,0x21,0x3f,0x79,0xcd,0xa9,0x17,0x62,0xbc,0xbb,0x61,0x4c,0xe0,0x75,
2666 0x38,0x6c,0xf3,0xde,0x60,0x86,0x03,0x97,0x65,0xeb,0x1e,0x6b,0xdb,0x53,0x85,0xad,
2667 0x68,0x21,0xf1,0x5d,0xe7,0x1f,0xe6,0x53,0xb4,0xbb,0x59,0x3e,0x14,0x27,0xb1,0x83,
2668 0xa7,0x3a,0x54,0xe2 };
2669
2670 static const BYTE asnEncodedPublicKey[] = {
2671 0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7,0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,
2672 0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21,0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,
2673 0x65,0x97,0x03,0x86,0x60,0xde,0xf3,0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,
2674 0x17,0xa9,0xcd,0x79,0x3f,0x21,0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,
2675 0x6b,0xd0,0x1c,0x10,0x79,0x02,0x03,0x01,0x00,0x01 };
2676
2677 static void testAcquireCertPrivateKey(void)
2678 {
2679     BOOL ret;
2680     PCCERT_CONTEXT cert;
2681     HCRYPTPROV csp;
2682     DWORD size, keySpec;
2683     BOOL callerFree;
2684     CRYPT_KEY_PROV_INFO keyProvInfo;
2685     HCRYPTKEY key;
2686     WCHAR ms_def_prov_w[MAX_PATH];
2687
2688     lstrcpyW(ms_def_prov_w, MS_DEF_PROV_W);
2689
2690     keyProvInfo.pwszContainerName = cspNameW;
2691     keyProvInfo.pwszProvName = ms_def_prov_w;
2692     keyProvInfo.dwProvType = PROV_RSA_FULL;
2693     keyProvInfo.dwFlags = 0;
2694     keyProvInfo.cProvParam = 0;
2695     keyProvInfo.rgProvParam = NULL;
2696     keyProvInfo.dwKeySpec = AT_SIGNATURE;
2697
2698     pCryptAcquireContextW(NULL, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
2699      CRYPT_DELETEKEYSET);
2700
2701     cert = CertCreateCertificateContext(X509_ASN_ENCODING, selfSignedCert,
2702      sizeof(selfSignedCert));
2703
2704     /* Crash
2705     ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, NULL, NULL);
2706     ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, NULL,
2707      &callerFree);
2708     ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, &keySpec,
2709      NULL);
2710     ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, &csp, NULL, NULL);
2711     ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, &csp, &keySpec,
2712      &callerFree);
2713     ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, NULL, NULL, NULL);
2714      */
2715
2716     /* Missing private key */
2717     ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, NULL, NULL);
2718     ok(!ret && GetLastError() == CRYPT_E_NO_KEY_PROPERTY,
2719      "Expected CRYPT_E_NO_KEY_PROPERTY, got %08x\n", GetLastError());
2720     ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, &keySpec,
2721      &callerFree);
2722     ok(!ret && GetLastError() == CRYPT_E_NO_KEY_PROPERTY,
2723      "Expected CRYPT_E_NO_KEY_PROPERTY, got %08x\n", GetLastError());
2724     CertSetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, 0,
2725      &keyProvInfo);
2726     ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, &keySpec,
2727      &callerFree);
2728     ok(!ret && GetLastError() == CRYPT_E_NO_KEY_PROPERTY,
2729      "Expected CRYPT_E_NO_KEY_PROPERTY, got %08x\n", GetLastError());
2730
2731     pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
2732      CRYPT_NEWKEYSET);
2733     ret = CryptImportKey(csp, privKey, sizeof(privKey), 0, 0, &key);
2734     ok(ret, "CryptImportKey failed: %08x\n", GetLastError());
2735     if (ret)
2736     {
2737         HCRYPTPROV certCSP;
2738         DWORD size;
2739         CERT_KEY_CONTEXT keyContext;
2740
2741         /* Don't cache provider */
2742         ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &certCSP,
2743          &keySpec, &callerFree);
2744         ok(ret, "CryptAcquireCertificatePrivateKey failed: %08x\n",
2745          GetLastError());
2746         ok(callerFree, "Expected callerFree to be TRUE\n");
2747         CryptReleaseContext(certCSP, 0);
2748         ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &certCSP,
2749          NULL, NULL);
2750         ok(ret, "CryptAcquireCertificatePrivateKey failed: %08x\n",
2751          GetLastError());
2752         CryptReleaseContext(certCSP, 0);
2753
2754         /* Use the key prov info's caching (there shouldn't be any) */
2755         ret = CryptAcquireCertificatePrivateKey(cert,
2756          CRYPT_ACQUIRE_USE_PROV_INFO_FLAG, NULL, &certCSP, &keySpec,
2757          &callerFree);
2758         ok(ret, "CryptAcquireCertificatePrivateKey failed: %08x\n",
2759          GetLastError());
2760         ok(callerFree, "Expected callerFree to be TRUE\n");
2761         CryptReleaseContext(certCSP, 0);
2762
2763         /* Cache it (and check that it's cached) */
2764         ret = CryptAcquireCertificatePrivateKey(cert,
2765          CRYPT_ACQUIRE_CACHE_FLAG, NULL, &certCSP, &keySpec, &callerFree);
2766         ok(ret, "CryptAcquireCertificatePrivateKey failed: %08x\n",
2767          GetLastError());
2768         ok(!callerFree, "Expected callerFree to be FALSE\n");
2769         size = sizeof(keyContext);
2770         ret = CertGetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID,
2771          &keyContext, &size);
2772         ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
2773          GetLastError());
2774
2775         /* Remove the cached provider */
2776         CryptReleaseContext(keyContext.hCryptProv, 0);
2777         CertSetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID, 0,
2778          NULL);
2779         /* Allow caching via the key prov info */
2780         keyProvInfo.dwFlags = CERT_SET_KEY_CONTEXT_PROP_ID;
2781         CertSetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, 0,
2782          &keyProvInfo);
2783         /* Now use the key prov info's caching */
2784         ret = CryptAcquireCertificatePrivateKey(cert,
2785          CRYPT_ACQUIRE_USE_PROV_INFO_FLAG, NULL, &certCSP, &keySpec,
2786          &callerFree);
2787         ok(ret, "CryptAcquireCertificatePrivateKey failed: %08x\n",
2788          GetLastError());
2789         ok(!callerFree, "Expected callerFree to be FALSE\n");
2790         size = sizeof(keyContext);
2791         ret = CertGetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID,
2792          &keyContext, &size);
2793         ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
2794          GetLastError());
2795
2796         CryptDestroyKey(key);
2797     }
2798
2799     /* Some sanity-checking on public key exporting */
2800     ret = CryptImportPublicKeyInfo(csp, X509_ASN_ENCODING,
2801      &cert->pCertInfo->SubjectPublicKeyInfo, &key);
2802     ok(ret, "CryptImportPublicKeyInfo failed: %08x\n", GetLastError());
2803     if (ret)
2804     {
2805         ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &size);
2806         ok(ret, "CryptExportKey failed: %08x\n", GetLastError());
2807         if (ret)
2808         {
2809             LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, size), encodedKey;
2810
2811             ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, buf, &size);
2812             ok(ret, "CryptExportKey failed: %08x\n", GetLastError());
2813             ok(size == sizeof(exportedPublicKeyBlob), "Unexpected size %d\n",
2814              size);
2815             ok(!memcmp(buf, exportedPublicKeyBlob, size), "Unexpected value\n");
2816             ret = CryptEncodeObjectEx(X509_ASN_ENCODING, RSA_CSP_PUBLICKEYBLOB,
2817              buf, CRYPT_ENCODE_ALLOC_FLAG, NULL, &encodedKey, &size);
2818             ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2819             if (ret)
2820             {
2821                 ok(size == sizeof(asnEncodedPublicKey), "Unexpected size %d\n",
2822                  size);
2823                 ok(!memcmp(encodedKey, asnEncodedPublicKey, size),
2824                  "Unexpected value\n");
2825                 LocalFree(encodedKey);
2826             }
2827             HeapFree(GetProcessHeap(), 0, buf);
2828         }
2829         CryptDestroyKey(key);
2830     }
2831     ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
2832      NULL, 0, NULL, NULL, &size);
2833     ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
2834     if (ret)
2835     {
2836         PCERT_PUBLIC_KEY_INFO info = HeapAlloc(GetProcessHeap(), 0, size);
2837
2838         ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
2839          NULL, 0, NULL, info, &size);
2840         ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
2841         if (ret)
2842         {
2843             ok(info->PublicKey.cbData == sizeof(asnEncodedPublicKey),
2844              "Unexpected size %d\n", info->PublicKey.cbData);
2845             ok(!memcmp(info->PublicKey.pbData, asnEncodedPublicKey,
2846              info->PublicKey.cbData), "Unexpected value\n");
2847         }
2848         HeapFree(GetProcessHeap(), 0, info);
2849     }
2850
2851     CryptReleaseContext(csp, 0);
2852     pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
2853      CRYPT_DELETEKEYSET);
2854
2855     CertFreeCertificateContext(cert);
2856 }
2857
2858 static void testGetPublicKeyLength(void)
2859 {
2860     static char oid_rsa_rsa[] = szOID_RSA_RSA;
2861     static char oid_rsa_dh[] = szOID_RSA_DH;
2862     static char bogusOID[] = "1.2.3";
2863     DWORD ret;
2864     CERT_PUBLIC_KEY_INFO info = { { 0 } };
2865     BYTE bogusKey[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
2866     BYTE key[] = { 0x30,0x0f,0x02,0x08,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
2867      0x02,0x03,0x01,0x00,0x01 };
2868
2869     /* Crashes
2870     ret = CertGetPublicKeyLength(0, NULL);
2871      */
2872     /* With an empty public key info */
2873     SetLastError(0xdeadbeef);
2874     ret = CertGetPublicKeyLength(0, &info);
2875     ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
2876      "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
2877      ret, GetLastError());
2878     SetLastError(0xdeadbeef);
2879     ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
2880     ok(ret == 0 && GetLastError() == CRYPT_E_ASN1_EOD,
2881      "Expected length 0 and CRYPT_E_ASN1_EOD, got length %d, %08x\n",
2882      ret, GetLastError());
2883     /* With a nearly-empty public key info */
2884     info.Algorithm.pszObjId = oid_rsa_rsa;
2885     SetLastError(0xdeadbeef);
2886     ret = CertGetPublicKeyLength(0, &info);
2887     ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
2888      "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
2889      ret, GetLastError());
2890     SetLastError(0xdeadbeef);
2891     ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
2892     ok(ret == 0 && GetLastError() == CRYPT_E_ASN1_EOD,
2893      "Expected length 0 and CRYPT_E_ASN1_EOD, got length %d, %08x\n",
2894      ret, GetLastError());
2895     /* With a bogus key */
2896     info.PublicKey.cbData = sizeof(bogusKey);
2897     info.PublicKey.pbData = bogusKey;
2898     SetLastError(0xdeadbeef);
2899     ret = CertGetPublicKeyLength(0, &info);
2900     ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
2901      "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
2902      ret, GetLastError());
2903     SetLastError(0xdeadbeef);
2904     ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
2905     ok(ret == 0 && GetLastError() == CRYPT_E_ASN1_BADTAG,
2906      "Expected length 0 and CRYPT_E_ASN1_BADTAGTAG, got length %d, %08x\n",
2907      ret, GetLastError());
2908     /* With a believable RSA key but a bogus OID */
2909     info.Algorithm.pszObjId = bogusOID;
2910     info.PublicKey.cbData = sizeof(key);
2911     info.PublicKey.pbData = key;
2912     SetLastError(0xdeadbeef);
2913     ret = CertGetPublicKeyLength(0, &info);
2914     ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
2915      "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
2916      ret, GetLastError());
2917     SetLastError(0xdeadbeef);
2918     ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
2919     ok(ret == 56, "Expected length 56, got %d\n", ret);
2920     /* An RSA key with the DH OID */
2921     info.Algorithm.pszObjId = oid_rsa_dh;
2922     SetLastError(0xdeadbeef);
2923     ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
2924     ok(ret == 0 && GetLastError() == CRYPT_E_ASN1_BADTAG,
2925      "Expected length 0 and CRYPT_E_ASN1_BADTAG, got length %d, %08x\n",
2926      ret, GetLastError());
2927     /* With the RSA OID */
2928     info.Algorithm.pszObjId = oid_rsa_rsa;
2929     SetLastError(0xdeadbeef);
2930     ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
2931     ok(ret == 56, "Expected length 56, got %d\n", ret);
2932 }
2933
2934 START_TEST(cert)
2935 {
2936     init_function_pointers();
2937
2938     testAddCert();
2939     testCertProperties();
2940     testDupCert();
2941     testFindCert();
2942     testGetSubjectCert();
2943     testGetIssuerCert();
2944
2945     testCryptHashCert();
2946     testCertSigs();
2947     testSignAndEncodeCert();
2948     testCreateSelfSignCert();
2949     testKeyUsage();
2950     testGetValidUsages();
2951     testCompareCertName();
2952     testCompareIntegerBlob();
2953     testComparePublicKeyInfo();
2954     testHashPublicKeyInfo();
2955     testCompareCert();
2956     testVerifySubjectCert();
2957     testVerifyRevocation();
2958     testAcquireCertPrivateKey();
2959     testGetPublicKeyLength();
2960 }