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