mcicda: Exclude unused headers.
[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 * pCryptVerifyCertificateSignatureEx)
33                         (HCRYPTPROV, DWORD, DWORD, void *, DWORD, void *, DWORD, void *);
34
35 #define CRYPT_GET_PROC(func)                                       \
36     p ## func = (void *)GetProcAddress(hCrypt32, #func);           \
37     if(!p ## func)                                                 \
38         trace("GetProcAddress(hCrypt32, \"%s\") failed\n", #func); \
39
40 static void init_function_pointers(void)
41 {
42     HMODULE hCrypt32;
43
44     pCryptVerifyCertificateSignatureEx = NULL;
45
46     hCrypt32 = GetModuleHandleA("crypt32.dll");
47     assert(hCrypt32);
48
49     CRYPT_GET_PROC(CryptVerifyCertificateSignatureEx);
50 }
51
52 static BYTE subjectName[] = { 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
53  0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
54  0x6e, 0x67, 0x00 };
55 static BYTE serialNum[] = { 1 };
56 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
57  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
58  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
59  0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
60  0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
61  0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
62  0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
63  0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
64  0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
65  0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
66 static BYTE bigCertHash[] = { 0x6e, 0x30, 0x90, 0x71, 0x5f, 0xd9, 0x23,
67  0x56, 0xeb, 0xae, 0x25, 0x40, 0xe6, 0x22, 0xda, 0x19, 0x26, 0x02, 0xa6, 0x08 };
68
69 static const BYTE bigCertWithDifferentSubject[] = { 0x30, 0x7a, 0x02, 0x01, 0x02,
70  0x30, 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
71  0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67,
72  0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31,
73  0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
74  0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15,
75  0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c,
76  0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06,
77  0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55,
78  0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02,
79  0x01, 0x01 };
80 static const BYTE bigCertWithDifferentIssuer[] = { 0x30, 0x7a, 0x02, 0x01,
81  0x01, 0x30, 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
82  0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e,
83  0x67, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
84  0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30,
85  0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30,
86  0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
87  0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02,
88  0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03,
89  0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff,
90  0x02, 0x01, 0x01 };
91
92 static BYTE subjectName2[] = { 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
93  0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61,
94  0x6e, 0x67, 0x00 };
95 static const BYTE bigCert2[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
96  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
97  0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
98  0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
99  0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
100  0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
101  0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20,
102  0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
103  0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
104  0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
105 static const BYTE bigCert2WithDifferentSerial[] = { 0x30, 0x7a, 0x02, 0x01,
106  0x02, 0x30, 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
107  0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e,
108  0x67, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
109  0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30,
110  0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30,
111  0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41,
112  0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02,
113  0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03,
114  0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff,
115  0x02, 0x01, 0x01 };
116 static BYTE bigCert2Hash[] = { 0x4a, 0x7f, 0x32, 0x1f, 0xcf, 0x3b, 0xc0,
117  0x87, 0x48, 0x2b, 0xa1, 0x86, 0x54, 0x18, 0xe4, 0x3a, 0x0e, 0x53, 0x7e, 0x2b };
118
119 static const BYTE certWithUsage[] = { 0x30, 0x81, 0x93, 0x02, 0x01, 0x01, 0x30,
120  0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04,
121  0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00,
122  0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
123  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
124  0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31,
125  0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61,
126  0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00,
127  0x03, 0x01, 0x00, 0xa3, 0x2f, 0x30, 0x2d, 0x30, 0x2b, 0x06, 0x03, 0x55, 0x1d,
128  0x25, 0x01, 0x01, 0xff, 0x04, 0x21, 0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01,
129  0x05, 0x05, 0x07, 0x03, 0x03, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
130  0x03, 0x02, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
131
132 static void testAddCert(void)
133 {
134     HCERTSTORE store;
135     HCERTSTORE collection;
136     PCCERT_CONTEXT context;
137     BOOL ret;
138
139     store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
140      CERT_STORE_CREATE_NEW_FLAG, NULL);
141     ok(store != NULL, "CertOpenStore failed: %d\n", GetLastError());
142     if (!store)
143         return;
144
145     /* Weird--bad add disposition leads to an access violation in Windows.
146      */
147     ret = CertAddEncodedCertificateToStore(0, X509_ASN_ENCODING, bigCert,
148      sizeof(bigCert), 0, NULL);
149     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
150      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
151     ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
152      bigCert, sizeof(bigCert), 0, NULL);
153     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
154      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
155
156     /* Weird--can add a cert to the NULL store (does this have special
157      * meaning?)
158      */
159     context = NULL;
160     ret = CertAddEncodedCertificateToStore(0, X509_ASN_ENCODING, bigCert,
161      sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
162     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
163      GetLastError());
164     if (context)
165         CertFreeCertificateContext(context);
166
167     ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
168      bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
169     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
170      GetLastError());
171     ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
172      bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, NULL);
173     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
174      GetLastError());
175     /* This has the same name as bigCert, so finding isn't done by name */
176     ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
177      certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, &context);
178     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
179      GetLastError());
180     ok(context != NULL, "Expected a context\n");
181     if (context)
182     {
183         CRYPT_DATA_BLOB hash = { sizeof(bigCert2Hash), bigCert2Hash };
184
185         /* Duplicate (AddRef) the context so we can still use it after
186          * deleting it from the store.
187          */
188         CertDuplicateCertificateContext(context);
189         CertDeleteCertificateFromStore(context);
190         /* Set the same hash as bigCert2, and try to readd it */
191         ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID,
192          0, &hash);
193         ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
194          GetLastError());
195         ret = CertAddCertificateContextToStore(store, context,
196          CERT_STORE_ADD_NEW, NULL);
197         /* The failure is a bit odd (CRYPT_E_ASN1_BADTAG), so just check
198          * that it fails.
199          */
200         ok(!ret, "Expected failure\n");
201         CertFreeCertificateContext(context);
202     }
203     context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert2,
204      sizeof(bigCert2));
205     ok(context != NULL, "Expected a context\n");
206     if (context)
207     {
208         /* Try to readd bigCert2 to the store */
209         ret = CertAddCertificateContextToStore(store, context,
210          CERT_STORE_ADD_NEW, NULL);
211         ok(!ret && GetLastError() == CRYPT_E_EXISTS,
212          "Expected CRYPT_E_EXISTS, got %08x\n", GetLastError());
213         CertFreeCertificateContext(context);
214     }
215
216     /* Adding a cert with the same issuer name and serial number (but
217      * different subject) as an existing cert succeeds.
218      */
219     context = NULL;
220     ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
221      bigCert2WithDifferentSerial, sizeof(bigCert2WithDifferentSerial),
222      CERT_STORE_ADD_NEW, &context);
223     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
224      GetLastError());
225     if (context)
226         CertDeleteCertificateFromStore(context);
227
228     /* Adding a cert with the same subject name and serial number (but
229      * different issuer) as an existing cert succeeds.
230      */
231     context = NULL;
232     ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
233      bigCertWithDifferentSubject, sizeof(bigCertWithDifferentSubject),
234      CERT_STORE_ADD_NEW, &context);
235     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
236      GetLastError());
237     if (context)
238         CertDeleteCertificateFromStore(context);
239
240     /* Adding a cert with the same issuer name and serial number (but
241      * different otherwise) as an existing cert succeeds.
242      */
243     context = NULL;
244     ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
245      bigCertWithDifferentIssuer, sizeof(bigCertWithDifferentIssuer),
246      CERT_STORE_ADD_NEW, &context);
247     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
248      GetLastError());
249     if (context)
250         CertDeleteCertificateFromStore(context);
251
252     collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
253      CERT_STORE_CREATE_NEW_FLAG, NULL);
254     ok(collection != NULL, "CertOpenStore failed: %08x\n", GetLastError());
255     if (collection)
256     {
257         /* Add store to the collection, but disable updates */
258         CertAddStoreToCollection(collection, store, 0, 0);
259
260         context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert2,
261          sizeof(bigCert2));
262         ok(context != NULL, "Expected a context\n");
263         if (context)
264         {
265             /* Try to readd bigCert2 to the collection */
266             ret = CertAddCertificateContextToStore(collection, context,
267              CERT_STORE_ADD_NEW, NULL);
268             ok(!ret && GetLastError() == CRYPT_E_EXISTS,
269              "Expected CRYPT_E_EXISTS, got %08x\n", GetLastError());
270             /* Replacing an existing certificate context is allowed, even
271              * though updates to the collection aren't..
272              */
273             ret = CertAddCertificateContextToStore(collection, context,
274              CERT_STORE_ADD_REPLACE_EXISTING, NULL);
275             ok(ret, "CertAddCertificateContextToStore failed: %08x\n",
276              GetLastError());
277             /* but adding a new certificate isn't allowed. */
278             ret = CertAddCertificateContextToStore(collection, context,
279              CERT_STORE_ADD_ALWAYS, NULL);
280             ok(!ret && GetLastError() == E_ACCESSDENIED,
281              "Expected E_ACCESSDENIED, got %08x\n", GetLastError());
282             CertFreeCertificateContext(context);
283         }
284
285         CertCloseStore(collection, 0);
286     }
287
288     CertCloseStore(store, 0);
289 }
290
291 static void checkHash(const BYTE *data, DWORD dataLen, ALG_ID algID,
292  PCCERT_CONTEXT context, DWORD propID)
293 {
294     BYTE hash[20] = { 0 }, hashProperty[20];
295     BOOL ret;
296     DWORD size;
297
298     memset(hash, 0, sizeof(hash));
299     memset(hashProperty, 0, sizeof(hashProperty));
300     size = sizeof(hash);
301     ret = CryptHashCertificate(0, algID, 0, data, dataLen, hash, &size);
302     ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
303     ret = CertGetCertificateContextProperty(context, propID, hashProperty,
304      &size);
305     ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
306      GetLastError());
307     ok(!memcmp(hash, hashProperty, size), "Unexpected hash for property %d\n",
308      propID);
309 }
310
311 static WCHAR cspNameW[] = { 'W','i','n','e','C','r','y','p','t','T','e','m','p',0 };
312
313 static void testCertProperties(void)
314 {
315     PCCERT_CONTEXT context = CertCreateCertificateContext(X509_ASN_ENCODING,
316      bigCert, sizeof(bigCert));
317     DWORD propID, numProps, access, size;
318     BOOL ret;
319     BYTE hash[20] = { 0 }, hashProperty[20];
320     CRYPT_DATA_BLOB blob;
321     CERT_KEY_CONTEXT keyContext;
322     HCRYPTPROV csp;
323
324     ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
325      GetLastError());
326     if (!context)
327         return;
328
329     /* This crashes
330     propID = CertEnumCertificateContextProperties(NULL, 0);
331      */
332
333     propID = 0;
334     numProps = 0;
335     do {
336         propID = CertEnumCertificateContextProperties(context, propID);
337         if (propID)
338             numProps++;
339     } while (propID != 0);
340     ok(numProps == 0, "Expected 0 properties, got %d\n", numProps);
341
342     /* Tests with a NULL cert context.  Prop ID 0 fails.. */
343     ret = CertSetCertificateContextProperty(NULL, 0, 0, NULL);
344     ok(!ret && GetLastError() == E_INVALIDARG,
345      "Expected E_INVALIDARG, got %08x\n", GetLastError());
346     /* while this just crashes.
347     ret = CertSetCertificateContextProperty(NULL,
348      CERT_KEY_PROV_HANDLE_PROP_ID, 0, NULL);
349      */
350
351     ret = CertSetCertificateContextProperty(context, 0, 0, NULL);
352     ok(!ret && GetLastError() == E_INVALIDARG,
353      "Expected E_INVALIDARG, got %08x\n", GetLastError());
354     /* Can't set the cert property directly, this crashes.
355     ret = CertSetCertificateContextProperty(context,
356      CERT_CERT_PROP_ID, 0, bigCert2);
357      */
358
359     /* These all crash.
360     ret = CertGetCertificateContextProperty(context,
361      CERT_ACCESS_STATE_PROP_ID, 0, NULL);
362     ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID, 
363      NULL, NULL);
364     ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID, 
365      hashProperty, NULL);
366      */
367     /* A missing prop */
368     size = 0;
369     ret = CertGetCertificateContextProperty(context,
370      CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
371     ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
372      "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
373     /* And, an implicit property */
374     size = sizeof(access);
375     ret = CertGetCertificateContextProperty(context,
376      CERT_ACCESS_STATE_PROP_ID, &access, &size);
377     ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
378      GetLastError());
379     ok(!(access & CERT_ACCESS_STATE_WRITE_PERSIST_FLAG),
380      "Didn't expect a persisted cert\n");
381     /* Trying to set this "read only" property crashes.
382     access |= CERT_ACCESS_STATE_WRITE_PERSIST_FLAG;
383     ret = CertSetCertificateContextProperty(context,
384      CERT_ACCESS_STATE_PROP_ID, 0, &access);
385      */
386
387     /* Can I set the hash to an invalid hash? */
388     blob.pbData = hash;
389     blob.cbData = sizeof(hash);
390     ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID, 0,
391      &blob);
392     ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
393      GetLastError());
394     size = sizeof(hashProperty);
395     ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
396      hashProperty, &size);
397     ok(!memcmp(hashProperty, hash, sizeof(hash)), "Unexpected hash\n");
398     /* Delete the (bogus) hash, and get the real one */
399     ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID, 0,
400      NULL);
401     ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
402      GetLastError());
403     checkHash(bigCert, sizeof(bigCert), CALG_SHA1, context,
404      CERT_HASH_PROP_ID);
405
406     /* Now that the hash property is set, we should get one property when
407      * enumerating.
408      */
409     propID = 0;
410     numProps = 0;
411     do {
412         propID = CertEnumCertificateContextProperties(context, propID);
413         if (propID)
414             numProps++;
415     } while (propID != 0);
416     ok(numProps == 1, "Expected 1 properties, got %d\n", numProps);
417
418     /* Check a few other implicit properties */
419     checkHash(bigCert, sizeof(bigCert), CALG_MD5, context,
420      CERT_MD5_HASH_PROP_ID);
421     checkHash(
422      context->pCertInfo->Subject.pbData,
423      context->pCertInfo->Subject.cbData,
424      CALG_MD5, context, CERT_SUBJECT_NAME_MD5_HASH_PROP_ID);
425     checkHash(
426      context->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData,
427      context->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData,
428      CALG_MD5, context, CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID);
429
430     /* Test key identifiers and handles and such */
431     size = 0;
432     ret = CertGetCertificateContextProperty(context,
433      CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size);
434     ok(!ret && GetLastError() == ERROR_INVALID_DATA,
435      "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
436     size = sizeof(CERT_KEY_CONTEXT);
437     ret = CertGetCertificateContextProperty(context,
438      CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size);
439     ok(!ret && GetLastError() == ERROR_INVALID_DATA,
440      "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
441     ret = CertGetCertificateContextProperty(context,
442      CERT_KEY_IDENTIFIER_PROP_ID, &keyContext, &size);
443     ok(!ret && GetLastError() == ERROR_INVALID_DATA,
444      "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
445     /* Key context with an invalid size */
446     keyContext.cbSize = 0;
447     ret = CertSetCertificateContextProperty(context,
448      CERT_KEY_IDENTIFIER_PROP_ID, 0, &keyContext);
449     ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
450      GetLastError());
451     size = sizeof(keyContext);
452     ret = CertGetCertificateContextProperty(context,
453      CERT_KEY_IDENTIFIER_PROP_ID, &keyContext, &size);
454     ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
455      GetLastError());
456     keyContext.cbSize = sizeof(keyContext);
457     keyContext.hCryptProv = 0;
458     keyContext.dwKeySpec = AT_SIGNATURE;
459     /* Crash
460     ret = CertSetCertificateContextProperty(context,
461      CERT_KEY_IDENTIFIER_PROP_ID, 0, &keyContext);
462     ret = CertSetCertificateContextProperty(context,
463      CERT_KEY_IDENTIFIER_PROP_ID, CERT_STORE_NO_CRYPT_RELEASE_FLAG,
464      &keyContext);
465      */
466     ret = CryptAcquireContextW(&csp, cspNameW,
467      MS_DEF_PROV_W, PROV_RSA_FULL, CRYPT_NEWKEYSET);
468     ok(ret, "CryptAcquireContextW failed: %08x\n", GetLastError());
469     keyContext.hCryptProv = csp;
470     ret = CertSetCertificateContextProperty(context,
471      CERT_KEY_CONTEXT_PROP_ID, 0, &keyContext);
472     ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
473      GetLastError());
474     /* Now that that's set, the key prov handle property is also gettable.
475      */
476     size = sizeof(DWORD);
477     ret = CertGetCertificateContextProperty(context,
478      CERT_KEY_PROV_HANDLE_PROP_ID, &keyContext.hCryptProv, &size);
479     ok(ret, "Expected to get the CERT_KEY_PROV_HANDLE_PROP_ID, got %08x\n",
480      GetLastError());
481     /* Remove the key prov handle property.. */
482     ret = CertSetCertificateContextProperty(context,
483      CERT_KEY_PROV_HANDLE_PROP_ID, 0, NULL);
484     ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
485      GetLastError());
486     /* and the key context's CSP is set to NULL. */
487     size = sizeof(keyContext);
488     ret = CertGetCertificateContextProperty(context,
489      CERT_KEY_CONTEXT_PROP_ID, &keyContext, &size);
490     ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
491      GetLastError());
492     ok(keyContext.hCryptProv == 0, "Expected no hCryptProv\n");
493
494     CryptReleaseContext(csp, 0);
495
496     CertFreeCertificateContext(context);
497 }
498
499 static void testDupCert(void)
500 {
501     HCERTSTORE store;
502     PCCERT_CONTEXT context, dupContext;
503     BOOL ret;
504
505     store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
506      CERT_STORE_CREATE_NEW_FLAG, NULL);
507     ok(store != NULL, "CertOpenStore failed: %d\n", GetLastError());
508     if (!store)
509         return;
510
511     ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
512      bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
513     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
514      GetLastError());
515     ok(context != NULL, "Expected a valid cert context\n");
516     if (context)
517     {
518         ok(context->cbCertEncoded == sizeof(bigCert),
519          "Wrong cert size %d\n", context->cbCertEncoded);
520         ok(!memcmp(context->pbCertEncoded, bigCert, sizeof(bigCert)),
521          "Unexpected encoded cert in context\n");
522         ok(context->hCertStore == store, "Unexpected store\n");
523
524         dupContext = CertDuplicateCertificateContext(context);
525         ok(dupContext != NULL, "Expected valid duplicate\n");
526         /* Not only is it a duplicate, it's identical: the address is the
527          * same.
528          */
529         ok(dupContext == context, "Expected identical context addresses\n");
530         CertFreeCertificateContext(dupContext);
531         CertFreeCertificateContext(context);
532     }
533     CertCloseStore(store, 0);
534 }
535
536 static void testFindCert(void)
537 {
538     HCERTSTORE store;
539     PCCERT_CONTEXT context = NULL;
540     BOOL ret;
541     CERT_INFO certInfo = { 0 };
542     CRYPT_HASH_BLOB blob;
543
544     store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
545      CERT_STORE_CREATE_NEW_FLAG, NULL);
546     ok(store != NULL, "CertOpenStore failed: %d\n", GetLastError());
547     if (!store)
548         return;
549
550     ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
551      bigCert, sizeof(bigCert), CERT_STORE_ADD_NEW, NULL);
552     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
553      GetLastError());
554     ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
555      bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, NULL);
556     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
557      GetLastError());
558     /* This has the same name as bigCert */
559     ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
560      certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, NULL);
561     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
562      GetLastError());
563
564     /* Crashes
565     context = CertFindCertificateInStore(NULL, 0, 0, 0, NULL, NULL);
566      */
567
568     /* Check first cert's there, by issuer */
569     certInfo.Subject.pbData = subjectName;
570     certInfo.Subject.cbData = sizeof(subjectName);
571     certInfo.SerialNumber.pbData = serialNum;
572     certInfo.SerialNumber.cbData = sizeof(serialNum);
573     context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
574      CERT_FIND_ISSUER_NAME, &certInfo.Subject, NULL);
575     ok(context != NULL, "CertFindCertificateInStore failed: %08x\n",
576      GetLastError());
577     if (context)
578     {
579         context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
580          CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
581         ok(context != NULL, "Expected more than one cert\n");
582         if (context)
583         {
584             context = CertFindCertificateInStore(store, X509_ASN_ENCODING,
585              0, CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
586             ok(context == NULL, "Expected precisely two certs\n");
587         }
588     }
589
590     /* Check second cert's there as well, by subject name */
591     certInfo.Subject.pbData = subjectName2;
592     certInfo.Subject.cbData = sizeof(subjectName2);
593     context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
594      CERT_FIND_SUBJECT_NAME, &certInfo.Subject, NULL);
595     ok(context != NULL, "CertFindCertificateInStore failed: %08x\n",
596      GetLastError());
597     if (context)
598     {
599         context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
600          CERT_FIND_SUBJECT_NAME, &certInfo.Subject, context);
601         ok(context == NULL, "Expected one cert only\n");
602     }
603
604     /* Strange but true: searching for the subject cert requires you to set
605      * the issuer, not the subject
606      */
607     context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
608      CERT_FIND_SUBJECT_CERT, &certInfo.Subject, NULL);
609     ok(context == NULL, "Expected no certificate\n");
610     certInfo.Subject.pbData = NULL;
611     certInfo.Subject.cbData = 0;
612     certInfo.Issuer.pbData = subjectName2;
613     certInfo.Issuer.cbData = sizeof(subjectName2);
614     context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
615      CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
616     ok(context != NULL, "CertFindCertificateInStore failed: %08x\n",
617      GetLastError());
618     if (context)
619     {
620         context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
621          CERT_FIND_SUBJECT_CERT, &certInfo.Subject, context);
622         ok(context == NULL, "Expected one cert only\n");
623     }
624
625     /* The nice thing about hashes, they're unique */
626     blob.pbData = bigCertHash;
627     blob.cbData = sizeof(bigCertHash);
628     context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
629      CERT_FIND_SHA1_HASH, &blob, NULL);
630     ok(context != NULL, "CertFindCertificateInStore failed: %08x\n",
631      GetLastError());
632     if (context)
633     {
634         context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
635          CERT_FIND_SHA1_HASH, &certInfo.Subject, context);
636         ok(context == NULL, "Expected one cert only\n");
637     }
638
639     CertCloseStore(store, 0);
640 }
641
642 static void testGetSubjectCert(void)
643 {
644     HCERTSTORE store;
645     PCCERT_CONTEXT context1, context2;
646     CERT_INFO info = { 0 };
647     BOOL ret;
648
649     store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
650      CERT_STORE_CREATE_NEW_FLAG, NULL);
651     ok(store != NULL, "CertOpenStore failed: %d\n", GetLastError());
652     if (!store)
653         return;
654
655     ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
656      bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
657     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
658      GetLastError());
659     ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
660      bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, &context1);
661     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
662      GetLastError());
663     ok(context1 != NULL, "Expected a context\n");
664     ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
665      certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, NULL);
666     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
667      GetLastError());
668
669     context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
670      NULL);
671     ok(!context2 && GetLastError() == E_INVALIDARG,
672      "Expected E_INVALIDARG, got %08x\n", GetLastError());
673     context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
674      &info);
675     ok(!context2 && GetLastError() == CRYPT_E_NOT_FOUND,
676      "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
677     info.SerialNumber.cbData = sizeof(serialNum);
678     info.SerialNumber.pbData = serialNum;
679     context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
680      &info);
681     ok(!context2 && GetLastError() == CRYPT_E_NOT_FOUND,
682      "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
683     info.Issuer.cbData = sizeof(subjectName2);
684     info.Issuer.pbData = subjectName2;
685     context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
686      &info);
687     ok(context2 != NULL,
688      "CertGetSubjectCertificateFromStore failed: %08x\n", GetLastError());
689     /* Not only should this find a context, but it should be the same
690      * (same address) as context1.
691      */
692     ok(context1 == context2, "Expected identical context addresses\n");
693     CertFreeCertificateContext(context2);
694
695     CertFreeCertificateContext(context1);
696     CertCloseStore(store, 0);
697 }
698
699 /* This expires in 1970 or so */
700 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
701  0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
702  0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
703  0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
704  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
705  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
706  0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
707  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
708  0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
709  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
710  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
711  0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
712  0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
713  0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
714  0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
715  0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
716  0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
717  0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
718  0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
719  0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
720  0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
721  0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
722  0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
723  0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
724  0x49, 0xe5, 0xf9, 0x65, 0xf3 };
725
726 /* This expires in 2036 or so */
727 static const BYTE childOfExpired[] = { 0x30, 0x81, 0xcc, 0x30, 0x78, 0xa0,
728  0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
729  0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d,
730  0x30, 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63,
731  0x40, 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e,
732  0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x35, 0x30, 0x35,
733  0x31, 0x37, 0x31, 0x32, 0x34, 0x39, 0x5a, 0x17, 0x0d, 0x33, 0x36, 0x30, 0x35,
734  0x30, 0x35, 0x31, 0x37, 0x31, 0x32, 0x34, 0x39, 0x5a, 0x30, 0x15, 0x31, 0x13,
735  0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e,
736  0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03,
737  0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
738  0x01, 0x05, 0x05, 0x00, 0x03, 0x41, 0x00, 0x20, 0x3b, 0xdb, 0x4d, 0x67, 0x50,
739  0xec, 0x73, 0x9d, 0xf9, 0x85, 0x5d, 0x18, 0xe9, 0xb4, 0x98, 0xe3, 0x31, 0xb7,
740  0x03, 0x0b, 0xc0, 0x39, 0x93, 0x56, 0x81, 0x0a, 0xfc, 0x78, 0xa8, 0x29, 0x42,
741  0x5f, 0x69, 0xfb, 0xbc, 0x5b, 0xf2, 0xa6, 0x2a, 0xbe, 0x91, 0x2c, 0xfc, 0x89,
742  0x69, 0x15, 0x18, 0x58, 0xe5, 0x02, 0x75, 0xf7, 0x2a, 0xb6, 0xa9, 0xfb, 0x47,
743  0x6a, 0x6e, 0x0a, 0x9b, 0xe9, 0xdc };
744
745 static void testGetIssuerCert(void)
746 {
747     BOOL ret;
748     PCCERT_CONTEXT parent, child;
749     DWORD flags = 0xffffffff;
750     HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
751      CERT_STORE_CREATE_NEW_FLAG, NULL);
752
753     ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
754
755     ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
756      expiredCert, sizeof(expiredCert), CERT_STORE_ADD_ALWAYS, NULL);
757     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
758      GetLastError());
759
760     ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
761      childOfExpired, sizeof(childOfExpired), CERT_STORE_ADD_ALWAYS, &child);
762     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
763      GetLastError());
764
765     /* These crash:
766     parent = CertGetIssuerCertificateFromStore(NULL, NULL, NULL, NULL);
767     parent = CertGetIssuerCertificateFromStore(store, NULL, NULL, NULL);
768      */
769     parent = CertGetIssuerCertificateFromStore(NULL, NULL, NULL, &flags);
770     ok(!parent && GetLastError() == E_INVALIDARG,
771      "Expected E_INVALIDARG, got %08x\n", GetLastError());
772     parent = CertGetIssuerCertificateFromStore(store, NULL, NULL, &flags);
773     ok(!parent && GetLastError() == E_INVALIDARG,
774      "Expected E_INVALIDARG, got %08x\n", GetLastError());
775     parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
776     ok(!parent && GetLastError() == E_INVALIDARG,
777      "Expected E_INVALIDARG, got %08x\n", GetLastError());
778     /* Confusing: the caller cannot set either of the
779      * CERT_STORE_NO_*_FLAGs, as these are not checks,
780      * they're results:
781      */
782     flags = CERT_STORE_NO_CRL_FLAG | CERT_STORE_NO_ISSUER_FLAG;
783     parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
784     ok(!parent && GetLastError() == E_INVALIDARG,
785      "Expected E_INVALIDARG, got %08x\n", GetLastError());
786     /* Perform no checks */
787     flags = 0;
788     parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
789     ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08x\n",
790      GetLastError());
791     if (parent)
792         CertFreeCertificateContext(parent);
793     /* Check revocation and signature only */
794     flags = CERT_STORE_REVOCATION_FLAG | CERT_STORE_SIGNATURE_FLAG;
795     parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
796     ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08x\n",
797      GetLastError());
798     /* Confusing: CERT_STORE_REVOCATION_FLAG succeeds when there is no CRL by
799      * setting CERT_STORE_NO_CRL_FLAG.
800      */
801     ok(flags == (CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG),
802      "Expected CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG, got %08x\n",
803      flags);
804     if (parent)
805         CertFreeCertificateContext(parent);
806     /* Now check just the time */
807     flags = CERT_STORE_TIME_VALIDITY_FLAG;
808     parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
809     ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08x\n",
810      GetLastError());
811     /* Oops: the child is not expired, so the time validity check actually
812      * succeeds, even though the signing cert is expired.
813      */
814     ok(!flags, "Expected check to succeed, got %08x\n", flags);
815     if (parent)
816         CertFreeCertificateContext(parent);
817
818     CertFreeCertificateContext(child);
819     CertCloseStore(store, 0);
820 }
821
822 static void testCryptHashCert(void)
823 {
824     static const BYTE emptyHash[] = { 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b,
825      0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07,
826      0x09 };
827     static const BYTE knownHash[] = { 0xae, 0x9d, 0xbf, 0x6d, 0xf5, 0x46, 0xee,
828      0x8b, 0xc5, 0x7a, 0x13, 0xba, 0xc2, 0xb1, 0x04, 0xf2, 0xbf, 0x52, 0xa8,
829      0xa2 };
830     static const BYTE toHash[] = "abcdefghijklmnopqrstuvwxyz0123456789.,;!?:";
831     BOOL ret;
832     BYTE hash[20];
833     DWORD hashLen = sizeof(hash);
834
835     /* NULL buffer and nonzero length crashes
836     ret = CryptHashCertificate(0, 0, 0, NULL, size, hash, &hashLen);
837        empty hash length also crashes
838     ret = CryptHashCertificate(0, 0, 0, buf, size, hash, NULL);
839      */
840     /* Test empty hash */
841     ret = CryptHashCertificate(0, 0, 0, toHash, sizeof(toHash), NULL,
842      &hashLen);
843     ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
844     ok(hashLen == sizeof(hash), "Got unexpected size of hash %d\n", hashLen);
845     /* Test with empty buffer */
846     ret = CryptHashCertificate(0, 0, 0, NULL, 0, hash, &hashLen);
847     ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
848     ok(!memcmp(hash, emptyHash, sizeof(emptyHash)),
849      "Unexpected hash of nothing\n");
850     /* Test a known value */
851     ret = CryptHashCertificate(0, 0, 0, toHash, sizeof(toHash), hash,
852      &hashLen);
853     ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
854     ok(!memcmp(hash, knownHash, sizeof(knownHash)), "Unexpected hash\n");
855 }
856
857 static void verifySig(HCRYPTPROV csp, const BYTE *toSign, size_t toSignLen,
858  const BYTE *sig, unsigned int sigLen)
859 {
860     HCRYPTHASH hash;
861     BOOL ret = CryptCreateHash(csp, CALG_SHA1, 0, 0, &hash);
862
863     ok(ret, "CryptCreateHash failed: %08x\n", GetLastError());
864     if (ret)
865     {
866         BYTE mySig[64];
867         DWORD mySigSize = sizeof(mySig);
868
869         ret = CryptHashData(hash, toSign, toSignLen, 0);
870         ok(ret, "CryptHashData failed: %08x\n", GetLastError());
871         /* use the A variant so the test can run on Win9x */
872         ret = CryptSignHashA(hash, AT_SIGNATURE, NULL, 0, mySig, &mySigSize);
873         ok(ret, "CryptSignHash failed: %08x\n", GetLastError());
874         if (ret)
875         {
876             ok(mySigSize == sigLen, "Expected sig length %d, got %d\n",
877              sigLen, mySigSize);
878             ok(!memcmp(mySig, sig, sigLen), "Unexpected signature\n");
879         }
880         CryptDestroyHash(hash);
881     }
882 }
883
884 /* Tests signing the certificate described by toBeSigned with the CSP passed in,
885  * using the algorithm with OID sigOID.  The CSP is assumed to be empty, and a
886  * keyset named AT_SIGNATURE will be added to it.  The signing key will be
887  * stored in *key, and the signature will be stored in sig.  sigLen should be
888  * at least 64 bytes.
889  */
890 static void testSignCert(HCRYPTPROV csp, const CRYPT_DATA_BLOB *toBeSigned,
891  LPCSTR sigOID, HCRYPTKEY *key, BYTE *sig, DWORD *sigLen)
892 {
893     BOOL ret;
894     DWORD size = 0;
895     CRYPT_ALGORITHM_IDENTIFIER algoID = { NULL, { 0, NULL } };
896
897     /* These all crash
898     ret = CryptSignCertificate(0, 0, 0, NULL, 0, NULL, NULL, NULL, NULL);
899     ret = CryptSignCertificate(0, 0, 0, NULL, 0, NULL, NULL, NULL, &size);
900     ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
901      NULL, NULL, NULL, &size);
902      */
903     ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
904      &algoID, NULL, NULL, &size);
905     ok(!ret && GetLastError() == NTE_BAD_ALGID, 
906      "Expected NTE_BAD_ALGID, got %08x\n", GetLastError());
907     algoID.pszObjId = (LPSTR)sigOID;
908     ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
909      &algoID, NULL, NULL, &size);
910     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
911      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
912     ret = CryptSignCertificate(0, AT_SIGNATURE, 0, toBeSigned->pbData,
913      toBeSigned->cbData, &algoID, NULL, NULL, &size);
914     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
915      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
916
917     /* No keys exist in the new CSP yet.. */
918     ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
919      toBeSigned->cbData, &algoID, NULL, NULL, &size);
920     ok(!ret && (GetLastError() == NTE_BAD_KEYSET || GetLastError() ==
921      NTE_NO_KEY), "Expected NTE_BAD_KEYSET or NTE_NO_KEY, got %08x\n",
922      GetLastError());
923     ret = CryptGenKey(csp, AT_SIGNATURE, 0, key);
924     ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
925     if (ret)
926     {
927         ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
928          toBeSigned->cbData, &algoID, NULL, NULL, &size);
929         ok(ret, "CryptSignCertificate failed: %08x\n", GetLastError());
930         ok(size <= *sigLen, "Expected size <= %d, got %d\n", *sigLen, size);
931         if (ret)
932         {
933             ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
934              toBeSigned->cbData, &algoID, NULL, sig, &size);
935             ok(ret, "CryptSignCertificate failed: %08x\n", GetLastError());
936             if (ret)
937             {
938                 *sigLen = size;
939                 verifySig(csp, toBeSigned->pbData, toBeSigned->cbData, sig,
940                  size);
941             }
942         }
943     }
944 }
945
946 static void testVerifyCertSig(HCRYPTPROV csp, const CRYPT_DATA_BLOB *toBeSigned,
947  LPCSTR sigOID, const BYTE *sig, DWORD sigLen)
948 {
949     CERT_SIGNED_CONTENT_INFO info;
950     LPBYTE cert = NULL;
951     DWORD size = 0;
952     BOOL ret;
953
954     if(pCryptVerifyCertificateSignatureEx) {
955         ret = pCryptVerifyCertificateSignatureEx(0, 0, 0, NULL, 0, NULL, 0, NULL);
956         ok(!ret && GetLastError() == E_INVALIDARG,
957          "Expected E_INVALIDARG, got %08x\n", GetLastError());
958         ret = pCryptVerifyCertificateSignatureEx(csp, 0, 0, NULL, 0, NULL, 0, NULL);
959         ok(!ret && GetLastError() == E_INVALIDARG,
960          "Expected E_INVALIDARG, got %08x\n", GetLastError());
961         ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING, 0, NULL, 0,
962          NULL, 0, NULL);
963         ok(!ret && GetLastError() == E_INVALIDARG,
964          "Expected E_INVALIDARG, got %08x\n", GetLastError());
965         /* This crashes
966         ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
967          CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, NULL, 0, NULL, 0, NULL);
968          */
969     }
970     info.ToBeSigned.cbData = toBeSigned->cbData;
971     info.ToBeSigned.pbData = toBeSigned->pbData;
972     info.SignatureAlgorithm.pszObjId = (LPSTR)sigOID;
973     info.SignatureAlgorithm.Parameters.cbData = 0;
974     info.Signature.cbData = sigLen;
975     info.Signature.pbData = (BYTE *)sig;
976     info.Signature.cUnusedBits = 0;
977     ret = CryptEncodeObjectEx(X509_ASN_ENCODING, X509_CERT, &info,
978      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&cert, &size);
979     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
980     if (cert)
981     {
982         CRYPT_DATA_BLOB certBlob = { 0, NULL };
983         PCERT_PUBLIC_KEY_INFO pubKeyInfo = NULL;
984
985         if(pCryptVerifyCertificateSignatureEx) {
986             ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
987              CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
988             ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
989              "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
990             certBlob.cbData = 1;
991             certBlob.pbData = (void *)0xdeadbeef;
992             ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
993              CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
994             ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
995              "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
996             certBlob.cbData = size;
997             certBlob.pbData = cert;
998             ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
999              CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
1000             ok(!ret && GetLastError() == E_INVALIDARG,
1001              "Expected E_INVALIDARG, got %08x\n", GetLastError());
1002             ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1003              CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
1004              CRYPT_VERIFY_CERT_SIGN_ISSUER_NULL, NULL, 0, NULL);
1005             ok(!ret && GetLastError() == E_INVALIDARG,
1006              "Expected E_INVALIDARG, got %08x\n", GetLastError());
1007             /* This crashes
1008             ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1009              CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
1010              CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY, NULL, 0, NULL);
1011              */
1012         }
1013         CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
1014          (LPSTR)sigOID, 0, NULL, NULL, &size);
1015         pubKeyInfo = HeapAlloc(GetProcessHeap(), 0, size);
1016         if (pubKeyInfo)
1017         {
1018             ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
1019              X509_ASN_ENCODING, (LPSTR)sigOID, 0, NULL, pubKeyInfo, &size);
1020             ok(ret, "CryptExportKey failed: %08x\n", GetLastError());
1021             if (ret && pCryptVerifyCertificateSignatureEx)
1022             {
1023                 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1024                  CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
1025                  CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY, pubKeyInfo, 0, NULL);
1026                 ok(ret, "CryptVerifyCertificateSignatureEx failed: %08x\n",
1027                  GetLastError());
1028             }
1029             HeapFree(GetProcessHeap(), 0, pubKeyInfo);
1030         }
1031         LocalFree(cert);
1032     }
1033 }
1034
1035 static BYTE emptyCert[] = { 0x30, 0x00 };
1036
1037 static void testCertSigs(void)
1038 {
1039     HCRYPTPROV csp;
1040     CRYPT_DATA_BLOB toBeSigned = { sizeof(emptyCert), emptyCert };
1041     BOOL ret;
1042     HCRYPTKEY key;
1043     BYTE sig[64];
1044     DWORD sigSize = sizeof(sig);
1045
1046     /* Just in case a previous run failed, delete this thing */
1047     CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1048      CRYPT_DELETEKEYSET);
1049     ret = CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1050      CRYPT_NEWKEYSET);
1051     ok(ret, "CryptAcquireContext failed: %08x\n", GetLastError());
1052
1053     testSignCert(csp, &toBeSigned, szOID_RSA_SHA1RSA, &key, sig, &sigSize);
1054     testVerifyCertSig(csp, &toBeSigned, szOID_RSA_SHA1RSA, sig, sigSize);
1055
1056     CryptDestroyKey(key);
1057     CryptReleaseContext(csp, 0);
1058     ret = CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1059      CRYPT_DELETEKEYSET);
1060 }
1061
1062 static const BYTE md5SignedEmptyCert[] = {
1063 0x30,0x56,0x30,0x33,0x02,0x00,0x30,0x02,0x06,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,
1064 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,
1065 0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x07,
1066 0x30,0x02,0x06,0x00,0x03,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,
1067 0x0d,0x02,0x05,0x05,0x00,0x03,0x11,0x00,0xfb,0x0f,0x66,0x82,0x66,0xd9,0xe5,0xf8,
1068 0xd8,0xa2,0x55,0x2b,0xe1,0xa5,0xd9,0x04 };
1069 static const BYTE md5SignedEmptyCertNoNull[] = {
1070 0x30,0x54,0x30,0x33,0x02,0x00,0x30,0x02,0x06,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,
1071 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,
1072 0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x07,
1073 0x30,0x02,0x06,0x00,0x03,0x01,0x00,0x30,0x0a,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,
1074 0x0d,0x02,0x05,0x03,0x11,0x00,0x04,0xd9,0xa5,0xe1,0x2b,0x55,0xa2,0xd8,0xf8,0xe5,
1075 0xd9,0x66,0x82,0x66,0x0f,0xfb };
1076
1077 static void testSignAndEncodeCert(void)
1078 {
1079     static char oid_rsa_md5rsa[] = szOID_RSA_MD5RSA;
1080     static char oid_rsa_md5[] = szOID_RSA_MD5;
1081     BOOL ret;
1082     DWORD size;
1083     CRYPT_ALGORITHM_IDENTIFIER algID = { 0 };
1084     CERT_INFO info = { 0 };
1085
1086     /* Crash
1087     ret = CryptSignAndEncodeCertificate(0, 0, 0, NULL, NULL, NULL, NULL, NULL,
1088      NULL);
1089     ret = CryptSignAndEncodeCertificate(0, 0, 0, NULL, NULL, NULL, NULL, NULL,
1090      &size);
1091      */
1092     ret = CryptSignAndEncodeCertificate(0, 0, 0, NULL, NULL, &algID, NULL, NULL,
1093      &size);
1094     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1095      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1096     ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING, NULL, NULL,
1097      &algID, NULL, NULL, &size);
1098     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1099      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1100     ret = CryptSignAndEncodeCertificate(0, 0, 0, X509_CERT_TO_BE_SIGNED, NULL,
1101      &algID, NULL, NULL, &size);
1102     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1103      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1104     ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1105      X509_CERT_TO_BE_SIGNED, NULL, &algID, NULL, NULL, &size);
1106     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1107      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1108     /* Crashes
1109     ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1110      X509_CERT_TO_BE_SIGNED, &info, NULL, NULL, NULL, &size);
1111      */
1112     ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1113      X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, NULL, &size);
1114     ok(!ret && GetLastError() == NTE_BAD_ALGID,
1115      "Expected NTE_BAD_ALGID, got %08x\n", GetLastError());
1116     algID.pszObjId = oid_rsa_md5rsa;
1117     ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1118      X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, NULL, &size);
1119     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1120      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1121     algID.pszObjId = oid_rsa_md5;
1122     ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1123      X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, NULL, &size);
1124     ok(ret, "CryptSignAndEncodeCertificate failed: %08x\n", GetLastError());
1125     if (ret)
1126     {
1127         LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, size);
1128
1129         if (buf)
1130         {
1131             ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1132              X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, buf, &size);
1133             ok(ret, "CryptSignAndEncodeCertificate failed: %08x\n",
1134              GetLastError());
1135             /* Tricky: because the NULL parameters may either be omitted or
1136              * included as an asn.1-encoded NULL (0x05,0x00), two different
1137              * values are allowed.
1138              */
1139             ok(size == sizeof(md5SignedEmptyCert) ||
1140              size == sizeof(md5SignedEmptyCertNoNull), "Unexpected size %d\n",
1141              size);
1142             if (size == sizeof(md5SignedEmptyCert))
1143                 ok(!memcmp(buf, md5SignedEmptyCert, size),
1144                  "Unexpected value\n");
1145             else if (size == sizeof(md5SignedEmptyCertNoNull))
1146                 ok(!memcmp(buf, md5SignedEmptyCertNoNull, size),
1147                  "Unexpected value\n");
1148             HeapFree(GetProcessHeap(), 0, buf);
1149         }
1150     }
1151 }
1152
1153 static void testCreateSelfSignCert(void)
1154 {
1155     PCCERT_CONTEXT context;
1156     CERT_NAME_BLOB name = { sizeof(subjectName), subjectName };
1157     HCRYPTPROV csp;
1158     BOOL ret;
1159     HCRYPTKEY key;
1160
1161     /* This crashes:
1162     context = CertCreateSelfSignCertificate(0, NULL, 0, NULL, NULL, NULL, NULL,
1163      NULL);
1164      * Calling this with no first parameter creates a new key container, which
1165      * lasts beyond the test, so I don't test that.  Nb: the generated key
1166      * name is a GUID.
1167     context = CertCreateSelfSignCertificate(0, &name, 0, NULL, NULL, NULL, NULL,
1168      NULL);
1169      */
1170
1171     /* Acquire a CSP */
1172     CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1173      CRYPT_DELETEKEYSET);
1174     ret = CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1175      CRYPT_NEWKEYSET);
1176     ok(ret, "CryptAcquireContext failed: %08x\n", GetLastError());
1177
1178     context = CertCreateSelfSignCertificate(csp, &name, 0, NULL, NULL, NULL,
1179      NULL, NULL);
1180     ok(!context && GetLastError() == NTE_NO_KEY,
1181      "Expected NTE_NO_KEY, got %08x\n", GetLastError());
1182     ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
1183     ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
1184     if (ret)
1185     {
1186         context = CertCreateSelfSignCertificate(csp, &name, 0, NULL, NULL, NULL,
1187          NULL, NULL);
1188         ok(context != NULL, "CertCreateSelfSignCertificate failed: %08x\n",
1189          GetLastError());
1190         if (context)
1191         {
1192             DWORD size = 0;
1193             PCRYPT_KEY_PROV_INFO info;
1194
1195             /* The context must have a key provider info property */
1196             ret = CertGetCertificateContextProperty(context,
1197              CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
1198             ok(ret && size, "Expected non-zero key provider info\n");
1199             if (size)
1200             {
1201                 info = HeapAlloc(GetProcessHeap(), 0, size);
1202                 if (info)
1203                 {
1204                     ret = CertGetCertificateContextProperty(context,
1205                      CERT_KEY_PROV_INFO_PROP_ID, info, &size);
1206                     ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
1207                      GetLastError());
1208                     if (ret)
1209                     {
1210                         /* Sanity-check the key provider */
1211                         ok(!lstrcmpW(info->pwszContainerName, cspNameW),
1212                          "Unexpected key container\n");
1213                         ok(!lstrcmpW(info->pwszProvName, MS_DEF_PROV_W),
1214                          "Unexpected provider\n");
1215                         ok(info->dwKeySpec == AT_SIGNATURE,
1216                          "Expected AT_SIGNATURE, got %d\n", info->dwKeySpec);
1217                     }
1218                     HeapFree(GetProcessHeap(), 0, info);
1219                 }
1220             }
1221
1222             CertFreeCertificateContext(context);
1223         }
1224
1225         CryptDestroyKey(key);
1226     }
1227
1228     CryptReleaseContext(csp, 0);
1229     ret = CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1230      CRYPT_DELETEKEYSET);
1231 }
1232
1233 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
1234  szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
1235
1236 static void testKeyUsage(void)
1237 {
1238     BOOL ret;
1239     PCCERT_CONTEXT context;
1240     DWORD size;
1241
1242     /* Test base cases */
1243     ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, NULL);
1244     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1245      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1246     size = 1;
1247     ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, &size);
1248     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1249      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1250     size = 0;
1251     ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, &size);
1252     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1253      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1254     /* These crash
1255     ret = CertSetEnhancedKeyUsage(NULL, NULL);
1256     usage.cUsageIdentifier = 0;
1257     ret = CertSetEnhancedKeyUsage(NULL, &usage);
1258      */
1259     /* Test with a cert with no enhanced key usage extension */
1260     context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
1261      sizeof(bigCert));
1262     ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
1263      GetLastError());
1264     if (context)
1265     {
1266         static const char oid[] = "1.2.3.4";
1267         BYTE buf[sizeof(CERT_ENHKEY_USAGE) + 2 * (sizeof(LPSTR) + sizeof(oid))];
1268         PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1269
1270         ret = CertGetEnhancedKeyUsage(context, 0, NULL, NULL);
1271         ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1272          "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1273         size = 1;
1274         ret = CertGetEnhancedKeyUsage(context, 0, NULL, &size);
1275         if (ret)
1276         {
1277             /* Windows 2000, ME, or later: even though it succeeded, we expect
1278              * CRYPT_E_NOT_FOUND, which indicates there is no enhanced key
1279              * usage set for this cert (which implies it's valid for all uses.)
1280              */
1281             ok(GetLastError() == CRYPT_E_NOT_FOUND,
1282              "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1283             ok(size == sizeof(CERT_ENHKEY_USAGE), "Wrong size %d\n", size);
1284             ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1285             ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1286             ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %d\n",
1287              pUsage->cUsageIdentifier);
1288         }
1289         else
1290         {
1291             /* Windows NT, 95, or 98: it fails, and the last error is
1292              * CRYPT_E_NOT_FOUND.
1293              */
1294             ok(GetLastError() == CRYPT_E_NOT_FOUND,
1295              "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1296         }
1297         /* I can add a usage identifier when no key usage has been set */
1298         ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
1299         ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
1300          GetLastError());
1301         size = sizeof(buf);
1302         ret = CertGetEnhancedKeyUsage(context,
1303          CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1304         ok(ret && GetLastError() == 0,
1305          "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1306         ok(pUsage->cUsageIdentifier == 1, "Expected 1 usage, got %d\n",
1307          pUsage->cUsageIdentifier);
1308         if (pUsage->cUsageIdentifier)
1309             ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
1310              "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
1311         /* Now set an empty key usage */
1312         pUsage->cUsageIdentifier = 0;
1313         ret = CertSetEnhancedKeyUsage(context, pUsage);
1314         ok(ret, "CertSetEnhancedKeyUsage failed: %08x\n", GetLastError());
1315         /* Shouldn't find it in the cert */
1316         size = sizeof(buf);
1317         ret = CertGetEnhancedKeyUsage(context,
1318          CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1319         ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
1320          "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1321         /* Should find it as an extended property */
1322         ret = CertGetEnhancedKeyUsage(context,
1323          CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1324         ok(ret && GetLastError() == 0,
1325          "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1326         ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %d\n",
1327          pUsage->cUsageIdentifier);
1328         /* Should find it as either */
1329         ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1330         ok(ret && GetLastError() == 0,
1331          "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1332         ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %d\n",
1333          pUsage->cUsageIdentifier);
1334         /* Add a usage identifier */
1335         ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
1336         ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
1337          GetLastError());
1338         size = sizeof(buf);
1339         ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1340         ok(ret && GetLastError() == 0,
1341          "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1342         ok(pUsage->cUsageIdentifier == 1, "Expected 1 identifier, got %d\n",
1343          pUsage->cUsageIdentifier);
1344         if (pUsage->cUsageIdentifier)
1345             ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
1346              "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
1347         /* Yep, I can re-add the same usage identifier */
1348         ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
1349         ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
1350          GetLastError());
1351         size = sizeof(buf);
1352         ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1353         ok(ret && GetLastError() == 0,
1354          "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1355         ok(pUsage->cUsageIdentifier == 2, "Expected 2 identifiers, got %d\n",
1356          pUsage->cUsageIdentifier);
1357         if (pUsage->cUsageIdentifier)
1358             ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
1359              "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
1360         if (pUsage->cUsageIdentifier >= 2)
1361             ok(!strcmp(pUsage->rgpszUsageIdentifier[1], oid),
1362              "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[1]);
1363         /* Now set a NULL extended property--this deletes the property. */
1364         ret = CertSetEnhancedKeyUsage(context, NULL);
1365         ok(ret, "CertSetEnhancedKeyUsage failed: %08x\n", GetLastError());
1366         SetLastError(0xbaadcafe);
1367         size = sizeof(buf);
1368         ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1369         ok(GetLastError() == CRYPT_E_NOT_FOUND,
1370          "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1371
1372         CertFreeCertificateContext(context);
1373     }
1374     /* Now test with a cert with an enhanced key usage extension */
1375     context = CertCreateCertificateContext(X509_ASN_ENCODING, certWithUsage,
1376      sizeof(certWithUsage));
1377     ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
1378      GetLastError());
1379     if (context)
1380     {
1381         LPBYTE buf = NULL;
1382         DWORD bufSize = 0, i;
1383
1384         /* The size may depend on what flags are used to query it, so I
1385          * realloc the buffer for each test.
1386          */
1387         ret = CertGetEnhancedKeyUsage(context,
1388          CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, NULL, &bufSize);
1389         ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1390         buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
1391         if (buf)
1392         {
1393             PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1394
1395             /* Should find it in the cert */
1396             size = bufSize;
1397             ret = CertGetEnhancedKeyUsage(context,
1398              CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1399             ok(ret && GetLastError() == 0,
1400              "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1401             ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
1402              pUsage->cUsageIdentifier);
1403             for (i = 0; i < pUsage->cUsageIdentifier; i++)
1404                 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
1405                  "Expected %s, got %s\n", keyUsages[i],
1406                  pUsage->rgpszUsageIdentifier[i]);
1407             HeapFree(GetProcessHeap(), 0, buf);
1408         }
1409         ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
1410         ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1411         buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
1412         if (buf)
1413         {
1414             PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1415
1416             /* Should find it as either */
1417             size = bufSize;
1418             ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1419             /* In Windows, GetLastError returns CRYPT_E_NOT_FOUND not found
1420              * here, even though the return is successful and the usage id
1421              * count is positive.  I don't enforce that here.
1422              */
1423             ok(ret,
1424              "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1425             ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
1426              pUsage->cUsageIdentifier);
1427             for (i = 0; i < pUsage->cUsageIdentifier; i++)
1428                 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
1429                  "Expected %s, got %s\n", keyUsages[i],
1430                  pUsage->rgpszUsageIdentifier[i]);
1431             HeapFree(GetProcessHeap(), 0, buf);
1432         }
1433         /* Shouldn't find it as an extended property */
1434         ret = CertGetEnhancedKeyUsage(context,
1435          CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, NULL, &size);
1436         ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
1437          "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1438         /* Adding a usage identifier overrides the cert's usage!? */
1439         ret = CertAddEnhancedKeyUsageIdentifier(context, szOID_RSA_RSA);
1440         ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
1441          GetLastError());
1442         ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
1443         ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1444         buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
1445         if (buf)
1446         {
1447             PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1448
1449             /* Should find it as either */
1450             size = bufSize;
1451             ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1452             ok(ret,
1453              "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1454             ok(pUsage->cUsageIdentifier == 1, "Expected 1 usage, got %d\n",
1455              pUsage->cUsageIdentifier);
1456             ok(!strcmp(pUsage->rgpszUsageIdentifier[0], szOID_RSA_RSA),
1457              "Expected %s, got %s\n", szOID_RSA_RSA,
1458              pUsage->rgpszUsageIdentifier[0]);
1459             HeapFree(GetProcessHeap(), 0, buf);
1460         }
1461         /* But querying the cert directly returns its usage */
1462         ret = CertGetEnhancedKeyUsage(context,
1463          CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, NULL, &bufSize);
1464         ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1465         buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
1466         if (buf)
1467         {
1468             PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1469
1470             size = bufSize;
1471             ret = CertGetEnhancedKeyUsage(context,
1472              CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1473             ok(ret,
1474              "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1475             ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
1476              pUsage->cUsageIdentifier);
1477             for (i = 0; i < pUsage->cUsageIdentifier; i++)
1478                 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
1479                  "Expected %s, got %s\n", keyUsages[i],
1480                  pUsage->rgpszUsageIdentifier[i]);
1481             HeapFree(GetProcessHeap(), 0, buf);
1482         }
1483         /* And removing the only usage identifier in the extended property
1484          * results in the cert's key usage being found.
1485          */
1486         ret = CertRemoveEnhancedKeyUsageIdentifier(context, szOID_RSA_RSA);
1487         ok(ret, "CertRemoveEnhancedKeyUsage failed: %08x\n", GetLastError());
1488         ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
1489         ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1490         buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
1491         if (buf)
1492         {
1493             PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1494
1495             /* Should find it as either */
1496             size = bufSize;
1497             ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1498             ok(ret,
1499              "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1500             ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
1501              pUsage->cUsageIdentifier);
1502             for (i = 0; i < pUsage->cUsageIdentifier; i++)
1503                 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
1504                  "Expected %s, got %s\n", keyUsages[i],
1505                  pUsage->rgpszUsageIdentifier[i]);
1506             HeapFree(GetProcessHeap(), 0, buf);
1507         }
1508
1509         CertFreeCertificateContext(context);
1510     }
1511 }
1512
1513 static void testCompareCertName(void)
1514 {
1515     static BYTE bogus[] = { 1, 2, 3, 4 };
1516     static BYTE bogusPrime[] = { 0, 1, 2, 3, 4 };
1517     static BYTE emptyPrime[] = { 0x30, 0x00, 0x01 };
1518     BOOL ret;
1519     CERT_NAME_BLOB blob1, blob2;
1520
1521     /* crashes
1522     ret = CertCompareCertificateName(0, NULL, NULL);
1523      */
1524     /* An empty name checks against itself.. */
1525     blob1.pbData = emptyCert;
1526     blob1.cbData = sizeof(emptyCert);
1527     ret = CertCompareCertificateName(0, &blob1, &blob1);
1528     ok(ret, "CertCompareCertificateName failed: %08x\n", GetLastError());
1529     /* It doesn't have to be a valid encoded name.. */
1530     blob1.pbData = bogus;
1531     blob1.cbData = sizeof(bogus);
1532     ret = CertCompareCertificateName(0, &blob1, &blob1);
1533     ok(ret, "CertCompareCertificateName failed: %08x\n", GetLastError());
1534     /* Leading zeroes matter.. */
1535     blob2.pbData = bogusPrime;
1536     blob2.cbData = sizeof(bogusPrime);
1537     ret = CertCompareCertificateName(0, &blob1, &blob2);
1538     ok(!ret, "Expected failure\n");
1539     /* As do trailing extra bytes. */
1540     blob2.pbData = emptyPrime;
1541     blob2.cbData = sizeof(emptyPrime);
1542     ret = CertCompareCertificateName(0, &blob1, &blob2);
1543     ok(!ret, "Expected failure\n");
1544 }
1545
1546 static BYTE int1[] = { 0x88, 0xff, 0xff, 0xff };
1547 static BYTE int2[] = { 0x88, 0xff };
1548 static BYTE int3[] = { 0x23, 0xff };
1549 static BYTE int4[] = { 0x7f, 0x00 };
1550 static BYTE int5[] = { 0x7f };
1551 static BYTE int6[] = { 0x80, 0x00, 0x00, 0x00 };
1552 static BYTE int7[] = { 0x80, 0x00 };
1553
1554 static struct IntBlobTest
1555 {
1556     CRYPT_INTEGER_BLOB blob1;
1557     CRYPT_INTEGER_BLOB blob2;
1558     BOOL areEqual;
1559 } intBlobs[] = {
1560  { { sizeof(int1), int1 }, { sizeof(int2), int2 }, TRUE },
1561  { { sizeof(int3), int3 }, { sizeof(int3), int3 }, TRUE },
1562  { { sizeof(int4), int4 }, { sizeof(int5), int5 }, TRUE },
1563  { { sizeof(int6), int6 }, { sizeof(int7), int7 }, TRUE },
1564  { { sizeof(int1), int1 }, { sizeof(int7), int7 }, FALSE },
1565 };
1566
1567 static void testCompareIntegerBlob(void)
1568 {
1569     DWORD i;
1570     BOOL ret;
1571
1572     for (i = 0; i < sizeof(intBlobs) / sizeof(intBlobs[0]); i++)
1573     {
1574         ret = CertCompareIntegerBlob(&intBlobs[i].blob1, &intBlobs[i].blob2);
1575         ok(ret == intBlobs[i].areEqual,
1576          "%d: expected blobs %s compare\n", i, intBlobs[i].areEqual ?
1577          "to" : "not to");
1578     }
1579 }
1580
1581 static void testComparePublicKeyInfo(void)
1582 {
1583     BOOL ret;
1584     CERT_PUBLIC_KEY_INFO info1 = { { 0 } }, info2 = { { 0 } };
1585     static CHAR oid_rsa_rsa[]     = szOID_RSA_RSA;
1586     static CHAR oid_rsa_sha1rsa[] = szOID_RSA_SHA1RSA;
1587     static CHAR oid_x957_dsa[]    = szOID_X957_DSA;
1588     static BYTE bits1[] = { 1, 0 };
1589     static BYTE bits2[] = { 0 };
1590     static BYTE bits3[] = { 1 };
1591
1592     /* crashes
1593     ret = CertComparePublicKeyInfo(0, NULL, NULL);
1594      */
1595     /* Empty public keys compare */
1596     ret = CertComparePublicKeyInfo(0, &info1, &info2);
1597     ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
1598     /* Different OIDs appear to compare */
1599     info1.Algorithm.pszObjId = oid_rsa_rsa;
1600     info2.Algorithm.pszObjId = oid_rsa_sha1rsa;
1601     ret = CertComparePublicKeyInfo(0, &info1, &info2);
1602     ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
1603     info2.Algorithm.pszObjId = oid_x957_dsa;
1604     ret = CertComparePublicKeyInfo(0, &info1, &info2);
1605     ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
1606     info1.PublicKey.cbData = sizeof(bits1);
1607     info1.PublicKey.pbData = bits1;
1608     info1.PublicKey.cUnusedBits = 0;
1609     info2.PublicKey.cbData = sizeof(bits1);
1610     info2.PublicKey.pbData = bits1;
1611     info2.PublicKey.cUnusedBits = 0;
1612     ret = CertComparePublicKeyInfo(0, &info1, &info2);
1613     ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
1614     /* Even though they compare in their used bits, these do not compare */
1615     info1.PublicKey.cbData = sizeof(bits2);
1616     info1.PublicKey.pbData = bits2;
1617     info1.PublicKey.cUnusedBits = 0;
1618     info2.PublicKey.cbData = sizeof(bits3);
1619     info2.PublicKey.pbData = bits3;
1620     info2.PublicKey.cUnusedBits = 1;
1621     ret = CertComparePublicKeyInfo(0, &info1, &info2);
1622     /* Simple (non-comparing) case */
1623     ok(!ret, "Expected keys not to compare\n");
1624     info2.PublicKey.cbData = sizeof(bits1);
1625     info2.PublicKey.pbData = bits1;
1626     info2.PublicKey.cUnusedBits = 0;
1627     ret = CertComparePublicKeyInfo(0, &info1, &info2);
1628     ok(!ret, "Expected keys not to compare\n");
1629 }
1630
1631 static void testHashPublicKeyInfo(void)
1632 {
1633     BOOL ret;
1634     CERT_PUBLIC_KEY_INFO info = { { 0 } };
1635     DWORD len;
1636
1637     /* Crash
1638     ret = CryptHashPublicKeyInfo(0, 0, 0, 0, NULL, NULL, NULL);
1639     ret = CryptHashPublicKeyInfo(0, 0, 0, 0, &info, NULL, NULL);
1640      */
1641     ret = CryptHashPublicKeyInfo(0, 0, 0, 0, NULL, NULL, &len);
1642     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1643      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1644     ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, NULL, NULL, &len);
1645     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1646      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1647     ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, &info, NULL, &len);
1648     ok(ret, "CryptHashPublicKeyInfo failed: %08x\n", GetLastError());
1649     ok(len == 16, "Expected hash size 16, got %d\n", len);
1650     if (len == 16)
1651     {
1652         static const BYTE emptyHash[] = { 0xb8,0x51,0x3a,0x31,0x0e,0x9f,0x40,
1653          0x36,0x9c,0x92,0x45,0x1b,0x9d,0xc8,0xf9,0xf6 };
1654         BYTE buf[16];
1655
1656         ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, &info, buf,
1657          &len);
1658         ok(ret, "CryptHashPublicKeyInfo failed: %08x\n", GetLastError());
1659         ok(!memcmp(buf, emptyHash, len), "Unexpected hash\n");
1660     }
1661 }
1662
1663 static void testCompareCert(void)
1664 {
1665     CERT_INFO info1 = { 0 }, info2 = { 0 };
1666     BOOL ret;
1667
1668     /* Crashes
1669     ret = CertCompareCertificate(X509_ASN_ENCODING, NULL, NULL);
1670      */
1671
1672     /* Certs with the same issuer and serial number are equal, even if they
1673      * differ in other respects (like subject).
1674      */
1675     info1.SerialNumber.pbData = serialNum;
1676     info1.SerialNumber.cbData = sizeof(serialNum);
1677     info1.Issuer.pbData = subjectName;
1678     info1.Issuer.cbData = sizeof(subjectName);
1679     info1.Subject.pbData = subjectName2;
1680     info1.Subject.cbData = sizeof(subjectName2);
1681     info2.SerialNumber.pbData = serialNum;
1682     info2.SerialNumber.cbData = sizeof(serialNum);
1683     info2.Issuer.pbData = subjectName;
1684     info2.Issuer.cbData = sizeof(subjectName);
1685     info2.Subject.pbData = subjectName;
1686     info2.Subject.cbData = sizeof(subjectName);
1687     ret = CertCompareCertificate(X509_ASN_ENCODING, &info1, &info2);
1688     ok(ret, "Expected certs to be equal\n");
1689
1690     info2.Issuer.pbData = subjectName2;
1691     info2.Issuer.cbData = sizeof(subjectName2);
1692     ret = CertCompareCertificate(X509_ASN_ENCODING, &info1, &info2);
1693     ok(!ret, "Expected certs not to be equal\n");
1694 }
1695
1696 static void testVerifySubjectCert(void)
1697 {
1698     BOOL ret;
1699     DWORD flags;
1700     PCCERT_CONTEXT context1, context2;
1701
1702     /* Crashes
1703     ret = CertVerifySubjectCertificateContext(NULL, NULL, NULL);
1704      */
1705     flags = 0;
1706     ret = CertVerifySubjectCertificateContext(NULL, NULL, &flags);
1707     ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
1708      GetLastError());
1709     flags = CERT_STORE_NO_CRL_FLAG;
1710     ret = CertVerifySubjectCertificateContext(NULL, NULL, &flags);
1711     ok(!ret && GetLastError() == E_INVALIDARG,
1712      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1713
1714     flags = 0;
1715     context1 = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
1716      sizeof(bigCert));
1717     ret = CertVerifySubjectCertificateContext(NULL, context1, &flags);
1718     ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
1719      GetLastError());
1720     ret = CertVerifySubjectCertificateContext(context1, NULL, &flags);
1721     ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
1722      GetLastError());
1723     ret = CertVerifySubjectCertificateContext(context1, context1, &flags);
1724     ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
1725      GetLastError());
1726
1727     context2 = CertCreateCertificateContext(X509_ASN_ENCODING,
1728      bigCertWithDifferentSubject, sizeof(bigCertWithDifferentSubject));
1729     SetLastError(0xdeadbeef);
1730     ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
1731     ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
1732      GetLastError());
1733     flags = CERT_STORE_REVOCATION_FLAG;
1734     ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
1735     ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
1736      GetLastError());
1737     ok(flags == (CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG),
1738      "Expected CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG, got %08x\n",
1739      flags);
1740     flags = CERT_STORE_SIGNATURE_FLAG;
1741     ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
1742     ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
1743      GetLastError());
1744     ok(flags == CERT_STORE_SIGNATURE_FLAG,
1745      "Expected CERT_STORE_SIGNATURE_FLAG, got %08x\n", flags);
1746     CertFreeCertificateContext(context2);
1747
1748     CertFreeCertificateContext(context1);
1749 }
1750
1751 static BYTE privKey[] = {
1752  0x07, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x52, 0x53, 0x41, 0x32, 0x00,
1753  0x02, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x79, 0x10, 0x1c, 0xd0, 0x6b, 0x10,
1754  0x18, 0x30, 0x94, 0x61, 0xdc, 0x0e, 0xcb, 0x96, 0x4e, 0x21, 0x3f, 0x79, 0xcd,
1755  0xa9, 0x17, 0x62, 0xbc, 0xbb, 0x61, 0x4c, 0xe0, 0x75, 0x38, 0x6c, 0xf3, 0xde,
1756  0x60, 0x86, 0x03, 0x97, 0x65, 0xeb, 0x1e, 0x6b, 0xdb, 0x53, 0x85, 0xad, 0x68,
1757  0x21, 0xf1, 0x5d, 0xe7, 0x1f, 0xe6, 0x53, 0xb4, 0xbb, 0x59, 0x3e, 0x14, 0x27,
1758  0xb1, 0x83, 0xa7, 0x3a, 0x54, 0xe2, 0x8f, 0x65, 0x8e, 0x6a, 0x4a, 0xcf, 0x3b,
1759  0x1f, 0x65, 0xff, 0xfe, 0xf1, 0x31, 0x3a, 0x37, 0x7a, 0x8b, 0xcb, 0xc6, 0xd4,
1760  0x98, 0x50, 0x36, 0x67, 0xe4, 0xa1, 0xe8, 0x7e, 0x8a, 0xc5, 0x23, 0xf2, 0x77,
1761  0xf5, 0x37, 0x61, 0x49, 0x72, 0x59, 0xe8, 0x3d, 0xf7, 0x60, 0xb2, 0x77, 0xca,
1762  0x78, 0x54, 0x6d, 0x65, 0x9e, 0x03, 0x97, 0x1b, 0x61, 0xbd, 0x0c, 0xd8, 0x06,
1763  0x63, 0xe2, 0xc5, 0x48, 0xef, 0xb3, 0xe2, 0x6e, 0x98, 0x7d, 0xbd, 0x4e, 0x72,
1764  0x91, 0xdb, 0x31, 0x57, 0xe3, 0x65, 0x3a, 0x49, 0xca, 0xec, 0xd2, 0x02, 0x4e,
1765  0x22, 0x7e, 0x72, 0x8e, 0xf9, 0x79, 0x84, 0x82, 0xdf, 0x7b, 0x92, 0x2d, 0xaf,
1766  0xc9, 0xe4, 0x33, 0xef, 0x89, 0x5c, 0x66, 0x99, 0xd8, 0x80, 0x81, 0x47, 0x2b,
1767  0xb1, 0x66, 0x02, 0x84, 0x59, 0x7b, 0xc3, 0xbe, 0x98, 0x45, 0x4a, 0x3d, 0xdd,
1768  0xea, 0x2b, 0xdf, 0x4e, 0xb4, 0x24, 0x6b, 0xec, 0xe7, 0xd9, 0x0c, 0x45, 0xb8,
1769  0xbe, 0xca, 0x69, 0x37, 0x92, 0x4c, 0x38, 0x6b, 0x96, 0x6d, 0xcd, 0x86, 0x67,
1770  0x5c, 0xea, 0x54, 0x94, 0xa4, 0xca, 0xa4, 0x02, 0xa5, 0x21, 0x4d, 0xae, 0x40,
1771  0x8f, 0x9d, 0x51, 0x83, 0xf2, 0x3f, 0x33, 0xc1, 0x72, 0xb4, 0x1d, 0x94, 0x6e,
1772  0x7d, 0xe4, 0x27, 0x3f, 0xea, 0xff, 0xe5, 0x9b, 0xa7, 0x5e, 0x55, 0x8e, 0x0d,
1773  0x69, 0x1c, 0x7a, 0xff, 0x81, 0x9d, 0x53, 0x52, 0x97, 0x9a, 0x76, 0x79, 0xda,
1774  0x93, 0x32, 0x16, 0xec, 0x69, 0x51, 0x1a, 0x4e, 0xc3, 0xf1, 0x72, 0x80, 0x78,
1775  0x5e, 0x66, 0x4a, 0x8d, 0x85, 0x2f, 0x3f, 0xb2, 0xa7 };
1776
1777 static const BYTE selfSignedCert[] = {
1778  0x30, 0x82, 0x01, 0x1f, 0x30, 0x81, 0xce, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
1779  0x10, 0xeb, 0x0d, 0x57, 0x2a, 0x9c, 0x09, 0xba, 0xa4, 0x4a, 0xb7, 0x25, 0x49,
1780  0xd9, 0x3e, 0xb5, 0x73, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d,
1781  0x05, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
1782  0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30,
1783  0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x36, 0x32, 0x39, 0x30, 0x35, 0x30, 0x30,
1784  0x34, 0x36, 0x5a, 0x17, 0x0d, 0x30, 0x37, 0x30, 0x36, 0x32, 0x39, 0x31, 0x31,
1785  0x30, 0x30, 0x34, 0x36, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
1786  0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e,
1787  0x67, 0x00, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
1788  0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
1789  0x00, 0xe2, 0x54, 0x3a, 0xa7, 0x83, 0xb1, 0x27, 0x14, 0x3e, 0x59, 0xbb, 0xb4,
1790  0x53, 0xe6, 0x1f, 0xe7, 0x5d, 0xf1, 0x21, 0x68, 0xad, 0x85, 0x53, 0xdb, 0x6b,
1791  0x1e, 0xeb, 0x65, 0x97, 0x03, 0x86, 0x60, 0xde, 0xf3, 0x6c, 0x38, 0x75, 0xe0,
1792  0x4c, 0x61, 0xbb, 0xbc, 0x62, 0x17, 0xa9, 0xcd, 0x79, 0x3f, 0x21, 0x4e, 0x96,
1793  0xcb, 0x0e, 0xdc, 0x61, 0x94, 0x30, 0x18, 0x10, 0x6b, 0xd0, 0x1c, 0x10, 0x79,
1794  0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
1795  0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x25, 0x90, 0x53, 0x34, 0xd9, 0x56, 0x41,
1796  0x5e, 0xdb, 0x7e, 0x01, 0x36, 0xec, 0x27, 0x61, 0x5e, 0xb7, 0x4d, 0x90, 0x66,
1797  0xa2, 0xe1, 0x9d, 0x58, 0x76, 0xd4, 0x9c, 0xba, 0x2c, 0x84, 0xc6, 0x83, 0x7a,
1798  0x22, 0x0d, 0x03, 0x69, 0x32, 0x1a, 0x6d, 0xcb, 0x0c, 0x15, 0xb3, 0x6b, 0xc7,
1799  0x0a, 0x8c, 0xb4, 0x5c, 0x34, 0x78, 0xe0, 0x3c, 0x9c, 0xe9, 0xf3, 0x30, 0x9f,
1800  0xa8, 0x76, 0x57, 0x92, 0x36 };
1801
1802 static const BYTE exportedPublicKeyBlob[] = {
1803 0x06,0x02,0x00,0x00,0x00,0xa4,0x00,0x00,0x52,0x53,0x41,0x31,0x00,0x02,0x00,0x00,
1804 0x01,0x00,0x01,0x00,0x79,0x10,0x1c,0xd0,0x6b,0x10,0x18,0x30,0x94,0x61,0xdc,0x0e,
1805 0xcb,0x96,0x4e,0x21,0x3f,0x79,0xcd,0xa9,0x17,0x62,0xbc,0xbb,0x61,0x4c,0xe0,0x75,
1806 0x38,0x6c,0xf3,0xde,0x60,0x86,0x03,0x97,0x65,0xeb,0x1e,0x6b,0xdb,0x53,0x85,0xad,
1807 0x68,0x21,0xf1,0x5d,0xe7,0x1f,0xe6,0x53,0xb4,0xbb,0x59,0x3e,0x14,0x27,0xb1,0x83,
1808 0xa7,0x3a,0x54,0xe2 };
1809
1810 static const BYTE asnEncodedPublicKey[] = {
1811 0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7,0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,
1812 0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21,0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,
1813 0x65,0x97,0x03,0x86,0x60,0xde,0xf3,0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,
1814 0x17,0xa9,0xcd,0x79,0x3f,0x21,0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,
1815 0x6b,0xd0,0x1c,0x10,0x79,0x02,0x03,0x01,0x00,0x01 };
1816
1817 static void testAcquireCertPrivateKey(void)
1818 {
1819     BOOL ret;
1820     PCCERT_CONTEXT cert;
1821     HCRYPTPROV csp;
1822     DWORD size, keySpec;
1823     BOOL callerFree;
1824     CRYPT_KEY_PROV_INFO keyProvInfo;
1825     HCRYPTKEY key;
1826     WCHAR ms_def_prov_w[MAX_PATH];
1827
1828     lstrcpyW(ms_def_prov_w, MS_DEF_PROV_W);
1829
1830     keyProvInfo.pwszContainerName = cspNameW;
1831     keyProvInfo.pwszProvName = ms_def_prov_w;
1832     keyProvInfo.dwProvType = PROV_RSA_FULL;
1833     keyProvInfo.dwFlags = 0;
1834     keyProvInfo.cProvParam = 0;
1835     keyProvInfo.rgProvParam = NULL;
1836     keyProvInfo.dwKeySpec = AT_SIGNATURE;
1837
1838     CryptAcquireContextW(NULL, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1839      CRYPT_DELETEKEYSET);
1840
1841     cert = CertCreateCertificateContext(X509_ASN_ENCODING, selfSignedCert,
1842      sizeof(selfSignedCert));
1843
1844     /* Crash
1845     ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, NULL, NULL);
1846     ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, NULL,
1847      &callerFree);
1848     ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, &keySpec,
1849      NULL);
1850     ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, &csp, NULL, NULL);
1851     ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, &csp, &keySpec,
1852      &callerFree);
1853     ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, NULL, NULL, NULL);
1854      */
1855
1856     /* Missing private key */
1857     ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, NULL, NULL);
1858     ok(!ret && GetLastError() == CRYPT_E_NO_KEY_PROPERTY,
1859      "Expected CRYPT_E_NO_KEY_PROPERTY, got %08x\n", GetLastError());
1860     ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, &keySpec,
1861      &callerFree);
1862     ok(!ret && GetLastError() == CRYPT_E_NO_KEY_PROPERTY,
1863      "Expected CRYPT_E_NO_KEY_PROPERTY, got %08x\n", GetLastError());
1864     CertSetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, 0,
1865      &keyProvInfo);
1866     ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, &keySpec,
1867      &callerFree);
1868     ok(!ret && GetLastError() == CRYPT_E_NO_KEY_PROPERTY,
1869      "Expected CRYPT_E_NO_KEY_PROPERTY, got %08x\n", GetLastError());
1870
1871     CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1872      CRYPT_NEWKEYSET);
1873     ret = CryptImportKey(csp, privKey, sizeof(privKey), 0, 0, &key);
1874     ok(ret, "CryptImportKey failed: %08x\n", GetLastError());
1875     if (ret)
1876     {
1877         HCRYPTPROV certCSP;
1878         DWORD size;
1879         CERT_KEY_CONTEXT keyContext;
1880
1881         /* Don't cache provider */
1882         ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &certCSP,
1883          &keySpec, &callerFree);
1884         ok(ret, "CryptAcquireCertificatePrivateKey failed: %08x\n",
1885          GetLastError());
1886         ok(callerFree, "Expected callerFree to be TRUE\n");
1887         CryptReleaseContext(certCSP, 0);
1888         ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &certCSP,
1889          NULL, NULL);
1890         ok(ret, "CryptAcquireCertificatePrivateKey failed: %08x\n",
1891          GetLastError());
1892         CryptReleaseContext(certCSP, 0);
1893
1894         /* Use the key prov info's caching (there shouldn't be any) */
1895         ret = CryptAcquireCertificatePrivateKey(cert,
1896          CRYPT_ACQUIRE_USE_PROV_INFO_FLAG, NULL, &certCSP, &keySpec,
1897          &callerFree);
1898         ok(ret, "CryptAcquireCertificatePrivateKey failed: %08x\n",
1899          GetLastError());
1900         ok(callerFree, "Expected callerFree to be TRUE\n");
1901         CryptReleaseContext(certCSP, 0);
1902
1903         /* Cache it (and check that it's cached) */
1904         ret = CryptAcquireCertificatePrivateKey(cert,
1905          CRYPT_ACQUIRE_CACHE_FLAG, NULL, &certCSP, &keySpec, &callerFree);
1906         ok(ret, "CryptAcquireCertificatePrivateKey failed: %08x\n",
1907          GetLastError());
1908         ok(!callerFree, "Expected callerFree to be FALSE\n");
1909         size = sizeof(keyContext);
1910         ret = CertGetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID,
1911          &keyContext, &size);
1912         ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
1913          GetLastError());
1914
1915         /* Remove the cached provider */
1916         CryptReleaseContext(keyContext.hCryptProv, 0);
1917         CertSetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID, 0,
1918          NULL);
1919         /* Allow caching via the key prov info */
1920         keyProvInfo.dwFlags = CERT_SET_KEY_CONTEXT_PROP_ID;
1921         CertSetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, 0,
1922          &keyProvInfo);
1923         /* Now use the key prov info's caching */
1924         ret = CryptAcquireCertificatePrivateKey(cert,
1925          CRYPT_ACQUIRE_USE_PROV_INFO_FLAG, NULL, &certCSP, &keySpec,
1926          &callerFree);
1927         ok(ret, "CryptAcquireCertificatePrivateKey failed: %08x\n",
1928          GetLastError());
1929         ok(!callerFree, "Expected callerFree to be FALSE\n");
1930         size = sizeof(keyContext);
1931         ret = CertGetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID,
1932          &keyContext, &size);
1933         ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
1934          GetLastError());
1935
1936         CryptDestroyKey(key);
1937     }
1938
1939     /* Some sanity-checking on public key exporting */
1940     ret = CryptImportPublicKeyInfo(csp, X509_ASN_ENCODING,
1941      &cert->pCertInfo->SubjectPublicKeyInfo, &key);
1942     ok(ret, "CryptImportPublicKeyInfo failed: %08x\n", GetLastError());
1943     if (ret)
1944     {
1945         ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &size);
1946         ok(ret, "CryptExportKey failed: %08x\n", GetLastError());
1947         if (ret)
1948         {
1949             LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, size), encodedKey;
1950
1951             ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, buf, &size);
1952             ok(ret, "CryptExportKey failed: %08x\n", GetLastError());
1953             ok(size == sizeof(exportedPublicKeyBlob), "Unexpected size %d\n",
1954              size);
1955             ok(!memcmp(buf, exportedPublicKeyBlob, size), "Unexpected value\n");
1956             ret = CryptEncodeObjectEx(X509_ASN_ENCODING, RSA_CSP_PUBLICKEYBLOB,
1957              buf, CRYPT_ENCODE_ALLOC_FLAG, NULL, &encodedKey, &size);
1958             ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1959             if (ret)
1960             {
1961                 ok(size == sizeof(asnEncodedPublicKey), "Unexpected size %d\n",
1962                  size);
1963                 ok(!memcmp(encodedKey, asnEncodedPublicKey, size),
1964                  "Unexpected value\n");
1965                 LocalFree(encodedKey);
1966             }
1967             HeapFree(GetProcessHeap(), 0, buf);
1968         }
1969         CryptDestroyKey(key);
1970     }
1971     ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
1972      NULL, 0, NULL, NULL, &size);
1973     ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
1974     if (ret)
1975     {
1976         PCERT_PUBLIC_KEY_INFO info = HeapAlloc(GetProcessHeap(), 0, size);
1977
1978         ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
1979          NULL, 0, NULL, info, &size);
1980         ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
1981         if (ret)
1982         {
1983             ok(info->PublicKey.cbData == sizeof(asnEncodedPublicKey),
1984              "Unexpected size %d\n", info->PublicKey.cbData);
1985             ok(!memcmp(info->PublicKey.pbData, asnEncodedPublicKey,
1986              info->PublicKey.cbData), "Unexpected value\n");
1987         }
1988         HeapFree(GetProcessHeap(), 0, info);
1989     }
1990
1991     CryptReleaseContext(csp, 0);
1992     CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1993      CRYPT_DELETEKEYSET);
1994
1995     CertFreeCertificateContext(cert);
1996 }
1997
1998 static void testGetPublicKeyLength(void)
1999 {
2000     static char oid_rsa_rsa[] = szOID_RSA_RSA;
2001     static char oid_rsa_dh[] = szOID_RSA_DH;
2002     static char bogusOID[] = "1.2.3";
2003     DWORD ret;
2004     CERT_PUBLIC_KEY_INFO info = { { 0 } };
2005     BYTE bogusKey[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
2006     BYTE key[] = { 0x30,0x0f,0x02,0x08,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
2007      0x02,0x03,0x01,0x00,0x01 };
2008
2009     /* Crashes
2010     ret = CertGetPublicKeyLength(0, NULL);
2011      */
2012     /* With an empty public key info */
2013     SetLastError(0xdeadbeef);
2014     ret = CertGetPublicKeyLength(0, &info);
2015     ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
2016      "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
2017      ret, GetLastError());
2018     SetLastError(0xdeadbeef);
2019     ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
2020     ok(ret == 0 && GetLastError() == CRYPT_E_ASN1_EOD,
2021      "Expected length 0 and CRYPT_E_ASN1_EOD, got length %d, %08x\n",
2022      ret, GetLastError());
2023     /* With a nearly-empty public key info */
2024     info.Algorithm.pszObjId = oid_rsa_rsa;
2025     SetLastError(0xdeadbeef);
2026     ret = CertGetPublicKeyLength(0, &info);
2027     ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
2028      "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
2029      ret, GetLastError());
2030     SetLastError(0xdeadbeef);
2031     ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
2032     ok(ret == 0 && GetLastError() == CRYPT_E_ASN1_EOD,
2033      "Expected length 0 and CRYPT_E_ASN1_EOD, got length %d, %08x\n",
2034      ret, GetLastError());
2035     /* With a bogus key */
2036     info.PublicKey.cbData = sizeof(bogusKey);
2037     info.PublicKey.pbData = bogusKey;
2038     SetLastError(0xdeadbeef);
2039     ret = CertGetPublicKeyLength(0, &info);
2040     ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
2041      "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
2042      ret, GetLastError());
2043     SetLastError(0xdeadbeef);
2044     ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
2045     ok(ret == 0 && GetLastError() == CRYPT_E_ASN1_BADTAG,
2046      "Expected length 0 and CRYPT_E_ASN1_BADTAGTAG, got length %d, %08x\n",
2047      ret, GetLastError());
2048     /* With a believable RSA key but a bogus OID */
2049     info.Algorithm.pszObjId = bogusOID;
2050     info.PublicKey.cbData = sizeof(key);
2051     info.PublicKey.pbData = key;
2052     SetLastError(0xdeadbeef);
2053     ret = CertGetPublicKeyLength(0, &info);
2054     ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
2055      "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
2056      ret, GetLastError());
2057     SetLastError(0xdeadbeef);
2058     ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
2059     ok(ret == 56, "Expected length 56, got %d\n", ret);
2060     /* An RSA key with the DH OID */
2061     info.Algorithm.pszObjId = oid_rsa_dh;
2062     SetLastError(0xdeadbeef);
2063     ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
2064     ok(ret == 0 && GetLastError() == CRYPT_E_ASN1_BADTAG,
2065      "Expected length 0 and CRYPT_E_ASN1_BADTAG, got length %d, %08x\n",
2066      ret, GetLastError());
2067     /* With the RSA OID */
2068     info.Algorithm.pszObjId = oid_rsa_rsa;
2069     SetLastError(0xdeadbeef);
2070     ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
2071     ok(ret == 56, "Expected length 56, got %d\n", ret);
2072 }
2073
2074 START_TEST(cert)
2075 {
2076     init_function_pointers();
2077
2078     testAddCert();
2079     testCertProperties();
2080     testDupCert();
2081     testFindCert();
2082     testGetSubjectCert();
2083     testGetIssuerCert();
2084
2085     testCryptHashCert();
2086     testCertSigs();
2087     testSignAndEncodeCert();
2088     testCreateSelfSignCert();
2089     testKeyUsage();
2090     testCompareCertName();
2091     testCompareIntegerBlob();
2092     testComparePublicKeyInfo();
2093     testHashPublicKeyInfo();
2094     testCompareCert();
2095     testVerifySubjectCert();
2096     testAcquireCertPrivateKey();
2097     testGetPublicKeyLength();
2098 }