mshtml: Added IHTMLElement::get_offsetHeight implementation.
[wine] / dlls / crypt32 / tests / cert.c
1 /*
2  * crypt32 cert functions tests
3  *
4  * Copyright 2005-2006 Juan Lang
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include <assert.h>
22 #include <stdio.h>
23 #include <stdarg.h>
24 #include <windef.h>
25 #include <winbase.h>
26 #include <winreg.h>
27 #include <winerror.h>
28 #include <wincrypt.h>
29
30 #include "wine/test.h"
31
32 static BOOL (WINAPI *pCertAddStoreToCollection)(HCERTSTORE,HCERTSTORE,DWORD,DWORD);
33 static PCCERT_CONTEXT (WINAPI *pCertCreateSelfSignCertificate)(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE,PCERT_NAME_BLOB,DWORD,PCRYPT_KEY_PROV_INFO,PCRYPT_ALGORITHM_IDENTIFIER,PSYSTEMTIME,PSYSTEMTIME,PCERT_EXTENSIONS);
34 static BOOL (WINAPI *pCertGetValidUsages)(DWORD,PCCERT_CONTEXT*,int*,LPSTR*,DWORD*);
35 static BOOL (WINAPI *pCryptAcquireCertificatePrivateKey)(PCCERT_CONTEXT,DWORD,void*,HCRYPTPROV_OR_NCRYPT_KEY_HANDLE*,DWORD*,BOOL*);
36 static BOOL (WINAPI *pCryptEncodeObjectEx)(DWORD,LPCSTR,const void*,DWORD,PCRYPT_ENCODE_PARA,void*,DWORD*);
37 static BOOL (WINAPI * pCryptVerifyCertificateSignatureEx)
38                         (HCRYPTPROV, DWORD, DWORD, void *, DWORD, void *, DWORD, void *);
39
40 static BOOL (WINAPI * 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      * Both tests crash on some win9x boxes.
161      */
162     if (0)
163     {
164         ret = CertAddEncodedCertificateToStore(0, X509_ASN_ENCODING, bigCert,
165          sizeof(bigCert), 0, NULL);
166         ok(!ret && (GetLastError() == STATUS_ACCESS_VIOLATION ||
167          GetLastError() == E_INVALIDARG),
168          "Expected STATUS_ACCESS_VIOLATION or E_INVALIDARG, got %08x\n",
169          GetLastError());
170         ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
171          bigCert, sizeof(bigCert), 0, NULL);
172         ok(!ret && (GetLastError() == STATUS_ACCESS_VIOLATION ||
173          GetLastError() == E_INVALIDARG),
174          "Expected STATUS_ACCESS_VIOLATION or E_INVALIDARG, got %08x\n",
175          GetLastError());
176     }
177
178     /* Weird--can add a cert to the NULL store (does this have special
179      * meaning?)
180      */
181     context = NULL;
182     ret = CertAddEncodedCertificateToStore(0, X509_ASN_ENCODING, bigCert,
183      sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
184     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
185      GetLastError());
186     if (context)
187         CertFreeCertificateContext(context);
188
189     ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
190      bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
191     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
192      GetLastError());
193     ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
194      bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, NULL);
195     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
196      GetLastError());
197     /* This has the same name as bigCert, so finding isn't done by name */
198     ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
199      certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, &context);
200     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
201      GetLastError());
202     ok(context != NULL, "Expected a context\n");
203     if (context)
204     {
205         CRYPT_DATA_BLOB hash = { sizeof(bigCert2Hash), bigCert2Hash };
206
207         /* Duplicate (AddRef) the context so we can still use it after
208          * deleting it from the store.
209          */
210         CertDuplicateCertificateContext(context);
211         CertDeleteCertificateFromStore(context);
212         /* Set the same hash as bigCert2, and try to readd it */
213         ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID,
214          0, &hash);
215         ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
216          GetLastError());
217         ret = CertAddCertificateContextToStore(store, context,
218          CERT_STORE_ADD_NEW, NULL);
219         /* The failure is a bit odd (CRYPT_E_ASN1_BADTAG), so just check
220          * that it fails.
221          */
222         ok(!ret, "Expected failure\n");
223         CertFreeCertificateContext(context);
224     }
225     context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert2,
226      sizeof(bigCert2));
227     ok(context != NULL, "Expected a context\n");
228     if (context)
229     {
230         /* Try to readd bigCert2 to the store */
231         ret = CertAddCertificateContextToStore(store, context,
232          CERT_STORE_ADD_NEW, NULL);
233         ok(!ret && GetLastError() == CRYPT_E_EXISTS,
234          "Expected CRYPT_E_EXISTS, got %08x\n", GetLastError());
235         CertFreeCertificateContext(context);
236     }
237
238     /* Adding a cert with the same issuer name and serial number (but
239      * different subject) as an existing cert succeeds.
240      */
241     context = NULL;
242     ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
243      bigCert2WithDifferentSerial, sizeof(bigCert2WithDifferentSerial),
244      CERT_STORE_ADD_NEW, &context);
245     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
246      GetLastError());
247     if (context)
248         CertDeleteCertificateFromStore(context);
249
250     /* Adding a cert with the same subject name and serial number (but
251      * different issuer) as an existing cert succeeds.
252      */
253     context = NULL;
254     ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
255      bigCertWithDifferentSubject, sizeof(bigCertWithDifferentSubject),
256      CERT_STORE_ADD_NEW, &context);
257     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
258      GetLastError());
259     if (context)
260         CertDeleteCertificateFromStore(context);
261
262     /* Adding a cert with the same issuer name and serial number (but
263      * different otherwise) as an existing cert succeeds.
264      */
265     context = NULL;
266     ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
267      bigCertWithDifferentIssuer, sizeof(bigCertWithDifferentIssuer),
268      CERT_STORE_ADD_NEW, &context);
269     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
270      GetLastError());
271     if (context)
272         CertDeleteCertificateFromStore(context);
273
274     collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
275      CERT_STORE_CREATE_NEW_FLAG, NULL);
276     ok(collection != NULL, "CertOpenStore failed: %08x\n", GetLastError());
277     if (collection && pCertAddStoreToCollection)
278     {
279         /* Add store to the collection, but disable updates */
280         pCertAddStoreToCollection(collection, store, 0, 0);
281
282         context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert2,
283          sizeof(bigCert2));
284         ok(context != NULL, "Expected a context\n");
285         if (context)
286         {
287             /* Try to readd bigCert2 to the collection */
288             ret = CertAddCertificateContextToStore(collection, context,
289              CERT_STORE_ADD_NEW, NULL);
290             ok(!ret && GetLastError() == CRYPT_E_EXISTS,
291              "Expected CRYPT_E_EXISTS, got %08x\n", GetLastError());
292             /* Replacing an existing certificate context is allowed, even
293              * though updates to the collection aren't..
294              */
295             ret = CertAddCertificateContextToStore(collection, context,
296              CERT_STORE_ADD_REPLACE_EXISTING, NULL);
297             ok(ret, "CertAddCertificateContextToStore failed: %08x\n",
298              GetLastError());
299             /* use the existing certificate and ask for a copy of the context*/
300             copyContext = NULL;
301             ret = CertAddCertificateContextToStore(collection, context,
302              CERT_STORE_ADD_USE_EXISTING, &copyContext);
303             ok(ret, "CertAddCertificateContextToStore failed: %08x\n",
304              GetLastError());
305             ok(copyContext != NULL, "Expected on output a non NULL copyContext\n");
306             if (copyContext)
307                 CertFreeCertificateContext(copyContext);
308             /* but adding a new certificate isn't allowed. */
309             ret = CertAddCertificateContextToStore(collection, context,
310              CERT_STORE_ADD_ALWAYS, NULL);
311             ok(!ret && GetLastError() == E_ACCESSDENIED,
312              "Expected E_ACCESSDENIED, got %08x\n", GetLastError());
313             CertFreeCertificateContext(context);
314         }
315
316         CertCloseStore(collection, 0);
317     }
318
319     CertCloseStore(store, 0);
320 }
321
322 static void checkHash(const BYTE *data, DWORD dataLen, ALG_ID algID,
323  PCCERT_CONTEXT context, DWORD propID)
324 {
325     BYTE hash[20] = { 0 }, hashProperty[20];
326     BOOL ret;
327     DWORD size;
328     DWORD dwSizeWithNull;
329
330     memset(hash, 0, sizeof(hash));
331     memset(hashProperty, 0, sizeof(hashProperty));
332     size = sizeof(hash);
333     ret = CryptHashCertificate(0, algID, 0, data, dataLen, hash, &size);
334     ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
335     ret = CertGetCertificateContextProperty(context, propID, NULL,
336      &dwSizeWithNull);
337     ok(ret, "algID %08x, propID %d: CertGetCertificateContextProperty failed: %08x\n",
338      algID, propID, GetLastError());
339     ret = CertGetCertificateContextProperty(context, propID, hashProperty,
340      &size);
341     ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
342      GetLastError());
343     ok(!memcmp(hash, hashProperty, size), "Unexpected hash for property %d\n",
344      propID);
345     ok(size == dwSizeWithNull, "Unexpected length of hash for property: received %d instead of %d\n",
346      dwSizeWithNull,size);
347 }
348
349 static WCHAR cspNameW[] = { 'W','i','n','e','C','r','y','p','t','T','e','m','p',0 };
350 static const BYTE v1CertWithPubKey[] = {
351 0x30,0x81,0x95,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
352 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
353 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
354 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
355 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,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,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
358 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
359 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,
360 0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,
361 0x01,0x01 };
362 static const BYTE v1CertWithSubjectKeyId[] = {
363 0x30,0x7b,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
364 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
365 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
366 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
367 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
368 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
369 0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x17,0x30,0x15,0x30,
370 0x13,0x06,0x03,0x55,0x1d,0x0e,0x04,0x0c,0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,
371 0x4c,0x61,0x6e,0x67,0x00 };
372 static const BYTE subjectKeyId[] = {
373 0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
374
375 static void testCertProperties(void)
376 {
377     PCCERT_CONTEXT context = CertCreateCertificateContext(X509_ASN_ENCODING,
378      bigCert, sizeof(bigCert));
379     DWORD propID, numProps, access, size;
380     BOOL ret;
381     BYTE hash[20] = { 0 }, hashProperty[20];
382     CRYPT_DATA_BLOB blob;
383     CERT_KEY_CONTEXT keyContext;
384
385     ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
386      GetLastError());
387     if (!context)
388         return;
389
390     /* This crashes
391     propID = CertEnumCertificateContextProperties(NULL, 0);
392      */
393
394     propID = 0;
395     numProps = 0;
396     do {
397         propID = CertEnumCertificateContextProperties(context, propID);
398         if (propID)
399             numProps++;
400     } while (propID != 0);
401     ok(numProps == 0, "Expected 0 properties, got %d\n", numProps);
402
403     /* Tests with a NULL cert context.  Prop ID 0 fails.. */
404     ret = CertSetCertificateContextProperty(NULL, 0, 0, NULL);
405     ok(!ret && GetLastError() == E_INVALIDARG,
406      "Expected E_INVALIDARG, got %08x\n", GetLastError());
407     /* while this just crashes.
408     ret = CertSetCertificateContextProperty(NULL,
409      CERT_KEY_PROV_HANDLE_PROP_ID, 0, NULL);
410      */
411
412     ret = CertSetCertificateContextProperty(context, 0, 0, NULL);
413     ok(!ret && GetLastError() == E_INVALIDARG,
414      "Expected E_INVALIDARG, got %08x\n", GetLastError());
415     /* Can't set the cert property directly, this crashes.
416     ret = CertSetCertificateContextProperty(context,
417      CERT_CERT_PROP_ID, 0, bigCert2);
418      */
419
420     /* These all crash.
421     ret = CertGetCertificateContextProperty(context,
422      CERT_ACCESS_STATE_PROP_ID, 0, NULL);
423     ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID, 
424      NULL, NULL);
425     ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID, 
426      hashProperty, NULL);
427      */
428     /* A missing prop */
429     size = 0;
430     ret = CertGetCertificateContextProperty(context,
431      CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
432     ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
433      "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
434     /* And, an implicit property */
435     size = sizeof(access);
436     ret = CertGetCertificateContextProperty(context,
437      CERT_ACCESS_STATE_PROP_ID, &access, &size);
438     ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
439      GetLastError());
440     ok(!(access & CERT_ACCESS_STATE_WRITE_PERSIST_FLAG),
441      "Didn't expect a persisted cert\n");
442     /* Trying to set this "read only" property crashes.
443     access |= CERT_ACCESS_STATE_WRITE_PERSIST_FLAG;
444     ret = CertSetCertificateContextProperty(context,
445      CERT_ACCESS_STATE_PROP_ID, 0, &access);
446      */
447
448     /* Can I set the hash to an invalid hash? */
449     blob.pbData = hash;
450     blob.cbData = sizeof(hash);
451     ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID, 0,
452      &blob);
453     ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
454      GetLastError());
455     size = sizeof(hashProperty);
456     ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
457      hashProperty, &size);
458     ok(!memcmp(hashProperty, hash, sizeof(hash)), "Unexpected hash\n");
459     /* Delete the (bogus) hash, and get the real one */
460     ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID, 0,
461      NULL);
462     ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
463      GetLastError());
464     checkHash(bigCert, sizeof(bigCert), CALG_SHA1, context,
465      CERT_HASH_PROP_ID);
466
467     /* Now that the hash property is set, we should get one property when
468      * enumerating.
469      */
470     propID = 0;
471     numProps = 0;
472     do {
473         propID = CertEnumCertificateContextProperties(context, propID);
474         if (propID)
475             numProps++;
476     } while (propID != 0);
477     ok(numProps == 1, "Expected 1 properties, got %d\n", numProps);
478
479     /* Check a few other implicit properties */
480     checkHash(bigCert, sizeof(bigCert), CALG_MD5, context,
481      CERT_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 || NTE_BAD_ALGID),
1552      "Expected ERROR_INVALID_PARAMETER or NTE_BAD_ALGID, got %08x\n",
1553      GetLastError());
1554     ret = CryptSignCertificate(0, AT_SIGNATURE, 0, toBeSigned->pbData,
1555      toBeSigned->cbData, &algoID, NULL, NULL, &size);
1556     ok(!ret && (GetLastError() == ERROR_INVALID_PARAMETER || NTE_BAD_ALGID),
1557      "Expected ERROR_INVALID_PARAMETER or NTE_BAD_ALGID, got %08x\n",
1558      GetLastError());
1559
1560     /* No keys exist in the new CSP yet.. */
1561     ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
1562      toBeSigned->cbData, &algoID, NULL, NULL, &size);
1563     ok(!ret && (GetLastError() == NTE_BAD_KEYSET || GetLastError() ==
1564      NTE_NO_KEY), "Expected NTE_BAD_KEYSET or NTE_NO_KEY, got %08x\n",
1565      GetLastError());
1566     ret = CryptGenKey(csp, AT_SIGNATURE, 0, key);
1567     ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
1568     if (ret)
1569     {
1570         ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
1571          toBeSigned->cbData, &algoID, NULL, NULL, &size);
1572         ok(ret, "CryptSignCertificate failed: %08x\n", GetLastError());
1573         ok(size <= *sigLen, "Expected size <= %d, got %d\n", *sigLen, size);
1574         if (ret)
1575         {
1576             ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
1577              toBeSigned->cbData, &algoID, NULL, sig, &size);
1578             ok(ret, "CryptSignCertificate failed: %08x\n", GetLastError());
1579             if (ret)
1580             {
1581                 *sigLen = size;
1582                 verifySig(csp, toBeSigned->pbData, toBeSigned->cbData, sig,
1583                  size);
1584             }
1585         }
1586     }
1587 }
1588
1589 static void testVerifyCertSig(HCRYPTPROV csp, const CRYPT_DATA_BLOB *toBeSigned,
1590  LPCSTR sigOID, const BYTE *sig, DWORD sigLen)
1591 {
1592     CERT_SIGNED_CONTENT_INFO info;
1593     LPBYTE cert = NULL;
1594     DWORD size = 0;
1595     BOOL ret;
1596
1597     if (!pCryptVerifyCertificateSignatureEx)
1598     {
1599         skip("no CryptVerifyCertificateSignatureEx support\n");
1600         return;
1601     }
1602     if (!pCryptEncodeObjectEx)
1603     {
1604         skip("no CryptEncodeObjectEx support\n");
1605         return;
1606     }
1607     ret = pCryptVerifyCertificateSignatureEx(0, 0, 0, NULL, 0, NULL, 0, NULL);
1608     ok(!ret && GetLastError() == E_INVALIDARG,
1609      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1610     ret = pCryptVerifyCertificateSignatureEx(csp, 0, 0, NULL, 0, NULL, 0, NULL);
1611     ok(!ret && GetLastError() == E_INVALIDARG,
1612      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1613     ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING, 0, NULL, 0,
1614      NULL, 0, NULL);
1615     ok(!ret && GetLastError() == E_INVALIDARG,
1616      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1617     /* This crashes
1618     ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1619      CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, NULL, 0, NULL, 0, NULL);
1620      */
1621     info.ToBeSigned.cbData = toBeSigned->cbData;
1622     info.ToBeSigned.pbData = toBeSigned->pbData;
1623     info.SignatureAlgorithm.pszObjId = (LPSTR)sigOID;
1624     info.SignatureAlgorithm.Parameters.cbData = 0;
1625     info.Signature.cbData = sigLen;
1626     info.Signature.pbData = (BYTE *)sig;
1627     info.Signature.cUnusedBits = 0;
1628     ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, X509_CERT, &info,
1629      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&cert, &size);
1630     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1631     if (cert)
1632     {
1633         CRYPT_DATA_BLOB certBlob = { 0, NULL };
1634         PCERT_PUBLIC_KEY_INFO pubKeyInfo = NULL;
1635
1636         ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1637          CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
1638         ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
1639          "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
1640         certBlob.cbData = 1;
1641         certBlob.pbData = (void *)0xdeadbeef;
1642         ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1643          CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
1644         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1645          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1646         certBlob.cbData = size;
1647         certBlob.pbData = cert;
1648         ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1649          CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
1650         ok(!ret && GetLastError() == E_INVALIDARG,
1651          "Expected E_INVALIDARG, got %08x\n", GetLastError());
1652         ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1653          CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
1654          CRYPT_VERIFY_CERT_SIGN_ISSUER_NULL, NULL, 0, NULL);
1655         ok(!ret && GetLastError() == E_INVALIDARG,
1656          "Expected E_INVALIDARG, got %08x\n", GetLastError());
1657         /* This crashes
1658         ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1659          CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
1660          CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY, NULL, 0, NULL);
1661          */
1662         CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
1663          (LPSTR)sigOID, 0, NULL, NULL, &size);
1664         pubKeyInfo = HeapAlloc(GetProcessHeap(), 0, size);
1665         if (pubKeyInfo)
1666         {
1667             ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
1668              X509_ASN_ENCODING, (LPSTR)sigOID, 0, NULL, pubKeyInfo, &size);
1669             ok(ret, "CryptExportKey failed: %08x\n", GetLastError());
1670             if (ret)
1671             {
1672                 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1673                  CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
1674                  CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY, pubKeyInfo, 0, NULL);
1675                 ok(ret, "CryptVerifyCertificateSignatureEx failed: %08x\n",
1676                  GetLastError());
1677             }
1678             HeapFree(GetProcessHeap(), 0, pubKeyInfo);
1679         }
1680         LocalFree(cert);
1681     }
1682 }
1683
1684 static BYTE emptyCert[] = { 0x30, 0x00 };
1685
1686 static void testCertSigs(void)
1687 {
1688     HCRYPTPROV csp;
1689     CRYPT_DATA_BLOB toBeSigned = { sizeof(emptyCert), emptyCert };
1690     BOOL ret;
1691     HCRYPTKEY key;
1692     BYTE sig[64];
1693     DWORD sigSize = sizeof(sig);
1694
1695     /* Just in case a previous run failed, delete this thing */
1696     pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1697      CRYPT_DELETEKEYSET);
1698     ret = pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1699      CRYPT_NEWKEYSET);
1700     ok(ret, "CryptAcquireContext failed: %08x\n", GetLastError());
1701
1702     testSignCert(csp, &toBeSigned, szOID_RSA_SHA1RSA, &key, sig, &sigSize);
1703     testVerifyCertSig(csp, &toBeSigned, szOID_RSA_SHA1RSA, sig, sigSize);
1704
1705     CryptDestroyKey(key);
1706     CryptReleaseContext(csp, 0);
1707     ret = pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1708      CRYPT_DELETEKEYSET);
1709 }
1710
1711 static const BYTE md5SignedEmptyCert[] = {
1712 0x30,0x56,0x30,0x33,0x02,0x00,0x30,0x02,0x06,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,
1713 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,
1714 0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x07,
1715 0x30,0x02,0x06,0x00,0x03,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,
1716 0x0d,0x02,0x05,0x05,0x00,0x03,0x11,0x00,0xfb,0x0f,0x66,0x82,0x66,0xd9,0xe5,0xf8,
1717 0xd8,0xa2,0x55,0x2b,0xe1,0xa5,0xd9,0x04 };
1718 static const BYTE md5SignedEmptyCertNoNull[] = {
1719 0x30,0x54,0x30,0x33,0x02,0x00,0x30,0x02,0x06,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,
1720 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,
1721 0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x07,
1722 0x30,0x02,0x06,0x00,0x03,0x01,0x00,0x30,0x0a,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,
1723 0x0d,0x02,0x05,0x03,0x11,0x00,0x04,0xd9,0xa5,0xe1,0x2b,0x55,0xa2,0xd8,0xf8,0xe5,
1724 0xd9,0x66,0x82,0x66,0x0f,0xfb };
1725
1726 static void testSignAndEncodeCert(void)
1727 {
1728     static char oid_rsa_md5rsa[] = szOID_RSA_MD5RSA;
1729     static char oid_rsa_md5[] = szOID_RSA_MD5;
1730     BOOL ret;
1731     DWORD size;
1732     CRYPT_ALGORITHM_IDENTIFIER algID = { 0 };
1733     CERT_INFO info = { 0 };
1734
1735     /* Crash
1736     ret = CryptSignAndEncodeCertificate(0, 0, 0, NULL, NULL, NULL, NULL, NULL,
1737      NULL);
1738     ret = CryptSignAndEncodeCertificate(0, 0, 0, NULL, NULL, NULL, NULL, NULL,
1739      &size);
1740      */
1741     ret = CryptSignAndEncodeCertificate(0, 0, 0, NULL, NULL, &algID, NULL, NULL,
1742      &size);
1743     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1744      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1745     ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING, NULL, NULL,
1746      &algID, NULL, NULL, &size);
1747     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1748      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1749     ret = CryptSignAndEncodeCertificate(0, 0, 0, X509_CERT_TO_BE_SIGNED, NULL,
1750      &algID, NULL, NULL, &size);
1751     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1752      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1753     /* Crashes on some win9x boxes */
1754     if (0)
1755     {
1756         ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1757          X509_CERT_TO_BE_SIGNED, NULL, &algID, NULL, NULL, &size);
1758         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1759          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1760     }
1761     /* Crashes
1762     ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1763      X509_CERT_TO_BE_SIGNED, &info, NULL, NULL, NULL, &size);
1764      */
1765     ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1766      X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, NULL, &size);
1767     ok(!ret && GetLastError() == NTE_BAD_ALGID,
1768      "Expected NTE_BAD_ALGID, got %08x\n", GetLastError());
1769     algID.pszObjId = oid_rsa_md5rsa;
1770     ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1771      X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, NULL, &size);
1772     ok(!ret && (GetLastError() == ERROR_INVALID_PARAMETER || NTE_BAD_ALGID),
1773      "Expected ERROR_INVALID_PARAMETER or NTE_BAD_ALGID, got %08x\n",
1774      GetLastError());
1775     algID.pszObjId = oid_rsa_md5;
1776     ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1777      X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, NULL, &size);
1778     /* oid_rsa_md5 not present in some win2k */
1779     if (ret)
1780     {
1781         LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, size);
1782
1783         if (buf)
1784         {
1785             ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1786              X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, buf, &size);
1787             ok(ret, "CryptSignAndEncodeCertificate failed: %08x\n",
1788              GetLastError());
1789             /* Tricky: because the NULL parameters may either be omitted or
1790              * included as an asn.1-encoded NULL (0x05,0x00), two different
1791              * values are allowed.
1792              */
1793             ok(size == sizeof(md5SignedEmptyCert) ||
1794              size == sizeof(md5SignedEmptyCertNoNull), "Unexpected size %d\n",
1795              size);
1796             if (size == sizeof(md5SignedEmptyCert))
1797                 ok(!memcmp(buf, md5SignedEmptyCert, size),
1798                  "Unexpected value\n");
1799             else if (size == sizeof(md5SignedEmptyCertNoNull))
1800                 ok(!memcmp(buf, md5SignedEmptyCertNoNull, size),
1801                  "Unexpected value\n");
1802             HeapFree(GetProcessHeap(), 0, buf);
1803         }
1804     }
1805 }
1806
1807 static void testCreateSelfSignCert(void)
1808 {
1809     PCCERT_CONTEXT context;
1810     CERT_NAME_BLOB name = { sizeof(subjectName), subjectName };
1811     HCRYPTPROV csp;
1812     BOOL ret;
1813     HCRYPTKEY key;
1814     CRYPT_KEY_PROV_INFO info;
1815
1816     if (!pCertCreateSelfSignCertificate)
1817     {
1818         skip("CertCreateSelfSignCertificate() is not available\n");
1819         return;
1820     }
1821
1822     /* This crashes:
1823     context = pCertCreateSelfSignCertificate(0, NULL, 0, NULL, NULL, NULL, NULL,
1824      NULL);
1825      * Calling this with no first parameter creates a new key container, which
1826      * lasts beyond the test, so I don't test that.  Nb: the generated key
1827      * name is a GUID.
1828     context = pCertCreateSelfSignCertificate(0, &name, 0, NULL, NULL, NULL, NULL,
1829      NULL);
1830      */
1831
1832     /* Acquire a CSP */
1833     pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1834      CRYPT_DELETEKEYSET);
1835     ret = pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1836      CRYPT_NEWKEYSET);
1837     ok(ret, "CryptAcquireContext failed: %08x\n", GetLastError());
1838
1839     context = pCertCreateSelfSignCertificate(csp, &name, 0, NULL, NULL, NULL,
1840      NULL, NULL);
1841     ok(!context && GetLastError() == NTE_NO_KEY,
1842      "Expected NTE_NO_KEY, got %08x\n", GetLastError());
1843     ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
1844     ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
1845     if (ret)
1846     {
1847         context = pCertCreateSelfSignCertificate(csp, &name, 0, NULL, NULL, NULL,
1848          NULL, NULL);
1849         ok(context != NULL, "CertCreateSelfSignCertificate failed: %08x\n",
1850          GetLastError());
1851         if (context)
1852         {
1853             DWORD size = 0;
1854             PCRYPT_KEY_PROV_INFO info;
1855
1856             /* The context must have a key provider info property */
1857             ret = CertGetCertificateContextProperty(context,
1858              CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
1859             ok(ret && size, "Expected non-zero key provider info\n");
1860             if (size)
1861             {
1862                 info = HeapAlloc(GetProcessHeap(), 0, size);
1863                 if (info)
1864                 {
1865                     ret = CertGetCertificateContextProperty(context,
1866                      CERT_KEY_PROV_INFO_PROP_ID, info, &size);
1867                     ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
1868                      GetLastError());
1869                     if (ret)
1870                     {
1871                         /* Sanity-check the key provider */
1872                         ok(!lstrcmpW(info->pwszContainerName, cspNameW),
1873                          "Unexpected key container\n");
1874                         ok(!lstrcmpW(info->pwszProvName, MS_DEF_PROV_W),
1875                          "Unexpected provider\n");
1876                         ok(info->dwKeySpec == AT_SIGNATURE,
1877                          "Expected AT_SIGNATURE, got %d\n", info->dwKeySpec);
1878                     }
1879                     HeapFree(GetProcessHeap(), 0, info);
1880                 }
1881             }
1882
1883             CertFreeCertificateContext(context);
1884         }
1885
1886         CryptDestroyKey(key);
1887     }
1888
1889     CryptReleaseContext(csp, 0);
1890     ret = pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1891      CRYPT_DELETEKEYSET);
1892
1893     /* do the same test with AT_KEYEXCHANGE  and key info*/
1894     memset(&info,0,sizeof(info));
1895     info.dwProvType = PROV_RSA_FULL;
1896     info.dwKeySpec = AT_KEYEXCHANGE;
1897     info.pwszProvName = (LPWSTR) MS_DEF_PROV_W;
1898     info.pwszContainerName = cspNameW;
1899     context = pCertCreateSelfSignCertificate(0, &name, 0, &info, NULL, NULL,
1900         NULL, NULL);
1901     ok(context != NULL, "CertCreateSelfSignCertificate failed: %08x\n",
1902         GetLastError());
1903     if (context)
1904     {
1905         DWORD size = 0;
1906         PCRYPT_KEY_PROV_INFO info;
1907
1908         /* The context must have a key provider info property */
1909         ret = CertGetCertificateContextProperty(context,
1910             CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
1911         ok(ret && size, "Expected non-zero key provider info\n");
1912         if (size)
1913         {
1914             info = HeapAlloc(GetProcessHeap(), 0, size);
1915             if (info)
1916             {
1917                 ret = CertGetCertificateContextProperty(context,
1918                     CERT_KEY_PROV_INFO_PROP_ID, info, &size);
1919                 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
1920                     GetLastError());
1921                 if (ret)
1922                 {
1923                     /* Sanity-check the key provider */
1924                     ok(!lstrcmpW(info->pwszContainerName, cspNameW),
1925                         "Unexpected key container\n");
1926                     ok(!lstrcmpW(info->pwszProvName, MS_DEF_PROV_W),
1927                         "Unexpected provider\n");
1928                     ok(info->dwKeySpec == AT_KEYEXCHANGE,
1929                         "Expected AT_KEYEXCHANGE, got %d\n", info->dwKeySpec);
1930                 }
1931                 HeapFree(GetProcessHeap(), 0, info);
1932             }
1933         }
1934
1935         CertFreeCertificateContext(context);
1936     }
1937
1938     pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1939         CRYPT_DELETEKEYSET);
1940 }
1941
1942 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
1943  szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
1944
1945 static void testKeyUsage(void)
1946 {
1947     BOOL ret;
1948     PCCERT_CONTEXT context;
1949     DWORD size;
1950
1951     /* Test base cases */
1952     ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, NULL);
1953     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1954      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1955     size = 1;
1956     ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, &size);
1957     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1958      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1959     size = 0;
1960     ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, &size);
1961     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1962      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1963     /* These crash
1964     ret = CertSetEnhancedKeyUsage(NULL, NULL);
1965     usage.cUsageIdentifier = 0;
1966     ret = CertSetEnhancedKeyUsage(NULL, &usage);
1967      */
1968     /* Test with a cert with no enhanced key usage extension */
1969     context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
1970      sizeof(bigCert));
1971     ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
1972      GetLastError());
1973     if (context)
1974     {
1975         static const char oid[] = "1.2.3.4";
1976         BYTE buf[sizeof(CERT_ENHKEY_USAGE) + 2 * (sizeof(LPSTR) + sizeof(oid))];
1977         PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1978
1979         ret = CertGetEnhancedKeyUsage(context, 0, NULL, NULL);
1980         ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1981          "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1982         size = 1;
1983         ret = CertGetEnhancedKeyUsage(context, 0, NULL, &size);
1984         if (ret)
1985         {
1986             /* Windows 2000, ME, or later: even though it succeeded, we expect
1987              * CRYPT_E_NOT_FOUND, which indicates there is no enhanced key
1988              * usage set for this cert (which implies it's valid for all uses.)
1989              */
1990             ok(GetLastError() == CRYPT_E_NOT_FOUND,
1991              "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1992             ok(size == sizeof(CERT_ENHKEY_USAGE), "Wrong size %d\n", size);
1993             ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1994             ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1995             ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %d\n",
1996              pUsage->cUsageIdentifier);
1997         }
1998         else
1999         {
2000             /* Windows NT, 95, or 98: it fails, and the last error is
2001              * CRYPT_E_NOT_FOUND.
2002              */
2003             ok(GetLastError() == CRYPT_E_NOT_FOUND,
2004              "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
2005         }
2006         /* I can add a usage identifier when no key usage has been set */
2007         ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
2008         ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
2009          GetLastError());
2010         size = sizeof(buf);
2011         ret = CertGetEnhancedKeyUsage(context,
2012          CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
2013         ok(ret && GetLastError() == 0,
2014          "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2015         ok(pUsage->cUsageIdentifier == 1, "Expected 1 usage, got %d\n",
2016          pUsage->cUsageIdentifier);
2017         if (pUsage->cUsageIdentifier)
2018             ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
2019              "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
2020         /* Now set an empty key usage */
2021         pUsage->cUsageIdentifier = 0;
2022         ret = CertSetEnhancedKeyUsage(context, pUsage);
2023         ok(ret, "CertSetEnhancedKeyUsage failed: %08x\n", GetLastError());
2024         /* Shouldn't find it in the cert */
2025         size = sizeof(buf);
2026         ret = CertGetEnhancedKeyUsage(context,
2027          CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
2028         ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
2029          "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
2030         /* Should find it as an extended property */
2031         ret = CertGetEnhancedKeyUsage(context,
2032          CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
2033         ok(ret && GetLastError() == 0,
2034          "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2035         ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %d\n",
2036          pUsage->cUsageIdentifier);
2037         /* Should find it as either */
2038         ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2039         ok(ret && GetLastError() == 0,
2040          "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2041         ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %d\n",
2042          pUsage->cUsageIdentifier);
2043         /* Add a usage identifier */
2044         ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
2045         ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
2046          GetLastError());
2047         size = sizeof(buf);
2048         ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2049         ok(ret && GetLastError() == 0,
2050          "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2051         ok(pUsage->cUsageIdentifier == 1, "Expected 1 identifier, got %d\n",
2052          pUsage->cUsageIdentifier);
2053         if (pUsage->cUsageIdentifier)
2054             ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
2055              "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
2056         /* Re-adding the same usage identifier succeeds, though it only adds
2057          * a duplicate usage identifier on versions prior to Vista
2058          */
2059         ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
2060         ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
2061          GetLastError());
2062         size = sizeof(buf);
2063         ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2064         ok(ret && GetLastError() == 0,
2065          "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2066         ok(pUsage->cUsageIdentifier == 1 || pUsage->cUsageIdentifier == 2,
2067          "Expected 1 or 2 identifiers, got %d\n", pUsage->cUsageIdentifier);
2068         if (pUsage->cUsageIdentifier)
2069             ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
2070              "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
2071         if (pUsage->cUsageIdentifier >= 2)
2072             ok(!strcmp(pUsage->rgpszUsageIdentifier[1], oid),
2073              "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[1]);
2074         /* Now set a NULL extended property--this deletes the property. */
2075         ret = CertSetEnhancedKeyUsage(context, NULL);
2076         ok(ret, "CertSetEnhancedKeyUsage failed: %08x\n", GetLastError());
2077         SetLastError(0xbaadcafe);
2078         size = sizeof(buf);
2079         ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2080         ok(GetLastError() == CRYPT_E_NOT_FOUND,
2081          "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
2082
2083         CertFreeCertificateContext(context);
2084     }
2085     /* Now test with a cert with an enhanced key usage extension */
2086     context = CertCreateCertificateContext(X509_ASN_ENCODING, certWithUsage,
2087      sizeof(certWithUsage));
2088     ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
2089      GetLastError());
2090     if (context)
2091     {
2092         LPBYTE buf = NULL;
2093         DWORD bufSize = 0, i;
2094
2095         /* The size may depend on what flags are used to query it, so I
2096          * realloc the buffer for each test.
2097          */
2098         ret = CertGetEnhancedKeyUsage(context,
2099          CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, NULL, &bufSize);
2100         ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2101         buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
2102         if (buf)
2103         {
2104             PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
2105
2106             /* Should find it in the cert */
2107             size = bufSize;
2108             ret = CertGetEnhancedKeyUsage(context,
2109              CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
2110             ok(ret && GetLastError() == 0,
2111              "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2112             ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
2113              pUsage->cUsageIdentifier);
2114             for (i = 0; i < pUsage->cUsageIdentifier; i++)
2115                 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
2116                  "Expected %s, got %s\n", keyUsages[i],
2117                  pUsage->rgpszUsageIdentifier[i]);
2118             HeapFree(GetProcessHeap(), 0, buf);
2119         }
2120         ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
2121         ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2122         buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
2123         if (buf)
2124         {
2125             PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
2126
2127             /* Should find it as either */
2128             size = bufSize;
2129             ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2130             /* In Windows, GetLastError returns CRYPT_E_NOT_FOUND not found
2131              * here, even though the return is successful and the usage id
2132              * count is positive.  I don't enforce that here.
2133              */
2134             ok(ret,
2135              "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2136             ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
2137              pUsage->cUsageIdentifier);
2138             for (i = 0; i < pUsage->cUsageIdentifier; i++)
2139                 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
2140                  "Expected %s, got %s\n", keyUsages[i],
2141                  pUsage->rgpszUsageIdentifier[i]);
2142             HeapFree(GetProcessHeap(), 0, buf);
2143         }
2144         /* Shouldn't find it as an extended property */
2145         ret = CertGetEnhancedKeyUsage(context,
2146          CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, NULL, &size);
2147         ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
2148          "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
2149         /* Adding a usage identifier overrides the cert's usage!? */
2150         ret = CertAddEnhancedKeyUsageIdentifier(context, szOID_RSA_RSA);
2151         ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
2152          GetLastError());
2153         ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
2154         ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2155         buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
2156         if (buf)
2157         {
2158             PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
2159
2160             /* Should find it as either */
2161             size = bufSize;
2162             ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2163             ok(ret,
2164              "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2165             ok(pUsage->cUsageIdentifier == 1, "Expected 1 usage, got %d\n",
2166              pUsage->cUsageIdentifier);
2167             ok(!strcmp(pUsage->rgpszUsageIdentifier[0], szOID_RSA_RSA),
2168              "Expected %s, got %s\n", szOID_RSA_RSA,
2169              pUsage->rgpszUsageIdentifier[0]);
2170             HeapFree(GetProcessHeap(), 0, buf);
2171         }
2172         /* But querying the cert directly returns its usage */
2173         ret = CertGetEnhancedKeyUsage(context,
2174          CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, NULL, &bufSize);
2175         ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2176         buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
2177         if (buf)
2178         {
2179             PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
2180
2181             size = bufSize;
2182             ret = CertGetEnhancedKeyUsage(context,
2183              CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
2184             ok(ret,
2185              "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2186             ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
2187              pUsage->cUsageIdentifier);
2188             for (i = 0; i < pUsage->cUsageIdentifier; i++)
2189                 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
2190                  "Expected %s, got %s\n", keyUsages[i],
2191                  pUsage->rgpszUsageIdentifier[i]);
2192             HeapFree(GetProcessHeap(), 0, buf);
2193         }
2194         /* And removing the only usage identifier in the extended property
2195          * results in the cert's key usage being found.
2196          */
2197         ret = CertRemoveEnhancedKeyUsageIdentifier(context, szOID_RSA_RSA);
2198         ok(ret, "CertRemoveEnhancedKeyUsage failed: %08x\n", GetLastError());
2199         ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
2200         ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2201         buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
2202         if (buf)
2203         {
2204             PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
2205
2206             /* Should find it as either */
2207             size = bufSize;
2208             ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2209             ok(ret,
2210              "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2211             ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
2212              pUsage->cUsageIdentifier);
2213             for (i = 0; i < pUsage->cUsageIdentifier; i++)
2214                 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
2215                  "Expected %s, got %s\n", keyUsages[i],
2216                  pUsage->rgpszUsageIdentifier[i]);
2217             HeapFree(GetProcessHeap(), 0, buf);
2218         }
2219
2220         CertFreeCertificateContext(context);
2221     }
2222 }
2223
2224 static const BYTE cert2WithUsage[] = {
2225 0x30,0x81,0x89,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2226 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2227 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2228 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2229 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2230 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2231 0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x25,0x30,0x23,
2232 0x30,0x21,0x06,0x03,0x55,0x1d,0x25,0x01,0x01,0xff,0x04,0x17,0x30,0x15,0x06,
2233 0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x03,0x02,0x06,0x09,0x2a,0x86,0x48,0x86,
2234 0xf7,0x0d,0x01,0x01,0x01 };
2235
2236 static void testGetValidUsages(void)
2237 {
2238     static const LPCSTR expectedOIDs[] = {
2239      "1.3.6.1.5.5.7.3.3",
2240      "1.3.6.1.5.5.7.3.2",
2241      "1.2.840.113549.1.1.1",
2242     };
2243     static const LPCSTR expectedOIDs2[] = {
2244      "1.3.6.1.5.5.7.3.2",
2245      "1.2.840.113549.1.1.1",
2246     };
2247     BOOL ret;
2248     int numOIDs;
2249     DWORD size;
2250     LPSTR *oids = NULL;
2251     PCCERT_CONTEXT contexts[3];
2252
2253     if (!pCertGetValidUsages)
2254     {
2255         skip("CertGetValidUsages() is not available\n");
2256         return;
2257     }
2258
2259     /* Crash
2260     ret = pCertGetValidUsages(0, NULL, NULL, NULL, NULL);
2261     ret = pCertGetValidUsages(0, NULL, NULL, NULL, &size);
2262      */
2263     contexts[0] = NULL;
2264     numOIDs = size = 0xdeadbeef;
2265     SetLastError(0xdeadbeef);
2266     ret = pCertGetValidUsages(1, &contexts[0], &numOIDs, NULL, &size);
2267     ok(ret, "CertGetValidUsages failed: %d\n", GetLastError());
2268     ok(numOIDs == -1, "Expected -1, got %d\n", numOIDs);
2269     ok(size == 0, "Expected size 0, got %d\n", size);
2270     contexts[0] = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
2271      sizeof(bigCert));
2272     contexts[1] = CertCreateCertificateContext(X509_ASN_ENCODING, certWithUsage,
2273      sizeof(certWithUsage));
2274     contexts[2] = CertCreateCertificateContext(X509_ASN_ENCODING,
2275      cert2WithUsage, sizeof(cert2WithUsage));
2276     numOIDs = size = 0xdeadbeef;
2277     ret = pCertGetValidUsages(0, NULL, &numOIDs, NULL, &size);
2278     ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2279     ok(numOIDs == -1, "Expected -1, got %d\n", numOIDs);
2280     ok(size == 0, "Expected size 0, got %d\n", size);
2281     numOIDs = size = 0xdeadbeef;
2282     ret = pCertGetValidUsages(1, contexts, &numOIDs, NULL, &size);
2283     ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2284     ok(numOIDs == -1, "Expected -1, got %d\n", numOIDs);
2285     ok(size == 0, "Expected size 0, got %d\n", size);
2286     ret = pCertGetValidUsages(1, &contexts[1], &numOIDs, NULL, &size);
2287     ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2288     ok(numOIDs == 3, "Expected 3, got %d\n", numOIDs);
2289     ok(size, "Expected non-zero size\n");
2290     oids = HeapAlloc(GetProcessHeap(), 0, size);
2291     if (oids)
2292     {
2293         int i;
2294         DWORD smallSize = 1;
2295
2296         SetLastError(0xdeadbeef);
2297         ret = pCertGetValidUsages(1, &contexts[1], &numOIDs, oids, &smallSize);
2298         ok(!ret && GetLastError() == ERROR_MORE_DATA,
2299          "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
2300         ret = pCertGetValidUsages(1, &contexts[1], &numOIDs, oids, &size);
2301         ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2302         for (i = 0; i < numOIDs; i++)
2303             ok(!lstrcmpA(oids[i], expectedOIDs[i]), "unexpected OID %s\n",
2304              oids[i]);
2305         HeapFree(GetProcessHeap(), 0, oids);
2306     }
2307     numOIDs = size = 0xdeadbeef;
2308     /* Oddly enough, this crashes when the number of contexts is not 1:
2309     ret = pCertGetValidUsages(2, contexts, &numOIDs, NULL, &size);
2310      * but setting size to 0 allows it to succeed:
2311      */
2312     size = 0;
2313     ret = pCertGetValidUsages(2, contexts, &numOIDs, NULL, &size);
2314     ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2315     ok(numOIDs == 3, "Expected 3, got %d\n", numOIDs);
2316     ok(size, "Expected non-zero size\n");
2317     oids = HeapAlloc(GetProcessHeap(), 0, size);
2318     if (oids)
2319     {
2320         int i;
2321
2322         ret = pCertGetValidUsages(1, &contexts[1], &numOIDs, oids, &size);
2323         ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2324         for (i = 0; i < numOIDs; i++)
2325             ok(!lstrcmpA(oids[i], expectedOIDs[i]), "unexpected OID %s\n",
2326              oids[i]);
2327         HeapFree(GetProcessHeap(), 0, oids);
2328     }
2329     numOIDs = 0xdeadbeef;
2330     size = 0;
2331     ret = pCertGetValidUsages(1, &contexts[2], &numOIDs, NULL, &size);
2332     ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2333     ok(numOIDs == 2, "Expected 2, got %d\n", numOIDs);
2334     ok(size, "Expected non-zero size\n");
2335     oids = HeapAlloc(GetProcessHeap(), 0, size);
2336     if (oids)
2337     {
2338         int i;
2339
2340         ret = pCertGetValidUsages(1, &contexts[2], &numOIDs, oids, &size);
2341         ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2342         for (i = 0; i < numOIDs; i++)
2343             ok(!lstrcmpA(oids[i], expectedOIDs2[i]), "unexpected OID %s\n",
2344              oids[i]);
2345         HeapFree(GetProcessHeap(), 0, oids);
2346     }
2347     numOIDs = 0xdeadbeef;
2348     size = 0;
2349     ret = pCertGetValidUsages(3, contexts, &numOIDs, NULL, &size);
2350     ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2351     ok(numOIDs == 2, "Expected 2, got %d\n", numOIDs);
2352     ok(size, "Expected non-zero size\n");
2353     oids = HeapAlloc(GetProcessHeap(), 0, size);
2354     if (oids)
2355     {
2356         int i;
2357
2358         ret = pCertGetValidUsages(3, contexts, &numOIDs, oids, &size);
2359         ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2360         for (i = 0; i < numOIDs; i++)
2361             ok(!lstrcmpA(oids[i], expectedOIDs2[i]), "unexpected OID %s\n",
2362              oids[i]);
2363         HeapFree(GetProcessHeap(), 0, oids);
2364     }
2365     CertFreeCertificateContext(contexts[0]);
2366     CertFreeCertificateContext(contexts[1]);
2367     CertFreeCertificateContext(contexts[2]);
2368 }
2369
2370 static void testCompareCertName(void)
2371 {
2372     static BYTE bogus[] = { 1, 2, 3, 4 };
2373     static BYTE bogusPrime[] = { 0, 1, 2, 3, 4 };
2374     static BYTE emptyPrime[] = { 0x30, 0x00, 0x01 };
2375     BOOL ret;
2376     CERT_NAME_BLOB blob1, blob2;
2377
2378     /* crashes
2379     ret = CertCompareCertificateName(0, NULL, NULL);
2380      */
2381     /* An empty name checks against itself.. */
2382     blob1.pbData = emptyCert;
2383     blob1.cbData = sizeof(emptyCert);
2384     ret = CertCompareCertificateName(0, &blob1, &blob1);
2385     ok(ret, "CertCompareCertificateName failed: %08x\n", GetLastError());
2386     /* It doesn't have to be a valid encoded name.. */
2387     blob1.pbData = bogus;
2388     blob1.cbData = sizeof(bogus);
2389     ret = CertCompareCertificateName(0, &blob1, &blob1);
2390     ok(ret, "CertCompareCertificateName failed: %08x\n", GetLastError());
2391     /* Leading zeroes matter.. */
2392     blob2.pbData = bogusPrime;
2393     blob2.cbData = sizeof(bogusPrime);
2394     ret = CertCompareCertificateName(0, &blob1, &blob2);
2395     ok(!ret, "Expected failure\n");
2396     /* As do trailing extra bytes. */
2397     blob2.pbData = emptyPrime;
2398     blob2.cbData = sizeof(emptyPrime);
2399     ret = CertCompareCertificateName(0, &blob1, &blob2);
2400     ok(!ret, "Expected failure\n");
2401 }
2402
2403 static BYTE int1[] = { 0x88, 0xff, 0xff, 0xff };
2404 static BYTE int2[] = { 0x88, 0xff };
2405 static BYTE int3[] = { 0x23, 0xff };
2406 static BYTE int4[] = { 0x7f, 0x00 };
2407 static BYTE int5[] = { 0x7f };
2408 static BYTE int6[] = { 0x80, 0x00, 0x00, 0x00 };
2409 static BYTE int7[] = { 0x80, 0x00 };
2410
2411 static struct IntBlobTest
2412 {
2413     CRYPT_INTEGER_BLOB blob1;
2414     CRYPT_INTEGER_BLOB blob2;
2415     BOOL areEqual;
2416 } intBlobs[] = {
2417  { { sizeof(int1), int1 }, { sizeof(int2), int2 }, TRUE },
2418  { { sizeof(int3), int3 }, { sizeof(int3), int3 }, TRUE },
2419  { { sizeof(int4), int4 }, { sizeof(int5), int5 }, TRUE },
2420  { { sizeof(int6), int6 }, { sizeof(int7), int7 }, TRUE },
2421  { { sizeof(int1), int1 }, { sizeof(int7), int7 }, FALSE },
2422 };
2423
2424 static void testCompareIntegerBlob(void)
2425 {
2426     DWORD i;
2427     BOOL ret;
2428
2429     for (i = 0; i < sizeof(intBlobs) / sizeof(intBlobs[0]); i++)
2430     {
2431         ret = CertCompareIntegerBlob(&intBlobs[i].blob1, &intBlobs[i].blob2);
2432         ok(ret == intBlobs[i].areEqual,
2433          "%d: expected blobs %s compare\n", i, intBlobs[i].areEqual ?
2434          "to" : "not to");
2435     }
2436 }
2437
2438 static void testComparePublicKeyInfo(void)
2439 {
2440     BOOL ret;
2441     CERT_PUBLIC_KEY_INFO info1 = { { 0 } }, info2 = { { 0 } };
2442     static CHAR oid_rsa_rsa[]     = szOID_RSA_RSA;
2443     static CHAR oid_rsa_sha1rsa[] = szOID_RSA_SHA1RSA;
2444     static CHAR oid_x957_dsa[]    = szOID_X957_DSA;
2445     static BYTE bits1[] = { 1, 0 };
2446     static BYTE bits2[] = { 0 };
2447     static BYTE bits3[] = { 1 };
2448     static BYTE bits4[] = { 0x30,8, 2,1,0x81, 2,3,1,0,1 };
2449     static BYTE bits5[] = { 0x30,9, 2,2,0,0x81, 2,3,1,0,1 };
2450     static BYTE bits6[] = { 0x30,9, 2,2,0,0x82, 2,3,1,0,1 };
2451
2452     /* crashes
2453     ret = CertComparePublicKeyInfo(0, NULL, NULL);
2454      */
2455     /* Empty public keys compare */
2456     ret = CertComparePublicKeyInfo(0, &info1, &info2);
2457     ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
2458     /* Different OIDs appear to compare */
2459     info1.Algorithm.pszObjId = oid_rsa_rsa;
2460     info2.Algorithm.pszObjId = oid_rsa_sha1rsa;
2461     ret = CertComparePublicKeyInfo(0, &info1, &info2);
2462     ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
2463     info2.Algorithm.pszObjId = oid_x957_dsa;
2464     ret = CertComparePublicKeyInfo(0, &info1, &info2);
2465     ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
2466     info1.PublicKey.cbData = sizeof(bits1);
2467     info1.PublicKey.pbData = bits1;
2468     info1.PublicKey.cUnusedBits = 0;
2469     info2.PublicKey.cbData = sizeof(bits1);
2470     info2.PublicKey.pbData = bits1;
2471     info2.PublicKey.cUnusedBits = 0;
2472     ret = CertComparePublicKeyInfo(0, &info1, &info2);
2473     ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
2474     info2.Algorithm.pszObjId = oid_rsa_rsa;
2475     info1.PublicKey.cbData = sizeof(bits4);
2476     info1.PublicKey.pbData = bits4;
2477     info1.PublicKey.cUnusedBits = 0;
2478     info2.PublicKey.cbData = sizeof(bits5);
2479     info2.PublicKey.pbData = bits5;
2480     info2.PublicKey.cUnusedBits = 0;
2481     ret = CertComparePublicKeyInfo(0, &info1, &info2);
2482     ok(!ret, "CertComparePublicKeyInfo: as raw binary: keys should be unequal\n");
2483     ret = CertComparePublicKeyInfo(X509_ASN_ENCODING, &info1, &info2);
2484     ok(ret, "CertComparePublicKeyInfo: as ASN.1 encoded: keys should be equal\n");
2485     info1.PublicKey.cUnusedBits = 1;
2486     info2.PublicKey.cUnusedBits = 5;
2487     ret = CertComparePublicKeyInfo(X509_ASN_ENCODING, &info1, &info2);
2488     ok(ret, "CertComparePublicKeyInfo: ASN.1 encoding should ignore cUnusedBits\n");
2489     info1.PublicKey.cUnusedBits = 0;
2490     info2.PublicKey.cUnusedBits = 0;
2491     info1.PublicKey.cbData--; /* kill one byte, make ASN.1 encoded data invalid */
2492     ret = CertComparePublicKeyInfo(X509_ASN_ENCODING, &info1, &info2);
2493     ok(!ret, "CertComparePublicKeyInfo: comparing bad ASN.1 encoded key should fail\n");
2494     /* Even though they compare in their used bits, these do not compare */
2495     info1.PublicKey.cbData = sizeof(bits2);
2496     info1.PublicKey.pbData = bits2;
2497     info1.PublicKey.cUnusedBits = 0;
2498     info2.PublicKey.cbData = sizeof(bits3);
2499     info2.PublicKey.pbData = bits3;
2500     info2.PublicKey.cUnusedBits = 1;
2501     ret = CertComparePublicKeyInfo(0, &info1, &info2);
2502     /* Simple (non-comparing) case */
2503     ok(!ret, "Expected keys not to compare\n");
2504     info2.PublicKey.cbData = sizeof(bits1);
2505     info2.PublicKey.pbData = bits1;
2506     info2.PublicKey.cUnusedBits = 0;
2507     ret = CertComparePublicKeyInfo(0, &info1, &info2);
2508     ok(!ret, "Expected keys not to compare\n");
2509     /* ASN.1 encoded non-comparing case */
2510     info1.PublicKey.cbData = sizeof(bits5);
2511     info1.PublicKey.pbData = bits5;
2512     info1.PublicKey.cUnusedBits = 0;
2513     info2.PublicKey.cbData = sizeof(bits6);
2514     info2.PublicKey.pbData = bits6;
2515     info2.PublicKey.cUnusedBits = 0;
2516     ret = CertComparePublicKeyInfo(X509_ASN_ENCODING, &info1, &info2);
2517     ok(!ret, "CertComparePublicKeyInfo: different keys should be unequal\n");
2518 }
2519
2520 static void testHashPublicKeyInfo(void)
2521 {
2522     BOOL ret;
2523     CERT_PUBLIC_KEY_INFO info = { { 0 } };
2524     DWORD len;
2525
2526     /* Crash
2527     ret = CryptHashPublicKeyInfo(0, 0, 0, 0, NULL, NULL, NULL);
2528     ret = CryptHashPublicKeyInfo(0, 0, 0, 0, &info, NULL, NULL);
2529      */
2530     ret = CryptHashPublicKeyInfo(0, 0, 0, 0, NULL, NULL, &len);
2531     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2532      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2533     /* Crashes on some win9x boxes */
2534     if (0)
2535     {
2536         ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, NULL, NULL, &len);
2537         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2538          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
2539     }
2540     ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, &info, NULL, &len);
2541     ok(ret, "CryptHashPublicKeyInfo failed: %08x\n", GetLastError());
2542     ok(len == 16, "Expected hash size 16, got %d\n", len);
2543     if (len == 16)
2544     {
2545         static const BYTE emptyHash[] = { 0xb8,0x51,0x3a,0x31,0x0e,0x9f,0x40,
2546          0x36,0x9c,0x92,0x45,0x1b,0x9d,0xc8,0xf9,0xf6 };
2547         BYTE buf[16];
2548
2549         ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, &info, buf,
2550          &len);
2551         ok(ret, "CryptHashPublicKeyInfo failed: %08x\n", GetLastError());
2552         ok(!memcmp(buf, emptyHash, len), "Unexpected hash\n");
2553     }
2554 }
2555
2556 static void testCompareCert(void)
2557 {
2558     CERT_INFO info1 = { 0 }, info2 = { 0 };
2559     BOOL ret;
2560
2561     /* Crashes
2562     ret = CertCompareCertificate(X509_ASN_ENCODING, NULL, NULL);
2563      */
2564
2565     /* Certs with the same issuer and serial number are equal, even if they
2566      * differ in other respects (like subject).
2567      */
2568     info1.SerialNumber.pbData = serialNum;
2569     info1.SerialNumber.cbData = sizeof(serialNum);
2570     info1.Issuer.pbData = subjectName;
2571     info1.Issuer.cbData = sizeof(subjectName);
2572     info1.Subject.pbData = subjectName2;
2573     info1.Subject.cbData = sizeof(subjectName2);
2574     info2.SerialNumber.pbData = serialNum;
2575     info2.SerialNumber.cbData = sizeof(serialNum);
2576     info2.Issuer.pbData = subjectName;
2577     info2.Issuer.cbData = sizeof(subjectName);
2578     info2.Subject.pbData = subjectName;
2579     info2.Subject.cbData = sizeof(subjectName);
2580     ret = CertCompareCertificate(X509_ASN_ENCODING, &info1, &info2);
2581     ok(ret, "Expected certs to be equal\n");
2582
2583     info2.Issuer.pbData = subjectName2;
2584     info2.Issuer.cbData = sizeof(subjectName2);
2585     ret = CertCompareCertificate(X509_ASN_ENCODING, &info1, &info2);
2586     ok(!ret, "Expected certs not to be equal\n");
2587 }
2588
2589 static void testVerifySubjectCert(void)
2590 {
2591     BOOL ret;
2592     DWORD flags;
2593     PCCERT_CONTEXT context1, context2;
2594
2595     /* Crashes
2596     ret = CertVerifySubjectCertificateContext(NULL, NULL, NULL);
2597      */
2598     flags = 0;
2599     ret = CertVerifySubjectCertificateContext(NULL, NULL, &flags);
2600     ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
2601      GetLastError());
2602     flags = CERT_STORE_NO_CRL_FLAG;
2603     ret = CertVerifySubjectCertificateContext(NULL, NULL, &flags);
2604     ok(!ret && GetLastError() == E_INVALIDARG,
2605      "Expected E_INVALIDARG, got %08x\n", GetLastError());
2606
2607     flags = 0;
2608     context1 = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
2609      sizeof(bigCert));
2610     ret = CertVerifySubjectCertificateContext(NULL, context1, &flags);
2611     ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
2612      GetLastError());
2613     ret = CertVerifySubjectCertificateContext(context1, NULL, &flags);
2614     ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
2615      GetLastError());
2616     ret = CertVerifySubjectCertificateContext(context1, context1, &flags);
2617     ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
2618      GetLastError());
2619
2620     context2 = CertCreateCertificateContext(X509_ASN_ENCODING,
2621      bigCertWithDifferentSubject, sizeof(bigCertWithDifferentSubject));
2622     SetLastError(0xdeadbeef);
2623     ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
2624     ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
2625      GetLastError());
2626     flags = CERT_STORE_REVOCATION_FLAG;
2627     ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
2628     ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
2629      GetLastError());
2630     ok(flags == (CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG),
2631      "Expected CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG, got %08x\n",
2632      flags);
2633     flags = CERT_STORE_SIGNATURE_FLAG;
2634     ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
2635     ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
2636      GetLastError());
2637     ok(flags == CERT_STORE_SIGNATURE_FLAG,
2638      "Expected CERT_STORE_SIGNATURE_FLAG, got %08x\n", flags);
2639     CertFreeCertificateContext(context2);
2640
2641     CertFreeCertificateContext(context1);
2642 }
2643
2644 static void testVerifyRevocation(void)
2645 {
2646     BOOL ret;
2647     CERT_REVOCATION_STATUS status = { 0 };
2648     PCCERT_CONTEXT cert = CertCreateCertificateContext(X509_ASN_ENCODING,
2649      bigCert, sizeof(bigCert));
2650
2651     /* Crash
2652     ret = CertVerifyRevocation(0, 0, 0, NULL, 0, NULL, NULL);
2653      */
2654     SetLastError(0xdeadbeef);
2655     ret = CertVerifyRevocation(0, 0, 0, NULL, 0, NULL, &status);
2656     ok(!ret && GetLastError() == E_INVALIDARG,
2657      "Expected E_INVALIDARG, got %08x\n", GetLastError());
2658     status.cbSize = sizeof(status);
2659     ret = CertVerifyRevocation(0, 0, 0, NULL, 0, NULL, &status);
2660     ok(ret, "CertVerifyRevocation failed: %08x\n", GetLastError());
2661     ret = CertVerifyRevocation(0, 2, 0, NULL, 0, NULL, &status);
2662     ok(ret, "CertVerifyRevocation failed: %08x\n", GetLastError());
2663     ret = CertVerifyRevocation(2, 0, 0, NULL, 0, NULL, &status);
2664     ok(ret, "CertVerifyRevocation failed: %08x\n", GetLastError());
2665     SetLastError(0xdeadbeef);
2666     ret = CertVerifyRevocation(0, 0, 1, (void **)&cert, 0, NULL, &status);
2667     ok(!ret && GetLastError() == CRYPT_E_NO_REVOCATION_DLL,
2668      "Expected CRYPT_E_NO_REVOCATION_DLL, got %08x\n", GetLastError());
2669     SetLastError(0xdeadbeef);
2670     ret = CertVerifyRevocation(0, 2, 1, (void **)&cert, 0, NULL, &status);
2671     ok(!ret && GetLastError() == CRYPT_E_NO_REVOCATION_DLL,
2672      "Expected CRYPT_E_NO_REVOCATION_DLL, got %08x\n", GetLastError());
2673
2674     CertFreeCertificateContext(cert);
2675 }
2676
2677 static BYTE privKey[] = {
2678  0x07, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x52, 0x53, 0x41, 0x32, 0x00,
2679  0x02, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x79, 0x10, 0x1c, 0xd0, 0x6b, 0x10,
2680  0x18, 0x30, 0x94, 0x61, 0xdc, 0x0e, 0xcb, 0x96, 0x4e, 0x21, 0x3f, 0x79, 0xcd,
2681  0xa9, 0x17, 0x62, 0xbc, 0xbb, 0x61, 0x4c, 0xe0, 0x75, 0x38, 0x6c, 0xf3, 0xde,
2682  0x60, 0x86, 0x03, 0x97, 0x65, 0xeb, 0x1e, 0x6b, 0xdb, 0x53, 0x85, 0xad, 0x68,
2683  0x21, 0xf1, 0x5d, 0xe7, 0x1f, 0xe6, 0x53, 0xb4, 0xbb, 0x59, 0x3e, 0x14, 0x27,
2684  0xb1, 0x83, 0xa7, 0x3a, 0x54, 0xe2, 0x8f, 0x65, 0x8e, 0x6a, 0x4a, 0xcf, 0x3b,
2685  0x1f, 0x65, 0xff, 0xfe, 0xf1, 0x31, 0x3a, 0x37, 0x7a, 0x8b, 0xcb, 0xc6, 0xd4,
2686  0x98, 0x50, 0x36, 0x67, 0xe4, 0xa1, 0xe8, 0x7e, 0x8a, 0xc5, 0x23, 0xf2, 0x77,
2687  0xf5, 0x37, 0x61, 0x49, 0x72, 0x59, 0xe8, 0x3d, 0xf7, 0x60, 0xb2, 0x77, 0xca,
2688  0x78, 0x54, 0x6d, 0x65, 0x9e, 0x03, 0x97, 0x1b, 0x61, 0xbd, 0x0c, 0xd8, 0x06,
2689  0x63, 0xe2, 0xc5, 0x48, 0xef, 0xb3, 0xe2, 0x6e, 0x98, 0x7d, 0xbd, 0x4e, 0x72,
2690  0x91, 0xdb, 0x31, 0x57, 0xe3, 0x65, 0x3a, 0x49, 0xca, 0xec, 0xd2, 0x02, 0x4e,
2691  0x22, 0x7e, 0x72, 0x8e, 0xf9, 0x79, 0x84, 0x82, 0xdf, 0x7b, 0x92, 0x2d, 0xaf,
2692  0xc9, 0xe4, 0x33, 0xef, 0x89, 0x5c, 0x66, 0x99, 0xd8, 0x80, 0x81, 0x47, 0x2b,
2693  0xb1, 0x66, 0x02, 0x84, 0x59, 0x7b, 0xc3, 0xbe, 0x98, 0x45, 0x4a, 0x3d, 0xdd,
2694  0xea, 0x2b, 0xdf, 0x4e, 0xb4, 0x24, 0x6b, 0xec, 0xe7, 0xd9, 0x0c, 0x45, 0xb8,
2695  0xbe, 0xca, 0x69, 0x37, 0x92, 0x4c, 0x38, 0x6b, 0x96, 0x6d, 0xcd, 0x86, 0x67,
2696  0x5c, 0xea, 0x54, 0x94, 0xa4, 0xca, 0xa4, 0x02, 0xa5, 0x21, 0x4d, 0xae, 0x40,
2697  0x8f, 0x9d, 0x51, 0x83, 0xf2, 0x3f, 0x33, 0xc1, 0x72, 0xb4, 0x1d, 0x94, 0x6e,
2698  0x7d, 0xe4, 0x27, 0x3f, 0xea, 0xff, 0xe5, 0x9b, 0xa7, 0x5e, 0x55, 0x8e, 0x0d,
2699  0x69, 0x1c, 0x7a, 0xff, 0x81, 0x9d, 0x53, 0x52, 0x97, 0x9a, 0x76, 0x79, 0xda,
2700  0x93, 0x32, 0x16, 0xec, 0x69, 0x51, 0x1a, 0x4e, 0xc3, 0xf1, 0x72, 0x80, 0x78,
2701  0x5e, 0x66, 0x4a, 0x8d, 0x85, 0x2f, 0x3f, 0xb2, 0xa7 };
2702
2703 static const BYTE selfSignedCert[] = {
2704  0x30, 0x82, 0x01, 0x1f, 0x30, 0x81, 0xce, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
2705  0x10, 0xeb, 0x0d, 0x57, 0x2a, 0x9c, 0x09, 0xba, 0xa4, 0x4a, 0xb7, 0x25, 0x49,
2706  0xd9, 0x3e, 0xb5, 0x73, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d,
2707  0x05, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
2708  0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30,
2709  0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x36, 0x32, 0x39, 0x30, 0x35, 0x30, 0x30,
2710  0x34, 0x36, 0x5a, 0x17, 0x0d, 0x30, 0x37, 0x30, 0x36, 0x32, 0x39, 0x31, 0x31,
2711  0x30, 0x30, 0x34, 0x36, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
2712  0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e,
2713  0x67, 0x00, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
2714  0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
2715  0x00, 0xe2, 0x54, 0x3a, 0xa7, 0x83, 0xb1, 0x27, 0x14, 0x3e, 0x59, 0xbb, 0xb4,
2716  0x53, 0xe6, 0x1f, 0xe7, 0x5d, 0xf1, 0x21, 0x68, 0xad, 0x85, 0x53, 0xdb, 0x6b,
2717  0x1e, 0xeb, 0x65, 0x97, 0x03, 0x86, 0x60, 0xde, 0xf3, 0x6c, 0x38, 0x75, 0xe0,
2718  0x4c, 0x61, 0xbb, 0xbc, 0x62, 0x17, 0xa9, 0xcd, 0x79, 0x3f, 0x21, 0x4e, 0x96,
2719  0xcb, 0x0e, 0xdc, 0x61, 0x94, 0x30, 0x18, 0x10, 0x6b, 0xd0, 0x1c, 0x10, 0x79,
2720  0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
2721  0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x25, 0x90, 0x53, 0x34, 0xd9, 0x56, 0x41,
2722  0x5e, 0xdb, 0x7e, 0x01, 0x36, 0xec, 0x27, 0x61, 0x5e, 0xb7, 0x4d, 0x90, 0x66,
2723  0xa2, 0xe1, 0x9d, 0x58, 0x76, 0xd4, 0x9c, 0xba, 0x2c, 0x84, 0xc6, 0x83, 0x7a,
2724  0x22, 0x0d, 0x03, 0x69, 0x32, 0x1a, 0x6d, 0xcb, 0x0c, 0x15, 0xb3, 0x6b, 0xc7,
2725  0x0a, 0x8c, 0xb4, 0x5c, 0x34, 0x78, 0xe0, 0x3c, 0x9c, 0xe9, 0xf3, 0x30, 0x9f,
2726  0xa8, 0x76, 0x57, 0x92, 0x36 };
2727
2728 static const BYTE exportedPublicKeyBlob[] = {
2729 0x06,0x02,0x00,0x00,0x00,0xa4,0x00,0x00,0x52,0x53,0x41,0x31,0x00,0x02,0x00,0x00,
2730 0x01,0x00,0x01,0x00,0x79,0x10,0x1c,0xd0,0x6b,0x10,0x18,0x30,0x94,0x61,0xdc,0x0e,
2731 0xcb,0x96,0x4e,0x21,0x3f,0x79,0xcd,0xa9,0x17,0x62,0xbc,0xbb,0x61,0x4c,0xe0,0x75,
2732 0x38,0x6c,0xf3,0xde,0x60,0x86,0x03,0x97,0x65,0xeb,0x1e,0x6b,0xdb,0x53,0x85,0xad,
2733 0x68,0x21,0xf1,0x5d,0xe7,0x1f,0xe6,0x53,0xb4,0xbb,0x59,0x3e,0x14,0x27,0xb1,0x83,
2734 0xa7,0x3a,0x54,0xe2 };
2735
2736 static const BYTE asnEncodedPublicKey[] = {
2737 0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7,0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,
2738 0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21,0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,
2739 0x65,0x97,0x03,0x86,0x60,0xde,0xf3,0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,
2740 0x17,0xa9,0xcd,0x79,0x3f,0x21,0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,
2741 0x6b,0xd0,0x1c,0x10,0x79,0x02,0x03,0x01,0x00,0x01 };
2742
2743 static void testAcquireCertPrivateKey(void)
2744 {
2745     BOOL ret;
2746     PCCERT_CONTEXT cert;
2747     HCRYPTPROV csp;
2748     DWORD size, keySpec;
2749     BOOL callerFree;
2750     CRYPT_KEY_PROV_INFO keyProvInfo;
2751     HCRYPTKEY key;
2752     WCHAR ms_def_prov_w[MAX_PATH];
2753
2754     if (!pCryptAcquireCertificatePrivateKey)
2755     {
2756         skip("CryptAcquireCertificatePrivateKey() is not available\n");
2757         return;
2758     }
2759
2760     lstrcpyW(ms_def_prov_w, MS_DEF_PROV_W);
2761
2762     keyProvInfo.pwszContainerName = cspNameW;
2763     keyProvInfo.pwszProvName = ms_def_prov_w;
2764     keyProvInfo.dwProvType = PROV_RSA_FULL;
2765     keyProvInfo.dwFlags = 0;
2766     keyProvInfo.cProvParam = 0;
2767     keyProvInfo.rgProvParam = NULL;
2768     keyProvInfo.dwKeySpec = AT_SIGNATURE;
2769
2770     pCryptAcquireContextW(NULL, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
2771      CRYPT_DELETEKEYSET);
2772
2773     cert = CertCreateCertificateContext(X509_ASN_ENCODING, selfSignedCert,
2774      sizeof(selfSignedCert));
2775
2776     /* Crash
2777     ret = pCryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, NULL, NULL);
2778     ret = pCryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, NULL,
2779      &callerFree);
2780     ret = pCryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, &keySpec,
2781      NULL);
2782     ret = pCryptAcquireCertificatePrivateKey(NULL, 0, NULL, &csp, NULL, NULL);
2783     ret = pCryptAcquireCertificatePrivateKey(NULL, 0, NULL, &csp, &keySpec,
2784      &callerFree);
2785     ret = pCryptAcquireCertificatePrivateKey(cert, 0, NULL, NULL, NULL, NULL);
2786      */
2787
2788     /* Missing private key */
2789     ret = pCryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, NULL, NULL);
2790     ok(!ret && GetLastError() == CRYPT_E_NO_KEY_PROPERTY,
2791      "Expected CRYPT_E_NO_KEY_PROPERTY, got %08x\n", GetLastError());
2792     ret = pCryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, &keySpec,
2793      &callerFree);
2794     ok(!ret && GetLastError() == CRYPT_E_NO_KEY_PROPERTY,
2795      "Expected CRYPT_E_NO_KEY_PROPERTY, got %08x\n", GetLastError());
2796     CertSetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, 0,
2797      &keyProvInfo);
2798     ret = pCryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, &keySpec,
2799      &callerFree);
2800     ok(!ret && GetLastError() == CRYPT_E_NO_KEY_PROPERTY,
2801      "Expected CRYPT_E_NO_KEY_PROPERTY, got %08x\n", GetLastError());
2802
2803     pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
2804      CRYPT_NEWKEYSET);
2805     ret = CryptImportKey(csp, privKey, sizeof(privKey), 0, 0, &key);
2806     ok(ret, "CryptImportKey failed: %08x\n", GetLastError());
2807     if (ret)
2808     {
2809         HCRYPTPROV certCSP;
2810         DWORD size;
2811         CERT_KEY_CONTEXT keyContext;
2812
2813         /* Don't cache provider */
2814         ret = pCryptAcquireCertificatePrivateKey(cert, 0, NULL, &certCSP,
2815          &keySpec, &callerFree);
2816         ok(ret, "CryptAcquireCertificatePrivateKey failed: %08x\n",
2817          GetLastError());
2818         ok(callerFree, "Expected callerFree to be TRUE\n");
2819         CryptReleaseContext(certCSP, 0);
2820         ret = pCryptAcquireCertificatePrivateKey(cert, 0, NULL, &certCSP,
2821          NULL, NULL);
2822         ok(ret, "CryptAcquireCertificatePrivateKey failed: %08x\n",
2823          GetLastError());
2824         CryptReleaseContext(certCSP, 0);
2825
2826         /* Use the key prov info's caching (there shouldn't be any) */
2827         ret = pCryptAcquireCertificatePrivateKey(cert,
2828          CRYPT_ACQUIRE_USE_PROV_INFO_FLAG, NULL, &certCSP, &keySpec,
2829          &callerFree);
2830         ok(ret, "CryptAcquireCertificatePrivateKey failed: %08x\n",
2831          GetLastError());
2832         ok(callerFree, "Expected callerFree to be TRUE\n");
2833         CryptReleaseContext(certCSP, 0);
2834
2835         /* Cache it (and check that it's cached) */
2836         ret = pCryptAcquireCertificatePrivateKey(cert,
2837          CRYPT_ACQUIRE_CACHE_FLAG, NULL, &certCSP, &keySpec, &callerFree);
2838         ok(ret, "CryptAcquireCertificatePrivateKey failed: %08x\n",
2839          GetLastError());
2840         ok(!callerFree, "Expected callerFree to be FALSE\n");
2841         size = sizeof(keyContext);
2842         ret = CertGetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID,
2843          &keyContext, &size);
2844         ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
2845          GetLastError());
2846
2847         /* Remove the cached provider */
2848         CryptReleaseContext(keyContext.hCryptProv, 0);
2849         CertSetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID, 0,
2850          NULL);
2851         /* Allow caching via the key prov info */
2852         keyProvInfo.dwFlags = CERT_SET_KEY_CONTEXT_PROP_ID;
2853         CertSetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, 0,
2854          &keyProvInfo);
2855         /* Now use the key prov info's caching */
2856         ret = pCryptAcquireCertificatePrivateKey(cert,
2857          CRYPT_ACQUIRE_USE_PROV_INFO_FLAG, NULL, &certCSP, &keySpec,
2858          &callerFree);
2859         ok(ret, "CryptAcquireCertificatePrivateKey failed: %08x\n",
2860          GetLastError());
2861         ok(!callerFree, "Expected callerFree to be FALSE\n");
2862         size = sizeof(keyContext);
2863         ret = CertGetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID,
2864          &keyContext, &size);
2865         ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
2866          GetLastError());
2867         CryptReleaseContext(certCSP, 0);
2868
2869         CryptDestroyKey(key);
2870     }
2871
2872     /* Some sanity-checking on public key exporting */
2873     ret = CryptImportPublicKeyInfo(csp, X509_ASN_ENCODING,
2874      &cert->pCertInfo->SubjectPublicKeyInfo, &key);
2875     ok(ret, "CryptImportPublicKeyInfo failed: %08x\n", GetLastError());
2876     if (ret)
2877     {
2878         ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &size);
2879         ok(ret, "CryptExportKey failed: %08x\n", GetLastError());
2880         if (ret)
2881         {
2882             LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, size), encodedKey;
2883
2884             ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, buf, &size);
2885             ok(ret, "CryptExportKey failed: %08x\n", GetLastError());
2886             ok(size == sizeof(exportedPublicKeyBlob), "Unexpected size %d\n",
2887              size);
2888             ok(!memcmp(buf, exportedPublicKeyBlob, size), "Unexpected value\n");
2889             ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, RSA_CSP_PUBLICKEYBLOB,
2890              buf, CRYPT_ENCODE_ALLOC_FLAG, NULL, &encodedKey, &size);
2891             ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2892             if (ret)
2893             {
2894                 ok(size == sizeof(asnEncodedPublicKey), "Unexpected size %d\n",
2895                  size);
2896                 ok(!memcmp(encodedKey, asnEncodedPublicKey, size),
2897                  "Unexpected value\n");
2898                 LocalFree(encodedKey);
2899             }
2900             HeapFree(GetProcessHeap(), 0, buf);
2901         }
2902         CryptDestroyKey(key);
2903     }
2904     ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
2905      NULL, 0, NULL, NULL, &size);
2906     ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
2907     if (ret)
2908     {
2909         PCERT_PUBLIC_KEY_INFO info = HeapAlloc(GetProcessHeap(), 0, size);
2910
2911         ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
2912          NULL, 0, NULL, info, &size);
2913         ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
2914         if (ret)
2915         {
2916             ok(info->PublicKey.cbData == sizeof(asnEncodedPublicKey),
2917              "Unexpected size %d\n", info->PublicKey.cbData);
2918             ok(!memcmp(info->PublicKey.pbData, asnEncodedPublicKey,
2919              info->PublicKey.cbData), "Unexpected value\n");
2920         }
2921         HeapFree(GetProcessHeap(), 0, info);
2922     }
2923
2924     CryptReleaseContext(csp, 0);
2925     pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
2926      CRYPT_DELETEKEYSET);
2927
2928     CertFreeCertificateContext(cert);
2929 }
2930
2931 static void testGetPublicKeyLength(void)
2932 {
2933     static char oid_rsa_rsa[] = szOID_RSA_RSA;
2934     static char oid_rsa_dh[] = szOID_RSA_DH;
2935     static char bogusOID[] = "1.2.3";
2936     DWORD ret;
2937     CERT_PUBLIC_KEY_INFO info = { { 0 } };
2938     BYTE bogusKey[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
2939     BYTE key[] = { 0x30,0x0f,0x02,0x08,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
2940      0x02,0x03,0x01,0x00,0x01 };
2941
2942     /* Crashes
2943     ret = CertGetPublicKeyLength(0, NULL);
2944      */
2945     /* With an empty public key info */
2946     SetLastError(0xdeadbeef);
2947     ret = CertGetPublicKeyLength(0, &info);
2948     ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
2949      "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
2950      ret, GetLastError());
2951     SetLastError(0xdeadbeef);
2952     ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
2953     ok(ret == 0 && GetLastError() == CRYPT_E_ASN1_EOD,
2954      "Expected length 0 and CRYPT_E_ASN1_EOD, got length %d, %08x\n",
2955      ret, GetLastError());
2956     /* With a nearly-empty public key info */
2957     info.Algorithm.pszObjId = oid_rsa_rsa;
2958     SetLastError(0xdeadbeef);
2959     ret = CertGetPublicKeyLength(0, &info);
2960     ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
2961      "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
2962      ret, GetLastError());
2963     SetLastError(0xdeadbeef);
2964     ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
2965     ok(ret == 0 && GetLastError() == CRYPT_E_ASN1_EOD,
2966      "Expected length 0 and CRYPT_E_ASN1_EOD, got length %d, %08x\n",
2967      ret, GetLastError());
2968     /* With a bogus key */
2969     info.PublicKey.cbData = sizeof(bogusKey);
2970     info.PublicKey.pbData = bogusKey;
2971     SetLastError(0xdeadbeef);
2972     ret = CertGetPublicKeyLength(0, &info);
2973     ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
2974      "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
2975      ret, GetLastError());
2976     SetLastError(0xdeadbeef);
2977     ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
2978     ok(ret == 0 && GetLastError() == CRYPT_E_ASN1_BADTAG,
2979      "Expected length 0 and CRYPT_E_ASN1_BADTAGTAG, got length %d, %08x\n",
2980      ret, GetLastError());
2981     /* With a believable RSA key but a bogus OID */
2982     info.Algorithm.pszObjId = bogusOID;
2983     info.PublicKey.cbData = sizeof(key);
2984     info.PublicKey.pbData = key;
2985     SetLastError(0xdeadbeef);
2986     ret = CertGetPublicKeyLength(0, &info);
2987     ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
2988      "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
2989      ret, GetLastError());
2990     SetLastError(0xdeadbeef);
2991     ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
2992     ok(ret == 56, "Expected length 56, got %d\n", ret);
2993     /* An RSA key with the DH OID */
2994     info.Algorithm.pszObjId = oid_rsa_dh;
2995     SetLastError(0xdeadbeef);
2996     ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
2997     ok(ret == 0 && GetLastError() == CRYPT_E_ASN1_BADTAG,
2998      "Expected length 0 and CRYPT_E_ASN1_BADTAG, got length %d, %08x\n",
2999      ret, GetLastError());
3000     /* With the RSA OID */
3001     info.Algorithm.pszObjId = oid_rsa_rsa;
3002     SetLastError(0xdeadbeef);
3003     ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
3004     ok(ret == 56, "Expected length 56, got %d\n", ret);
3005     /* With the RSA OID and a message encoding */
3006     info.Algorithm.pszObjId = oid_rsa_rsa;
3007     SetLastError(0xdeadbeef);
3008     ret = CertGetPublicKeyLength(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, &info);
3009     ok(ret == 56, "Expected length 56, got %d\n", ret);
3010 }
3011
3012 START_TEST(cert)
3013 {
3014     init_function_pointers();
3015
3016     testAddCert();
3017     testCertProperties();
3018     testDupCert();
3019     testFindCert();
3020     testGetSubjectCert();
3021     testGetIssuerCert();
3022
3023     testCryptHashCert();
3024     testCertSigs();
3025     testSignAndEncodeCert();
3026     testCreateSelfSignCert();
3027     testKeyUsage();
3028     testGetValidUsages();
3029     testCompareCertName();
3030     testCompareIntegerBlob();
3031     testComparePublicKeyInfo();
3032     testHashPublicKeyInfo();
3033     testCompareCert();
3034     testVerifySubjectCert();
3035     testVerifyRevocation();
3036     testAcquireCertPrivateKey();
3037     testGetPublicKeyLength();
3038 }