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