comctl32: Update Polish translation.
[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: %ld\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 %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 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: %08lx\n", GetLastError());
304     ret = CertGetCertificateContextProperty(context, propID, hashProperty,
305      &size);
306     ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
307      GetLastError());
308     ok(!memcmp(hash, hashProperty, size), "Unexpected hash for property %ld\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: %08lx\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 %ld\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 %08lx\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 %08lx\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 %08lx\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: %08lx\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: %08lx\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: %08lx\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 %ld\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 %08lx\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 %08lx\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 %08lx\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: %08lx\n",
452      GetLastError());
453     size = sizeof(keyContext);
454     ret = CertGetCertificateContextProperty(context,
455      CERT_KEY_IDENTIFIER_PROP_ID, &keyContext, &size);
456     ok(ret, "CertGetCertificateContextProperty failed: %08lx\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: %08lx\n", GetLastError());
471     keyContext.hCryptProv = csp;
472     ret = CertSetCertificateContextProperty(context,
473      CERT_KEY_CONTEXT_PROP_ID, 0, &keyContext);
474     ok(ret, "CertSetCertificateContextProperty failed: %08lx\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 %08lx\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: %08lx\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: %08lx\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: %ld\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: %08lx\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 %ld\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: %ld\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: %08lx\n",
555      GetLastError());
556     ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
557      bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, NULL);
558     ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\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: %08lx\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: %08lx\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: %08lx\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: %08lx\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: %08lx\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: %ld\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: %08lx\n",
660      GetLastError());
661     ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
662      bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, &context1);
663     ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\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: %08lx\n",
669      GetLastError());
670
671     context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
672      NULL);
673     ok(!context2 && GetLastError() == E_INVALIDARG,
674      "Expected E_INVALIDARG, got %08lx\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 %08lx\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 %08lx\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: %08lx\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: %08lx\n", GetLastError());
756
757     ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
758      expiredCert, sizeof(expiredCert), CERT_STORE_ADD_ALWAYS, NULL);
759     ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\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: %08lx\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 %08lx\n", GetLastError());
774     parent = CertGetIssuerCertificateFromStore(store, NULL, NULL, &flags);
775     ok(!parent && GetLastError() == E_INVALIDARG,
776      "Expected E_INVALIDARG, got %08lx\n", GetLastError());
777     parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
778     ok(!parent && GetLastError() == E_INVALIDARG,
779      "Expected E_INVALIDARG, got %08lx\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 %08lx\n", GetLastError());
788     /* Perform no checks */
789     flags = 0;
790     parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
791     ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08lx\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: %08lx\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 %08lx\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: %08lx\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 %08lx\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: %08lx\n", GetLastError());
846     ok(hashLen == sizeof(hash), "Got unexpected size of hash %ld\n", hashLen);
847     /* Test with empty buffer */
848     ret = CryptHashCertificate(0, 0, 0, NULL, 0, hash, &hashLen);
849     ok(ret, "CryptHashCertificate failed: %08lx\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: %08lx\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: %08lx\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: %08lx\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: %08lx\n", GetLastError());
876         if (ret)
877         {
878             ok(mySigSize == sigLen, "Expected sig length %d, got %ld\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 %08lx\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 %08lx\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 %08lx\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 %08lx\n",
924      GetLastError());
925     ret = CryptGenKey(csp, AT_SIGNATURE, 0, key);
926     ok(ret, "CryptGenKey failed: %08lx\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: %08lx\n", GetLastError());
932         ok(size <= *sigLen, "Expected size <= %ld, got %ld\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: %08lx\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 %08lx\n", GetLastError());
960         ret = pCryptVerifyCertificateSignatureEx(csp, 0, 0, NULL, 0, NULL, 0, NULL);
961         ok(!ret && GetLastError() == E_INVALIDARG,
962          "Expected E_INVALIDARG, got %08lx\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 %08lx\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: %08lx\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 %08lx\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 %08lx\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 %08lx\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 %08lx\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: %08lx\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: %08lx\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: %08lx\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 void testCreateSelfSignCert(void)
1065 {
1066     PCCERT_CONTEXT context;
1067     CERT_NAME_BLOB name = { sizeof(subjectName), (LPBYTE)subjectName };
1068     HCRYPTPROV csp;
1069     BOOL ret;
1070     HCRYPTKEY key;
1071
1072     /* This crashes:
1073     context = CertCreateSelfSignCertificate(0, NULL, 0, NULL, NULL, NULL, NULL,
1074      NULL);
1075      * Calling this with no first parameter creates a new key container, which
1076      * lasts beyond the test, so I don't test that.  Nb: the generated key
1077      * name is a GUID.
1078     context = CertCreateSelfSignCertificate(0, &name, 0, NULL, NULL, NULL, NULL,
1079      NULL);
1080      */
1081
1082     /* Acquire a CSP */
1083     CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1084      CRYPT_DELETEKEYSET);
1085     ret = CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1086      CRYPT_NEWKEYSET);
1087     ok(ret, "CryptAcquireContext failed: %08lx\n", GetLastError());
1088
1089     context = CertCreateSelfSignCertificate(csp, &name, 0, NULL, NULL, NULL,
1090      NULL, NULL);
1091     ok(!context && GetLastError() == NTE_NO_KEY,
1092      "Expected NTE_NO_KEY, got %08lx\n", GetLastError());
1093     ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
1094     ok(ret, "CryptGenKey failed: %08lx\n", GetLastError());
1095     if (ret)
1096     {
1097         context = CertCreateSelfSignCertificate(csp, &name, 0, NULL, NULL, NULL,
1098          NULL, NULL);
1099         ok(context != NULL, "CertCreateSelfSignCertificate failed: %08lx\n",
1100          GetLastError());
1101         if (context)
1102         {
1103             DWORD size = 0;
1104             PCRYPT_KEY_PROV_INFO info;
1105
1106             /* The context must have a key provider info property */
1107             ret = CertGetCertificateContextProperty(context,
1108              CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
1109             ok(ret && size, "Expected non-zero key provider info\n");
1110             if (size)
1111             {
1112                 info = HeapAlloc(GetProcessHeap(), 0, size);
1113                 if (info)
1114                 {
1115                     ret = CertGetCertificateContextProperty(context,
1116                      CERT_KEY_PROV_INFO_PROP_ID, info, &size);
1117                     ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
1118                      GetLastError());
1119                     if (ret)
1120                     {
1121                         /* Sanity-check the key provider */
1122                         ok(!lstrcmpW(info->pwszContainerName, cspNameW),
1123                          "Unexpected key container\n");
1124                         ok(!lstrcmpW(info->pwszProvName, MS_DEF_PROV_W),
1125                          "Unexpected provider\n");
1126                         ok(info->dwKeySpec == AT_SIGNATURE,
1127                          "Expected AT_SIGNATURE, got %ld\n", info->dwKeySpec);
1128                     }
1129                     HeapFree(GetProcessHeap(), 0, info);
1130                 }
1131             }
1132
1133             CertFreeCertificateContext(context);
1134         }
1135
1136         CryptDestroyKey(key);
1137     }
1138
1139     CryptReleaseContext(csp, 0);
1140     ret = CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1141      CRYPT_DELETEKEYSET);
1142 }
1143
1144 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
1145  szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
1146
1147 static void testKeyUsage(void)
1148 {
1149     BOOL ret;
1150     PCCERT_CONTEXT context;
1151     DWORD size;
1152
1153     /* Test base cases */
1154     ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, NULL);
1155     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1156      "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
1157     size = 1;
1158     ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, &size);
1159     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1160      "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
1161     size = 0;
1162     ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, &size);
1163     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1164      "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
1165     /* These crash
1166     ret = CertSetEnhancedKeyUsage(NULL, NULL);
1167     usage.cUsageIdentifier = 0;
1168     ret = CertSetEnhancedKeyUsage(NULL, &usage);
1169      */
1170     /* Test with a cert with no enhanced key usage extension */
1171     context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
1172      sizeof(bigCert));
1173     ok(context != NULL, "CertCreateCertificateContext failed: %08lx\n",
1174      GetLastError());
1175     if (context)
1176     {
1177         static const char oid[] = "1.2.3.4";
1178         BYTE buf[sizeof(CERT_ENHKEY_USAGE) + 2 * (sizeof(LPSTR) + sizeof(oid))];
1179         PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1180
1181         ret = CertGetEnhancedKeyUsage(context, 0, NULL, NULL);
1182         ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1183          "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
1184         size = 1;
1185         ret = CertGetEnhancedKeyUsage(context, 0, NULL, &size);
1186         if (ret)
1187         {
1188             /* Windows 2000, ME, or later: even though it succeeded, we expect
1189              * CRYPT_E_NOT_FOUND, which indicates there is no enhanced key
1190              * usage set for this cert (which implies it's valid for all uses.)
1191              */
1192             ok(GetLastError() == CRYPT_E_NOT_FOUND,
1193              "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
1194             ok(size == sizeof(CERT_ENHKEY_USAGE), "Wrong size %ld\n", size);
1195             ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1196             ok(ret, "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1197             ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %ld\n",
1198              pUsage->cUsageIdentifier);
1199         }
1200         else
1201         {
1202             /* Windows NT, 95, or 98: it fails, and the last error is
1203              * CRYPT_E_NOT_FOUND.
1204              */
1205             ok(GetLastError() == CRYPT_E_NOT_FOUND,
1206              "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
1207         }
1208         /* I can add a usage identifier when no key usage has been set */
1209         ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
1210         ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08lx\n",
1211          GetLastError());
1212         size = sizeof(buf);
1213         ret = CertGetEnhancedKeyUsage(context,
1214          CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1215         ok(ret && GetLastError() == 0,
1216          "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1217         ok(pUsage->cUsageIdentifier == 1, "Expected 1 usage, got %ld\n",
1218          pUsage->cUsageIdentifier);
1219         if (pUsage->cUsageIdentifier)
1220             ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
1221              "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
1222         /* Now set an empty key usage */
1223         pUsage->cUsageIdentifier = 0;
1224         ret = CertSetEnhancedKeyUsage(context, pUsage);
1225         ok(ret, "CertSetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1226         /* Shouldn't find it in the cert */
1227         size = sizeof(buf);
1228         ret = CertGetEnhancedKeyUsage(context,
1229          CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1230         ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
1231          "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
1232         /* Should find it as an extended property */
1233         ret = CertGetEnhancedKeyUsage(context,
1234          CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1235         ok(ret && GetLastError() == 0,
1236          "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1237         ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %ld\n",
1238          pUsage->cUsageIdentifier);
1239         /* Should find it as either */
1240         ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1241         ok(ret && GetLastError() == 0,
1242          "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1243         ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %ld\n",
1244          pUsage->cUsageIdentifier);
1245         /* Add a usage identifier */
1246         ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
1247         ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08lx\n",
1248          GetLastError());
1249         size = sizeof(buf);
1250         ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1251         ok(ret && GetLastError() == 0,
1252          "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1253         ok(pUsage->cUsageIdentifier == 1, "Expected 1 identifier, got %ld\n",
1254          pUsage->cUsageIdentifier);
1255         if (pUsage->cUsageIdentifier)
1256             ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
1257              "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
1258         /* Yep, I can re-add the same usage identifier */
1259         ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
1260         ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08lx\n",
1261          GetLastError());
1262         size = sizeof(buf);
1263         ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1264         ok(ret && GetLastError() == 0,
1265          "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1266         ok(pUsage->cUsageIdentifier == 2, "Expected 2 identifiers, got %ld\n",
1267          pUsage->cUsageIdentifier);
1268         if (pUsage->cUsageIdentifier)
1269             ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
1270              "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
1271         if (pUsage->cUsageIdentifier >= 2)
1272             ok(!strcmp(pUsage->rgpszUsageIdentifier[1], oid),
1273              "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[1]);
1274         /* Now set a NULL extended property--this deletes the property. */
1275         ret = CertSetEnhancedKeyUsage(context, NULL);
1276         ok(ret, "CertSetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1277         SetLastError(0xbaadcafe);
1278         size = sizeof(buf);
1279         ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1280         ok(GetLastError() == CRYPT_E_NOT_FOUND,
1281          "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
1282
1283         CertFreeCertificateContext(context);
1284     }
1285     /* Now test with a cert with an enhanced key usage extension */
1286     context = CertCreateCertificateContext(X509_ASN_ENCODING, certWithUsage,
1287      sizeof(certWithUsage));
1288     ok(context != NULL, "CertCreateCertificateContext failed: %08lx\n",
1289      GetLastError());
1290     if (context)
1291     {
1292         LPBYTE buf = NULL;
1293         DWORD bufSize = 0, i;
1294
1295         /* The size may depend on what flags are used to query it, so I
1296          * realloc the buffer for each test.
1297          */
1298         ret = CertGetEnhancedKeyUsage(context,
1299          CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, NULL, &bufSize);
1300         ok(ret, "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1301         buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
1302         if (buf)
1303         {
1304             PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1305
1306             /* Should find it in the cert */
1307             size = bufSize;
1308             ret = CertGetEnhancedKeyUsage(context,
1309              CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1310             ok(ret && GetLastError() == 0,
1311              "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1312             ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %ld\n",
1313              pUsage->cUsageIdentifier);
1314             for (i = 0; i < pUsage->cUsageIdentifier; i++)
1315                 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
1316                  "Expected %s, got %s\n", keyUsages[i],
1317                  pUsage->rgpszUsageIdentifier[i]);
1318             HeapFree(GetProcessHeap(), 0, buf);
1319         }
1320         ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
1321         ok(ret, "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1322         buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
1323         if (buf)
1324         {
1325             PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1326
1327             /* Should find it as either */
1328             size = bufSize;
1329             ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1330             /* In Windows, GetLastError returns CRYPT_E_NOT_FOUND not found
1331              * here, even though the return is successful and the usage id
1332              * count is positive.  I don't enforce that here.
1333              */
1334             ok(ret,
1335              "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1336             ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %ld\n",
1337              pUsage->cUsageIdentifier);
1338             for (i = 0; i < pUsage->cUsageIdentifier; i++)
1339                 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
1340                  "Expected %s, got %s\n", keyUsages[i],
1341                  pUsage->rgpszUsageIdentifier[i]);
1342             HeapFree(GetProcessHeap(), 0, buf);
1343         }
1344         /* Shouldn't find it as an extended property */
1345         ret = CertGetEnhancedKeyUsage(context,
1346          CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, NULL, &size);
1347         ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
1348          "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
1349         /* Adding a usage identifier overrides the cert's usage!? */
1350         ret = CertAddEnhancedKeyUsageIdentifier(context, szOID_RSA_RSA);
1351         ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08lx\n",
1352          GetLastError());
1353         ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
1354         ok(ret, "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1355         buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
1356         if (buf)
1357         {
1358             PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1359
1360             /* Should find it as either */
1361             size = bufSize;
1362             ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1363             ok(ret,
1364              "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1365             ok(pUsage->cUsageIdentifier == 1, "Expected 1 usage, got %ld\n",
1366              pUsage->cUsageIdentifier);
1367             ok(!strcmp(pUsage->rgpszUsageIdentifier[0], szOID_RSA_RSA),
1368              "Expected %s, got %s\n", szOID_RSA_RSA,
1369              pUsage->rgpszUsageIdentifier[0]);
1370             HeapFree(GetProcessHeap(), 0, buf);
1371         }
1372         /* But querying the cert directly returns its usage */
1373         ret = CertGetEnhancedKeyUsage(context,
1374          CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, NULL, &bufSize);
1375         ok(ret, "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1376         buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
1377         if (buf)
1378         {
1379             PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1380
1381             size = bufSize;
1382             ret = CertGetEnhancedKeyUsage(context,
1383              CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1384             ok(ret,
1385              "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1386             ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %ld\n",
1387              pUsage->cUsageIdentifier);
1388             for (i = 0; i < pUsage->cUsageIdentifier; i++)
1389                 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
1390                  "Expected %s, got %s\n", keyUsages[i],
1391                  pUsage->rgpszUsageIdentifier[i]);
1392             HeapFree(GetProcessHeap(), 0, buf);
1393         }
1394         /* And removing the only usage identifier in the extended property
1395          * results in the cert's key usage being found.
1396          */
1397         ret = CertRemoveEnhancedKeyUsageIdentifier(context, szOID_RSA_RSA);
1398         ok(ret, "CertRemoveEnhancedKeyUsage failed: %08lx\n", GetLastError());
1399         ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
1400         ok(ret, "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1401         buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
1402         if (buf)
1403         {
1404             PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1405
1406             /* Should find it as either */
1407             size = bufSize;
1408             ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1409             ok(ret,
1410              "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1411             ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %ld\n",
1412              pUsage->cUsageIdentifier);
1413             for (i = 0; i < pUsage->cUsageIdentifier; i++)
1414                 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
1415                  "Expected %s, got %s\n", keyUsages[i],
1416                  pUsage->rgpszUsageIdentifier[i]);
1417             HeapFree(GetProcessHeap(), 0, buf);
1418         }
1419
1420         CertFreeCertificateContext(context);
1421     }
1422 }
1423
1424 static void testCompareCertName(void)
1425 {
1426     static const BYTE bogus[] = { 1, 2, 3, 4 };
1427     static const BYTE bogusPrime[] = { 0, 1, 2, 3, 4 };
1428     static const BYTE emptyPrime[] = { 0x30, 0x00, 0x01 };
1429     BOOL ret;
1430     CERT_NAME_BLOB blob1, blob2;
1431
1432     /* crashes
1433     ret = CertCompareCertificateName(0, NULL, NULL);
1434      */
1435     /* An empty name checks against itself.. */
1436     blob1.pbData = (LPBYTE)emptyCert;
1437     blob1.cbData = sizeof(emptyCert);
1438     ret = CertCompareCertificateName(0, &blob1, &blob1);
1439     ok(ret, "CertCompareCertificateName failed: %08lx\n", GetLastError());
1440     /* It doesn't have to be a valid encoded name.. */
1441     blob1.pbData = (LPBYTE)bogus;
1442     blob1.cbData = sizeof(bogus);
1443     ret = CertCompareCertificateName(0, &blob1, &blob1);
1444     ok(ret, "CertCompareCertificateName failed: %08lx\n", GetLastError());
1445     /* Leading zeroes matter.. */
1446     blob2.pbData = (LPBYTE)bogusPrime;
1447     blob2.cbData = sizeof(bogusPrime);
1448     ret = CertCompareCertificateName(0, &blob1, &blob2);
1449     ok(!ret, "Expected failure\n");
1450     /* As do trailing extra bytes. */
1451     blob2.pbData = (LPBYTE)emptyPrime;
1452     blob2.cbData = sizeof(emptyPrime);
1453     ret = CertCompareCertificateName(0, &blob1, &blob2);
1454     ok(!ret, "Expected failure\n");
1455 }
1456
1457 static const BYTE int1[] = { 0x88, 0xff, 0xff, 0xff };
1458 static const BYTE int2[] = { 0x88, 0xff };
1459 static const BYTE int3[] = { 0x23, 0xff };
1460 static const BYTE int4[] = { 0x7f, 0x00 };
1461 static const BYTE int5[] = { 0x7f };
1462 static const BYTE int6[] = { 0x80, 0x00, 0x00, 0x00 };
1463 static const BYTE int7[] = { 0x80, 0x00 };
1464
1465 struct IntBlobTest
1466 {
1467     CRYPT_INTEGER_BLOB blob1;
1468     CRYPT_INTEGER_BLOB blob2;
1469     BOOL areEqual;
1470 } intBlobs[] = {
1471  { { sizeof(int1), (LPBYTE)int1 }, { sizeof(int2), (LPBYTE)int2 }, TRUE },
1472  { { sizeof(int3), (LPBYTE)int3 }, { sizeof(int3), (LPBYTE)int3 }, TRUE },
1473  { { sizeof(int4), (LPBYTE)int4 }, { sizeof(int5), (LPBYTE)int5 }, TRUE },
1474  { { sizeof(int6), (LPBYTE)int6 }, { sizeof(int7), (LPBYTE)int7 }, TRUE },
1475  { { sizeof(int1), (LPBYTE)int1 }, { sizeof(int7), (LPBYTE)int7 }, FALSE },
1476 };
1477
1478 static void testCompareIntegerBlob(void)
1479 {
1480     DWORD i;
1481     BOOL ret;
1482
1483     for (i = 0; i < sizeof(intBlobs) / sizeof(intBlobs[0]); i++)
1484     {
1485         ret = CertCompareIntegerBlob(&intBlobs[i].blob1, &intBlobs[i].blob2);
1486         ok(ret == intBlobs[i].areEqual,
1487          "%ld: expected blobs %s compare\n", i, intBlobs[i].areEqual ?
1488          "to" : "not to");
1489     }
1490 }
1491
1492 static void testComparePublicKeyInfo(void)
1493 {
1494     BOOL ret;
1495     CERT_PUBLIC_KEY_INFO info1 = { { 0 } }, info2 = { { 0 } };
1496     static CHAR oid_rsa_rsa[]     = szOID_RSA_RSA;
1497     static CHAR oid_rsa_sha1rsa[] = szOID_RSA_SHA1RSA;
1498     static CHAR oid_x957_dsa[]    = szOID_X957_DSA;
1499     static const BYTE bits1[] = { 1, 0 };
1500     static const BYTE bits2[] = { 0 };
1501     static const BYTE bits3[] = { 1 };
1502
1503     /* crashes
1504     ret = CertComparePublicKeyInfo(0, NULL, NULL);
1505      */
1506     /* Empty public keys compare */
1507     ret = CertComparePublicKeyInfo(0, &info1, &info2);
1508     ok(ret, "CertComparePublicKeyInfo failed: %08lx\n", GetLastError());
1509     /* Different OIDs appear to compare */
1510     info1.Algorithm.pszObjId = oid_rsa_rsa;
1511     info2.Algorithm.pszObjId = oid_rsa_sha1rsa;
1512     ret = CertComparePublicKeyInfo(0, &info1, &info2);
1513     ok(ret, "CertComparePublicKeyInfo failed: %08lx\n", GetLastError());
1514     info2.Algorithm.pszObjId = oid_x957_dsa;
1515     ret = CertComparePublicKeyInfo(0, &info1, &info2);
1516     ok(ret, "CertComparePublicKeyInfo failed: %08lx\n", GetLastError());
1517     info1.PublicKey.cbData = sizeof(bits1);
1518     info1.PublicKey.pbData = (LPBYTE)bits1;
1519     info1.PublicKey.cUnusedBits = 0;
1520     info2.PublicKey.cbData = sizeof(bits1);
1521     info2.PublicKey.pbData = (LPBYTE)bits1;
1522     info2.PublicKey.cUnusedBits = 0;
1523     ret = CertComparePublicKeyInfo(0, &info1, &info2);
1524     ok(ret, "CertComparePublicKeyInfo failed: %08lx\n", GetLastError());
1525     /* Even though they compare in their used bits, these do not compare */
1526     info1.PublicKey.cbData = sizeof(bits2);
1527     info1.PublicKey.pbData = (LPBYTE)bits2;
1528     info1.PublicKey.cUnusedBits = 0;
1529     info2.PublicKey.cbData = sizeof(bits3);
1530     info2.PublicKey.pbData = (LPBYTE)bits3;
1531     info2.PublicKey.cUnusedBits = 1;
1532     ret = CertComparePublicKeyInfo(0, &info1, &info2);
1533     /* Simple (non-comparing) case */
1534     ok(!ret, "Expected keys not to compare\n");
1535     info2.PublicKey.cbData = sizeof(bits1);
1536     info2.PublicKey.pbData = (LPBYTE)bits1;
1537     info2.PublicKey.cUnusedBits = 0;
1538     ret = CertComparePublicKeyInfo(0, &info1, &info2);
1539     ok(!ret, "Expected keys not to compare\n");
1540 }
1541
1542 static void testHashPublicKeyInfo(void)
1543 {
1544     BOOL ret;
1545     CERT_PUBLIC_KEY_INFO info = { { 0 } };
1546     DWORD len;
1547
1548     /* Crash
1549     ret = CryptHashPublicKeyInfo(0, 0, 0, 0, NULL, NULL, NULL);
1550     ret = CryptHashPublicKeyInfo(0, 0, 0, 0, &info, NULL, NULL);
1551      */
1552     ret = CryptHashPublicKeyInfo(0, 0, 0, 0, NULL, NULL, &len);
1553     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1554      "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1555     ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, NULL, NULL, &len);
1556     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1557      "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
1558     ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, &info, NULL, &len);
1559     ok(ret, "CryptHashPublicKeyInfo failed: %08lx\n", GetLastError());
1560     ok(len == 16, "Expected hash size 16, got %ld\n", len);
1561     if (len == 16)
1562     {
1563         static const BYTE emptyHash[] = { 0xb8,0x51,0x3a,0x31,0x0e,0x9f,0x40,
1564          0x36,0x9c,0x92,0x45,0x1b,0x9d,0xc8,0xf9,0xf6 };
1565         BYTE buf[16];
1566
1567         ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, &info, buf,
1568          &len);
1569         ok(ret, "CryptHashPublicKeyInfo failed: %08lx\n", GetLastError());
1570         ok(!memcmp(buf, emptyHash, len), "Unexpected hash\n");
1571     }
1572 }
1573
1574 void testCompareCert(void)
1575 {
1576     CERT_INFO info1 = { 0 }, info2 = { 0 };
1577     BOOL ret;
1578
1579     /* Crashes
1580     ret = CertCompareCertificate(X509_ASN_ENCODING, NULL, NULL);
1581      */
1582
1583     /* Certs with the same issuer and serial number are equal, even if they
1584      * differ in other respects (like subject).
1585      */
1586     info1.SerialNumber.pbData = (LPBYTE)serialNum;
1587     info1.SerialNumber.cbData = sizeof(serialNum);
1588     info1.Issuer.pbData = (LPBYTE)subjectName;
1589     info1.Issuer.cbData = sizeof(subjectName);
1590     info1.Subject.pbData = (LPBYTE)subjectName2;
1591     info1.Subject.cbData = sizeof(subjectName2);
1592     info2.SerialNumber.pbData = (LPBYTE)serialNum;
1593     info2.SerialNumber.cbData = sizeof(serialNum);
1594     info2.Issuer.pbData = (LPBYTE)subjectName;
1595     info2.Issuer.cbData = sizeof(subjectName);
1596     info2.Subject.pbData = (LPBYTE)subjectName;
1597     info2.Subject.cbData = sizeof(subjectName);
1598     ret = CertCompareCertificate(X509_ASN_ENCODING, &info1, &info2);
1599     ok(ret, "Expected certs to be equal\n");
1600
1601     info2.Issuer.pbData = (LPBYTE)subjectName2;
1602     info2.Issuer.cbData = sizeof(subjectName2);
1603     ret = CertCompareCertificate(X509_ASN_ENCODING, &info1, &info2);
1604     ok(!ret, "Expected certs not to be equal\n");
1605 }
1606
1607 static void testVerifySubjectCert(void)
1608 {
1609     BOOL ret;
1610     DWORD flags;
1611     PCCERT_CONTEXT context1, context2;
1612
1613     /* Crashes
1614     ret = CertVerifySubjectCertificateContext(NULL, NULL, NULL);
1615      */
1616     flags = 0;
1617     ret = CertVerifySubjectCertificateContext(NULL, NULL, &flags);
1618     ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n",
1619      GetLastError());
1620     flags = CERT_STORE_NO_CRL_FLAG;
1621     ret = CertVerifySubjectCertificateContext(NULL, NULL, &flags);
1622     ok(!ret && GetLastError() == E_INVALIDARG,
1623      "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1624
1625     flags = 0;
1626     context1 = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
1627      sizeof(bigCert));
1628     ret = CertVerifySubjectCertificateContext(NULL, context1, &flags);
1629     ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n",
1630      GetLastError());
1631     ret = CertVerifySubjectCertificateContext(context1, NULL, &flags);
1632     ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n",
1633      GetLastError());
1634     ret = CertVerifySubjectCertificateContext(context1, context1, &flags);
1635     ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n",
1636      GetLastError());
1637
1638     context2 = CertCreateCertificateContext(X509_ASN_ENCODING,
1639      bigCertWithDifferentSubject, sizeof(bigCertWithDifferentSubject));
1640     SetLastError(0xdeadbeef);
1641     ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
1642     ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n",
1643      GetLastError());
1644     flags = CERT_STORE_REVOCATION_FLAG;
1645     ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
1646     ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n",
1647      GetLastError());
1648     ok(flags == (CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG),
1649      "Expected CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG, got %08lx\n",
1650      flags);
1651     flags = CERT_STORE_SIGNATURE_FLAG;
1652     ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
1653     ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n",
1654      GetLastError());
1655     ok(flags == CERT_STORE_SIGNATURE_FLAG,
1656      "Expected CERT_STORE_SIGNATURE_FLAG, got %08lx\n", flags);
1657     CertFreeCertificateContext(context2);
1658
1659     CertFreeCertificateContext(context1);
1660 }
1661
1662 static const BYTE privKey[] = {
1663  0x07, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x52, 0x53, 0x41, 0x32, 0x00,
1664  0x02, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x79, 0x10, 0x1c, 0xd0, 0x6b, 0x10,
1665  0x18, 0x30, 0x94, 0x61, 0xdc, 0x0e, 0xcb, 0x96, 0x4e, 0x21, 0x3f, 0x79, 0xcd,
1666  0xa9, 0x17, 0x62, 0xbc, 0xbb, 0x61, 0x4c, 0xe0, 0x75, 0x38, 0x6c, 0xf3, 0xde,
1667  0x60, 0x86, 0x03, 0x97, 0x65, 0xeb, 0x1e, 0x6b, 0xdb, 0x53, 0x85, 0xad, 0x68,
1668  0x21, 0xf1, 0x5d, 0xe7, 0x1f, 0xe6, 0x53, 0xb4, 0xbb, 0x59, 0x3e, 0x14, 0x27,
1669  0xb1, 0x83, 0xa7, 0x3a, 0x54, 0xe2, 0x8f, 0x65, 0x8e, 0x6a, 0x4a, 0xcf, 0x3b,
1670  0x1f, 0x65, 0xff, 0xfe, 0xf1, 0x31, 0x3a, 0x37, 0x7a, 0x8b, 0xcb, 0xc6, 0xd4,
1671  0x98, 0x50, 0x36, 0x67, 0xe4, 0xa1, 0xe8, 0x7e, 0x8a, 0xc5, 0x23, 0xf2, 0x77,
1672  0xf5, 0x37, 0x61, 0x49, 0x72, 0x59, 0xe8, 0x3d, 0xf7, 0x60, 0xb2, 0x77, 0xca,
1673  0x78, 0x54, 0x6d, 0x65, 0x9e, 0x03, 0x97, 0x1b, 0x61, 0xbd, 0x0c, 0xd8, 0x06,
1674  0x63, 0xe2, 0xc5, 0x48, 0xef, 0xb3, 0xe2, 0x6e, 0x98, 0x7d, 0xbd, 0x4e, 0x72,
1675  0x91, 0xdb, 0x31, 0x57, 0xe3, 0x65, 0x3a, 0x49, 0xca, 0xec, 0xd2, 0x02, 0x4e,
1676  0x22, 0x7e, 0x72, 0x8e, 0xf9, 0x79, 0x84, 0x82, 0xdf, 0x7b, 0x92, 0x2d, 0xaf,
1677  0xc9, 0xe4, 0x33, 0xef, 0x89, 0x5c, 0x66, 0x99, 0xd8, 0x80, 0x81, 0x47, 0x2b,
1678  0xb1, 0x66, 0x02, 0x84, 0x59, 0x7b, 0xc3, 0xbe, 0x98, 0x45, 0x4a, 0x3d, 0xdd,
1679  0xea, 0x2b, 0xdf, 0x4e, 0xb4, 0x24, 0x6b, 0xec, 0xe7, 0xd9, 0x0c, 0x45, 0xb8,
1680  0xbe, 0xca, 0x69, 0x37, 0x92, 0x4c, 0x38, 0x6b, 0x96, 0x6d, 0xcd, 0x86, 0x67,
1681  0x5c, 0xea, 0x54, 0x94, 0xa4, 0xca, 0xa4, 0x02, 0xa5, 0x21, 0x4d, 0xae, 0x40,
1682  0x8f, 0x9d, 0x51, 0x83, 0xf2, 0x3f, 0x33, 0xc1, 0x72, 0xb4, 0x1d, 0x94, 0x6e,
1683  0x7d, 0xe4, 0x27, 0x3f, 0xea, 0xff, 0xe5, 0x9b, 0xa7, 0x5e, 0x55, 0x8e, 0x0d,
1684  0x69, 0x1c, 0x7a, 0xff, 0x81, 0x9d, 0x53, 0x52, 0x97, 0x9a, 0x76, 0x79, 0xda,
1685  0x93, 0x32, 0x16, 0xec, 0x69, 0x51, 0x1a, 0x4e, 0xc3, 0xf1, 0x72, 0x80, 0x78,
1686  0x5e, 0x66, 0x4a, 0x8d, 0x85, 0x2f, 0x3f, 0xb2, 0xa7 };
1687
1688 static const BYTE selfSignedCert[] = {
1689  0x30, 0x82, 0x01, 0x1f, 0x30, 0x81, 0xce, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
1690  0x10, 0xeb, 0x0d, 0x57, 0x2a, 0x9c, 0x09, 0xba, 0xa4, 0x4a, 0xb7, 0x25, 0x49,
1691  0xd9, 0x3e, 0xb5, 0x73, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d,
1692  0x05, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
1693  0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30,
1694  0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x36, 0x32, 0x39, 0x30, 0x35, 0x30, 0x30,
1695  0x34, 0x36, 0x5a, 0x17, 0x0d, 0x30, 0x37, 0x30, 0x36, 0x32, 0x39, 0x31, 0x31,
1696  0x30, 0x30, 0x34, 0x36, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
1697  0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e,
1698  0x67, 0x00, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
1699  0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
1700  0x00, 0xe2, 0x54, 0x3a, 0xa7, 0x83, 0xb1, 0x27, 0x14, 0x3e, 0x59, 0xbb, 0xb4,
1701  0x53, 0xe6, 0x1f, 0xe7, 0x5d, 0xf1, 0x21, 0x68, 0xad, 0x85, 0x53, 0xdb, 0x6b,
1702  0x1e, 0xeb, 0x65, 0x97, 0x03, 0x86, 0x60, 0xde, 0xf3, 0x6c, 0x38, 0x75, 0xe0,
1703  0x4c, 0x61, 0xbb, 0xbc, 0x62, 0x17, 0xa9, 0xcd, 0x79, 0x3f, 0x21, 0x4e, 0x96,
1704  0xcb, 0x0e, 0xdc, 0x61, 0x94, 0x30, 0x18, 0x10, 0x6b, 0xd0, 0x1c, 0x10, 0x79,
1705  0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
1706  0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x25, 0x90, 0x53, 0x34, 0xd9, 0x56, 0x41,
1707  0x5e, 0xdb, 0x7e, 0x01, 0x36, 0xec, 0x27, 0x61, 0x5e, 0xb7, 0x4d, 0x90, 0x66,
1708  0xa2, 0xe1, 0x9d, 0x58, 0x76, 0xd4, 0x9c, 0xba, 0x2c, 0x84, 0xc6, 0x83, 0x7a,
1709  0x22, 0x0d, 0x03, 0x69, 0x32, 0x1a, 0x6d, 0xcb, 0x0c, 0x15, 0xb3, 0x6b, 0xc7,
1710  0x0a, 0x8c, 0xb4, 0x5c, 0x34, 0x78, 0xe0, 0x3c, 0x9c, 0xe9, 0xf3, 0x30, 0x9f,
1711  0xa8, 0x76, 0x57, 0x92, 0x36 };
1712
1713 static const BYTE exportedPublicKeyBlob[] = {
1714 0x06,0x02,0x00,0x00,0x00,0xa4,0x00,0x00,0x52,0x53,0x41,0x31,0x00,0x02,0x00,0x00,
1715 0x01,0x00,0x01,0x00,0x79,0x10,0x1c,0xd0,0x6b,0x10,0x18,0x30,0x94,0x61,0xdc,0x0e,
1716 0xcb,0x96,0x4e,0x21,0x3f,0x79,0xcd,0xa9,0x17,0x62,0xbc,0xbb,0x61,0x4c,0xe0,0x75,
1717 0x38,0x6c,0xf3,0xde,0x60,0x86,0x03,0x97,0x65,0xeb,0x1e,0x6b,0xdb,0x53,0x85,0xad,
1718 0x68,0x21,0xf1,0x5d,0xe7,0x1f,0xe6,0x53,0xb4,0xbb,0x59,0x3e,0x14,0x27,0xb1,0x83,
1719 0xa7,0x3a,0x54,0xe2 };
1720
1721 static const BYTE asnEncodedPublicKey[] = {
1722 0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7,0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,
1723 0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21,0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,
1724 0x65,0x97,0x03,0x86,0x60,0xde,0xf3,0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,
1725 0x17,0xa9,0xcd,0x79,0x3f,0x21,0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,
1726 0x6b,0xd0,0x1c,0x10,0x79,0x02,0x03,0x01,0x00,0x01 };
1727
1728 static void testAcquireCertPrivateKey(void)
1729 {
1730     BOOL ret;
1731     PCCERT_CONTEXT cert;
1732     HCRYPTPROV csp;
1733     DWORD size, keySpec;
1734     BOOL callerFree;
1735     CRYPT_KEY_PROV_INFO keyProvInfo;
1736     HCRYPTKEY key;
1737
1738     keyProvInfo.pwszContainerName = (LPWSTR)cspNameW;
1739     keyProvInfo.pwszProvName = (LPWSTR)MS_DEF_PROV_W;
1740     keyProvInfo.dwProvType = PROV_RSA_FULL;
1741     keyProvInfo.dwFlags = 0;
1742     keyProvInfo.cProvParam = 0;
1743     keyProvInfo.rgProvParam = NULL;
1744     keyProvInfo.dwKeySpec = AT_SIGNATURE;
1745
1746     CryptAcquireContextW(NULL, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1747      CRYPT_DELETEKEYSET);
1748
1749     cert = CertCreateCertificateContext(X509_ASN_ENCODING, selfSignedCert,
1750      sizeof(selfSignedCert));
1751
1752     /* Crash
1753     ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, NULL, NULL);
1754     ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, NULL,
1755      &callerFree);
1756     ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, &keySpec,
1757      NULL);
1758     ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, &csp, NULL, NULL);
1759     ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, &csp, &keySpec,
1760      &callerFree);
1761     ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, NULL, NULL, NULL);
1762      */
1763
1764     /* Missing private key */
1765     ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, NULL, NULL);
1766     ok(!ret && GetLastError() == CRYPT_E_NO_KEY_PROPERTY,
1767      "Expected CRYPT_E_NO_KEY_PROPERTY, got %08lx\n", GetLastError());
1768     ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, &keySpec,
1769      &callerFree);
1770     ok(!ret && GetLastError() == CRYPT_E_NO_KEY_PROPERTY,
1771      "Expected CRYPT_E_NO_KEY_PROPERTY, got %08lx\n", GetLastError());
1772     CertSetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, 0,
1773      &keyProvInfo);
1774     ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, &keySpec,
1775      &callerFree);
1776     ok(!ret && GetLastError() == CRYPT_E_NO_KEY_PROPERTY,
1777      "Expected CRYPT_E_NO_KEY_PROPERTY, got %08lx\n", GetLastError());
1778
1779     CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1780      CRYPT_NEWKEYSET);
1781     ret = CryptImportKey(csp, (LPBYTE)privKey, sizeof(privKey), 0, 0, &key);
1782     ok(ret, "CryptImportKey failed: %08lx\n", GetLastError());
1783     if (ret)
1784     {
1785         HCRYPTPROV certCSP;
1786         DWORD size;
1787         CERT_KEY_CONTEXT keyContext;
1788
1789         /* Don't cache provider */
1790         ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &certCSP,
1791          &keySpec, &callerFree);
1792         ok(ret, "CryptAcquireCertificatePrivateKey failed: %08lx\n",
1793          GetLastError());
1794         ok(callerFree, "Expected callerFree to be TRUE\n");
1795         CryptReleaseContext(certCSP, 0);
1796         ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &certCSP,
1797          NULL, NULL);
1798         ok(ret, "CryptAcquireCertificatePrivateKey failed: %08lx\n",
1799          GetLastError());
1800         CryptReleaseContext(certCSP, 0);
1801
1802         /* Use the key prov info's caching (there shouldn't be any) */
1803         ret = CryptAcquireCertificatePrivateKey(cert,
1804          CRYPT_ACQUIRE_USE_PROV_INFO_FLAG, NULL, &certCSP, &keySpec,
1805          &callerFree);
1806         ok(ret, "CryptAcquireCertificatePrivateKey failed: %08lx\n",
1807          GetLastError());
1808         ok(callerFree, "Expected callerFree to be TRUE\n");
1809         CryptReleaseContext(certCSP, 0);
1810
1811         /* Cache it (and check that it's cached) */
1812         ret = CryptAcquireCertificatePrivateKey(cert,
1813          CRYPT_ACQUIRE_CACHE_FLAG, NULL, &certCSP, &keySpec, &callerFree);
1814         ok(ret, "CryptAcquireCertificatePrivateKey failed: %08lx\n",
1815          GetLastError());
1816         ok(!callerFree, "Expected callerFree to be FALSE\n");
1817         size = sizeof(keyContext);
1818         ret = CertGetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID,
1819          &keyContext, &size);
1820         ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
1821          GetLastError());
1822
1823         /* Remove the cached provider */
1824         CryptReleaseContext(keyContext.hCryptProv, 0);
1825         CertSetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID, 0,
1826          NULL);
1827         /* Allow caching via the key prov info */
1828         keyProvInfo.dwFlags = CERT_SET_KEY_CONTEXT_PROP_ID;
1829         CertSetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, 0,
1830          &keyProvInfo);
1831         /* Now use the key prov info's caching */
1832         ret = CryptAcquireCertificatePrivateKey(cert,
1833          CRYPT_ACQUIRE_USE_PROV_INFO_FLAG, NULL, &certCSP, &keySpec,
1834          &callerFree);
1835         ok(ret, "CryptAcquireCertificatePrivateKey failed: %08lx\n",
1836          GetLastError());
1837         ok(!callerFree, "Expected callerFree to be FALSE\n");
1838         size = sizeof(keyContext);
1839         ret = CertGetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID,
1840          &keyContext, &size);
1841         ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
1842          GetLastError());
1843
1844         CryptDestroyKey(key);
1845     }
1846
1847     /* Some sanity-checking on public key exporting */
1848     ret = CryptImportPublicKeyInfo(csp, X509_ASN_ENCODING,
1849      &cert->pCertInfo->SubjectPublicKeyInfo, &key);
1850     ok(ret, "CryptImportPublicKeyInfo failed: %08lx\n", GetLastError());
1851     if (ret)
1852     {
1853         ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &size);
1854         ok(ret, "CryptExportKey failed: %08lx\n", GetLastError());
1855         if (ret)
1856         {
1857             LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, size), encodedKey;
1858
1859             ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, buf, &size);
1860             ok(ret, "CryptExportKey failed: %08lx\n", GetLastError());
1861             ok(size == sizeof(exportedPublicKeyBlob), "Unexpected size %ld\n",
1862              size);
1863             ok(!memcmp(buf, exportedPublicKeyBlob, size), "Unexpected value\n");
1864             ret = CryptEncodeObjectEx(X509_ASN_ENCODING, RSA_CSP_PUBLICKEYBLOB,
1865              buf, CRYPT_ENCODE_ALLOC_FLAG, NULL, &encodedKey, &size);
1866             ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1867             if (ret)
1868             {
1869                 ok(size == sizeof(asnEncodedPublicKey), "Unexpected size %ld\n",
1870                  size);
1871                 ok(!memcmp(encodedKey, asnEncodedPublicKey, size),
1872                  "Unexpected value\n");
1873                 LocalFree(encodedKey);
1874             }
1875             HeapFree(GetProcessHeap(), 0, buf);
1876         }
1877         CryptDestroyKey(key);
1878     }
1879     ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
1880      NULL, 0, NULL, NULL, &size);
1881     ok(ret, "CryptExportPublicKeyInfoEx failed: %08lx\n", GetLastError());
1882     if (ret)
1883     {
1884         PCERT_PUBLIC_KEY_INFO info = HeapAlloc(GetProcessHeap(), 0, size);
1885
1886         ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
1887          NULL, 0, NULL, info, &size);
1888         ok(ret, "CryptExportPublicKeyInfoEx failed: %08lx\n", GetLastError());
1889         if (ret)
1890         {
1891             ok(info->PublicKey.cbData == sizeof(asnEncodedPublicKey),
1892              "Unexpected size %ld\n", info->PublicKey.cbData);
1893             ok(!memcmp(info->PublicKey.pbData, asnEncodedPublicKey,
1894              info->PublicKey.cbData), "Unexpected value\n");
1895         }
1896         HeapFree(GetProcessHeap(), 0, info);
1897     }
1898
1899     CryptReleaseContext(csp, 0);
1900     CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1901      CRYPT_DELETEKEYSET);
1902
1903     CertFreeCertificateContext(cert);
1904 }
1905
1906 START_TEST(cert)
1907 {
1908     init_function_pointers();
1909
1910     testAddCert();
1911     testCertProperties();
1912     testDupCert();
1913     testFindCert();
1914     testGetSubjectCert();
1915     testGetIssuerCert();
1916
1917     testCryptHashCert();
1918     testCertSigs();
1919     testCreateSelfSignCert();
1920     testKeyUsage();
1921     testCompareCertName();
1922     testCompareIntegerBlob();
1923     testComparePublicKeyInfo();
1924     testHashPublicKeyInfo();
1925     testCompareCert();
1926     testVerifySubjectCert();
1927     testAcquireCertPrivateKey();
1928 }