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