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