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