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