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