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