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