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