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