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