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