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