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