wintrust: Use a helper function to get a signer's cert info from a message.
[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
1224 static void testGetIssuerCert(void)
1225 {
1226     BOOL ret;
1227     PCCERT_CONTEXT parent, child;
1228     DWORD flags = 0xffffffff;
1229     HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1230      CERT_STORE_CREATE_NEW_FLAG, NULL);
1231
1232     ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1233
1234     ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1235      expiredCert, sizeof(expiredCert), CERT_STORE_ADD_ALWAYS, NULL);
1236     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1237      GetLastError());
1238
1239     ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1240      childOfExpired, sizeof(childOfExpired), CERT_STORE_ADD_ALWAYS, &child);
1241     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1242      GetLastError());
1243
1244     /* These crash:
1245     parent = CertGetIssuerCertificateFromStore(NULL, NULL, NULL, NULL);
1246     parent = CertGetIssuerCertificateFromStore(store, NULL, NULL, NULL);
1247      */
1248     parent = CertGetIssuerCertificateFromStore(NULL, NULL, NULL, &flags);
1249     ok(!parent && GetLastError() == E_INVALIDARG,
1250      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1251     parent = CertGetIssuerCertificateFromStore(store, NULL, NULL, &flags);
1252     ok(!parent && GetLastError() == E_INVALIDARG,
1253      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1254     parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1255     ok(!parent && GetLastError() == E_INVALIDARG,
1256      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1257     /* Confusing: the caller cannot set either of the
1258      * CERT_STORE_NO_*_FLAGs, as these are not checks,
1259      * they're results:
1260      */
1261     flags = CERT_STORE_NO_CRL_FLAG | CERT_STORE_NO_ISSUER_FLAG;
1262     parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1263     ok(!parent && GetLastError() == E_INVALIDARG,
1264      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1265     /* Perform no checks */
1266     flags = 0;
1267     parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1268     ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08x\n",
1269      GetLastError());
1270     if (parent)
1271         CertFreeCertificateContext(parent);
1272     /* Check revocation and signature only */
1273     flags = CERT_STORE_REVOCATION_FLAG | CERT_STORE_SIGNATURE_FLAG;
1274     parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1275     ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08x\n",
1276      GetLastError());
1277     /* Confusing: CERT_STORE_REVOCATION_FLAG succeeds when there is no CRL by
1278      * setting CERT_STORE_NO_CRL_FLAG.
1279      */
1280     ok(flags == (CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG),
1281      "Expected CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG, got %08x\n",
1282      flags);
1283     if (parent)
1284         CertFreeCertificateContext(parent);
1285     /* Now check just the time */
1286     flags = CERT_STORE_TIME_VALIDITY_FLAG;
1287     parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1288     ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08x\n",
1289      GetLastError());
1290     /* Oops: the child is not expired, so the time validity check actually
1291      * succeeds, even though the signing cert is expired.
1292      */
1293     ok(!flags, "Expected check to succeed, got %08x\n", flags);
1294     if (parent)
1295         CertFreeCertificateContext(parent);
1296
1297     CertFreeCertificateContext(child);
1298     CertCloseStore(store, 0);
1299 }
1300
1301 static void testCryptHashCert(void)
1302 {
1303     static const BYTE emptyHash[] = { 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b,
1304      0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07,
1305      0x09 };
1306     static const BYTE knownHash[] = { 0xae, 0x9d, 0xbf, 0x6d, 0xf5, 0x46, 0xee,
1307      0x8b, 0xc5, 0x7a, 0x13, 0xba, 0xc2, 0xb1, 0x04, 0xf2, 0xbf, 0x52, 0xa8,
1308      0xa2 };
1309     static const BYTE toHash[] = "abcdefghijklmnopqrstuvwxyz0123456789.,;!?:";
1310     BOOL ret;
1311     BYTE hash[20];
1312     DWORD hashLen = sizeof(hash);
1313
1314     /* NULL buffer and nonzero length crashes
1315     ret = CryptHashCertificate(0, 0, 0, NULL, size, hash, &hashLen);
1316        empty hash length also crashes
1317     ret = CryptHashCertificate(0, 0, 0, buf, size, hash, NULL);
1318      */
1319     /* Test empty hash */
1320     ret = CryptHashCertificate(0, 0, 0, toHash, sizeof(toHash), NULL,
1321      &hashLen);
1322     ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
1323     ok(hashLen == sizeof(hash), "Got unexpected size of hash %d\n", hashLen);
1324     /* Test with empty buffer */
1325     ret = CryptHashCertificate(0, 0, 0, NULL, 0, hash, &hashLen);
1326     ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
1327     ok(!memcmp(hash, emptyHash, sizeof(emptyHash)),
1328      "Unexpected hash of nothing\n");
1329     /* Test a known value */
1330     ret = CryptHashCertificate(0, 0, 0, toHash, sizeof(toHash), hash,
1331      &hashLen);
1332     ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
1333     ok(!memcmp(hash, knownHash, sizeof(knownHash)), "Unexpected hash\n");
1334 }
1335
1336 static void verifySig(HCRYPTPROV csp, const BYTE *toSign, size_t toSignLen,
1337  const BYTE *sig, unsigned int sigLen)
1338 {
1339     HCRYPTHASH hash;
1340     BOOL ret = CryptCreateHash(csp, CALG_SHA1, 0, 0, &hash);
1341
1342     ok(ret, "CryptCreateHash failed: %08x\n", GetLastError());
1343     if (ret)
1344     {
1345         BYTE mySig[64];
1346         DWORD mySigSize = sizeof(mySig);
1347
1348         ret = CryptHashData(hash, toSign, toSignLen, 0);
1349         ok(ret, "CryptHashData failed: %08x\n", GetLastError());
1350         /* use the A variant so the test can run on Win9x */
1351         ret = CryptSignHashA(hash, AT_SIGNATURE, NULL, 0, mySig, &mySigSize);
1352         ok(ret, "CryptSignHash failed: %08x\n", GetLastError());
1353         if (ret)
1354         {
1355             ok(mySigSize == sigLen, "Expected sig length %d, got %d\n",
1356              sigLen, mySigSize);
1357             ok(!memcmp(mySig, sig, sigLen), "Unexpected signature\n");
1358         }
1359         CryptDestroyHash(hash);
1360     }
1361 }
1362
1363 /* Tests signing the certificate described by toBeSigned with the CSP passed in,
1364  * using the algorithm with OID sigOID.  The CSP is assumed to be empty, and a
1365  * keyset named AT_SIGNATURE will be added to it.  The signing key will be
1366  * stored in *key, and the signature will be stored in sig.  sigLen should be
1367  * at least 64 bytes.
1368  */
1369 static void testSignCert(HCRYPTPROV csp, const CRYPT_DATA_BLOB *toBeSigned,
1370  LPCSTR sigOID, HCRYPTKEY *key, BYTE *sig, DWORD *sigLen)
1371 {
1372     BOOL ret;
1373     DWORD size = 0;
1374     CRYPT_ALGORITHM_IDENTIFIER algoID = { NULL, { 0, NULL } };
1375
1376     /* These all crash
1377     ret = CryptSignCertificate(0, 0, 0, NULL, 0, NULL, NULL, NULL, NULL);
1378     ret = CryptSignCertificate(0, 0, 0, NULL, 0, NULL, NULL, NULL, &size);
1379     ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
1380      NULL, NULL, NULL, &size);
1381      */
1382     ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
1383      &algoID, NULL, NULL, &size);
1384     ok(!ret && GetLastError() == NTE_BAD_ALGID, 
1385      "Expected NTE_BAD_ALGID, got %08x\n", GetLastError());
1386     algoID.pszObjId = (LPSTR)sigOID;
1387     ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
1388      &algoID, NULL, NULL, &size);
1389     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1390      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1391     ret = CryptSignCertificate(0, AT_SIGNATURE, 0, toBeSigned->pbData,
1392      toBeSigned->cbData, &algoID, NULL, NULL, &size);
1393     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1394      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1395
1396     /* No keys exist in the new CSP yet.. */
1397     ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
1398      toBeSigned->cbData, &algoID, NULL, NULL, &size);
1399     ok(!ret && (GetLastError() == NTE_BAD_KEYSET || GetLastError() ==
1400      NTE_NO_KEY), "Expected NTE_BAD_KEYSET or NTE_NO_KEY, got %08x\n",
1401      GetLastError());
1402     ret = CryptGenKey(csp, AT_SIGNATURE, 0, key);
1403     ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
1404     if (ret)
1405     {
1406         ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
1407          toBeSigned->cbData, &algoID, NULL, NULL, &size);
1408         ok(ret, "CryptSignCertificate failed: %08x\n", GetLastError());
1409         ok(size <= *sigLen, "Expected size <= %d, got %d\n", *sigLen, size);
1410         if (ret)
1411         {
1412             ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
1413              toBeSigned->cbData, &algoID, NULL, sig, &size);
1414             ok(ret, "CryptSignCertificate failed: %08x\n", GetLastError());
1415             if (ret)
1416             {
1417                 *sigLen = size;
1418                 verifySig(csp, toBeSigned->pbData, toBeSigned->cbData, sig,
1419                  size);
1420             }
1421         }
1422     }
1423 }
1424
1425 static void testVerifyCertSig(HCRYPTPROV csp, const CRYPT_DATA_BLOB *toBeSigned,
1426  LPCSTR sigOID, const BYTE *sig, DWORD sigLen)
1427 {
1428     CERT_SIGNED_CONTENT_INFO info;
1429     LPBYTE cert = NULL;
1430     DWORD size = 0;
1431     BOOL ret;
1432
1433     if (!pCryptVerifyCertificateSignatureEx)
1434     {
1435         skip("no CryptVerifyCertificateSignatureEx support\n");
1436         return;
1437     }
1438     ret = pCryptVerifyCertificateSignatureEx(0, 0, 0, NULL, 0, NULL, 0, NULL);
1439     ok(!ret && GetLastError() == E_INVALIDARG,
1440      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1441     ret = pCryptVerifyCertificateSignatureEx(csp, 0, 0, NULL, 0, NULL, 0, NULL);
1442     ok(!ret && GetLastError() == E_INVALIDARG,
1443      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1444     ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING, 0, NULL, 0,
1445      NULL, 0, NULL);
1446     ok(!ret && GetLastError() == E_INVALIDARG,
1447      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1448     /* This crashes
1449     ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1450      CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, NULL, 0, NULL, 0, NULL);
1451      */
1452     info.ToBeSigned.cbData = toBeSigned->cbData;
1453     info.ToBeSigned.pbData = toBeSigned->pbData;
1454     info.SignatureAlgorithm.pszObjId = (LPSTR)sigOID;
1455     info.SignatureAlgorithm.Parameters.cbData = 0;
1456     info.Signature.cbData = sigLen;
1457     info.Signature.pbData = (BYTE *)sig;
1458     info.Signature.cUnusedBits = 0;
1459     ret = CryptEncodeObjectEx(X509_ASN_ENCODING, X509_CERT, &info,
1460      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&cert, &size);
1461     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1462     if (cert)
1463     {
1464         CRYPT_DATA_BLOB certBlob = { 0, NULL };
1465         PCERT_PUBLIC_KEY_INFO pubKeyInfo = NULL;
1466
1467         ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1468          CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
1469         ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
1470          "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
1471         certBlob.cbData = 1;
1472         certBlob.pbData = (void *)0xdeadbeef;
1473         ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1474          CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
1475         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1476          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1477         certBlob.cbData = size;
1478         certBlob.pbData = cert;
1479         ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1480          CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
1481         ok(!ret && GetLastError() == E_INVALIDARG,
1482          "Expected E_INVALIDARG, got %08x\n", GetLastError());
1483         ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1484          CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
1485          CRYPT_VERIFY_CERT_SIGN_ISSUER_NULL, NULL, 0, NULL);
1486         ok(!ret && GetLastError() == E_INVALIDARG,
1487          "Expected E_INVALIDARG, got %08x\n", GetLastError());
1488         /* This crashes
1489         ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1490          CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
1491          CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY, NULL, 0, NULL);
1492          */
1493         CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
1494          (LPSTR)sigOID, 0, NULL, NULL, &size);
1495         pubKeyInfo = HeapAlloc(GetProcessHeap(), 0, size);
1496         if (pubKeyInfo)
1497         {
1498             ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
1499              X509_ASN_ENCODING, (LPSTR)sigOID, 0, NULL, pubKeyInfo, &size);
1500             ok(ret, "CryptExportKey failed: %08x\n", GetLastError());
1501             if (ret)
1502             {
1503                 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1504                  CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
1505                  CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY, pubKeyInfo, 0, NULL);
1506                 ok(ret, "CryptVerifyCertificateSignatureEx failed: %08x\n",
1507                  GetLastError());
1508             }
1509             HeapFree(GetProcessHeap(), 0, pubKeyInfo);
1510         }
1511         LocalFree(cert);
1512     }
1513 }
1514
1515 static BYTE emptyCert[] = { 0x30, 0x00 };
1516
1517 static void testCertSigs(void)
1518 {
1519     HCRYPTPROV csp;
1520     CRYPT_DATA_BLOB toBeSigned = { sizeof(emptyCert), emptyCert };
1521     BOOL ret;
1522     HCRYPTKEY key;
1523     BYTE sig[64];
1524     DWORD sigSize = sizeof(sig);
1525
1526     /* Just in case a previous run failed, delete this thing */
1527     pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1528      CRYPT_DELETEKEYSET);
1529     ret = pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1530      CRYPT_NEWKEYSET);
1531     ok(ret, "CryptAcquireContext failed: %08x\n", GetLastError());
1532
1533     testSignCert(csp, &toBeSigned, szOID_RSA_SHA1RSA, &key, sig, &sigSize);
1534     testVerifyCertSig(csp, &toBeSigned, szOID_RSA_SHA1RSA, sig, sigSize);
1535
1536     CryptDestroyKey(key);
1537     CryptReleaseContext(csp, 0);
1538     ret = pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1539      CRYPT_DELETEKEYSET);
1540 }
1541
1542 static const BYTE md5SignedEmptyCert[] = {
1543 0x30,0x56,0x30,0x33,0x02,0x00,0x30,0x02,0x06,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,
1544 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,
1545 0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x07,
1546 0x30,0x02,0x06,0x00,0x03,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,
1547 0x0d,0x02,0x05,0x05,0x00,0x03,0x11,0x00,0xfb,0x0f,0x66,0x82,0x66,0xd9,0xe5,0xf8,
1548 0xd8,0xa2,0x55,0x2b,0xe1,0xa5,0xd9,0x04 };
1549 static const BYTE md5SignedEmptyCertNoNull[] = {
1550 0x30,0x54,0x30,0x33,0x02,0x00,0x30,0x02,0x06,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,
1551 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,
1552 0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x07,
1553 0x30,0x02,0x06,0x00,0x03,0x01,0x00,0x30,0x0a,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,
1554 0x0d,0x02,0x05,0x03,0x11,0x00,0x04,0xd9,0xa5,0xe1,0x2b,0x55,0xa2,0xd8,0xf8,0xe5,
1555 0xd9,0x66,0x82,0x66,0x0f,0xfb };
1556
1557 static void testSignAndEncodeCert(void)
1558 {
1559     static char oid_rsa_md5rsa[] = szOID_RSA_MD5RSA;
1560     static char oid_rsa_md5[] = szOID_RSA_MD5;
1561     BOOL ret;
1562     DWORD size;
1563     CRYPT_ALGORITHM_IDENTIFIER algID = { 0 };
1564     CERT_INFO info = { 0 };
1565
1566     /* Crash
1567     ret = CryptSignAndEncodeCertificate(0, 0, 0, NULL, NULL, NULL, NULL, NULL,
1568      NULL);
1569     ret = CryptSignAndEncodeCertificate(0, 0, 0, NULL, NULL, NULL, NULL, NULL,
1570      &size);
1571      */
1572     ret = CryptSignAndEncodeCertificate(0, 0, 0, NULL, NULL, &algID, NULL, NULL,
1573      &size);
1574     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1575      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1576     ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING, NULL, NULL,
1577      &algID, NULL, NULL, &size);
1578     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1579      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1580     ret = CryptSignAndEncodeCertificate(0, 0, 0, X509_CERT_TO_BE_SIGNED, NULL,
1581      &algID, NULL, NULL, &size);
1582     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1583      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1584     ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1585      X509_CERT_TO_BE_SIGNED, NULL, &algID, NULL, NULL, &size);
1586     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1587      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1588     /* Crashes
1589     ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1590      X509_CERT_TO_BE_SIGNED, &info, NULL, NULL, NULL, &size);
1591      */
1592     ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1593      X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, NULL, &size);
1594     ok(!ret && GetLastError() == NTE_BAD_ALGID,
1595      "Expected NTE_BAD_ALGID, got %08x\n", GetLastError());
1596     algID.pszObjId = oid_rsa_md5rsa;
1597     ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1598      X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, NULL, &size);
1599     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1600      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1601     algID.pszObjId = oid_rsa_md5;
1602     ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1603      X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, NULL, &size);
1604     ok(ret, "CryptSignAndEncodeCertificate failed: %08x\n", GetLastError());
1605     if (ret)
1606     {
1607         LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, size);
1608
1609         if (buf)
1610         {
1611             ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1612              X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, buf, &size);
1613             ok(ret, "CryptSignAndEncodeCertificate failed: %08x\n",
1614              GetLastError());
1615             /* Tricky: because the NULL parameters may either be omitted or
1616              * included as an asn.1-encoded NULL (0x05,0x00), two different
1617              * values are allowed.
1618              */
1619             ok(size == sizeof(md5SignedEmptyCert) ||
1620              size == sizeof(md5SignedEmptyCertNoNull), "Unexpected size %d\n",
1621              size);
1622             if (size == sizeof(md5SignedEmptyCert))
1623                 ok(!memcmp(buf, md5SignedEmptyCert, size),
1624                  "Unexpected value\n");
1625             else if (size == sizeof(md5SignedEmptyCertNoNull))
1626                 ok(!memcmp(buf, md5SignedEmptyCertNoNull, size),
1627                  "Unexpected value\n");
1628             HeapFree(GetProcessHeap(), 0, buf);
1629         }
1630     }
1631 }
1632
1633 static void testCreateSelfSignCert(void)
1634 {
1635     PCCERT_CONTEXT context;
1636     CERT_NAME_BLOB name = { sizeof(subjectName), subjectName };
1637     HCRYPTPROV csp;
1638     BOOL ret;
1639     HCRYPTKEY key;
1640     CRYPT_KEY_PROV_INFO info;
1641
1642     /* This crashes:
1643     context = CertCreateSelfSignCertificate(0, NULL, 0, NULL, NULL, NULL, NULL,
1644      NULL);
1645      * Calling this with no first parameter creates a new key container, which
1646      * lasts beyond the test, so I don't test that.  Nb: the generated key
1647      * name is a GUID.
1648     context = CertCreateSelfSignCertificate(0, &name, 0, NULL, NULL, NULL, NULL,
1649      NULL);
1650      */
1651
1652     /* Acquire a CSP */
1653     pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1654      CRYPT_DELETEKEYSET);
1655     ret = pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1656      CRYPT_NEWKEYSET);
1657     ok(ret, "CryptAcquireContext failed: %08x\n", GetLastError());
1658
1659     context = CertCreateSelfSignCertificate(csp, &name, 0, NULL, NULL, NULL,
1660      NULL, NULL);
1661     ok(!context && GetLastError() == NTE_NO_KEY,
1662      "Expected NTE_NO_KEY, got %08x\n", GetLastError());
1663     ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
1664     ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
1665     if (ret)
1666     {
1667         context = CertCreateSelfSignCertificate(csp, &name, 0, NULL, NULL, NULL,
1668          NULL, NULL);
1669         ok(context != NULL, "CertCreateSelfSignCertificate failed: %08x\n",
1670          GetLastError());
1671         if (context)
1672         {
1673             DWORD size = 0;
1674             PCRYPT_KEY_PROV_INFO info;
1675
1676             /* The context must have a key provider info property */
1677             ret = CertGetCertificateContextProperty(context,
1678              CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
1679             ok(ret && size, "Expected non-zero key provider info\n");
1680             if (size)
1681             {
1682                 info = HeapAlloc(GetProcessHeap(), 0, size);
1683                 if (info)
1684                 {
1685                     ret = CertGetCertificateContextProperty(context,
1686                      CERT_KEY_PROV_INFO_PROP_ID, info, &size);
1687                     ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
1688                      GetLastError());
1689                     if (ret)
1690                     {
1691                         /* Sanity-check the key provider */
1692                         ok(!lstrcmpW(info->pwszContainerName, cspNameW),
1693                          "Unexpected key container\n");
1694                         ok(!lstrcmpW(info->pwszProvName, MS_DEF_PROV_W),
1695                          "Unexpected provider\n");
1696                         ok(info->dwKeySpec == AT_SIGNATURE,
1697                          "Expected AT_SIGNATURE, got %d\n", info->dwKeySpec);
1698                     }
1699                     HeapFree(GetProcessHeap(), 0, info);
1700                 }
1701             }
1702
1703             CertFreeCertificateContext(context);
1704         }
1705
1706         CryptDestroyKey(key);
1707     }
1708
1709     CryptReleaseContext(csp, 0);
1710     ret = pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1711      CRYPT_DELETEKEYSET);
1712
1713     /* do the same test with AT_KEYEXCHANGE  and key info*/
1714     memset(&info,0,sizeof(info));
1715     info.dwProvType = PROV_RSA_FULL;
1716     info.dwKeySpec = AT_KEYEXCHANGE;
1717     info.pwszProvName = (LPWSTR) MS_DEF_PROV_W;
1718     info.pwszContainerName = cspNameW;
1719     context = CertCreateSelfSignCertificate(0, &name, 0, &info, NULL, NULL,
1720         NULL, NULL);
1721     ok(context != NULL, "CertCreateSelfSignCertificate failed: %08x\n",
1722         GetLastError());
1723     if (context)
1724     {
1725         DWORD size = 0;
1726         PCRYPT_KEY_PROV_INFO info;
1727
1728         /* The context must have a key provider info property */
1729         ret = CertGetCertificateContextProperty(context,
1730             CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
1731         ok(ret && size, "Expected non-zero key provider info\n");
1732         if (size)
1733         {
1734             info = HeapAlloc(GetProcessHeap(), 0, size);
1735             if (info)
1736             {
1737                 ret = CertGetCertificateContextProperty(context,
1738                     CERT_KEY_PROV_INFO_PROP_ID, info, &size);
1739                 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
1740                     GetLastError());
1741                 if (ret)
1742                 {
1743                     /* Sanity-check the key provider */
1744                     ok(!lstrcmpW(info->pwszContainerName, cspNameW),
1745                         "Unexpected key container\n");
1746                     ok(!lstrcmpW(info->pwszProvName, MS_DEF_PROV_W),
1747                         "Unexpected provider\n");
1748                     ok(info->dwKeySpec == AT_KEYEXCHANGE,
1749                         "Expected AT_KEYEXCHANGE, got %d\n", info->dwKeySpec);
1750                 }
1751                 HeapFree(GetProcessHeap(), 0, info);
1752             }
1753         }
1754
1755         CertFreeCertificateContext(context);
1756     }
1757
1758     pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1759         CRYPT_DELETEKEYSET);
1760 }
1761
1762 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
1763  szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
1764
1765 static void testKeyUsage(void)
1766 {
1767     BOOL ret;
1768     PCCERT_CONTEXT context;
1769     DWORD size;
1770
1771     /* Test base cases */
1772     ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, NULL);
1773     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1774      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1775     size = 1;
1776     ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, &size);
1777     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1778      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1779     size = 0;
1780     ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, &size);
1781     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1782      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1783     /* These crash
1784     ret = CertSetEnhancedKeyUsage(NULL, NULL);
1785     usage.cUsageIdentifier = 0;
1786     ret = CertSetEnhancedKeyUsage(NULL, &usage);
1787      */
1788     /* Test with a cert with no enhanced key usage extension */
1789     context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
1790      sizeof(bigCert));
1791     ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
1792      GetLastError());
1793     if (context)
1794     {
1795         static const char oid[] = "1.2.3.4";
1796         BYTE buf[sizeof(CERT_ENHKEY_USAGE) + 2 * (sizeof(LPSTR) + sizeof(oid))];
1797         PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1798
1799         ret = CertGetEnhancedKeyUsage(context, 0, NULL, NULL);
1800         ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1801          "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1802         size = 1;
1803         ret = CertGetEnhancedKeyUsage(context, 0, NULL, &size);
1804         if (ret)
1805         {
1806             /* Windows 2000, ME, or later: even though it succeeded, we expect
1807              * CRYPT_E_NOT_FOUND, which indicates there is no enhanced key
1808              * usage set for this cert (which implies it's valid for all uses.)
1809              */
1810             ok(GetLastError() == CRYPT_E_NOT_FOUND,
1811              "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1812             ok(size == sizeof(CERT_ENHKEY_USAGE), "Wrong size %d\n", size);
1813             ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1814             ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1815             ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %d\n",
1816              pUsage->cUsageIdentifier);
1817         }
1818         else
1819         {
1820             /* Windows NT, 95, or 98: it fails, and the last error is
1821              * CRYPT_E_NOT_FOUND.
1822              */
1823             ok(GetLastError() == CRYPT_E_NOT_FOUND,
1824              "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1825         }
1826         /* I can add a usage identifier when no key usage has been set */
1827         ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
1828         ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
1829          GetLastError());
1830         size = sizeof(buf);
1831         ret = CertGetEnhancedKeyUsage(context,
1832          CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1833         ok(ret && GetLastError() == 0,
1834          "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1835         ok(pUsage->cUsageIdentifier == 1, "Expected 1 usage, got %d\n",
1836          pUsage->cUsageIdentifier);
1837         if (pUsage->cUsageIdentifier)
1838             ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
1839              "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
1840         /* Now set an empty key usage */
1841         pUsage->cUsageIdentifier = 0;
1842         ret = CertSetEnhancedKeyUsage(context, pUsage);
1843         ok(ret, "CertSetEnhancedKeyUsage failed: %08x\n", GetLastError());
1844         /* Shouldn't find it in the cert */
1845         size = sizeof(buf);
1846         ret = CertGetEnhancedKeyUsage(context,
1847          CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1848         ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
1849          "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1850         /* Should find it as an extended property */
1851         ret = CertGetEnhancedKeyUsage(context,
1852          CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1853         ok(ret && GetLastError() == 0,
1854          "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1855         ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %d\n",
1856          pUsage->cUsageIdentifier);
1857         /* Should find it as either */
1858         ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1859         ok(ret && GetLastError() == 0,
1860          "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1861         ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %d\n",
1862          pUsage->cUsageIdentifier);
1863         /* Add a usage identifier */
1864         ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
1865         ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
1866          GetLastError());
1867         size = sizeof(buf);
1868         ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1869         ok(ret && GetLastError() == 0,
1870          "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1871         ok(pUsage->cUsageIdentifier == 1, "Expected 1 identifier, got %d\n",
1872          pUsage->cUsageIdentifier);
1873         if (pUsage->cUsageIdentifier)
1874             ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
1875              "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
1876         /* Yep, I can re-add the same usage identifier */
1877         ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
1878         ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
1879          GetLastError());
1880         size = sizeof(buf);
1881         ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1882         ok(ret && GetLastError() == 0,
1883          "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1884         ok(pUsage->cUsageIdentifier == 2, "Expected 2 identifiers, got %d\n",
1885          pUsage->cUsageIdentifier);
1886         if (pUsage->cUsageIdentifier)
1887             ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
1888              "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
1889         if (pUsage->cUsageIdentifier >= 2)
1890             ok(!strcmp(pUsage->rgpszUsageIdentifier[1], oid),
1891              "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[1]);
1892         /* Now set a NULL extended property--this deletes the property. */
1893         ret = CertSetEnhancedKeyUsage(context, NULL);
1894         ok(ret, "CertSetEnhancedKeyUsage failed: %08x\n", GetLastError());
1895         SetLastError(0xbaadcafe);
1896         size = sizeof(buf);
1897         ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1898         ok(GetLastError() == CRYPT_E_NOT_FOUND,
1899          "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1900
1901         CertFreeCertificateContext(context);
1902     }
1903     /* Now test with a cert with an enhanced key usage extension */
1904     context = CertCreateCertificateContext(X509_ASN_ENCODING, certWithUsage,
1905      sizeof(certWithUsage));
1906     ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
1907      GetLastError());
1908     if (context)
1909     {
1910         LPBYTE buf = NULL;
1911         DWORD bufSize = 0, i;
1912
1913         /* The size may depend on what flags are used to query it, so I
1914          * realloc the buffer for each test.
1915          */
1916         ret = CertGetEnhancedKeyUsage(context,
1917          CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, NULL, &bufSize);
1918         ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1919         buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
1920         if (buf)
1921         {
1922             PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1923
1924             /* Should find it in the cert */
1925             size = bufSize;
1926             ret = CertGetEnhancedKeyUsage(context,
1927              CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1928             ok(ret && GetLastError() == 0,
1929              "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1930             ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
1931              pUsage->cUsageIdentifier);
1932             for (i = 0; i < pUsage->cUsageIdentifier; i++)
1933                 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
1934                  "Expected %s, got %s\n", keyUsages[i],
1935                  pUsage->rgpszUsageIdentifier[i]);
1936             HeapFree(GetProcessHeap(), 0, buf);
1937         }
1938         ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
1939         ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1940         buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
1941         if (buf)
1942         {
1943             PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1944
1945             /* Should find it as either */
1946             size = bufSize;
1947             ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1948             /* In Windows, GetLastError returns CRYPT_E_NOT_FOUND not found
1949              * here, even though the return is successful and the usage id
1950              * count is positive.  I don't enforce that here.
1951              */
1952             ok(ret,
1953              "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1954             ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
1955              pUsage->cUsageIdentifier);
1956             for (i = 0; i < pUsage->cUsageIdentifier; i++)
1957                 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
1958                  "Expected %s, got %s\n", keyUsages[i],
1959                  pUsage->rgpszUsageIdentifier[i]);
1960             HeapFree(GetProcessHeap(), 0, buf);
1961         }
1962         /* Shouldn't find it as an extended property */
1963         ret = CertGetEnhancedKeyUsage(context,
1964          CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, NULL, &size);
1965         ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
1966          "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1967         /* Adding a usage identifier overrides the cert's usage!? */
1968         ret = CertAddEnhancedKeyUsageIdentifier(context, szOID_RSA_RSA);
1969         ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
1970          GetLastError());
1971         ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
1972         ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1973         buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
1974         if (buf)
1975         {
1976             PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1977
1978             /* Should find it as either */
1979             size = bufSize;
1980             ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1981             ok(ret,
1982              "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1983             ok(pUsage->cUsageIdentifier == 1, "Expected 1 usage, got %d\n",
1984              pUsage->cUsageIdentifier);
1985             ok(!strcmp(pUsage->rgpszUsageIdentifier[0], szOID_RSA_RSA),
1986              "Expected %s, got %s\n", szOID_RSA_RSA,
1987              pUsage->rgpszUsageIdentifier[0]);
1988             HeapFree(GetProcessHeap(), 0, buf);
1989         }
1990         /* But querying the cert directly returns its usage */
1991         ret = CertGetEnhancedKeyUsage(context,
1992          CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, NULL, &bufSize);
1993         ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1994         buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
1995         if (buf)
1996         {
1997             PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1998
1999             size = bufSize;
2000             ret = CertGetEnhancedKeyUsage(context,
2001              CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
2002             ok(ret,
2003              "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2004             ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
2005              pUsage->cUsageIdentifier);
2006             for (i = 0; i < pUsage->cUsageIdentifier; i++)
2007                 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
2008                  "Expected %s, got %s\n", keyUsages[i],
2009                  pUsage->rgpszUsageIdentifier[i]);
2010             HeapFree(GetProcessHeap(), 0, buf);
2011         }
2012         /* And removing the only usage identifier in the extended property
2013          * results in the cert's key usage being found.
2014          */
2015         ret = CertRemoveEnhancedKeyUsageIdentifier(context, szOID_RSA_RSA);
2016         ok(ret, "CertRemoveEnhancedKeyUsage failed: %08x\n", GetLastError());
2017         ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
2018         ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2019         buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
2020         if (buf)
2021         {
2022             PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
2023
2024             /* Should find it as either */
2025             size = bufSize;
2026             ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2027             ok(ret,
2028              "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2029             ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
2030              pUsage->cUsageIdentifier);
2031             for (i = 0; i < pUsage->cUsageIdentifier; i++)
2032                 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
2033                  "Expected %s, got %s\n", keyUsages[i],
2034                  pUsage->rgpszUsageIdentifier[i]);
2035             HeapFree(GetProcessHeap(), 0, buf);
2036         }
2037
2038         CertFreeCertificateContext(context);
2039     }
2040 }
2041
2042 static void testCompareCertName(void)
2043 {
2044     static BYTE bogus[] = { 1, 2, 3, 4 };
2045     static BYTE bogusPrime[] = { 0, 1, 2, 3, 4 };
2046     static BYTE emptyPrime[] = { 0x30, 0x00, 0x01 };
2047     BOOL ret;
2048     CERT_NAME_BLOB blob1, blob2;
2049
2050     /* crashes
2051     ret = CertCompareCertificateName(0, NULL, NULL);
2052      */
2053     /* An empty name checks against itself.. */
2054     blob1.pbData = emptyCert;
2055     blob1.cbData = sizeof(emptyCert);
2056     ret = CertCompareCertificateName(0, &blob1, &blob1);
2057     ok(ret, "CertCompareCertificateName failed: %08x\n", GetLastError());
2058     /* It doesn't have to be a valid encoded name.. */
2059     blob1.pbData = bogus;
2060     blob1.cbData = sizeof(bogus);
2061     ret = CertCompareCertificateName(0, &blob1, &blob1);
2062     ok(ret, "CertCompareCertificateName failed: %08x\n", GetLastError());
2063     /* Leading zeroes matter.. */
2064     blob2.pbData = bogusPrime;
2065     blob2.cbData = sizeof(bogusPrime);
2066     ret = CertCompareCertificateName(0, &blob1, &blob2);
2067     ok(!ret, "Expected failure\n");
2068     /* As do trailing extra bytes. */
2069     blob2.pbData = emptyPrime;
2070     blob2.cbData = sizeof(emptyPrime);
2071     ret = CertCompareCertificateName(0, &blob1, &blob2);
2072     ok(!ret, "Expected failure\n");
2073 }
2074
2075 static BYTE int1[] = { 0x88, 0xff, 0xff, 0xff };
2076 static BYTE int2[] = { 0x88, 0xff };
2077 static BYTE int3[] = { 0x23, 0xff };
2078 static BYTE int4[] = { 0x7f, 0x00 };
2079 static BYTE int5[] = { 0x7f };
2080 static BYTE int6[] = { 0x80, 0x00, 0x00, 0x00 };
2081 static BYTE int7[] = { 0x80, 0x00 };
2082
2083 static struct IntBlobTest
2084 {
2085     CRYPT_INTEGER_BLOB blob1;
2086     CRYPT_INTEGER_BLOB blob2;
2087     BOOL areEqual;
2088 } intBlobs[] = {
2089  { { sizeof(int1), int1 }, { sizeof(int2), int2 }, TRUE },
2090  { { sizeof(int3), int3 }, { sizeof(int3), int3 }, TRUE },
2091  { { sizeof(int4), int4 }, { sizeof(int5), int5 }, TRUE },
2092  { { sizeof(int6), int6 }, { sizeof(int7), int7 }, TRUE },
2093  { { sizeof(int1), int1 }, { sizeof(int7), int7 }, FALSE },
2094 };
2095
2096 static void testCompareIntegerBlob(void)
2097 {
2098     DWORD i;
2099     BOOL ret;
2100
2101     for (i = 0; i < sizeof(intBlobs) / sizeof(intBlobs[0]); i++)
2102     {
2103         ret = CertCompareIntegerBlob(&intBlobs[i].blob1, &intBlobs[i].blob2);
2104         ok(ret == intBlobs[i].areEqual,
2105          "%d: expected blobs %s compare\n", i, intBlobs[i].areEqual ?
2106          "to" : "not to");
2107     }
2108 }
2109
2110 static void testComparePublicKeyInfo(void)
2111 {
2112     BOOL ret;
2113     CERT_PUBLIC_KEY_INFO info1 = { { 0 } }, info2 = { { 0 } };
2114     static CHAR oid_rsa_rsa[]     = szOID_RSA_RSA;
2115     static CHAR oid_rsa_sha1rsa[] = szOID_RSA_SHA1RSA;
2116     static CHAR oid_x957_dsa[]    = szOID_X957_DSA;
2117     static BYTE bits1[] = { 1, 0 };
2118     static BYTE bits2[] = { 0 };
2119     static BYTE bits3[] = { 1 };
2120
2121     /* crashes
2122     ret = CertComparePublicKeyInfo(0, NULL, NULL);
2123      */
2124     /* Empty public keys compare */
2125     ret = CertComparePublicKeyInfo(0, &info1, &info2);
2126     ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
2127     /* Different OIDs appear to compare */
2128     info1.Algorithm.pszObjId = oid_rsa_rsa;
2129     info2.Algorithm.pszObjId = oid_rsa_sha1rsa;
2130     ret = CertComparePublicKeyInfo(0, &info1, &info2);
2131     ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
2132     info2.Algorithm.pszObjId = oid_x957_dsa;
2133     ret = CertComparePublicKeyInfo(0, &info1, &info2);
2134     ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
2135     info1.PublicKey.cbData = sizeof(bits1);
2136     info1.PublicKey.pbData = bits1;
2137     info1.PublicKey.cUnusedBits = 0;
2138     info2.PublicKey.cbData = sizeof(bits1);
2139     info2.PublicKey.pbData = bits1;
2140     info2.PublicKey.cUnusedBits = 0;
2141     ret = CertComparePublicKeyInfo(0, &info1, &info2);
2142     ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
2143     /* Even though they compare in their used bits, these do not compare */
2144     info1.PublicKey.cbData = sizeof(bits2);
2145     info1.PublicKey.pbData = bits2;
2146     info1.PublicKey.cUnusedBits = 0;
2147     info2.PublicKey.cbData = sizeof(bits3);
2148     info2.PublicKey.pbData = bits3;
2149     info2.PublicKey.cUnusedBits = 1;
2150     ret = CertComparePublicKeyInfo(0, &info1, &info2);
2151     /* Simple (non-comparing) case */
2152     ok(!ret, "Expected keys not to compare\n");
2153     info2.PublicKey.cbData = sizeof(bits1);
2154     info2.PublicKey.pbData = bits1;
2155     info2.PublicKey.cUnusedBits = 0;
2156     ret = CertComparePublicKeyInfo(0, &info1, &info2);
2157     ok(!ret, "Expected keys not to compare\n");
2158 }
2159
2160 static void testHashPublicKeyInfo(void)
2161 {
2162     BOOL ret;
2163     CERT_PUBLIC_KEY_INFO info = { { 0 } };
2164     DWORD len;
2165
2166     /* Crash
2167     ret = CryptHashPublicKeyInfo(0, 0, 0, 0, NULL, NULL, NULL);
2168     ret = CryptHashPublicKeyInfo(0, 0, 0, 0, &info, NULL, NULL);
2169      */
2170     ret = CryptHashPublicKeyInfo(0, 0, 0, 0, NULL, NULL, &len);
2171     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2172      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2173     ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, NULL, NULL, &len);
2174     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2175      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
2176     ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, &info, NULL, &len);
2177     ok(ret, "CryptHashPublicKeyInfo failed: %08x\n", GetLastError());
2178     ok(len == 16, "Expected hash size 16, got %d\n", len);
2179     if (len == 16)
2180     {
2181         static const BYTE emptyHash[] = { 0xb8,0x51,0x3a,0x31,0x0e,0x9f,0x40,
2182          0x36,0x9c,0x92,0x45,0x1b,0x9d,0xc8,0xf9,0xf6 };
2183         BYTE buf[16];
2184
2185         ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, &info, buf,
2186          &len);
2187         ok(ret, "CryptHashPublicKeyInfo failed: %08x\n", GetLastError());
2188         ok(!memcmp(buf, emptyHash, len), "Unexpected hash\n");
2189     }
2190 }
2191
2192 static void testCompareCert(void)
2193 {
2194     CERT_INFO info1 = { 0 }, info2 = { 0 };
2195     BOOL ret;
2196
2197     /* Crashes
2198     ret = CertCompareCertificate(X509_ASN_ENCODING, NULL, NULL);
2199      */
2200
2201     /* Certs with the same issuer and serial number are equal, even if they
2202      * differ in other respects (like subject).
2203      */
2204     info1.SerialNumber.pbData = serialNum;
2205     info1.SerialNumber.cbData = sizeof(serialNum);
2206     info1.Issuer.pbData = subjectName;
2207     info1.Issuer.cbData = sizeof(subjectName);
2208     info1.Subject.pbData = subjectName2;
2209     info1.Subject.cbData = sizeof(subjectName2);
2210     info2.SerialNumber.pbData = serialNum;
2211     info2.SerialNumber.cbData = sizeof(serialNum);
2212     info2.Issuer.pbData = subjectName;
2213     info2.Issuer.cbData = sizeof(subjectName);
2214     info2.Subject.pbData = subjectName;
2215     info2.Subject.cbData = sizeof(subjectName);
2216     ret = CertCompareCertificate(X509_ASN_ENCODING, &info1, &info2);
2217     ok(ret, "Expected certs to be equal\n");
2218
2219     info2.Issuer.pbData = subjectName2;
2220     info2.Issuer.cbData = sizeof(subjectName2);
2221     ret = CertCompareCertificate(X509_ASN_ENCODING, &info1, &info2);
2222     ok(!ret, "Expected certs not to be equal\n");
2223 }
2224
2225 static void testVerifySubjectCert(void)
2226 {
2227     BOOL ret;
2228     DWORD flags;
2229     PCCERT_CONTEXT context1, context2;
2230
2231     /* Crashes
2232     ret = CertVerifySubjectCertificateContext(NULL, NULL, NULL);
2233      */
2234     flags = 0;
2235     ret = CertVerifySubjectCertificateContext(NULL, NULL, &flags);
2236     ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
2237      GetLastError());
2238     flags = CERT_STORE_NO_CRL_FLAG;
2239     ret = CertVerifySubjectCertificateContext(NULL, NULL, &flags);
2240     ok(!ret && GetLastError() == E_INVALIDARG,
2241      "Expected E_INVALIDARG, got %08x\n", GetLastError());
2242
2243     flags = 0;
2244     context1 = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
2245      sizeof(bigCert));
2246     ret = CertVerifySubjectCertificateContext(NULL, context1, &flags);
2247     ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
2248      GetLastError());
2249     ret = CertVerifySubjectCertificateContext(context1, NULL, &flags);
2250     ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
2251      GetLastError());
2252     ret = CertVerifySubjectCertificateContext(context1, context1, &flags);
2253     ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
2254      GetLastError());
2255
2256     context2 = CertCreateCertificateContext(X509_ASN_ENCODING,
2257      bigCertWithDifferentSubject, sizeof(bigCertWithDifferentSubject));
2258     SetLastError(0xdeadbeef);
2259     ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
2260     ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
2261      GetLastError());
2262     flags = CERT_STORE_REVOCATION_FLAG;
2263     ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
2264     ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
2265      GetLastError());
2266     ok(flags == (CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG),
2267      "Expected CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG, got %08x\n",
2268      flags);
2269     flags = CERT_STORE_SIGNATURE_FLAG;
2270     ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
2271     ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
2272      GetLastError());
2273     ok(flags == CERT_STORE_SIGNATURE_FLAG,
2274      "Expected CERT_STORE_SIGNATURE_FLAG, got %08x\n", flags);
2275     CertFreeCertificateContext(context2);
2276
2277     CertFreeCertificateContext(context1);
2278 }
2279
2280 static BYTE privKey[] = {
2281  0x07, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x52, 0x53, 0x41, 0x32, 0x00,
2282  0x02, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x79, 0x10, 0x1c, 0xd0, 0x6b, 0x10,
2283  0x18, 0x30, 0x94, 0x61, 0xdc, 0x0e, 0xcb, 0x96, 0x4e, 0x21, 0x3f, 0x79, 0xcd,
2284  0xa9, 0x17, 0x62, 0xbc, 0xbb, 0x61, 0x4c, 0xe0, 0x75, 0x38, 0x6c, 0xf3, 0xde,
2285  0x60, 0x86, 0x03, 0x97, 0x65, 0xeb, 0x1e, 0x6b, 0xdb, 0x53, 0x85, 0xad, 0x68,
2286  0x21, 0xf1, 0x5d, 0xe7, 0x1f, 0xe6, 0x53, 0xb4, 0xbb, 0x59, 0x3e, 0x14, 0x27,
2287  0xb1, 0x83, 0xa7, 0x3a, 0x54, 0xe2, 0x8f, 0x65, 0x8e, 0x6a, 0x4a, 0xcf, 0x3b,
2288  0x1f, 0x65, 0xff, 0xfe, 0xf1, 0x31, 0x3a, 0x37, 0x7a, 0x8b, 0xcb, 0xc6, 0xd4,
2289  0x98, 0x50, 0x36, 0x67, 0xe4, 0xa1, 0xe8, 0x7e, 0x8a, 0xc5, 0x23, 0xf2, 0x77,
2290  0xf5, 0x37, 0x61, 0x49, 0x72, 0x59, 0xe8, 0x3d, 0xf7, 0x60, 0xb2, 0x77, 0xca,
2291  0x78, 0x54, 0x6d, 0x65, 0x9e, 0x03, 0x97, 0x1b, 0x61, 0xbd, 0x0c, 0xd8, 0x06,
2292  0x63, 0xe2, 0xc5, 0x48, 0xef, 0xb3, 0xe2, 0x6e, 0x98, 0x7d, 0xbd, 0x4e, 0x72,
2293  0x91, 0xdb, 0x31, 0x57, 0xe3, 0x65, 0x3a, 0x49, 0xca, 0xec, 0xd2, 0x02, 0x4e,
2294  0x22, 0x7e, 0x72, 0x8e, 0xf9, 0x79, 0x84, 0x82, 0xdf, 0x7b, 0x92, 0x2d, 0xaf,
2295  0xc9, 0xe4, 0x33, 0xef, 0x89, 0x5c, 0x66, 0x99, 0xd8, 0x80, 0x81, 0x47, 0x2b,
2296  0xb1, 0x66, 0x02, 0x84, 0x59, 0x7b, 0xc3, 0xbe, 0x98, 0x45, 0x4a, 0x3d, 0xdd,
2297  0xea, 0x2b, 0xdf, 0x4e, 0xb4, 0x24, 0x6b, 0xec, 0xe7, 0xd9, 0x0c, 0x45, 0xb8,
2298  0xbe, 0xca, 0x69, 0x37, 0x92, 0x4c, 0x38, 0x6b, 0x96, 0x6d, 0xcd, 0x86, 0x67,
2299  0x5c, 0xea, 0x54, 0x94, 0xa4, 0xca, 0xa4, 0x02, 0xa5, 0x21, 0x4d, 0xae, 0x40,
2300  0x8f, 0x9d, 0x51, 0x83, 0xf2, 0x3f, 0x33, 0xc1, 0x72, 0xb4, 0x1d, 0x94, 0x6e,
2301  0x7d, 0xe4, 0x27, 0x3f, 0xea, 0xff, 0xe5, 0x9b, 0xa7, 0x5e, 0x55, 0x8e, 0x0d,
2302  0x69, 0x1c, 0x7a, 0xff, 0x81, 0x9d, 0x53, 0x52, 0x97, 0x9a, 0x76, 0x79, 0xda,
2303  0x93, 0x32, 0x16, 0xec, 0x69, 0x51, 0x1a, 0x4e, 0xc3, 0xf1, 0x72, 0x80, 0x78,
2304  0x5e, 0x66, 0x4a, 0x8d, 0x85, 0x2f, 0x3f, 0xb2, 0xa7 };
2305
2306 static const BYTE selfSignedCert[] = {
2307  0x30, 0x82, 0x01, 0x1f, 0x30, 0x81, 0xce, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
2308  0x10, 0xeb, 0x0d, 0x57, 0x2a, 0x9c, 0x09, 0xba, 0xa4, 0x4a, 0xb7, 0x25, 0x49,
2309  0xd9, 0x3e, 0xb5, 0x73, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d,
2310  0x05, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
2311  0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30,
2312  0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x36, 0x32, 0x39, 0x30, 0x35, 0x30, 0x30,
2313  0x34, 0x36, 0x5a, 0x17, 0x0d, 0x30, 0x37, 0x30, 0x36, 0x32, 0x39, 0x31, 0x31,
2314  0x30, 0x30, 0x34, 0x36, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
2315  0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e,
2316  0x67, 0x00, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
2317  0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
2318  0x00, 0xe2, 0x54, 0x3a, 0xa7, 0x83, 0xb1, 0x27, 0x14, 0x3e, 0x59, 0xbb, 0xb4,
2319  0x53, 0xe6, 0x1f, 0xe7, 0x5d, 0xf1, 0x21, 0x68, 0xad, 0x85, 0x53, 0xdb, 0x6b,
2320  0x1e, 0xeb, 0x65, 0x97, 0x03, 0x86, 0x60, 0xde, 0xf3, 0x6c, 0x38, 0x75, 0xe0,
2321  0x4c, 0x61, 0xbb, 0xbc, 0x62, 0x17, 0xa9, 0xcd, 0x79, 0x3f, 0x21, 0x4e, 0x96,
2322  0xcb, 0x0e, 0xdc, 0x61, 0x94, 0x30, 0x18, 0x10, 0x6b, 0xd0, 0x1c, 0x10, 0x79,
2323  0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
2324  0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x25, 0x90, 0x53, 0x34, 0xd9, 0x56, 0x41,
2325  0x5e, 0xdb, 0x7e, 0x01, 0x36, 0xec, 0x27, 0x61, 0x5e, 0xb7, 0x4d, 0x90, 0x66,
2326  0xa2, 0xe1, 0x9d, 0x58, 0x76, 0xd4, 0x9c, 0xba, 0x2c, 0x84, 0xc6, 0x83, 0x7a,
2327  0x22, 0x0d, 0x03, 0x69, 0x32, 0x1a, 0x6d, 0xcb, 0x0c, 0x15, 0xb3, 0x6b, 0xc7,
2328  0x0a, 0x8c, 0xb4, 0x5c, 0x34, 0x78, 0xe0, 0x3c, 0x9c, 0xe9, 0xf3, 0x30, 0x9f,
2329  0xa8, 0x76, 0x57, 0x92, 0x36 };
2330
2331 static const BYTE exportedPublicKeyBlob[] = {
2332 0x06,0x02,0x00,0x00,0x00,0xa4,0x00,0x00,0x52,0x53,0x41,0x31,0x00,0x02,0x00,0x00,
2333 0x01,0x00,0x01,0x00,0x79,0x10,0x1c,0xd0,0x6b,0x10,0x18,0x30,0x94,0x61,0xdc,0x0e,
2334 0xcb,0x96,0x4e,0x21,0x3f,0x79,0xcd,0xa9,0x17,0x62,0xbc,0xbb,0x61,0x4c,0xe0,0x75,
2335 0x38,0x6c,0xf3,0xde,0x60,0x86,0x03,0x97,0x65,0xeb,0x1e,0x6b,0xdb,0x53,0x85,0xad,
2336 0x68,0x21,0xf1,0x5d,0xe7,0x1f,0xe6,0x53,0xb4,0xbb,0x59,0x3e,0x14,0x27,0xb1,0x83,
2337 0xa7,0x3a,0x54,0xe2 };
2338
2339 static const BYTE asnEncodedPublicKey[] = {
2340 0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7,0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,
2341 0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21,0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,
2342 0x65,0x97,0x03,0x86,0x60,0xde,0xf3,0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,
2343 0x17,0xa9,0xcd,0x79,0x3f,0x21,0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,
2344 0x6b,0xd0,0x1c,0x10,0x79,0x02,0x03,0x01,0x00,0x01 };
2345
2346 static void testAcquireCertPrivateKey(void)
2347 {
2348     BOOL ret;
2349     PCCERT_CONTEXT cert;
2350     HCRYPTPROV csp;
2351     DWORD size, keySpec;
2352     BOOL callerFree;
2353     CRYPT_KEY_PROV_INFO keyProvInfo;
2354     HCRYPTKEY key;
2355     WCHAR ms_def_prov_w[MAX_PATH];
2356
2357     lstrcpyW(ms_def_prov_w, MS_DEF_PROV_W);
2358
2359     keyProvInfo.pwszContainerName = cspNameW;
2360     keyProvInfo.pwszProvName = ms_def_prov_w;
2361     keyProvInfo.dwProvType = PROV_RSA_FULL;
2362     keyProvInfo.dwFlags = 0;
2363     keyProvInfo.cProvParam = 0;
2364     keyProvInfo.rgProvParam = NULL;
2365     keyProvInfo.dwKeySpec = AT_SIGNATURE;
2366
2367     pCryptAcquireContextW(NULL, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
2368      CRYPT_DELETEKEYSET);
2369
2370     cert = CertCreateCertificateContext(X509_ASN_ENCODING, selfSignedCert,
2371      sizeof(selfSignedCert));
2372
2373     /* Crash
2374     ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, NULL, NULL);
2375     ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, NULL,
2376      &callerFree);
2377     ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, &keySpec,
2378      NULL);
2379     ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, &csp, NULL, NULL);
2380     ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, &csp, &keySpec,
2381      &callerFree);
2382     ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, NULL, NULL, NULL);
2383      */
2384
2385     /* Missing private key */
2386     ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, NULL, NULL);
2387     ok(!ret && GetLastError() == CRYPT_E_NO_KEY_PROPERTY,
2388      "Expected CRYPT_E_NO_KEY_PROPERTY, got %08x\n", GetLastError());
2389     ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, &keySpec,
2390      &callerFree);
2391     ok(!ret && GetLastError() == CRYPT_E_NO_KEY_PROPERTY,
2392      "Expected CRYPT_E_NO_KEY_PROPERTY, got %08x\n", GetLastError());
2393     CertSetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, 0,
2394      &keyProvInfo);
2395     ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, &keySpec,
2396      &callerFree);
2397     ok(!ret && GetLastError() == CRYPT_E_NO_KEY_PROPERTY,
2398      "Expected CRYPT_E_NO_KEY_PROPERTY, got %08x\n", GetLastError());
2399
2400     pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
2401      CRYPT_NEWKEYSET);
2402     ret = CryptImportKey(csp, privKey, sizeof(privKey), 0, 0, &key);
2403     ok(ret, "CryptImportKey failed: %08x\n", GetLastError());
2404     if (ret)
2405     {
2406         HCRYPTPROV certCSP;
2407         DWORD size;
2408         CERT_KEY_CONTEXT keyContext;
2409
2410         /* Don't cache provider */
2411         ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &certCSP,
2412          &keySpec, &callerFree);
2413         ok(ret, "CryptAcquireCertificatePrivateKey failed: %08x\n",
2414          GetLastError());
2415         ok(callerFree, "Expected callerFree to be TRUE\n");
2416         CryptReleaseContext(certCSP, 0);
2417         ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &certCSP,
2418          NULL, NULL);
2419         ok(ret, "CryptAcquireCertificatePrivateKey failed: %08x\n",
2420          GetLastError());
2421         CryptReleaseContext(certCSP, 0);
2422
2423         /* Use the key prov info's caching (there shouldn't be any) */
2424         ret = CryptAcquireCertificatePrivateKey(cert,
2425          CRYPT_ACQUIRE_USE_PROV_INFO_FLAG, NULL, &certCSP, &keySpec,
2426          &callerFree);
2427         ok(ret, "CryptAcquireCertificatePrivateKey failed: %08x\n",
2428          GetLastError());
2429         ok(callerFree, "Expected callerFree to be TRUE\n");
2430         CryptReleaseContext(certCSP, 0);
2431
2432         /* Cache it (and check that it's cached) */
2433         ret = CryptAcquireCertificatePrivateKey(cert,
2434          CRYPT_ACQUIRE_CACHE_FLAG, NULL, &certCSP, &keySpec, &callerFree);
2435         ok(ret, "CryptAcquireCertificatePrivateKey failed: %08x\n",
2436          GetLastError());
2437         ok(!callerFree, "Expected callerFree to be FALSE\n");
2438         size = sizeof(keyContext);
2439         ret = CertGetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID,
2440          &keyContext, &size);
2441         ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
2442          GetLastError());
2443
2444         /* Remove the cached provider */
2445         CryptReleaseContext(keyContext.hCryptProv, 0);
2446         CertSetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID, 0,
2447          NULL);
2448         /* Allow caching via the key prov info */
2449         keyProvInfo.dwFlags = CERT_SET_KEY_CONTEXT_PROP_ID;
2450         CertSetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, 0,
2451          &keyProvInfo);
2452         /* Now use the key prov info's caching */
2453         ret = CryptAcquireCertificatePrivateKey(cert,
2454          CRYPT_ACQUIRE_USE_PROV_INFO_FLAG, NULL, &certCSP, &keySpec,
2455          &callerFree);
2456         ok(ret, "CryptAcquireCertificatePrivateKey failed: %08x\n",
2457          GetLastError());
2458         ok(!callerFree, "Expected callerFree to be FALSE\n");
2459         size = sizeof(keyContext);
2460         ret = CertGetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID,
2461          &keyContext, &size);
2462         ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
2463          GetLastError());
2464
2465         CryptDestroyKey(key);
2466     }
2467
2468     /* Some sanity-checking on public key exporting */
2469     ret = CryptImportPublicKeyInfo(csp, X509_ASN_ENCODING,
2470      &cert->pCertInfo->SubjectPublicKeyInfo, &key);
2471     ok(ret, "CryptImportPublicKeyInfo failed: %08x\n", GetLastError());
2472     if (ret)
2473     {
2474         ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &size);
2475         ok(ret, "CryptExportKey failed: %08x\n", GetLastError());
2476         if (ret)
2477         {
2478             LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, size), encodedKey;
2479
2480             ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, buf, &size);
2481             ok(ret, "CryptExportKey failed: %08x\n", GetLastError());
2482             ok(size == sizeof(exportedPublicKeyBlob), "Unexpected size %d\n",
2483              size);
2484             ok(!memcmp(buf, exportedPublicKeyBlob, size), "Unexpected value\n");
2485             ret = CryptEncodeObjectEx(X509_ASN_ENCODING, RSA_CSP_PUBLICKEYBLOB,
2486              buf, CRYPT_ENCODE_ALLOC_FLAG, NULL, &encodedKey, &size);
2487             ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2488             if (ret)
2489             {
2490                 ok(size == sizeof(asnEncodedPublicKey), "Unexpected size %d\n",
2491                  size);
2492                 ok(!memcmp(encodedKey, asnEncodedPublicKey, size),
2493                  "Unexpected value\n");
2494                 LocalFree(encodedKey);
2495             }
2496             HeapFree(GetProcessHeap(), 0, buf);
2497         }
2498         CryptDestroyKey(key);
2499     }
2500     ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
2501      NULL, 0, NULL, NULL, &size);
2502     ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
2503     if (ret)
2504     {
2505         PCERT_PUBLIC_KEY_INFO info = HeapAlloc(GetProcessHeap(), 0, size);
2506
2507         ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
2508          NULL, 0, NULL, info, &size);
2509         ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
2510         if (ret)
2511         {
2512             ok(info->PublicKey.cbData == sizeof(asnEncodedPublicKey),
2513              "Unexpected size %d\n", info->PublicKey.cbData);
2514             ok(!memcmp(info->PublicKey.pbData, asnEncodedPublicKey,
2515              info->PublicKey.cbData), "Unexpected value\n");
2516         }
2517         HeapFree(GetProcessHeap(), 0, info);
2518     }
2519
2520     CryptReleaseContext(csp, 0);
2521     pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
2522      CRYPT_DELETEKEYSET);
2523
2524     CertFreeCertificateContext(cert);
2525 }
2526
2527 static void testGetPublicKeyLength(void)
2528 {
2529     static char oid_rsa_rsa[] = szOID_RSA_RSA;
2530     static char oid_rsa_dh[] = szOID_RSA_DH;
2531     static char bogusOID[] = "1.2.3";
2532     DWORD ret;
2533     CERT_PUBLIC_KEY_INFO info = { { 0 } };
2534     BYTE bogusKey[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
2535     BYTE key[] = { 0x30,0x0f,0x02,0x08,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
2536      0x02,0x03,0x01,0x00,0x01 };
2537
2538     /* Crashes
2539     ret = CertGetPublicKeyLength(0, NULL);
2540      */
2541     /* With an empty public key info */
2542     SetLastError(0xdeadbeef);
2543     ret = CertGetPublicKeyLength(0, &info);
2544     ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
2545      "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
2546      ret, GetLastError());
2547     SetLastError(0xdeadbeef);
2548     ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
2549     ok(ret == 0 && GetLastError() == CRYPT_E_ASN1_EOD,
2550      "Expected length 0 and CRYPT_E_ASN1_EOD, got length %d, %08x\n",
2551      ret, GetLastError());
2552     /* With a nearly-empty public key info */
2553     info.Algorithm.pszObjId = oid_rsa_rsa;
2554     SetLastError(0xdeadbeef);
2555     ret = CertGetPublicKeyLength(0, &info);
2556     ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
2557      "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
2558      ret, GetLastError());
2559     SetLastError(0xdeadbeef);
2560     ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
2561     ok(ret == 0 && GetLastError() == CRYPT_E_ASN1_EOD,
2562      "Expected length 0 and CRYPT_E_ASN1_EOD, got length %d, %08x\n",
2563      ret, GetLastError());
2564     /* With a bogus key */
2565     info.PublicKey.cbData = sizeof(bogusKey);
2566     info.PublicKey.pbData = bogusKey;
2567     SetLastError(0xdeadbeef);
2568     ret = CertGetPublicKeyLength(0, &info);
2569     ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
2570      "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
2571      ret, GetLastError());
2572     SetLastError(0xdeadbeef);
2573     ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
2574     ok(ret == 0 && GetLastError() == CRYPT_E_ASN1_BADTAG,
2575      "Expected length 0 and CRYPT_E_ASN1_BADTAGTAG, got length %d, %08x\n",
2576      ret, GetLastError());
2577     /* With a believable RSA key but a bogus OID */
2578     info.Algorithm.pszObjId = bogusOID;
2579     info.PublicKey.cbData = sizeof(key);
2580     info.PublicKey.pbData = key;
2581     SetLastError(0xdeadbeef);
2582     ret = CertGetPublicKeyLength(0, &info);
2583     ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
2584      "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
2585      ret, GetLastError());
2586     SetLastError(0xdeadbeef);
2587     ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
2588     ok(ret == 56, "Expected length 56, got %d\n", ret);
2589     /* An RSA key with the DH OID */
2590     info.Algorithm.pszObjId = oid_rsa_dh;
2591     SetLastError(0xdeadbeef);
2592     ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
2593     ok(ret == 0 && GetLastError() == CRYPT_E_ASN1_BADTAG,
2594      "Expected length 0 and CRYPT_E_ASN1_BADTAG, got length %d, %08x\n",
2595      ret, GetLastError());
2596     /* With the RSA OID */
2597     info.Algorithm.pszObjId = oid_rsa_rsa;
2598     SetLastError(0xdeadbeef);
2599     ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
2600     ok(ret == 56, "Expected length 56, got %d\n", ret);
2601 }
2602
2603 START_TEST(cert)
2604 {
2605     init_function_pointers();
2606
2607     testAddCert();
2608     testCertProperties();
2609     testDupCert();
2610     testFindCert();
2611     testGetSubjectCert();
2612     testGetIssuerCert();
2613
2614     testCryptHashCert();
2615     testCertSigs();
2616     testSignAndEncodeCert();
2617     testCreateSelfSignCert();
2618     testKeyUsage();
2619     testCompareCertName();
2620     testCompareIntegerBlob();
2621     testComparePublicKeyInfo();
2622     testHashPublicKeyInfo();
2623     testCompareCert();
2624     testVerifySubjectCert();
2625     testAcquireCertPrivateKey();
2626     testGetPublicKeyLength();
2627 }