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