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