push 4d5485f9b89f417d46b39b93e8d940437007f325
[wine/hacks.git] / dlls / crypt32 / tests / cert.c
blob89b51e7cdbf1250d2fc0cee1e003077760fc33f3
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 static BOOL (WINAPI * pCryptAcquireContextW)
36 (HCRYPTPROV *, LPCWSTR, LPCWSTR, DWORD, DWORD);
38 static void init_function_pointers(void)
40 HMODULE hCrypt32 = GetModuleHandleA("crypt32.dll");
41 HMODULE hAdvapi32 = GetModuleHandleA("advapi32.dll");
43 #define GET_PROC(dll, func) \
44 p ## func = (void *)GetProcAddress(dll, #func); \
45 if(!p ## func) \
46 trace("GetProcAddress(%s) failed\n", #func);
48 GET_PROC(hCrypt32, CryptVerifyCertificateSignatureEx)
50 GET_PROC(hAdvapi32, CryptAcquireContextW)
52 #undef GET_PROC
55 static BYTE subjectName[] = { 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
56 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
57 0x6e, 0x67, 0x00 };
58 static BYTE serialNum[] = { 1 };
59 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
60 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
61 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
62 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
63 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
64 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
65 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
66 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
67 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
68 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
69 static BYTE bigCertHash[] = { 0x6e, 0x30, 0x90, 0x71, 0x5f, 0xd9, 0x23,
70 0x56, 0xeb, 0xae, 0x25, 0x40, 0xe6, 0x22, 0xda, 0x19, 0x26, 0x02, 0xa6, 0x08 };
72 static const BYTE bigCertWithDifferentSubject[] = { 0x30, 0x7a, 0x02, 0x01, 0x02,
73 0x30, 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
74 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67,
75 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31,
76 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
77 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15,
78 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c,
79 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06,
80 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55,
81 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02,
82 0x01, 0x01 };
83 static const BYTE bigCertWithDifferentIssuer[] = { 0x30, 0x7a, 0x02, 0x01,
84 0x01, 0x30, 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
85 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e,
86 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
87 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30,
88 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30,
89 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
90 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02,
91 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03,
92 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff,
93 0x02, 0x01, 0x01 };
95 static BYTE subjectName2[] = { 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
96 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61,
97 0x6e, 0x67, 0x00 };
98 static const BYTE bigCert2[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
99 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
100 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
101 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
102 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
103 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
104 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20,
105 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
106 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
107 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
108 static const BYTE bigCert2WithDifferentSerial[] = { 0x30, 0x7a, 0x02, 0x01,
109 0x02, 0x30, 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
110 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e,
111 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
112 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30,
113 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30,
114 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41,
115 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02,
116 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03,
117 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff,
118 0x02, 0x01, 0x01 };
119 static BYTE bigCert2Hash[] = { 0x4a, 0x7f, 0x32, 0x1f, 0xcf, 0x3b, 0xc0,
120 0x87, 0x48, 0x2b, 0xa1, 0x86, 0x54, 0x18, 0xe4, 0x3a, 0x0e, 0x53, 0x7e, 0x2b };
122 static const BYTE certWithUsage[] = { 0x30, 0x81, 0x93, 0x02, 0x01, 0x01, 0x30,
123 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04,
124 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00,
125 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
126 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
127 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31,
128 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61,
129 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00,
130 0x03, 0x01, 0x00, 0xa3, 0x2f, 0x30, 0x2d, 0x30, 0x2b, 0x06, 0x03, 0x55, 0x1d,
131 0x25, 0x01, 0x01, 0xff, 0x04, 0x21, 0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01,
132 0x05, 0x05, 0x07, 0x03, 0x03, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
133 0x03, 0x02, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
135 static void testAddCert(void)
137 HCERTSTORE store;
138 HCERTSTORE collection;
139 PCCERT_CONTEXT context;
140 PCCERT_CONTEXT copyContext;
141 BOOL ret;
143 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
144 CERT_STORE_CREATE_NEW_FLAG, NULL);
145 ok(store != NULL, "CertOpenStore failed: %d\n", GetLastError());
146 if (!store)
147 return;
149 /* Weird--bad add disposition leads to an access violation in Windows.
151 ret = CertAddEncodedCertificateToStore(0, X509_ASN_ENCODING, bigCert,
152 sizeof(bigCert), 0, NULL);
153 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
154 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
155 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
156 bigCert, sizeof(bigCert), 0, NULL);
157 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
158 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
160 /* Weird--can add a cert to the NULL store (does this have special
161 * meaning?)
163 context = NULL;
164 ret = CertAddEncodedCertificateToStore(0, X509_ASN_ENCODING, bigCert,
165 sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
166 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
167 GetLastError());
168 if (context)
169 CertFreeCertificateContext(context);
171 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
172 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
173 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
174 GetLastError());
175 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
176 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, NULL);
177 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
178 GetLastError());
179 /* This has the same name as bigCert, so finding isn't done by name */
180 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
181 certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, &context);
182 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
183 GetLastError());
184 ok(context != NULL, "Expected a context\n");
185 if (context)
187 CRYPT_DATA_BLOB hash = { sizeof(bigCert2Hash), bigCert2Hash };
189 /* Duplicate (AddRef) the context so we can still use it after
190 * deleting it from the store.
192 CertDuplicateCertificateContext(context);
193 CertDeleteCertificateFromStore(context);
194 /* Set the same hash as bigCert2, and try to readd it */
195 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID,
196 0, &hash);
197 ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
198 GetLastError());
199 ret = CertAddCertificateContextToStore(store, context,
200 CERT_STORE_ADD_NEW, NULL);
201 /* The failure is a bit odd (CRYPT_E_ASN1_BADTAG), so just check
202 * that it fails.
204 ok(!ret, "Expected failure\n");
205 CertFreeCertificateContext(context);
207 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert2,
208 sizeof(bigCert2));
209 ok(context != NULL, "Expected a context\n");
210 if (context)
212 /* Try to readd bigCert2 to the store */
213 ret = CertAddCertificateContextToStore(store, context,
214 CERT_STORE_ADD_NEW, NULL);
215 ok(!ret && GetLastError() == CRYPT_E_EXISTS,
216 "Expected CRYPT_E_EXISTS, got %08x\n", GetLastError());
217 CertFreeCertificateContext(context);
220 /* Adding a cert with the same issuer name and serial number (but
221 * different subject) as an existing cert succeeds.
223 context = NULL;
224 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
225 bigCert2WithDifferentSerial, sizeof(bigCert2WithDifferentSerial),
226 CERT_STORE_ADD_NEW, &context);
227 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
228 GetLastError());
229 if (context)
230 CertDeleteCertificateFromStore(context);
232 /* Adding a cert with the same subject name and serial number (but
233 * different issuer) as an existing cert succeeds.
235 context = NULL;
236 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
237 bigCertWithDifferentSubject, sizeof(bigCertWithDifferentSubject),
238 CERT_STORE_ADD_NEW, &context);
239 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
240 GetLastError());
241 if (context)
242 CertDeleteCertificateFromStore(context);
244 /* Adding a cert with the same issuer name and serial number (but
245 * different otherwise) as an existing cert succeeds.
247 context = NULL;
248 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
249 bigCertWithDifferentIssuer, sizeof(bigCertWithDifferentIssuer),
250 CERT_STORE_ADD_NEW, &context);
251 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
252 GetLastError());
253 if (context)
254 CertDeleteCertificateFromStore(context);
256 collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
257 CERT_STORE_CREATE_NEW_FLAG, NULL);
258 ok(collection != NULL, "CertOpenStore failed: %08x\n", GetLastError());
259 if (collection)
261 /* Add store to the collection, but disable updates */
262 CertAddStoreToCollection(collection, store, 0, 0);
264 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert2,
265 sizeof(bigCert2));
266 ok(context != NULL, "Expected a context\n");
267 if (context)
269 /* Try to readd bigCert2 to the collection */
270 ret = CertAddCertificateContextToStore(collection, context,
271 CERT_STORE_ADD_NEW, NULL);
272 ok(!ret && GetLastError() == CRYPT_E_EXISTS,
273 "Expected CRYPT_E_EXISTS, got %08x\n", GetLastError());
274 /* Replacing an existing certificate context is allowed, even
275 * though updates to the collection aren't..
277 ret = CertAddCertificateContextToStore(collection, context,
278 CERT_STORE_ADD_REPLACE_EXISTING, NULL);
279 ok(ret, "CertAddCertificateContextToStore failed: %08x\n",
280 GetLastError());
281 /* use the existing certificate and ask for a copy of the context*/
282 copyContext = NULL;
283 ret = CertAddCertificateContextToStore(collection, context,
284 CERT_STORE_ADD_USE_EXISTING, &copyContext);
285 ok(ret, "CertAddCertificateContextToStore failed: %08x\n",
286 GetLastError());
287 ok(copyContext != NULL, "Expected on output a non NULL copyContext\n");
288 if (copyContext)
289 CertFreeCertificateContext(copyContext);
290 /* but adding a new certificate isn't allowed. */
291 ret = CertAddCertificateContextToStore(collection, context,
292 CERT_STORE_ADD_ALWAYS, NULL);
293 ok(!ret && GetLastError() == E_ACCESSDENIED,
294 "Expected E_ACCESSDENIED, got %08x\n", GetLastError());
295 CertFreeCertificateContext(context);
298 CertCloseStore(collection, 0);
301 CertCloseStore(store, 0);
304 static void checkHash(const BYTE *data, DWORD dataLen, ALG_ID algID,
305 PCCERT_CONTEXT context, DWORD propID)
307 BYTE hash[20] = { 0 }, hashProperty[20];
308 BOOL ret;
309 DWORD size;
310 DWORD dwSizeWithNull;
312 memset(hash, 0, sizeof(hash));
313 memset(hashProperty, 0, sizeof(hashProperty));
314 size = sizeof(hash);
315 ret = CryptHashCertificate(0, algID, 0, data, dataLen, hash, &size);
316 ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
317 ret = CertGetCertificateContextProperty(context, propID, NULL,
318 &dwSizeWithNull);
319 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
320 GetLastError());
321 ret = CertGetCertificateContextProperty(context, propID, hashProperty,
322 &size);
323 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
324 GetLastError());
325 ok(!memcmp(hash, hashProperty, size), "Unexpected hash for property %d\n",
326 propID);
327 ok(size == dwSizeWithNull, "Unexpected length of hash for property: received %d instead of %d\n",
328 dwSizeWithNull,size);
331 static WCHAR cspNameW[] = { 'W','i','n','e','C','r','y','p','t','T','e','m','p',0 };
332 static const BYTE v1CertWithPubKey[] = {
333 0x30,0x81,0x95,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
334 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
335 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
336 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
337 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
338 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
339 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
340 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
341 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,
342 0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,
343 0x01,0x01 };
344 static const BYTE v1CertWithSubjectKeyId[] = {
345 0x30,0x7b,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
346 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
347 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
348 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
349 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
350 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
351 0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x17,0x30,0x15,0x30,
352 0x13,0x06,0x03,0x55,0x1d,0x0e,0x04,0x0c,0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,
353 0x4c,0x61,0x6e,0x67,0x00 };
354 static const BYTE subjectKeyId[] = {
355 0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
357 static void testCertProperties(void)
359 PCCERT_CONTEXT context = CertCreateCertificateContext(X509_ASN_ENCODING,
360 bigCert, sizeof(bigCert));
361 DWORD propID, numProps, access, size;
362 BOOL ret;
363 BYTE hash[20] = { 0 }, hashProperty[20];
364 CRYPT_DATA_BLOB blob;
365 CERT_KEY_CONTEXT keyContext;
367 ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
368 GetLastError());
369 if (!context)
370 return;
372 /* This crashes
373 propID = CertEnumCertificateContextProperties(NULL, 0);
376 propID = 0;
377 numProps = 0;
378 do {
379 propID = CertEnumCertificateContextProperties(context, propID);
380 if (propID)
381 numProps++;
382 } while (propID != 0);
383 ok(numProps == 0, "Expected 0 properties, got %d\n", numProps);
385 /* Tests with a NULL cert context. Prop ID 0 fails.. */
386 ret = CertSetCertificateContextProperty(NULL, 0, 0, NULL);
387 ok(!ret && GetLastError() == E_INVALIDARG,
388 "Expected E_INVALIDARG, got %08x\n", GetLastError());
389 /* while this just crashes.
390 ret = CertSetCertificateContextProperty(NULL,
391 CERT_KEY_PROV_HANDLE_PROP_ID, 0, NULL);
394 ret = CertSetCertificateContextProperty(context, 0, 0, NULL);
395 ok(!ret && GetLastError() == E_INVALIDARG,
396 "Expected E_INVALIDARG, got %08x\n", GetLastError());
397 /* Can't set the cert property directly, this crashes.
398 ret = CertSetCertificateContextProperty(context,
399 CERT_CERT_PROP_ID, 0, bigCert2);
402 /* These all crash.
403 ret = CertGetCertificateContextProperty(context,
404 CERT_ACCESS_STATE_PROP_ID, 0, NULL);
405 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
406 NULL, NULL);
407 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
408 hashProperty, NULL);
410 /* A missing prop */
411 size = 0;
412 ret = CertGetCertificateContextProperty(context,
413 CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
414 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
415 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
416 /* And, an implicit property */
417 size = sizeof(access);
418 ret = CertGetCertificateContextProperty(context,
419 CERT_ACCESS_STATE_PROP_ID, &access, &size);
420 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
421 GetLastError());
422 ok(!(access & CERT_ACCESS_STATE_WRITE_PERSIST_FLAG),
423 "Didn't expect a persisted cert\n");
424 /* Trying to set this "read only" property crashes.
425 access |= CERT_ACCESS_STATE_WRITE_PERSIST_FLAG;
426 ret = CertSetCertificateContextProperty(context,
427 CERT_ACCESS_STATE_PROP_ID, 0, &access);
430 /* Can I set the hash to an invalid hash? */
431 blob.pbData = hash;
432 blob.cbData = sizeof(hash);
433 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID, 0,
434 &blob);
435 ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
436 GetLastError());
437 size = sizeof(hashProperty);
438 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
439 hashProperty, &size);
440 ok(!memcmp(hashProperty, hash, sizeof(hash)), "Unexpected hash\n");
441 /* Delete the (bogus) hash, and get the real one */
442 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID, 0,
443 NULL);
444 ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
445 GetLastError());
446 checkHash(bigCert, sizeof(bigCert), CALG_SHA1, context,
447 CERT_HASH_PROP_ID);
449 /* Now that the hash property is set, we should get one property when
450 * enumerating.
452 propID = 0;
453 numProps = 0;
454 do {
455 propID = CertEnumCertificateContextProperties(context, propID);
456 if (propID)
457 numProps++;
458 } while (propID != 0);
459 ok(numProps == 1, "Expected 1 properties, got %d\n", numProps);
461 /* Check a few other implicit properties */
462 checkHash(bigCert, sizeof(bigCert), CALG_MD5, context,
463 CERT_MD5_HASH_PROP_ID);
464 checkHash(
465 context->pCertInfo->Subject.pbData,
466 context->pCertInfo->Subject.cbData,
467 CALG_MD5, context, CERT_SUBJECT_NAME_MD5_HASH_PROP_ID);
468 checkHash(
469 context->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData,
470 context->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData,
471 CALG_MD5, context, CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID);
473 /* Test key contexts and handles and such */
474 size = 0;
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 size = sizeof(CERT_KEY_CONTEXT);
480 ret = CertGetCertificateContextProperty(context, CERT_KEY_CONTEXT_PROP_ID,
481 NULL, &size);
482 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
483 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
484 ret = CertGetCertificateContextProperty(context, CERT_KEY_CONTEXT_PROP_ID,
485 &keyContext, &size);
486 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
487 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
488 /* Key context with an invalid size */
489 keyContext.cbSize = 0;
490 ret = CertSetCertificateContextProperty(context, CERT_KEY_CONTEXT_PROP_ID,
491 0, &keyContext);
492 ok(!ret && GetLastError() == E_INVALIDARG,
493 "Expected E_INVALIDARG, got %08x\n", GetLastError());
494 size = sizeof(keyContext);
495 ret = CertGetCertificateContextProperty(context, CERT_KEY_CONTEXT_PROP_ID,
496 &keyContext, &size);
497 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
498 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
499 keyContext.cbSize = sizeof(keyContext);
500 keyContext.hCryptProv = 0;
501 keyContext.dwKeySpec = AT_SIGNATURE;
502 ret = CertSetCertificateContextProperty(context, CERT_KEY_CONTEXT_PROP_ID,
503 0, &keyContext);
504 ok(ret, "CertSetCertificateContextProperty failed: %08x\n", GetLastError());
505 /* Now that that's set, the key prov handle property is also gettable.
507 size = sizeof(DWORD);
508 ret = CertGetCertificateContextProperty(context,
509 CERT_KEY_PROV_HANDLE_PROP_ID, &keyContext.hCryptProv, &size);
510 ok(ret, "Expected to get the CERT_KEY_PROV_HANDLE_PROP_ID, got %08x\n",
511 GetLastError());
512 /* Remove the key prov handle property.. */
513 ret = CertSetCertificateContextProperty(context,
514 CERT_KEY_PROV_HANDLE_PROP_ID, 0, NULL);
515 ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
516 GetLastError());
517 /* and the key context's CSP is set to NULL. */
518 size = sizeof(keyContext);
519 ret = CertGetCertificateContextProperty(context,
520 CERT_KEY_CONTEXT_PROP_ID, &keyContext, &size);
521 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
522 GetLastError());
523 ok(keyContext.hCryptProv == 0, "Expected no hCryptProv\n");
525 /* According to MSDN the subject key id can be stored as a property,
526 * as a subject key extension, or as the SHA1 hash of the public key,
527 * but this cert has none of them:
529 ret = CertGetCertificateContextProperty(context,
530 CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size);
531 ok(!ret && GetLastError() == ERROR_INVALID_DATA,
532 "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
533 CertFreeCertificateContext(context);
534 /* This cert does have a public key, but its subject key identifier still
535 * isn't available: */
536 context = CertCreateCertificateContext(X509_ASN_ENCODING,
537 v1CertWithPubKey, sizeof(v1CertWithPubKey));
538 ret = CertGetCertificateContextProperty(context,
539 CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size);
540 ok(!ret && GetLastError() == ERROR_INVALID_DATA,
541 "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
542 CertFreeCertificateContext(context);
543 /* This cert with a subject key extension can have its key identifier
544 * property retrieved:
546 context = CertCreateCertificateContext(X509_ASN_ENCODING,
547 v1CertWithSubjectKeyId, sizeof(v1CertWithSubjectKeyId));
548 ret = CertGetCertificateContextProperty(context,
549 CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size);
550 ok(ret, "CertGetCertificateContextProperty failed: %08x\n", GetLastError());
551 if (ret)
553 LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, size);
555 if (buf)
557 ret = CertGetCertificateContextProperty(context,
558 CERT_KEY_IDENTIFIER_PROP_ID, buf, &size);
559 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
560 GetLastError());
561 ok(!memcmp(buf, subjectKeyId, size), "Unexpected subject key id\n");
562 HeapFree(GetProcessHeap(), 0, buf);
565 CertFreeCertificateContext(context);
568 static void testDupCert(void)
570 HCERTSTORE store;
571 PCCERT_CONTEXT context, dupContext;
572 BOOL ret;
574 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
575 CERT_STORE_CREATE_NEW_FLAG, NULL);
576 ok(store != NULL, "CertOpenStore failed: %d\n", GetLastError());
577 if (!store)
578 return;
580 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
581 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
582 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
583 GetLastError());
584 ok(context != NULL, "Expected a valid cert context\n");
585 if (context)
587 ok(context->cbCertEncoded == sizeof(bigCert),
588 "Wrong cert size %d\n", context->cbCertEncoded);
589 ok(!memcmp(context->pbCertEncoded, bigCert, sizeof(bigCert)),
590 "Unexpected encoded cert in context\n");
591 ok(context->hCertStore == store, "Unexpected store\n");
593 dupContext = CertDuplicateCertificateContext(context);
594 ok(dupContext != NULL, "Expected valid duplicate\n");
595 /* Not only is it a duplicate, it's identical: the address is the
596 * same.
598 ok(dupContext == context, "Expected identical context addresses\n");
599 CertFreeCertificateContext(dupContext);
600 CertFreeCertificateContext(context);
602 CertCloseStore(store, 0);
605 static BYTE subjectName3[] = { 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
606 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x52, 0x6f, 0x62, 0x20, 0x20, 0x4c, 0x61,
607 0x6e, 0x67, 0x00 };
608 static const BYTE iTunesCert0[] = {
609 0x30,0x82,0x03,0xc4,0x30,0x82,0x03,0x2d,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,
610 0x47,0xbf,0x19,0x95,0xdf,0x8d,0x52,0x46,0x43,0xf7,0xdb,0x6d,0x48,0x0d,0x31,
611 0xa4,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,
612 0x00,0x30,0x81,0x8b,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,
613 0x5a,0x41,0x31,0x15,0x30,0x13,0x06,0x03,0x55,0x04,0x08,0x13,0x0c,0x57,0x65,
614 0x73,0x74,0x65,0x72,0x6e,0x20,0x43,0x61,0x70,0x65,0x31,0x14,0x30,0x12,0x06,
615 0x03,0x55,0x04,0x07,0x13,0x0b,0x44,0x75,0x72,0x62,0x61,0x6e,0x76,0x69,0x6c,
616 0x6c,0x65,0x31,0x0f,0x30,0x0d,0x06,0x03,0x55,0x04,0x0a,0x13,0x06,0x54,0x68,
617 0x61,0x77,0x74,0x65,0x31,0x1d,0x30,0x1b,0x06,0x03,0x55,0x04,0x0b,0x13,0x14,
618 0x54,0x68,0x61,0x77,0x74,0x65,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,
619 0x61,0x74,0x69,0x6f,0x6e,0x31,0x1f,0x30,0x1d,0x06,0x03,0x55,0x04,0x03,0x13,
620 0x16,0x54,0x68,0x61,0x77,0x74,0x65,0x20,0x54,0x69,0x6d,0x65,0x73,0x74,0x61,
621 0x6d,0x70,0x69,0x6e,0x67,0x20,0x43,0x41,0x30,0x1e,0x17,0x0d,0x30,0x33,0x31,
622 0x32,0x30,0x34,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,0x31,0x33,0x31,
623 0x32,0x30,0x33,0x32,0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x53,0x31,0x0b,0x30,
624 0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x17,0x30,0x15,0x06,
625 0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x2c,
626 0x20,0x49,0x6e,0x63,0x2e,0x31,0x2b,0x30,0x29,0x06,0x03,0x55,0x04,0x03,0x13,
627 0x22,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x54,0x69,0x6d,0x65,0x20,
628 0x53,0x74,0x61,0x6d,0x70,0x69,0x6e,0x67,0x20,0x53,0x65,0x72,0x76,0x69,0x63,
629 0x65,0x73,0x20,0x43,0x41,0x30,0x82,0x01,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,
630 0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0f,0x00,0x30,
631 0x82,0x01,0x0a,0x02,0x82,0x01,0x01,0x00,0xa9,0xca,0xb2,0xa4,0xcc,0xcd,0x20,
632 0xaf,0x0a,0x7d,0x89,0xac,0x87,0x75,0xf0,0xb4,0x4e,0xf1,0xdf,0xc1,0x0f,0xbf,
633 0x67,0x61,0xbd,0xa3,0x64,0x1c,0xda,0xbb,0xf9,0xca,0x33,0xab,0x84,0x30,0x89,
634 0x58,0x7e,0x8c,0xdb,0x6b,0xdd,0x36,0x9e,0x0f,0xbf,0xd1,0xec,0x78,0xf2,0x77,
635 0xa6,0x7e,0x6f,0x3c,0xbf,0x93,0xaf,0x0d,0xba,0x68,0xf4,0x6c,0x94,0xca,0xbd,
636 0x52,0x2d,0xab,0x48,0x3d,0xf5,0xb6,0xd5,0x5d,0x5f,0x1b,0x02,0x9f,0xfa,0x2f,
637 0x6b,0x1e,0xa4,0xf7,0xa3,0x9a,0xa6,0x1a,0xc8,0x02,0xe1,0x7f,0x4c,0x52,0xe3,
638 0x0e,0x60,0xec,0x40,0x1c,0x7e,0xb9,0x0d,0xde,0x3f,0xc7,0xb4,0xdf,0x87,0xbd,
639 0x5f,0x7a,0x6a,0x31,0x2e,0x03,0x99,0x81,0x13,0xa8,0x47,0x20,0xce,0x31,0x73,
640 0x0d,0x57,0x2d,0xcd,0x78,0x34,0x33,0x95,0x12,0x99,0x12,0xb9,0xde,0x68,0x2f,
641 0xaa,0xe6,0xe3,0xc2,0x8a,0x8c,0x2a,0xc3,0x8b,0x21,0x87,0x66,0xbd,0x83,0x58,
642 0x57,0x6f,0x75,0xbf,0x3c,0xaa,0x26,0x87,0x5d,0xca,0x10,0x15,0x3c,0x9f,0x84,
643 0xea,0x54,0xc1,0x0a,0x6e,0xc4,0xfe,0xc5,0x4a,0xdd,0xb9,0x07,0x11,0x97,0x22,
644 0x7c,0xdb,0x3e,0x27,0xd1,0x1e,0x78,0xec,0x9f,0x31,0xc9,0xf1,0xe6,0x22,0x19,
645 0xdb,0xc4,0xb3,0x47,0x43,0x9a,0x1a,0x5f,0xa0,0x1e,0x90,0xe4,0x5e,0xf5,0xee,
646 0x7c,0xf1,0x7d,0xab,0x62,0x01,0x8f,0xf5,0x4d,0x0b,0xde,0xd0,0x22,0x56,0xa8,
647 0x95,0xcd,0xae,0x88,0x76,0xae,0xee,0xba,0x0d,0xf3,0xe4,0x4d,0xd9,0xa0,0xfb,
648 0x68,0xa0,0xae,0x14,0x3b,0xb3,0x87,0xc1,0xbb,0x02,0x03,0x01,0x00,0x01,0xa3,
649 0x81,0xdb,0x30,0x81,0xd8,0x30,0x34,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,
650 0x01,0x01,0x04,0x28,0x30,0x26,0x30,0x24,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,
651 0x07,0x30,0x01,0x86,0x18,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6f,0x63,0x73,
652 0x70,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x30,
653 0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,
654 0xff,0x02,0x01,0x00,0x30,0x41,0x06,0x03,0x55,0x1d,0x1f,0x04,0x3a,0x30,0x38,
655 0x30,0x36,0xa0,0x34,0xa0,0x32,0x86,0x30,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
656 0x63,0x72,0x6c,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,
657 0x6d,0x2f,0x54,0x68,0x61,0x77,0x74,0x65,0x54,0x69,0x6d,0x65,0x73,0x74,0x61,
658 0x6d,0x70,0x69,0x6e,0x67,0x43,0x41,0x2e,0x63,0x72,0x6c,0x30,0x13,0x06,0x03,
659 0x55,0x1d,0x25,0x04,0x0c,0x30,0x0a,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,
660 0x03,0x08,0x30,0x0e,0x06,0x03,0x55,0x1d,0x0f,0x01,0x01,0xff,0x04,0x04,0x03,
661 0x02,0x01,0x06,0x30,0x24,0x06,0x03,0x55,0x1d,0x11,0x04,0x1d,0x30,0x1b,0xa4,
662 0x19,0x30,0x17,0x31,0x15,0x30,0x13,0x06,0x03,0x55,0x04,0x03,0x13,0x0c,0x54,
663 0x53,0x41,0x32,0x30,0x34,0x38,0x2d,0x31,0x2d,0x35,0x33,0x30,0x0d,0x06,0x09,
664 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x03,0x81,0x81,0x00,
665 0x4a,0x6b,0xf9,0xea,0x58,0xc2,0x44,0x1c,0x31,0x89,0x79,0x99,0x2b,0x96,0xbf,
666 0x82,0xac,0x01,0xd6,0x1c,0x4c,0xcd,0xb0,0x8a,0x58,0x6e,0xdf,0x08,0x29,0xa3,
667 0x5e,0xc8,0xca,0x93,0x13,0xe7,0x04,0x52,0x0d,0xef,0x47,0x27,0x2f,0x00,0x38,
668 0xb0,0xe4,0xc9,0x93,0x4e,0x9a,0xd4,0x22,0x62,0x15,0xf7,0x3f,0x37,0x21,0x4f,
669 0x70,0x31,0x80,0xf1,0x8b,0x38,0x87,0xb3,0xe8,0xe8,0x97,0x00,0xfe,0xcf,0x55,
670 0x96,0x4e,0x24,0xd2,0xa9,0x27,0x4e,0x7a,0xae,0xb7,0x61,0x41,0xf3,0x2a,0xce,
671 0xe7,0xc9,0xd9,0x5e,0xdd,0xbb,0x2b,0x85,0x3e,0xb5,0x9d,0xb5,0xd9,0xe1,0x57,
672 0xff,0xbe,0xb4,0xc5,0x7e,0xf5,0xcf,0x0c,0x9e,0xf0,0x97,0xfe,0x2b,0xd3,0x3b,
673 0x52,0x1b,0x1b,0x38,0x27,0xf7,0x3f,0x4a };
674 static const BYTE iTunesCert1[] = {
675 0x30,0x82,0x03,0xff,0x30,0x82,0x02,0xe7,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,
676 0x0d,0xe9,0x2b,0xf0,0xd4,0xd8,0x29,0x88,0x18,0x32,0x05,0x09,0x5e,0x9a,0x76,
677 0x88,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,
678 0x00,0x30,0x53,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,
679 0x53,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,
680 0x69,0x53,0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x2b,0x30,0x29,
681 0x06,0x03,0x55,0x04,0x03,0x13,0x22,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,
682 0x20,0x54,0x69,0x6d,0x65,0x20,0x53,0x74,0x61,0x6d,0x70,0x69,0x6e,0x67,0x20,
683 0x53,0x65,0x72,0x76,0x69,0x63,0x65,0x73,0x20,0x43,0x41,0x30,0x1e,0x17,0x0d,
684 0x30,0x33,0x31,0x32,0x30,0x34,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,
685 0x30,0x38,0x31,0x32,0x30,0x33,0x32,0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x57,
686 0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x17,
687 0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,0x69,
688 0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x2f,0x30,0x2d,0x06,0x03,0x55,
689 0x04,0x03,0x13,0x26,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x54,0x69,
690 0x6d,0x65,0x20,0x53,0x74,0x61,0x6d,0x70,0x69,0x6e,0x67,0x20,0x53,0x65,0x72,
691 0x76,0x69,0x63,0x65,0x73,0x20,0x53,0x69,0x67,0x6e,0x65,0x72,0x30,0x82,0x01,
692 0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,
693 0x00,0x03,0x82,0x01,0x0f,0x00,0x30,0x82,0x01,0x0a,0x02,0x82,0x01,0x01,0x00,
694 0xb2,0x50,0x28,0x48,0xdd,0xd3,0x68,0x7a,0x84,0x18,0x44,0x66,0x75,0x5d,0x7e,
695 0xc4,0xb8,0x9f,0x63,0x26,0xff,0x3d,0x43,0x9c,0x7c,0x11,0x38,0x10,0x25,0x55,
696 0x73,0xd9,0x75,0x27,0x69,0xfd,0x4e,0xb9,0x20,0x5c,0xd3,0x0a,0xf9,0xa0,0x1b,
697 0x2a,0xed,0x55,0x56,0x21,0x61,0xd8,0x1e,0xdb,0xe4,0xbc,0x33,0x6b,0xc7,0xef,
698 0xdd,0xa3,0x37,0x65,0x8e,0x1b,0x93,0x0c,0xb6,0x53,0x1e,0x5c,0x7c,0x66,0x35,
699 0x5f,0x05,0x8a,0x45,0xfe,0x76,0x4e,0xdf,0x53,0x80,0xa2,0x81,0x20,0x9d,0xae,
700 0x88,0x5c,0xa2,0x08,0xf7,0xe5,0x30,0xf9,0xee,0x22,0x37,0x4c,0x42,0x0a,0xce,
701 0xdf,0xc6,0x1f,0xc4,0xd6,0x55,0xe9,0x81,0x3f,0xb5,0x52,0xa3,0x2c,0xaa,0x01,
702 0x7a,0xf2,0xa2,0xaa,0x8d,0x35,0xfe,0x9f,0xe6,0x5d,0x6a,0x05,0x9f,0x3d,0x6b,
703 0xe3,0xbf,0x96,0xc0,0xfe,0xcc,0x60,0xf9,0x40,0xe7,0x07,0xa0,0x44,0xeb,0x81,
704 0x51,0x6e,0xa5,0x2a,0xf2,0xb6,0x8a,0x10,0x28,0xed,0x8f,0xdc,0x06,0xa0,0x86,
705 0x50,0x9a,0x7b,0x4a,0x08,0x0d,0x30,0x1d,0xca,0x10,0x9e,0x6b,0xf7,0xe9,0x58,
706 0xae,0x04,0xa9,0x40,0x99,0xb2,0x28,0xe8,0x8f,0x16,0xac,0x3c,0xe3,0x53,0x6f,
707 0x4b,0xd3,0x35,0x9d,0xb5,0x6f,0x64,0x1d,0xb3,0x96,0x2c,0xbb,0x3d,0xe7,0x79,
708 0xeb,0x6d,0x7a,0xf9,0x16,0xe6,0x26,0xad,0xaf,0xef,0x99,0x53,0xb7,0x40,0x2c,
709 0x95,0xb8,0x79,0xaa,0xfe,0xd4,0x52,0xab,0x29,0x74,0x7e,0x42,0xec,0x39,0x1e,
710 0xa2,0x6a,0x16,0xe6,0x59,0xbb,0x24,0x68,0xd8,0x00,0x80,0x43,0x10,0x87,0x80,
711 0x6b,0x02,0x03,0x01,0x00,0x01,0xa3,0x81,0xca,0x30,0x81,0xc7,0x30,0x34,0x06,
712 0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x28,0x30,0x26,0x30,0x24,
713 0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x18,0x68,0x74,0x74,
714 0x70,0x3a,0x2f,0x2f,0x6f,0x63,0x73,0x70,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,
715 0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x30,0x0c,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
716 0xff,0x04,0x02,0x30,0x00,0x30,0x33,0x06,0x03,0x55,0x1d,0x1f,0x04,0x2c,0x30,
717 0x2a,0x30,0x28,0xa0,0x26,0xa0,0x24,0x86,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,
718 0x2f,0x63,0x72,0x6c,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,
719 0x6f,0x6d,0x2f,0x74,0x73,0x73,0x2d,0x63,0x61,0x2e,0x63,0x72,0x6c,0x30,0x16,
720 0x06,0x03,0x55,0x1d,0x25,0x01,0x01,0xff,0x04,0x0c,0x30,0x0a,0x06,0x08,0x2b,
721 0x06,0x01,0x05,0x05,0x07,0x03,0x08,0x30,0x0e,0x06,0x03,0x55,0x1d,0x0f,0x01,
722 0x01,0xff,0x04,0x04,0x03,0x02,0x06,0xc0,0x30,0x24,0x06,0x03,0x55,0x1d,0x11,
723 0x04,0x1d,0x30,0x1b,0xa4,0x19,0x30,0x17,0x31,0x15,0x30,0x13,0x06,0x03,0x55,
724 0x04,0x03,0x13,0x0c,0x54,0x53,0x41,0x32,0x30,0x34,0x38,0x2d,0x31,0x2d,0x35,
725 0x34,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,
726 0x00,0x03,0x82,0x01,0x01,0x00,0x87,0x78,0x70,0xda,0x4e,0x52,0x01,0x20,0x5b,
727 0xe0,0x79,0xc9,0x82,0x30,0xc4,0xfd,0xb9,0x19,0x96,0xbd,0x91,0x00,0xc3,0xbd,
728 0xcd,0xcd,0xc6,0xf4,0x0e,0xd8,0xff,0xf9,0x4d,0xc0,0x33,0x62,0x30,0x11,0xc5,
729 0xf5,0x74,0x1b,0xd4,0x92,0xde,0x5f,0x9c,0x20,0x13,0xb1,0x7c,0x45,0xbe,0x50,
730 0xcd,0x83,0xe7,0x80,0x17,0x83,0xa7,0x27,0x93,0x67,0x13,0x46,0xfb,0xca,0xb8,
731 0x98,0x41,0x03,0xcc,0x9b,0x51,0x5b,0x05,0x8b,0x7f,0xa8,0x6f,0xf3,0x1b,0x50,
732 0x1b,0x24,0x2e,0xf2,0x69,0x8d,0x6c,0x22,0xf7,0xbb,0xca,0x16,0x95,0xed,0x0c,
733 0x74,0xc0,0x68,0x77,0xd9,0xeb,0x99,0x62,0x87,0xc1,0x73,0x90,0xf8,0x89,0x74,
734 0x7a,0x23,0xab,0xa3,0x98,0x7b,0x97,0xb1,0xf7,0x8f,0x29,0x71,0x4d,0x2e,0x75,
735 0x1b,0x48,0x41,0xda,0xf0,0xb5,0x0d,0x20,0x54,0xd6,0x77,0xa0,0x97,0x82,0x63,
736 0x69,0xfd,0x09,0xcf,0x8a,0xf0,0x75,0xbb,0x09,0x9b,0xd9,0xf9,0x11,0x55,0x26,
737 0x9a,0x61,0x32,0xbe,0x7a,0x02,0xb0,0x7b,0x86,0xbe,0xa2,0xc3,0x8b,0x22,0x2c,
738 0x78,0xd1,0x35,0x76,0xbc,0x92,0x73,0x5c,0xf9,0xb9,0xe6,0x4c,0x15,0x0a,0x23,
739 0xcc,0xe4,0xd2,0xd4,0x34,0x2e,0x49,0x40,0x15,0x3c,0x0f,0x60,0x7a,0x24,0xc6,
740 0xa5,0x66,0xef,0x96,0xcf,0x70,0xeb,0x3e,0xe7,0xf4,0x0d,0x7e,0xdc,0xd1,0x7c,
741 0xa3,0x76,0x71,0x69,0xc1,0x9c,0x4f,0x47,0x30,0x35,0x21,0xb1,0xa2,0xaf,0x1a,
742 0x62,0x3c,0x2b,0xd9,0x8e,0xaa,0x2a,0x07,0x7b,0xd8,0x18,0xb3,0x5c,0x7b,0xe2,
743 0x9d,0xa5,0x6f,0xfe,0x3c,0x89,0xad };
744 static const BYTE iTunesCert2[] = {
745 0x30,0x82,0x04,0xbf,0x30,0x82,0x04,0x28,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,
746 0x41,0x91,0xa1,0x5a,0x39,0x78,0xdf,0xcf,0x49,0x65,0x66,0x38,0x1d,0x4c,0x75,
747 0xc2,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,
748 0x00,0x30,0x5f,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,
749 0x53,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,
750 0x69,0x53,0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x37,0x30,0x35,
751 0x06,0x03,0x55,0x04,0x0b,0x13,0x2e,0x43,0x6c,0x61,0x73,0x73,0x20,0x33,0x20,
752 0x50,0x75,0x62,0x6c,0x69,0x63,0x20,0x50,0x72,0x69,0x6d,0x61,0x72,0x79,0x20,
753 0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x41,
754 0x75,0x74,0x68,0x6f,0x72,0x69,0x74,0x79,0x30,0x1e,0x17,0x0d,0x30,0x34,0x30,
755 0x37,0x31,0x36,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,0x31,0x34,0x30,
756 0x37,0x31,0x35,0x32,0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x81,0xb4,0x31,0x0b,
757 0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x17,0x30,0x15,
758 0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,
759 0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x1f,0x30,0x1d,0x06,0x03,0x55,0x04,0x0b,
760 0x13,0x16,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x54,0x72,0x75,0x73,
761 0x74,0x20,0x4e,0x65,0x74,0x77,0x6f,0x72,0x6b,0x31,0x3b,0x30,0x39,0x06,0x03,
762 0x55,0x04,0x0b,0x13,0x32,0x54,0x65,0x72,0x6d,0x73,0x20,0x6f,0x66,0x20,0x75,
763 0x73,0x65,0x20,0x61,0x74,0x20,0x68,0x74,0x74,0x70,0x73,0x3a,0x2f,0x2f,0x77,
764 0x77,0x77,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,
765 0x2f,0x72,0x70,0x61,0x20,0x28,0x63,0x29,0x30,0x34,0x31,0x2e,0x30,0x2c,0x06,
766 0x03,0x55,0x04,0x03,0x13,0x25,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,
767 0x43,0x6c,0x61,0x73,0x73,0x20,0x33,0x20,0x43,0x6f,0x64,0x65,0x20,0x53,0x69,
768 0x67,0x6e,0x69,0x6e,0x67,0x20,0x32,0x30,0x30,0x34,0x20,0x43,0x41,0x30,0x82,
769 0x01,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,
770 0x05,0x00,0x03,0x82,0x01,0x0f,0x00,0x30,0x82,0x01,0x0a,0x02,0x82,0x01,0x01,
771 0x00,0xbe,0xbc,0xee,0xbc,0x7e,0xef,0x83,0xeb,0xe0,0x37,0x4f,0xfb,0x03,0x10,
772 0x38,0xbe,0x08,0xd2,0x8c,0x7d,0x9d,0xfa,0x92,0x7f,0x19,0x0c,0xc2,0x6b,0xee,
773 0x42,0x52,0x8c,0xde,0xd3,0x1c,0x48,0x13,0x25,0xea,0xc1,0x63,0x7a,0xf9,0x51,
774 0x65,0xee,0xd3,0xaa,0x3b,0xf5,0xf0,0x94,0x9c,0x2b,0xfb,0xf2,0x66,0xd4,0x24,
775 0xda,0xf7,0xf5,0x9f,0x6e,0x19,0x39,0x36,0xbc,0xd0,0xa3,0x76,0x08,0x1e,0x22,
776 0x27,0x24,0x6c,0x38,0x91,0x27,0xe2,0x84,0x49,0xae,0x1b,0x8a,0xa1,0xfd,0x25,
777 0x82,0x2c,0x10,0x30,0xe8,0x71,0xab,0x28,0xe8,0x77,0x4a,0x51,0xf1,0xec,0xcd,
778 0xf8,0xf0,0x54,0xd4,0x6f,0xc0,0xe3,0x6d,0x0a,0x8f,0xd9,0xd8,0x64,0x8d,0x63,
779 0xb2,0x2d,0x4e,0x27,0xf6,0x85,0x0e,0xfe,0x6d,0xe3,0x29,0x99,0xe2,0x85,0x47,
780 0x7c,0x2d,0x86,0x7f,0xe8,0x57,0x8f,0xad,0x67,0xc2,0x33,0x32,0x91,0x13,0x20,
781 0xfc,0xa9,0x23,0x14,0x9a,0x6d,0xc2,0x84,0x4b,0x76,0x68,0x04,0xd5,0x71,0x2c,
782 0x5d,0x21,0xfa,0x88,0x0d,0x26,0xfd,0x1f,0x2d,0x91,0x2b,0xe7,0x01,0x55,0x4d,
783 0xf2,0x6d,0x35,0x28,0x82,0xdf,0xd9,0x6b,0x5c,0xb6,0xd6,0xd9,0xaa,0x81,0xfd,
784 0x5f,0xcd,0x83,0xba,0x63,0x9d,0xd0,0x22,0xfc,0xa9,0x3b,0x42,0x69,0xb2,0x8e,
785 0x3a,0xb5,0xbc,0xb4,0x9e,0x0f,0x5e,0xc4,0xea,0x2c,0x82,0x8b,0x28,0xfd,0x53,
786 0x08,0x96,0xdd,0xb5,0x01,0x20,0xd1,0xf9,0xa5,0x18,0xe7,0xc0,0xee,0x51,0x70,
787 0x37,0xe1,0xb6,0x05,0x48,0x52,0x48,0x6f,0x38,0xea,0xc3,0xe8,0x6c,0x7b,0x44,
788 0x84,0xbb,0x02,0x03,0x01,0x00,0x01,0xa3,0x82,0x01,0xa0,0x30,0x82,0x01,0x9c,
789 0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,
790 0x01,0xff,0x02,0x01,0x00,0x30,0x44,0x06,0x03,0x55,0x1d,0x20,0x04,0x3d,0x30,
791 0x3b,0x30,0x39,0x06,0x0b,0x60,0x86,0x48,0x01,0x86,0xf8,0x45,0x01,0x07,0x17,
792 0x03,0x30,0x2a,0x30,0x28,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x02,0x01,
793 0x16,0x1c,0x68,0x74,0x74,0x70,0x73,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x76,
794 0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x2f,0x72,0x70,0x61,
795 0x30,0x31,0x06,0x03,0x55,0x1d,0x1f,0x04,0x2a,0x30,0x28,0x30,0x26,0xa0,0x24,
796 0xa0,0x22,0x86,0x20,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x63,0x72,0x6c,0x2e,
797 0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x2f,0x70,0x63,
798 0x61,0x33,0x2e,0x63,0x72,0x6c,0x30,0x1d,0x06,0x03,0x55,0x1d,0x25,0x04,0x16,
799 0x30,0x14,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x03,0x02,0x06,0x08,0x2b,
800 0x06,0x01,0x05,0x05,0x07,0x03,0x03,0x30,0x0e,0x06,0x03,0x55,0x1d,0x0f,0x01,
801 0x01,0xff,0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x11,0x06,0x09,0x60,0x86,0x48,
802 0x01,0x86,0xf8,0x42,0x01,0x01,0x04,0x04,0x03,0x02,0x00,0x01,0x30,0x29,0x06,
803 0x03,0x55,0x1d,0x11,0x04,0x22,0x30,0x20,0xa4,0x1e,0x30,0x1c,0x31,0x1a,0x30,
804 0x18,0x06,0x03,0x55,0x04,0x03,0x13,0x11,0x43,0x6c,0x61,0x73,0x73,0x33,0x43,
805 0x41,0x32,0x30,0x34,0x38,0x2d,0x31,0x2d,0x34,0x33,0x30,0x1d,0x06,0x03,0x55,
806 0x1d,0x0e,0x04,0x16,0x04,0x14,0x08,0xf5,0x51,0xe8,0xfb,0xfe,0x3d,0x3d,0x64,
807 0x36,0x7c,0x68,0xcf,0x5b,0x78,0xa8,0xdf,0xb9,0xc5,0x37,0x30,0x81,0x80,0x06,
808 0x03,0x55,0x1d,0x23,0x04,0x79,0x30,0x77,0xa1,0x63,0xa4,0x61,0x30,0x5f,0x31,
809 0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x17,0x30,
810 0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,0x69,0x67,
811 0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x37,0x30,0x35,0x06,0x03,0x55,0x04,
812 0x0b,0x13,0x2e,0x43,0x6c,0x61,0x73,0x73,0x20,0x33,0x20,0x50,0x75,0x62,0x6c,
813 0x69,0x63,0x20,0x50,0x72,0x69,0x6d,0x61,0x72,0x79,0x20,0x43,0x65,0x72,0x74,
814 0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x41,0x75,0x74,0x68,0x6f,
815 0x72,0x69,0x74,0x79,0x82,0x10,0x70,0xba,0xe4,0x1d,0x10,0xd9,0x29,0x34,0xb6,
816 0x38,0xca,0x7b,0x03,0xcc,0xba,0xbf,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,
817 0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x03,0x81,0x81,0x00,0xae,0x3a,0x17,0xb8,
818 0x4a,0x7b,0x55,0xfa,0x64,0x55,0xec,0x40,0xa4,0xed,0x49,0x41,0x90,0x99,0x9c,
819 0x89,0xbc,0xaf,0x2e,0x1d,0xca,0x78,0x23,0xf9,0x1c,0x19,0x0f,0x7f,0xeb,0x68,
820 0xbc,0x32,0xd9,0x88,0x38,0xde,0xdc,0x3f,0xd3,0x89,0xb4,0x3f,0xb1,0x82,0x96,
821 0xf1,0xa4,0x5a,0xba,0xed,0x2e,0x26,0xd3,0xde,0x7c,0x01,0x6e,0x00,0x0a,0x00,
822 0xa4,0x06,0x92,0x11,0x48,0x09,0x40,0xf9,0x1c,0x18,0x79,0x67,0x23,0x24,0xe0,
823 0xbb,0xd5,0xe1,0x50,0xae,0x1b,0xf5,0x0e,0xdd,0xe0,0x2e,0x81,0xcd,0x80,0xa3,
824 0x6c,0x52,0x4f,0x91,0x75,0x55,0x8a,0xba,0x22,0xf2,0xd2,0xea,0x41,0x75,0x88,
825 0x2f,0x63,0x55,0x7d,0x1e,0x54,0x5a,0x95,0x59,0xca,0xd9,0x34,0x81,0xc0,0x5f,
826 0x5e,0xf6,0x7a,0xb5 };
827 static const BYTE iTunesCert3[] = {
828 0x30,0x82,0x04,0xf1,0x30,0x82,0x03,0xd9,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,
829 0x0f,0x1a,0xa0,0xe0,0x9b,0x9b,0x61,0xa6,0xb6,0xfe,0x40,0xd2,0xdf,0x6a,0xf6,
830 0x8d,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,
831 0x00,0x30,0x81,0xb4,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,
832 0x55,0x53,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,
833 0x72,0x69,0x53,0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x1f,0x30,
834 0x1d,0x06,0x03,0x55,0x04,0x0b,0x13,0x16,0x56,0x65,0x72,0x69,0x53,0x69,0x67,
835 0x6e,0x20,0x54,0x72,0x75,0x73,0x74,0x20,0x4e,0x65,0x74,0x77,0x6f,0x72,0x6b,
836 0x31,0x3b,0x30,0x39,0x06,0x03,0x55,0x04,0x0b,0x13,0x32,0x54,0x65,0x72,0x6d,
837 0x73,0x20,0x6f,0x66,0x20,0x75,0x73,0x65,0x20,0x61,0x74,0x20,0x68,0x74,0x74,
838 0x70,0x73,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,
839 0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x2f,0x72,0x70,0x61,0x20,0x28,0x63,0x29,0x30,
840 0x34,0x31,0x2e,0x30,0x2c,0x06,0x03,0x55,0x04,0x03,0x13,0x25,0x56,0x65,0x72,
841 0x69,0x53,0x69,0x67,0x6e,0x20,0x43,0x6c,0x61,0x73,0x73,0x20,0x33,0x20,0x43,
842 0x6f,0x64,0x65,0x20,0x53,0x69,0x67,0x6e,0x69,0x6e,0x67,0x20,0x32,0x30,0x30,
843 0x34,0x20,0x43,0x41,0x30,0x1e,0x17,0x0d,0x30,0x36,0x30,0x31,0x31,0x37,0x30,
844 0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,0x30,0x38,0x30,0x31,0x32,0x32,0x32,
845 0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x81,0xb4,0x31,0x0b,0x30,0x09,0x06,0x03,
846 0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,
847 0x08,0x13,0x0a,0x43,0x61,0x6c,0x69,0x66,0x6f,0x72,0x6e,0x69,0x61,0x31,0x12,
848 0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x13,0x09,0x43,0x75,0x70,0x65,0x72,0x74,
849 0x69,0x6e,0x6f,0x31,0x1d,0x30,0x1b,0x06,0x03,0x55,0x04,0x0a,0x14,0x14,0x41,
850 0x70,0x70,0x6c,0x65,0x20,0x43,0x6f,0x6d,0x70,0x75,0x74,0x65,0x72,0x2c,0x20,
851 0x49,0x6e,0x63,0x2e,0x31,0x3e,0x30,0x3c,0x06,0x03,0x55,0x04,0x0b,0x13,0x35,
852 0x44,0x69,0x67,0x69,0x74,0x61,0x6c,0x20,0x49,0x44,0x20,0x43,0x6c,0x61,0x73,
853 0x73,0x20,0x33,0x20,0x2d,0x20,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,
854 0x20,0x53,0x6f,0x66,0x74,0x77,0x61,0x72,0x65,0x20,0x56,0x61,0x6c,0x69,0x64,
855 0x61,0x74,0x69,0x6f,0x6e,0x20,0x76,0x32,0x31,0x1d,0x30,0x1b,0x06,0x03,0x55,
856 0x04,0x03,0x14,0x14,0x41,0x70,0x70,0x6c,0x65,0x20,0x43,0x6f,0x6d,0x70,0x75,
857 0x74,0x65,0x72,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x30,0x81,0x9f,0x30,0x0d,0x06,
858 0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x81,0x8d,
859 0x00,0x30,0x81,0x89,0x02,0x81,0x81,0x00,0xd3,0xab,0x3b,0x7f,0xec,0x48,0x84,
860 0xce,0xa8,0x1a,0x12,0xf3,0x3c,0x87,0xcb,0x24,0x58,0x96,0x02,0x87,0x66,0x49,
861 0xeb,0x89,0xee,0x79,0x44,0x70,0x8d,0xe7,0xd4,0x1f,0x30,0x92,0xc0,0x9c,0x35,
862 0x78,0xc0,0xaf,0x1c,0xb6,0x28,0xd3,0xe0,0xe0,0x9d,0xd3,0x49,0x76,0x73,0x57,
863 0x19,0x4d,0x8d,0x70,0x85,0x64,0x4d,0x1d,0xc6,0x02,0x3e,0xe5,0x2c,0x66,0x07,
864 0xd2,0x27,0x4b,0xd6,0xc8,0x3c,0x93,0xb6,0x15,0x0c,0xde,0x5b,0xd7,0x93,0xdd,
865 0xbe,0x85,0x62,0x34,0x17,0x8a,0x05,0x60,0xf0,0x8a,0x1c,0x5a,0x40,0x21,0x8d,
866 0x51,0x6c,0xb0,0x62,0xd8,0xb5,0xd4,0xf9,0xb1,0xd0,0x58,0x7a,0x7a,0x82,0x55,
867 0xb3,0xf9,0x53,0x71,0xde,0xd2,0xc9,0x37,0x8c,0xf6,0x5a,0x1f,0x2d,0xcd,0x7c,
868 0x67,0x02,0x03,0x01,0x00,0x01,0xa3,0x82,0x01,0x7f,0x30,0x82,0x01,0x7b,0x30,
869 0x09,0x06,0x03,0x55,0x1d,0x13,0x04,0x02,0x30,0x00,0x30,0x0e,0x06,0x03,0x55,
870 0x1d,0x0f,0x01,0x01,0xff,0x04,0x04,0x03,0x02,0x07,0x80,0x30,0x40,0x06,0x03,
871 0x55,0x1d,0x1f,0x04,0x39,0x30,0x37,0x30,0x35,0xa0,0x33,0xa0,0x31,0x86,0x2f,
872 0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x43,0x53,0x43,0x33,0x2d,0x32,0x30,0x30,
873 0x34,0x2d,0x63,0x72,0x6c,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,
874 0x63,0x6f,0x6d,0x2f,0x43,0x53,0x43,0x33,0x2d,0x32,0x30,0x30,0x34,0x2e,0x63,
875 0x72,0x6c,0x30,0x44,0x06,0x03,0x55,0x1d,0x20,0x04,0x3d,0x30,0x3b,0x30,0x39,
876 0x06,0x0b,0x60,0x86,0x48,0x01,0x86,0xf8,0x45,0x01,0x07,0x17,0x03,0x30,0x2a,
877 0x30,0x28,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x1c,0x68,
878 0x74,0x74,0x70,0x73,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x76,0x65,0x72,0x69,
879 0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x2f,0x72,0x70,0x61,0x30,0x13,0x06,
880 0x03,0x55,0x1d,0x25,0x04,0x0c,0x30,0x0a,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,
881 0x07,0x03,0x03,0x30,0x75,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x01,0x01,
882 0x04,0x69,0x30,0x67,0x30,0x24,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,
883 0x01,0x86,0x18,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6f,0x63,0x73,0x70,0x2e,
884 0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x30,0x3f,0x06,
885 0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x33,0x68,0x74,0x74,0x70,
886 0x3a,0x2f,0x2f,0x43,0x53,0x43,0x33,0x2d,0x32,0x30,0x30,0x34,0x2d,0x61,0x69,
887 0x61,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x2f,
888 0x43,0x53,0x43,0x33,0x2d,0x32,0x30,0x30,0x34,0x2d,0x61,0x69,0x61,0x2e,0x63,
889 0x65,0x72,0x30,0x1f,0x06,0x03,0x55,0x1d,0x23,0x04,0x18,0x30,0x16,0x80,0x14,
890 0x08,0xf5,0x51,0xe8,0xfb,0xfe,0x3d,0x3d,0x64,0x36,0x7c,0x68,0xcf,0x5b,0x78,
891 0xa8,0xdf,0xb9,0xc5,0x37,0x30,0x11,0x06,0x09,0x60,0x86,0x48,0x01,0x86,0xf8,
892 0x42,0x01,0x01,0x04,0x04,0x03,0x02,0x04,0x10,0x30,0x16,0x06,0x0a,0x2b,0x06,
893 0x01,0x04,0x01,0x82,0x37,0x02,0x01,0x1b,0x04,0x08,0x30,0x06,0x01,0x01,0x00,
894 0x01,0x01,0xff,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,
895 0x05,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x6a,0xa6,0x06,0xd0,0x33,0x18,0x64,
896 0xe2,0x69,0x82,0xee,0x6e,0x36,0x9e,0x9d,0x9a,0x0e,0x18,0xa8,0xac,0x9d,0x10,
897 0xed,0x01,0x3c,0xb9,0x61,0x04,0x62,0xf3,0x85,0x8f,0xcc,0x4f,0x2c,0x66,0x35,
898 0x54,0x25,0x45,0x8d,0x95,0x1c,0xd2,0x33,0xbe,0x2e,0xdd,0x7f,0x74,0xaf,0x03,
899 0x7b,0x86,0x63,0xb0,0xc9,0xe6,0xbd,0xc7,0x8e,0xde,0x03,0x18,0x98,0x82,0xc3,
900 0xbb,0xf8,0x15,0x99,0x1a,0xa9,0xdd,0xb9,0x5d,0xb9,0xbd,0x53,0x95,0x25,0x76,
901 0xfb,0x5c,0x53,0x90,0xea,0x01,0x0a,0xa0,0xb1,0xbf,0x09,0x1b,0x97,0x8f,0x40,
902 0xfa,0x85,0x12,0x74,0x01,0xdb,0xf6,0xdb,0x09,0xd6,0x5f,0x4f,0xd7,0x17,0xb4,
903 0xbf,0x9e,0x2f,0x86,0x52,0x5d,0x70,0x24,0x52,0x32,0x1e,0xa5,0x1d,0x39,0x8b,
904 0x66,0xf6,0xba,0x9b,0x69,0x8e,0x12,0x60,0xdb,0xb6,0xcf,0xe6,0x0d,0xd6,0x1c,
905 0x8f,0xd4,0x5b,0x4b,0x00,0xde,0x21,0x93,0xfb,0x6e,0xc7,0x3d,0xb4,0x66,0x0d,
906 0x29,0x0c,0x4e,0xe9,0x3f,0x94,0xd6,0xd6,0xdc,0xec,0xf8,0x53,0x3b,0x62,0xd5,
907 0x97,0x50,0x53,0x84,0x17,0xfe,0xe2,0xed,0x4c,0x23,0x0a,0x49,0xce,0x5b,0xe9,
908 0x70,0x31,0xc1,0x04,0x02,0x02,0x6c,0xb8,0x52,0xcd,0xc7,0x4e,0x70,0xb4,0x13,
909 0xd7,0xe0,0x92,0xba,0x44,0x1a,0x10,0x4c,0x6e,0x45,0xc6,0x86,0x04,0xc6,0x64,
910 0xd3,0x9c,0x6e,0xc1,0x9c,0xac,0x74,0x3d,0x77,0x06,0x5e,0x28,0x28,0x5c,0xf5,
911 0xe0,0x9c,0x19,0xd8,0xba,0x74,0x81,0x2d,0x67,0x77,0x93,0x8d,0xbf,0xd2,0x52,
912 0x00,0xe6,0xa5,0x38,0x4e,0x2e,0x73,0x66,0x7a };
913 static BYTE iTunesIssuer[] = {
914 0x30,0x81,0xb4,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,
915 0x13,0x02,0x55,0x53,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,
916 0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x2c,
917 0x20,0x49,0x6e,0x63,0x2e,0x31,0x1f,0x30,0x1d,0x06,0x03,0x55,
918 0x04,0x0b,0x13,0x16,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,
919 0x20,0x54,0x72,0x75,0x73,0x74,0x20,0x4e,0x65,0x74,0x77,0x6f,
920 0x72,0x6b,0x31,0x3b,0x30,0x39,0x06,0x03,0x55,0x04,0x0b,0x13,
921 0x32,0x54,0x65,0x72,0x6d,0x73,0x20,0x6f,0x66,0x20,0x75,0x73,
922 0x65,0x20,0x61,0x74,0x20,0x68,0x74,0x74,0x70,0x73,0x3a,0x2f,
923 0x2f,0x77,0x77,0x77,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,
924 0x6e,0x2e,0x63,0x6f,0x6d,0x2f,0x72,0x70,0x61,0x20,0x28,0x63,
925 0x29,0x30,0x34,0x31,0x2e,0x30,0x2c,0x06,0x03,0x55,0x04,0x03,
926 0x13,0x25,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x43,
927 0x6c,0x61,0x73,0x73,0x20,0x33,0x20,0x43,0x6f,0x64,0x65,0x20,
928 0x53,0x69,0x67,0x6e,0x69,0x6e,0x67,0x20,0x32,0x30,0x30,0x34,
929 0x20,0x43,0x41 };
930 static BYTE iTunesSerialNum[] = {
931 0x8d,0xf6,0x6a,0xdf,0xd2,0x40,0xfe,0xb6,0xa6,0x61,0x9b,0x9b,
932 0xe0,0xa0,0x1a,0x0f };
934 static void testFindCert(void)
936 HCERTSTORE store;
937 PCCERT_CONTEXT context = NULL, subject;
938 BOOL ret;
939 CERT_INFO certInfo = { 0 };
940 CRYPT_HASH_BLOB blob;
941 BYTE otherSerialNumber[] = { 2 };
943 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
944 CERT_STORE_CREATE_NEW_FLAG, NULL);
945 ok(store != NULL, "CertOpenStore failed: %d\n", GetLastError());
946 if (!store)
947 return;
949 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
950 bigCert, sizeof(bigCert), CERT_STORE_ADD_NEW, NULL);
951 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
952 GetLastError());
953 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
954 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, NULL);
955 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
956 GetLastError());
957 /* This has the same name as bigCert */
958 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
959 certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, NULL);
960 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
961 GetLastError());
963 /* Crashes
964 context = CertFindCertificateInStore(NULL, 0, 0, 0, NULL, NULL);
967 /* Check first cert's there, by issuer */
968 certInfo.Subject.pbData = subjectName;
969 certInfo.Subject.cbData = sizeof(subjectName);
970 certInfo.SerialNumber.pbData = serialNum;
971 certInfo.SerialNumber.cbData = sizeof(serialNum);
972 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
973 CERT_FIND_ISSUER_NAME, &certInfo.Subject, NULL);
974 ok(context != NULL, "CertFindCertificateInStore failed: %08x\n",
975 GetLastError());
976 if (context)
978 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
979 CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
980 ok(context != NULL, "Expected more than one cert\n");
981 if (context)
983 context = CertFindCertificateInStore(store, X509_ASN_ENCODING,
984 0, CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
985 ok(context == NULL, "Expected precisely two certs\n");
989 /* Check second cert's there as well, by subject name */
990 certInfo.Subject.pbData = subjectName2;
991 certInfo.Subject.cbData = sizeof(subjectName2);
992 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
993 CERT_FIND_SUBJECT_NAME, &certInfo.Subject, NULL);
994 ok(context != NULL, "CertFindCertificateInStore failed: %08x\n",
995 GetLastError());
996 if (context)
998 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
999 CERT_FIND_SUBJECT_NAME, &certInfo.Subject, context);
1000 ok(context == NULL, "Expected one cert only\n");
1003 /* Strange but true: searching for the subject cert requires you to set
1004 * the issuer, not the subject
1006 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1007 CERT_FIND_SUBJECT_CERT, &certInfo.Subject, NULL);
1008 ok(context == NULL, "Expected no certificate\n");
1009 certInfo.Subject.pbData = NULL;
1010 certInfo.Subject.cbData = 0;
1011 certInfo.Issuer.pbData = subjectName2;
1012 certInfo.Issuer.cbData = sizeof(subjectName2);
1013 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1014 CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
1015 ok(context != NULL, "CertFindCertificateInStore failed: %08x\n",
1016 GetLastError());
1017 if (context)
1019 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1020 CERT_FIND_SUBJECT_CERT, &certInfo.Subject, context);
1021 ok(context == NULL, "Expected one cert only\n");
1023 /* A non-matching serial number will not match. */
1024 certInfo.SerialNumber.pbData = otherSerialNumber;
1025 certInfo.SerialNumber.cbData = sizeof(otherSerialNumber);
1026 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1027 CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
1028 ok(context == NULL, "Expected no match\n");
1029 /* No serial number will not match */
1030 certInfo.SerialNumber.cbData = 0;
1031 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1032 CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
1033 ok(context == NULL, "Expected no match\n");
1034 /* A serial number still won't match if the name doesn't */
1035 certInfo.SerialNumber.pbData = serialNum;
1036 certInfo.SerialNumber.cbData = sizeof(serialNum);
1037 certInfo.Issuer.pbData = subjectName3;
1038 certInfo.Issuer.cbData = sizeof(subjectName3);
1039 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1040 CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
1041 ok(context == NULL, "Expected no match\n");
1043 /* The nice thing about hashes, they're unique */
1044 blob.pbData = bigCertHash;
1045 blob.cbData = sizeof(bigCertHash);
1046 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1047 CERT_FIND_SHA1_HASH, &blob, NULL);
1048 ok(context != NULL, "CertFindCertificateInStore failed: %08x\n",
1049 GetLastError());
1050 if (context)
1052 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1053 CERT_FIND_SHA1_HASH, &certInfo.Subject, context);
1054 ok(context == NULL, "Expected one cert only\n");
1057 CertCloseStore(store, 0);
1059 /* Another subject cert search, using iTunes's certs */
1060 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1061 CERT_STORE_CREATE_NEW_FLAG, NULL);
1062 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1063 iTunesCert0, sizeof(iTunesCert0), CERT_STORE_ADD_NEW, NULL);
1064 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1065 GetLastError());
1066 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1067 iTunesCert1, sizeof(iTunesCert1), CERT_STORE_ADD_NEW, NULL);
1068 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1069 GetLastError());
1070 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1071 iTunesCert2, sizeof(iTunesCert2), CERT_STORE_ADD_NEW, NULL);
1072 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1073 GetLastError());
1074 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1075 iTunesCert3, sizeof(iTunesCert3), CERT_STORE_ADD_NEW, &subject);
1076 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1077 GetLastError());
1079 /* The certInfo's issuer does not match any subject, but the serial
1080 * number does match a cert whose issuer matches certInfo's issuer.
1081 * This yields a match.
1083 certInfo.SerialNumber.cbData = sizeof(iTunesSerialNum);
1084 certInfo.SerialNumber.pbData = iTunesSerialNum;
1085 certInfo.Issuer.cbData = sizeof(iTunesIssuer);
1086 certInfo.Issuer.pbData = iTunesIssuer;
1087 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1088 CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
1089 ok(context != NULL, "Expected a match\n");
1090 if (context)
1092 ret = CertCompareCertificateName(context->dwCertEncodingType,
1093 &certInfo.Issuer, &context->pCertInfo->Subject);
1094 ok(!ret, "Expected subject name not to match\n");
1095 ret = CertCompareCertificateName(context->dwCertEncodingType,
1096 &certInfo.Issuer, &context->pCertInfo->Issuer);
1097 ok(ret, "Expected issuer name to match\n");
1098 ret = CertCompareIntegerBlob(&certInfo.SerialNumber,
1099 &context->pCertInfo->SerialNumber);
1100 ok(ret, "Expected serial number to match\n");
1101 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1102 CERT_FIND_SUBJECT_CERT, &certInfo, context);
1103 ok(context == NULL, "Expected one cert only\n");
1106 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1107 CERT_FIND_ISSUER_OF, subject, NULL);
1108 ok(context != NULL, "Expected an issuer\n");
1109 if (context)
1111 PCCERT_CONTEXT none = CertFindCertificateInStore(store,
1112 X509_ASN_ENCODING, 0, CERT_FIND_ISSUER_OF, context, NULL);
1114 ok(!none, "Expected no parent of issuer\n");
1115 CertFreeCertificateContext(context);
1117 CertFreeCertificateContext(subject);
1118 CertCloseStore(store, 0);
1121 static void testGetSubjectCert(void)
1123 HCERTSTORE store;
1124 PCCERT_CONTEXT context1, context2;
1125 CERT_INFO info = { 0 };
1126 BOOL ret;
1128 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1129 CERT_STORE_CREATE_NEW_FLAG, NULL);
1130 ok(store != NULL, "CertOpenStore failed: %d\n", GetLastError());
1131 if (!store)
1132 return;
1134 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1135 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
1136 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1137 GetLastError());
1138 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1139 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, &context1);
1140 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1141 GetLastError());
1142 ok(context1 != NULL, "Expected a context\n");
1143 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1144 certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, NULL);
1145 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1146 GetLastError());
1148 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
1149 NULL);
1150 ok(!context2 && GetLastError() == E_INVALIDARG,
1151 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1152 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
1153 &info);
1154 ok(!context2 && GetLastError() == CRYPT_E_NOT_FOUND,
1155 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1156 info.SerialNumber.cbData = sizeof(serialNum);
1157 info.SerialNumber.pbData = serialNum;
1158 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
1159 &info);
1160 ok(!context2 && GetLastError() == CRYPT_E_NOT_FOUND,
1161 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1162 info.Issuer.cbData = sizeof(subjectName2);
1163 info.Issuer.pbData = subjectName2;
1164 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
1165 &info);
1166 ok(context2 != NULL,
1167 "CertGetSubjectCertificateFromStore failed: %08x\n", GetLastError());
1168 /* Not only should this find a context, but it should be the same
1169 * (same address) as context1.
1171 ok(context1 == context2, "Expected identical context addresses\n");
1172 CertFreeCertificateContext(context2);
1174 CertFreeCertificateContext(context1);
1175 CertCloseStore(store, 0);
1178 /* This expires in 1970 or so */
1179 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
1180 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
1181 0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
1182 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
1183 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
1184 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
1185 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
1186 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
1187 0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
1188 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
1189 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
1190 0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
1191 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
1192 0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
1193 0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
1194 0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
1195 0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
1196 0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
1197 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
1198 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
1199 0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
1200 0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
1201 0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
1202 0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
1203 0x49, 0xe5, 0xf9, 0x65, 0xf3 };
1205 /* This expires in 2036 or so */
1206 static const BYTE childOfExpired[] = { 0x30, 0x81, 0xcc, 0x30, 0x78, 0xa0,
1207 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
1208 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d,
1209 0x30, 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63,
1210 0x40, 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e,
1211 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x35, 0x30, 0x35,
1212 0x31, 0x37, 0x31, 0x32, 0x34, 0x39, 0x5a, 0x17, 0x0d, 0x33, 0x36, 0x30, 0x35,
1213 0x30, 0x35, 0x31, 0x37, 0x31, 0x32, 0x34, 0x39, 0x5a, 0x30, 0x15, 0x31, 0x13,
1214 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e,
1215 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03,
1216 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
1217 0x01, 0x05, 0x05, 0x00, 0x03, 0x41, 0x00, 0x20, 0x3b, 0xdb, 0x4d, 0x67, 0x50,
1218 0xec, 0x73, 0x9d, 0xf9, 0x85, 0x5d, 0x18, 0xe9, 0xb4, 0x98, 0xe3, 0x31, 0xb7,
1219 0x03, 0x0b, 0xc0, 0x39, 0x93, 0x56, 0x81, 0x0a, 0xfc, 0x78, 0xa8, 0x29, 0x42,
1220 0x5f, 0x69, 0xfb, 0xbc, 0x5b, 0xf2, 0xa6, 0x2a, 0xbe, 0x91, 0x2c, 0xfc, 0x89,
1221 0x69, 0x15, 0x18, 0x58, 0xe5, 0x02, 0x75, 0xf7, 0x2a, 0xb6, 0xa9, 0xfb, 0x47,
1222 0x6a, 0x6e, 0x0a, 0x9b, 0xe9, 0xdc };
1224 static void testGetIssuerCert(void)
1226 BOOL ret;
1227 PCCERT_CONTEXT parent, child;
1228 DWORD flags = 0xffffffff;
1229 HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1230 CERT_STORE_CREATE_NEW_FLAG, NULL);
1232 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1234 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1235 expiredCert, sizeof(expiredCert), CERT_STORE_ADD_ALWAYS, NULL);
1236 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1237 GetLastError());
1239 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1240 childOfExpired, sizeof(childOfExpired), CERT_STORE_ADD_ALWAYS, &child);
1241 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1242 GetLastError());
1244 /* These crash:
1245 parent = CertGetIssuerCertificateFromStore(NULL, NULL, NULL, NULL);
1246 parent = CertGetIssuerCertificateFromStore(store, NULL, NULL, NULL);
1248 parent = CertGetIssuerCertificateFromStore(NULL, NULL, NULL, &flags);
1249 ok(!parent && GetLastError() == E_INVALIDARG,
1250 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1251 parent = CertGetIssuerCertificateFromStore(store, NULL, NULL, &flags);
1252 ok(!parent && GetLastError() == E_INVALIDARG,
1253 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1254 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1255 ok(!parent && GetLastError() == E_INVALIDARG,
1256 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1257 /* Confusing: the caller cannot set either of the
1258 * CERT_STORE_NO_*_FLAGs, as these are not checks,
1259 * they're results:
1261 flags = CERT_STORE_NO_CRL_FLAG | CERT_STORE_NO_ISSUER_FLAG;
1262 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1263 ok(!parent && GetLastError() == E_INVALIDARG,
1264 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1265 /* Perform no checks */
1266 flags = 0;
1267 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1268 ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08x\n",
1269 GetLastError());
1270 if (parent)
1271 CertFreeCertificateContext(parent);
1272 /* Check revocation and signature only */
1273 flags = CERT_STORE_REVOCATION_FLAG | CERT_STORE_SIGNATURE_FLAG;
1274 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1275 ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08x\n",
1276 GetLastError());
1277 /* Confusing: CERT_STORE_REVOCATION_FLAG succeeds when there is no CRL by
1278 * setting CERT_STORE_NO_CRL_FLAG.
1280 ok(flags == (CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG),
1281 "Expected CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG, got %08x\n",
1282 flags);
1283 if (parent)
1284 CertFreeCertificateContext(parent);
1285 /* Now check just the time */
1286 flags = CERT_STORE_TIME_VALIDITY_FLAG;
1287 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1288 ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08x\n",
1289 GetLastError());
1290 /* Oops: the child is not expired, so the time validity check actually
1291 * succeeds, even though the signing cert is expired.
1293 ok(!flags, "Expected check to succeed, got %08x\n", flags);
1294 if (parent)
1295 CertFreeCertificateContext(parent);
1297 CertFreeCertificateContext(child);
1298 CertCloseStore(store, 0);
1301 static void testCryptHashCert(void)
1303 static const BYTE emptyHash[] = { 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b,
1304 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07,
1305 0x09 };
1306 static const BYTE knownHash[] = { 0xae, 0x9d, 0xbf, 0x6d, 0xf5, 0x46, 0xee,
1307 0x8b, 0xc5, 0x7a, 0x13, 0xba, 0xc2, 0xb1, 0x04, 0xf2, 0xbf, 0x52, 0xa8,
1308 0xa2 };
1309 static const BYTE toHash[] = "abcdefghijklmnopqrstuvwxyz0123456789.,;!?:";
1310 BOOL ret;
1311 BYTE hash[20];
1312 DWORD hashLen = sizeof(hash);
1314 /* NULL buffer and nonzero length crashes
1315 ret = CryptHashCertificate(0, 0, 0, NULL, size, hash, &hashLen);
1316 empty hash length also crashes
1317 ret = CryptHashCertificate(0, 0, 0, buf, size, hash, NULL);
1319 /* Test empty hash */
1320 ret = CryptHashCertificate(0, 0, 0, toHash, sizeof(toHash), NULL,
1321 &hashLen);
1322 ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
1323 ok(hashLen == sizeof(hash), "Got unexpected size of hash %d\n", hashLen);
1324 /* Test with empty buffer */
1325 ret = CryptHashCertificate(0, 0, 0, NULL, 0, hash, &hashLen);
1326 ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
1327 ok(!memcmp(hash, emptyHash, sizeof(emptyHash)),
1328 "Unexpected hash of nothing\n");
1329 /* Test a known value */
1330 ret = CryptHashCertificate(0, 0, 0, toHash, sizeof(toHash), hash,
1331 &hashLen);
1332 ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
1333 ok(!memcmp(hash, knownHash, sizeof(knownHash)), "Unexpected hash\n");
1336 static void verifySig(HCRYPTPROV csp, const BYTE *toSign, size_t toSignLen,
1337 const BYTE *sig, unsigned int sigLen)
1339 HCRYPTHASH hash;
1340 BOOL ret = CryptCreateHash(csp, CALG_SHA1, 0, 0, &hash);
1342 ok(ret, "CryptCreateHash failed: %08x\n", GetLastError());
1343 if (ret)
1345 BYTE mySig[64];
1346 DWORD mySigSize = sizeof(mySig);
1348 ret = CryptHashData(hash, toSign, toSignLen, 0);
1349 ok(ret, "CryptHashData failed: %08x\n", GetLastError());
1350 /* use the A variant so the test can run on Win9x */
1351 ret = CryptSignHashA(hash, AT_SIGNATURE, NULL, 0, mySig, &mySigSize);
1352 ok(ret, "CryptSignHash failed: %08x\n", GetLastError());
1353 if (ret)
1355 ok(mySigSize == sigLen, "Expected sig length %d, got %d\n",
1356 sigLen, mySigSize);
1357 ok(!memcmp(mySig, sig, sigLen), "Unexpected signature\n");
1359 CryptDestroyHash(hash);
1363 /* Tests signing the certificate described by toBeSigned with the CSP passed in,
1364 * using the algorithm with OID sigOID. The CSP is assumed to be empty, and a
1365 * keyset named AT_SIGNATURE will be added to it. The signing key will be
1366 * stored in *key, and the signature will be stored in sig. sigLen should be
1367 * at least 64 bytes.
1369 static void testSignCert(HCRYPTPROV csp, const CRYPT_DATA_BLOB *toBeSigned,
1370 LPCSTR sigOID, HCRYPTKEY *key, BYTE *sig, DWORD *sigLen)
1372 BOOL ret;
1373 DWORD size = 0;
1374 CRYPT_ALGORITHM_IDENTIFIER algoID = { NULL, { 0, NULL } };
1376 /* These all crash
1377 ret = CryptSignCertificate(0, 0, 0, NULL, 0, NULL, NULL, NULL, NULL);
1378 ret = CryptSignCertificate(0, 0, 0, NULL, 0, NULL, NULL, NULL, &size);
1379 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
1380 NULL, NULL, NULL, &size);
1382 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
1383 &algoID, NULL, NULL, &size);
1384 ok(!ret && GetLastError() == NTE_BAD_ALGID,
1385 "Expected NTE_BAD_ALGID, got %08x\n", GetLastError());
1386 algoID.pszObjId = (LPSTR)sigOID;
1387 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
1388 &algoID, NULL, NULL, &size);
1389 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1390 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1391 ret = CryptSignCertificate(0, AT_SIGNATURE, 0, toBeSigned->pbData,
1392 toBeSigned->cbData, &algoID, NULL, NULL, &size);
1393 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1394 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1396 /* No keys exist in the new CSP yet.. */
1397 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
1398 toBeSigned->cbData, &algoID, NULL, NULL, &size);
1399 ok(!ret && (GetLastError() == NTE_BAD_KEYSET || GetLastError() ==
1400 NTE_NO_KEY), "Expected NTE_BAD_KEYSET or NTE_NO_KEY, got %08x\n",
1401 GetLastError());
1402 ret = CryptGenKey(csp, AT_SIGNATURE, 0, key);
1403 ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
1404 if (ret)
1406 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
1407 toBeSigned->cbData, &algoID, NULL, NULL, &size);
1408 ok(ret, "CryptSignCertificate failed: %08x\n", GetLastError());
1409 ok(size <= *sigLen, "Expected size <= %d, got %d\n", *sigLen, size);
1410 if (ret)
1412 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
1413 toBeSigned->cbData, &algoID, NULL, sig, &size);
1414 ok(ret, "CryptSignCertificate failed: %08x\n", GetLastError());
1415 if (ret)
1417 *sigLen = size;
1418 verifySig(csp, toBeSigned->pbData, toBeSigned->cbData, sig,
1419 size);
1425 static void testVerifyCertSig(HCRYPTPROV csp, const CRYPT_DATA_BLOB *toBeSigned,
1426 LPCSTR sigOID, const BYTE *sig, DWORD sigLen)
1428 CERT_SIGNED_CONTENT_INFO info;
1429 LPBYTE cert = NULL;
1430 DWORD size = 0;
1431 BOOL ret;
1433 if (!pCryptVerifyCertificateSignatureEx)
1435 skip("no CryptVerifyCertificateSignatureEx support\n");
1436 return;
1438 ret = pCryptVerifyCertificateSignatureEx(0, 0, 0, NULL, 0, NULL, 0, NULL);
1439 ok(!ret && GetLastError() == E_INVALIDARG,
1440 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1441 ret = pCryptVerifyCertificateSignatureEx(csp, 0, 0, NULL, 0, NULL, 0, NULL);
1442 ok(!ret && GetLastError() == E_INVALIDARG,
1443 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1444 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING, 0, NULL, 0,
1445 NULL, 0, NULL);
1446 ok(!ret && GetLastError() == E_INVALIDARG,
1447 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1448 /* This crashes
1449 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1450 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, NULL, 0, NULL, 0, NULL);
1452 info.ToBeSigned.cbData = toBeSigned->cbData;
1453 info.ToBeSigned.pbData = toBeSigned->pbData;
1454 info.SignatureAlgorithm.pszObjId = (LPSTR)sigOID;
1455 info.SignatureAlgorithm.Parameters.cbData = 0;
1456 info.Signature.cbData = sigLen;
1457 info.Signature.pbData = (BYTE *)sig;
1458 info.Signature.cUnusedBits = 0;
1459 ret = CryptEncodeObjectEx(X509_ASN_ENCODING, X509_CERT, &info,
1460 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&cert, &size);
1461 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1462 if (cert)
1464 CRYPT_DATA_BLOB certBlob = { 0, NULL };
1465 PCERT_PUBLIC_KEY_INFO pubKeyInfo = NULL;
1467 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1468 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
1469 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
1470 "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
1471 certBlob.cbData = 1;
1472 certBlob.pbData = (void *)0xdeadbeef;
1473 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1474 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
1475 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1476 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1477 certBlob.cbData = size;
1478 certBlob.pbData = cert;
1479 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1480 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
1481 ok(!ret && GetLastError() == E_INVALIDARG,
1482 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1483 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1484 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
1485 CRYPT_VERIFY_CERT_SIGN_ISSUER_NULL, NULL, 0, NULL);
1486 ok(!ret && GetLastError() == E_INVALIDARG,
1487 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1488 /* This crashes
1489 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1490 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
1491 CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY, NULL, 0, NULL);
1493 CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
1494 (LPSTR)sigOID, 0, NULL, NULL, &size);
1495 pubKeyInfo = HeapAlloc(GetProcessHeap(), 0, size);
1496 if (pubKeyInfo)
1498 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
1499 X509_ASN_ENCODING, (LPSTR)sigOID, 0, NULL, pubKeyInfo, &size);
1500 ok(ret, "CryptExportKey failed: %08x\n", GetLastError());
1501 if (ret)
1503 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1504 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
1505 CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY, pubKeyInfo, 0, NULL);
1506 ok(ret, "CryptVerifyCertificateSignatureEx failed: %08x\n",
1507 GetLastError());
1509 HeapFree(GetProcessHeap(), 0, pubKeyInfo);
1511 LocalFree(cert);
1515 static BYTE emptyCert[] = { 0x30, 0x00 };
1517 static void testCertSigs(void)
1519 HCRYPTPROV csp;
1520 CRYPT_DATA_BLOB toBeSigned = { sizeof(emptyCert), emptyCert };
1521 BOOL ret;
1522 HCRYPTKEY key;
1523 BYTE sig[64];
1524 DWORD sigSize = sizeof(sig);
1526 /* Just in case a previous run failed, delete this thing */
1527 pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1528 CRYPT_DELETEKEYSET);
1529 ret = pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1530 CRYPT_NEWKEYSET);
1531 ok(ret, "CryptAcquireContext failed: %08x\n", GetLastError());
1533 testSignCert(csp, &toBeSigned, szOID_RSA_SHA1RSA, &key, sig, &sigSize);
1534 testVerifyCertSig(csp, &toBeSigned, szOID_RSA_SHA1RSA, sig, sigSize);
1536 CryptDestroyKey(key);
1537 CryptReleaseContext(csp, 0);
1538 ret = pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1539 CRYPT_DELETEKEYSET);
1542 static const BYTE md5SignedEmptyCert[] = {
1543 0x30,0x56,0x30,0x33,0x02,0x00,0x30,0x02,0x06,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,
1544 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,
1545 0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x07,
1546 0x30,0x02,0x06,0x00,0x03,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,
1547 0x0d,0x02,0x05,0x05,0x00,0x03,0x11,0x00,0xfb,0x0f,0x66,0x82,0x66,0xd9,0xe5,0xf8,
1548 0xd8,0xa2,0x55,0x2b,0xe1,0xa5,0xd9,0x04 };
1549 static const BYTE md5SignedEmptyCertNoNull[] = {
1550 0x30,0x54,0x30,0x33,0x02,0x00,0x30,0x02,0x06,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,
1551 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,
1552 0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x07,
1553 0x30,0x02,0x06,0x00,0x03,0x01,0x00,0x30,0x0a,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,
1554 0x0d,0x02,0x05,0x03,0x11,0x00,0x04,0xd9,0xa5,0xe1,0x2b,0x55,0xa2,0xd8,0xf8,0xe5,
1555 0xd9,0x66,0x82,0x66,0x0f,0xfb };
1557 static void testSignAndEncodeCert(void)
1559 static char oid_rsa_md5rsa[] = szOID_RSA_MD5RSA;
1560 static char oid_rsa_md5[] = szOID_RSA_MD5;
1561 BOOL ret;
1562 DWORD size;
1563 CRYPT_ALGORITHM_IDENTIFIER algID = { 0 };
1564 CERT_INFO info = { 0 };
1566 /* Crash
1567 ret = CryptSignAndEncodeCertificate(0, 0, 0, NULL, NULL, NULL, NULL, NULL,
1568 NULL);
1569 ret = CryptSignAndEncodeCertificate(0, 0, 0, NULL, NULL, NULL, NULL, NULL,
1570 &size);
1572 ret = CryptSignAndEncodeCertificate(0, 0, 0, NULL, NULL, &algID, NULL, NULL,
1573 &size);
1574 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1575 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1576 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING, NULL, NULL,
1577 &algID, NULL, NULL, &size);
1578 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1579 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1580 ret = CryptSignAndEncodeCertificate(0, 0, 0, X509_CERT_TO_BE_SIGNED, NULL,
1581 &algID, NULL, NULL, &size);
1582 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1583 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1584 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1585 X509_CERT_TO_BE_SIGNED, NULL, &algID, NULL, NULL, &size);
1586 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1587 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1588 /* Crashes
1589 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1590 X509_CERT_TO_BE_SIGNED, &info, NULL, NULL, NULL, &size);
1592 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1593 X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, NULL, &size);
1594 ok(!ret && GetLastError() == NTE_BAD_ALGID,
1595 "Expected NTE_BAD_ALGID, got %08x\n", GetLastError());
1596 algID.pszObjId = oid_rsa_md5rsa;
1597 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1598 X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, NULL, &size);
1599 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1600 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1601 algID.pszObjId = oid_rsa_md5;
1602 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1603 X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, NULL, &size);
1604 ok(ret, "CryptSignAndEncodeCertificate failed: %08x\n", GetLastError());
1605 if (ret)
1607 LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, size);
1609 if (buf)
1611 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1612 X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, buf, &size);
1613 ok(ret, "CryptSignAndEncodeCertificate failed: %08x\n",
1614 GetLastError());
1615 /* Tricky: because the NULL parameters may either be omitted or
1616 * included as an asn.1-encoded NULL (0x05,0x00), two different
1617 * values are allowed.
1619 ok(size == sizeof(md5SignedEmptyCert) ||
1620 size == sizeof(md5SignedEmptyCertNoNull), "Unexpected size %d\n",
1621 size);
1622 if (size == sizeof(md5SignedEmptyCert))
1623 ok(!memcmp(buf, md5SignedEmptyCert, size),
1624 "Unexpected value\n");
1625 else if (size == sizeof(md5SignedEmptyCertNoNull))
1626 ok(!memcmp(buf, md5SignedEmptyCertNoNull, size),
1627 "Unexpected value\n");
1628 HeapFree(GetProcessHeap(), 0, buf);
1633 static void testCreateSelfSignCert(void)
1635 PCCERT_CONTEXT context;
1636 CERT_NAME_BLOB name = { sizeof(subjectName), subjectName };
1637 HCRYPTPROV csp;
1638 BOOL ret;
1639 HCRYPTKEY key;
1640 CRYPT_KEY_PROV_INFO info;
1642 /* This crashes:
1643 context = CertCreateSelfSignCertificate(0, NULL, 0, NULL, NULL, NULL, NULL,
1644 NULL);
1645 * Calling this with no first parameter creates a new key container, which
1646 * lasts beyond the test, so I don't test that. Nb: the generated key
1647 * name is a GUID.
1648 context = CertCreateSelfSignCertificate(0, &name, 0, NULL, NULL, NULL, NULL,
1649 NULL);
1652 /* Acquire a CSP */
1653 pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1654 CRYPT_DELETEKEYSET);
1655 ret = pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1656 CRYPT_NEWKEYSET);
1657 ok(ret, "CryptAcquireContext failed: %08x\n", GetLastError());
1659 context = CertCreateSelfSignCertificate(csp, &name, 0, NULL, NULL, NULL,
1660 NULL, NULL);
1661 ok(!context && GetLastError() == NTE_NO_KEY,
1662 "Expected NTE_NO_KEY, got %08x\n", GetLastError());
1663 ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
1664 ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
1665 if (ret)
1667 context = CertCreateSelfSignCertificate(csp, &name, 0, NULL, NULL, NULL,
1668 NULL, NULL);
1669 ok(context != NULL, "CertCreateSelfSignCertificate failed: %08x\n",
1670 GetLastError());
1671 if (context)
1673 DWORD size = 0;
1674 PCRYPT_KEY_PROV_INFO info;
1676 /* The context must have a key provider info property */
1677 ret = CertGetCertificateContextProperty(context,
1678 CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
1679 ok(ret && size, "Expected non-zero key provider info\n");
1680 if (size)
1682 info = HeapAlloc(GetProcessHeap(), 0, size);
1683 if (info)
1685 ret = CertGetCertificateContextProperty(context,
1686 CERT_KEY_PROV_INFO_PROP_ID, info, &size);
1687 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
1688 GetLastError());
1689 if (ret)
1691 /* Sanity-check the key provider */
1692 ok(!lstrcmpW(info->pwszContainerName, cspNameW),
1693 "Unexpected key container\n");
1694 ok(!lstrcmpW(info->pwszProvName, MS_DEF_PROV_W),
1695 "Unexpected provider\n");
1696 ok(info->dwKeySpec == AT_SIGNATURE,
1697 "Expected AT_SIGNATURE, got %d\n", info->dwKeySpec);
1699 HeapFree(GetProcessHeap(), 0, info);
1703 CertFreeCertificateContext(context);
1706 CryptDestroyKey(key);
1709 CryptReleaseContext(csp, 0);
1710 ret = pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1711 CRYPT_DELETEKEYSET);
1713 /* do the same test with AT_KEYEXCHANGE and key info*/
1714 memset(&info,0,sizeof(info));
1715 info.dwProvType = PROV_RSA_FULL;
1716 info.dwKeySpec = AT_KEYEXCHANGE;
1717 info.pwszProvName = (LPWSTR) MS_DEF_PROV_W;
1718 info.pwszContainerName = cspNameW;
1719 context = CertCreateSelfSignCertificate(0, &name, 0, &info, NULL, NULL,
1720 NULL, NULL);
1721 ok(context != NULL, "CertCreateSelfSignCertificate failed: %08x\n",
1722 GetLastError());
1723 if (context)
1725 DWORD size = 0;
1726 PCRYPT_KEY_PROV_INFO info;
1728 /* The context must have a key provider info property */
1729 ret = CertGetCertificateContextProperty(context,
1730 CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
1731 ok(ret && size, "Expected non-zero key provider info\n");
1732 if (size)
1734 info = HeapAlloc(GetProcessHeap(), 0, size);
1735 if (info)
1737 ret = CertGetCertificateContextProperty(context,
1738 CERT_KEY_PROV_INFO_PROP_ID, info, &size);
1739 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
1740 GetLastError());
1741 if (ret)
1743 /* Sanity-check the key provider */
1744 ok(!lstrcmpW(info->pwszContainerName, cspNameW),
1745 "Unexpected key container\n");
1746 ok(!lstrcmpW(info->pwszProvName, MS_DEF_PROV_W),
1747 "Unexpected provider\n");
1748 ok(info->dwKeySpec == AT_KEYEXCHANGE,
1749 "Expected AT_KEYEXCHANGE, got %d\n", info->dwKeySpec);
1751 HeapFree(GetProcessHeap(), 0, info);
1755 CertFreeCertificateContext(context);
1758 pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1759 CRYPT_DELETEKEYSET);
1762 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
1763 szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
1765 static void testKeyUsage(void)
1767 BOOL ret;
1768 PCCERT_CONTEXT context;
1769 DWORD size;
1771 /* Test base cases */
1772 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, NULL);
1773 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1774 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1775 size = 1;
1776 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, &size);
1777 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1778 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1779 size = 0;
1780 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, &size);
1781 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1782 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1783 /* These crash
1784 ret = CertSetEnhancedKeyUsage(NULL, NULL);
1785 usage.cUsageIdentifier = 0;
1786 ret = CertSetEnhancedKeyUsage(NULL, &usage);
1788 /* Test with a cert with no enhanced key usage extension */
1789 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
1790 sizeof(bigCert));
1791 ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
1792 GetLastError());
1793 if (context)
1795 static const char oid[] = "1.2.3.4";
1796 BYTE buf[sizeof(CERT_ENHKEY_USAGE) + 2 * (sizeof(LPSTR) + sizeof(oid))];
1797 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1799 ret = CertGetEnhancedKeyUsage(context, 0, NULL, NULL);
1800 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1801 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1802 size = 1;
1803 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &size);
1804 if (ret)
1806 /* Windows 2000, ME, or later: even though it succeeded, we expect
1807 * CRYPT_E_NOT_FOUND, which indicates there is no enhanced key
1808 * usage set for this cert (which implies it's valid for all uses.)
1810 ok(GetLastError() == CRYPT_E_NOT_FOUND,
1811 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1812 ok(size == sizeof(CERT_ENHKEY_USAGE), "Wrong size %d\n", size);
1813 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1814 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1815 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %d\n",
1816 pUsage->cUsageIdentifier);
1818 else
1820 /* Windows NT, 95, or 98: it fails, and the last error is
1821 * CRYPT_E_NOT_FOUND.
1823 ok(GetLastError() == CRYPT_E_NOT_FOUND,
1824 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1826 /* I can add a usage identifier when no key usage has been set */
1827 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
1828 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
1829 GetLastError());
1830 size = sizeof(buf);
1831 ret = CertGetEnhancedKeyUsage(context,
1832 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1833 ok(ret && GetLastError() == 0,
1834 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1835 ok(pUsage->cUsageIdentifier == 1, "Expected 1 usage, got %d\n",
1836 pUsage->cUsageIdentifier);
1837 if (pUsage->cUsageIdentifier)
1838 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
1839 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
1840 /* Now set an empty key usage */
1841 pUsage->cUsageIdentifier = 0;
1842 ret = CertSetEnhancedKeyUsage(context, pUsage);
1843 ok(ret, "CertSetEnhancedKeyUsage failed: %08x\n", GetLastError());
1844 /* Shouldn't find it in the cert */
1845 size = sizeof(buf);
1846 ret = CertGetEnhancedKeyUsage(context,
1847 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1848 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
1849 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1850 /* Should find it as an extended property */
1851 ret = CertGetEnhancedKeyUsage(context,
1852 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1853 ok(ret && GetLastError() == 0,
1854 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1855 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %d\n",
1856 pUsage->cUsageIdentifier);
1857 /* Should find it as either */
1858 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1859 ok(ret && GetLastError() == 0,
1860 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1861 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %d\n",
1862 pUsage->cUsageIdentifier);
1863 /* Add a usage identifier */
1864 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
1865 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
1866 GetLastError());
1867 size = sizeof(buf);
1868 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1869 ok(ret && GetLastError() == 0,
1870 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1871 ok(pUsage->cUsageIdentifier == 1, "Expected 1 identifier, got %d\n",
1872 pUsage->cUsageIdentifier);
1873 if (pUsage->cUsageIdentifier)
1874 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
1875 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
1876 /* Yep, I can re-add the same usage identifier */
1877 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
1878 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
1879 GetLastError());
1880 size = sizeof(buf);
1881 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1882 ok(ret && GetLastError() == 0,
1883 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1884 ok(pUsage->cUsageIdentifier == 2, "Expected 2 identifiers, got %d\n",
1885 pUsage->cUsageIdentifier);
1886 if (pUsage->cUsageIdentifier)
1887 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
1888 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
1889 if (pUsage->cUsageIdentifier >= 2)
1890 ok(!strcmp(pUsage->rgpszUsageIdentifier[1], oid),
1891 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[1]);
1892 /* Now set a NULL extended property--this deletes the property. */
1893 ret = CertSetEnhancedKeyUsage(context, NULL);
1894 ok(ret, "CertSetEnhancedKeyUsage failed: %08x\n", GetLastError());
1895 SetLastError(0xbaadcafe);
1896 size = sizeof(buf);
1897 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1898 ok(GetLastError() == CRYPT_E_NOT_FOUND,
1899 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1901 CertFreeCertificateContext(context);
1903 /* Now test with a cert with an enhanced key usage extension */
1904 context = CertCreateCertificateContext(X509_ASN_ENCODING, certWithUsage,
1905 sizeof(certWithUsage));
1906 ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
1907 GetLastError());
1908 if (context)
1910 LPBYTE buf = NULL;
1911 DWORD bufSize = 0, i;
1913 /* The size may depend on what flags are used to query it, so I
1914 * realloc the buffer for each test.
1916 ret = CertGetEnhancedKeyUsage(context,
1917 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, NULL, &bufSize);
1918 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1919 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
1920 if (buf)
1922 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1924 /* Should find it in the cert */
1925 size = bufSize;
1926 ret = CertGetEnhancedKeyUsage(context,
1927 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1928 ok(ret && GetLastError() == 0,
1929 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1930 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
1931 pUsage->cUsageIdentifier);
1932 for (i = 0; i < pUsage->cUsageIdentifier; i++)
1933 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
1934 "Expected %s, got %s\n", keyUsages[i],
1935 pUsage->rgpszUsageIdentifier[i]);
1936 HeapFree(GetProcessHeap(), 0, buf);
1938 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
1939 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1940 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
1941 if (buf)
1943 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1945 /* Should find it as either */
1946 size = bufSize;
1947 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1948 /* In Windows, GetLastError returns CRYPT_E_NOT_FOUND not found
1949 * here, even though the return is successful and the usage id
1950 * count is positive. I don't enforce that here.
1952 ok(ret,
1953 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1954 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
1955 pUsage->cUsageIdentifier);
1956 for (i = 0; i < pUsage->cUsageIdentifier; i++)
1957 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
1958 "Expected %s, got %s\n", keyUsages[i],
1959 pUsage->rgpszUsageIdentifier[i]);
1960 HeapFree(GetProcessHeap(), 0, buf);
1962 /* Shouldn't find it as an extended property */
1963 ret = CertGetEnhancedKeyUsage(context,
1964 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, NULL, &size);
1965 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
1966 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1967 /* Adding a usage identifier overrides the cert's usage!? */
1968 ret = CertAddEnhancedKeyUsageIdentifier(context, szOID_RSA_RSA);
1969 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
1970 GetLastError());
1971 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
1972 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1973 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
1974 if (buf)
1976 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1978 /* Should find it as either */
1979 size = bufSize;
1980 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1981 ok(ret,
1982 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1983 ok(pUsage->cUsageIdentifier == 1, "Expected 1 usage, got %d\n",
1984 pUsage->cUsageIdentifier);
1985 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], szOID_RSA_RSA),
1986 "Expected %s, got %s\n", szOID_RSA_RSA,
1987 pUsage->rgpszUsageIdentifier[0]);
1988 HeapFree(GetProcessHeap(), 0, buf);
1990 /* But querying the cert directly returns its usage */
1991 ret = CertGetEnhancedKeyUsage(context,
1992 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, NULL, &bufSize);
1993 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1994 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
1995 if (buf)
1997 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1999 size = bufSize;
2000 ret = CertGetEnhancedKeyUsage(context,
2001 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
2002 ok(ret,
2003 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2004 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
2005 pUsage->cUsageIdentifier);
2006 for (i = 0; i < pUsage->cUsageIdentifier; i++)
2007 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
2008 "Expected %s, got %s\n", keyUsages[i],
2009 pUsage->rgpszUsageIdentifier[i]);
2010 HeapFree(GetProcessHeap(), 0, buf);
2012 /* And removing the only usage identifier in the extended property
2013 * results in the cert's key usage being found.
2015 ret = CertRemoveEnhancedKeyUsageIdentifier(context, szOID_RSA_RSA);
2016 ok(ret, "CertRemoveEnhancedKeyUsage failed: %08x\n", GetLastError());
2017 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
2018 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2019 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
2020 if (buf)
2022 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
2024 /* Should find it as either */
2025 size = bufSize;
2026 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2027 ok(ret,
2028 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2029 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
2030 pUsage->cUsageIdentifier);
2031 for (i = 0; i < pUsage->cUsageIdentifier; i++)
2032 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
2033 "Expected %s, got %s\n", keyUsages[i],
2034 pUsage->rgpszUsageIdentifier[i]);
2035 HeapFree(GetProcessHeap(), 0, buf);
2038 CertFreeCertificateContext(context);
2042 static void testCompareCertName(void)
2044 static BYTE bogus[] = { 1, 2, 3, 4 };
2045 static BYTE bogusPrime[] = { 0, 1, 2, 3, 4 };
2046 static BYTE emptyPrime[] = { 0x30, 0x00, 0x01 };
2047 BOOL ret;
2048 CERT_NAME_BLOB blob1, blob2;
2050 /* crashes
2051 ret = CertCompareCertificateName(0, NULL, NULL);
2053 /* An empty name checks against itself.. */
2054 blob1.pbData = emptyCert;
2055 blob1.cbData = sizeof(emptyCert);
2056 ret = CertCompareCertificateName(0, &blob1, &blob1);
2057 ok(ret, "CertCompareCertificateName failed: %08x\n", GetLastError());
2058 /* It doesn't have to be a valid encoded name.. */
2059 blob1.pbData = bogus;
2060 blob1.cbData = sizeof(bogus);
2061 ret = CertCompareCertificateName(0, &blob1, &blob1);
2062 ok(ret, "CertCompareCertificateName failed: %08x\n", GetLastError());
2063 /* Leading zeroes matter.. */
2064 blob2.pbData = bogusPrime;
2065 blob2.cbData = sizeof(bogusPrime);
2066 ret = CertCompareCertificateName(0, &blob1, &blob2);
2067 ok(!ret, "Expected failure\n");
2068 /* As do trailing extra bytes. */
2069 blob2.pbData = emptyPrime;
2070 blob2.cbData = sizeof(emptyPrime);
2071 ret = CertCompareCertificateName(0, &blob1, &blob2);
2072 ok(!ret, "Expected failure\n");
2075 static BYTE int1[] = { 0x88, 0xff, 0xff, 0xff };
2076 static BYTE int2[] = { 0x88, 0xff };
2077 static BYTE int3[] = { 0x23, 0xff };
2078 static BYTE int4[] = { 0x7f, 0x00 };
2079 static BYTE int5[] = { 0x7f };
2080 static BYTE int6[] = { 0x80, 0x00, 0x00, 0x00 };
2081 static BYTE int7[] = { 0x80, 0x00 };
2083 static struct IntBlobTest
2085 CRYPT_INTEGER_BLOB blob1;
2086 CRYPT_INTEGER_BLOB blob2;
2087 BOOL areEqual;
2088 } intBlobs[] = {
2089 { { sizeof(int1), int1 }, { sizeof(int2), int2 }, TRUE },
2090 { { sizeof(int3), int3 }, { sizeof(int3), int3 }, TRUE },
2091 { { sizeof(int4), int4 }, { sizeof(int5), int5 }, TRUE },
2092 { { sizeof(int6), int6 }, { sizeof(int7), int7 }, TRUE },
2093 { { sizeof(int1), int1 }, { sizeof(int7), int7 }, FALSE },
2096 static void testCompareIntegerBlob(void)
2098 DWORD i;
2099 BOOL ret;
2101 for (i = 0; i < sizeof(intBlobs) / sizeof(intBlobs[0]); i++)
2103 ret = CertCompareIntegerBlob(&intBlobs[i].blob1, &intBlobs[i].blob2);
2104 ok(ret == intBlobs[i].areEqual,
2105 "%d: expected blobs %s compare\n", i, intBlobs[i].areEqual ?
2106 "to" : "not to");
2110 static void testComparePublicKeyInfo(void)
2112 BOOL ret;
2113 CERT_PUBLIC_KEY_INFO info1 = { { 0 } }, info2 = { { 0 } };
2114 static CHAR oid_rsa_rsa[] = szOID_RSA_RSA;
2115 static CHAR oid_rsa_sha1rsa[] = szOID_RSA_SHA1RSA;
2116 static CHAR oid_x957_dsa[] = szOID_X957_DSA;
2117 static BYTE bits1[] = { 1, 0 };
2118 static BYTE bits2[] = { 0 };
2119 static BYTE bits3[] = { 1 };
2121 /* crashes
2122 ret = CertComparePublicKeyInfo(0, NULL, NULL);
2124 /* Empty public keys compare */
2125 ret = CertComparePublicKeyInfo(0, &info1, &info2);
2126 ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
2127 /* Different OIDs appear to compare */
2128 info1.Algorithm.pszObjId = oid_rsa_rsa;
2129 info2.Algorithm.pszObjId = oid_rsa_sha1rsa;
2130 ret = CertComparePublicKeyInfo(0, &info1, &info2);
2131 ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
2132 info2.Algorithm.pszObjId = oid_x957_dsa;
2133 ret = CertComparePublicKeyInfo(0, &info1, &info2);
2134 ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
2135 info1.PublicKey.cbData = sizeof(bits1);
2136 info1.PublicKey.pbData = bits1;
2137 info1.PublicKey.cUnusedBits = 0;
2138 info2.PublicKey.cbData = sizeof(bits1);
2139 info2.PublicKey.pbData = bits1;
2140 info2.PublicKey.cUnusedBits = 0;
2141 ret = CertComparePublicKeyInfo(0, &info1, &info2);
2142 ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
2143 /* Even though they compare in their used bits, these do not compare */
2144 info1.PublicKey.cbData = sizeof(bits2);
2145 info1.PublicKey.pbData = bits2;
2146 info1.PublicKey.cUnusedBits = 0;
2147 info2.PublicKey.cbData = sizeof(bits3);
2148 info2.PublicKey.pbData = bits3;
2149 info2.PublicKey.cUnusedBits = 1;
2150 ret = CertComparePublicKeyInfo(0, &info1, &info2);
2151 /* Simple (non-comparing) case */
2152 ok(!ret, "Expected keys not to compare\n");
2153 info2.PublicKey.cbData = sizeof(bits1);
2154 info2.PublicKey.pbData = bits1;
2155 info2.PublicKey.cUnusedBits = 0;
2156 ret = CertComparePublicKeyInfo(0, &info1, &info2);
2157 ok(!ret, "Expected keys not to compare\n");
2160 static void testHashPublicKeyInfo(void)
2162 BOOL ret;
2163 CERT_PUBLIC_KEY_INFO info = { { 0 } };
2164 DWORD len;
2166 /* Crash
2167 ret = CryptHashPublicKeyInfo(0, 0, 0, 0, NULL, NULL, NULL);
2168 ret = CryptHashPublicKeyInfo(0, 0, 0, 0, &info, NULL, NULL);
2170 ret = CryptHashPublicKeyInfo(0, 0, 0, 0, NULL, NULL, &len);
2171 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2172 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2173 ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, NULL, NULL, &len);
2174 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2175 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
2176 ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, &info, NULL, &len);
2177 ok(ret, "CryptHashPublicKeyInfo failed: %08x\n", GetLastError());
2178 ok(len == 16, "Expected hash size 16, got %d\n", len);
2179 if (len == 16)
2181 static const BYTE emptyHash[] = { 0xb8,0x51,0x3a,0x31,0x0e,0x9f,0x40,
2182 0x36,0x9c,0x92,0x45,0x1b,0x9d,0xc8,0xf9,0xf6 };
2183 BYTE buf[16];
2185 ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, &info, buf,
2186 &len);
2187 ok(ret, "CryptHashPublicKeyInfo failed: %08x\n", GetLastError());
2188 ok(!memcmp(buf, emptyHash, len), "Unexpected hash\n");
2192 static void testCompareCert(void)
2194 CERT_INFO info1 = { 0 }, info2 = { 0 };
2195 BOOL ret;
2197 /* Crashes
2198 ret = CertCompareCertificate(X509_ASN_ENCODING, NULL, NULL);
2201 /* Certs with the same issuer and serial number are equal, even if they
2202 * differ in other respects (like subject).
2204 info1.SerialNumber.pbData = serialNum;
2205 info1.SerialNumber.cbData = sizeof(serialNum);
2206 info1.Issuer.pbData = subjectName;
2207 info1.Issuer.cbData = sizeof(subjectName);
2208 info1.Subject.pbData = subjectName2;
2209 info1.Subject.cbData = sizeof(subjectName2);
2210 info2.SerialNumber.pbData = serialNum;
2211 info2.SerialNumber.cbData = sizeof(serialNum);
2212 info2.Issuer.pbData = subjectName;
2213 info2.Issuer.cbData = sizeof(subjectName);
2214 info2.Subject.pbData = subjectName;
2215 info2.Subject.cbData = sizeof(subjectName);
2216 ret = CertCompareCertificate(X509_ASN_ENCODING, &info1, &info2);
2217 ok(ret, "Expected certs to be equal\n");
2219 info2.Issuer.pbData = subjectName2;
2220 info2.Issuer.cbData = sizeof(subjectName2);
2221 ret = CertCompareCertificate(X509_ASN_ENCODING, &info1, &info2);
2222 ok(!ret, "Expected certs not to be equal\n");
2225 static void testVerifySubjectCert(void)
2227 BOOL ret;
2228 DWORD flags;
2229 PCCERT_CONTEXT context1, context2;
2231 /* Crashes
2232 ret = CertVerifySubjectCertificateContext(NULL, NULL, NULL);
2234 flags = 0;
2235 ret = CertVerifySubjectCertificateContext(NULL, NULL, &flags);
2236 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
2237 GetLastError());
2238 flags = CERT_STORE_NO_CRL_FLAG;
2239 ret = CertVerifySubjectCertificateContext(NULL, NULL, &flags);
2240 ok(!ret && GetLastError() == E_INVALIDARG,
2241 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2243 flags = 0;
2244 context1 = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
2245 sizeof(bigCert));
2246 ret = CertVerifySubjectCertificateContext(NULL, context1, &flags);
2247 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
2248 GetLastError());
2249 ret = CertVerifySubjectCertificateContext(context1, NULL, &flags);
2250 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
2251 GetLastError());
2252 ret = CertVerifySubjectCertificateContext(context1, context1, &flags);
2253 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
2254 GetLastError());
2256 context2 = CertCreateCertificateContext(X509_ASN_ENCODING,
2257 bigCertWithDifferentSubject, sizeof(bigCertWithDifferentSubject));
2258 SetLastError(0xdeadbeef);
2259 ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
2260 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
2261 GetLastError());
2262 flags = CERT_STORE_REVOCATION_FLAG;
2263 ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
2264 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
2265 GetLastError());
2266 ok(flags == (CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG),
2267 "Expected CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG, got %08x\n",
2268 flags);
2269 flags = CERT_STORE_SIGNATURE_FLAG;
2270 ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
2271 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
2272 GetLastError());
2273 ok(flags == CERT_STORE_SIGNATURE_FLAG,
2274 "Expected CERT_STORE_SIGNATURE_FLAG, got %08x\n", flags);
2275 CertFreeCertificateContext(context2);
2277 CertFreeCertificateContext(context1);
2280 static BYTE privKey[] = {
2281 0x07, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x52, 0x53, 0x41, 0x32, 0x00,
2282 0x02, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x79, 0x10, 0x1c, 0xd0, 0x6b, 0x10,
2283 0x18, 0x30, 0x94, 0x61, 0xdc, 0x0e, 0xcb, 0x96, 0x4e, 0x21, 0x3f, 0x79, 0xcd,
2284 0xa9, 0x17, 0x62, 0xbc, 0xbb, 0x61, 0x4c, 0xe0, 0x75, 0x38, 0x6c, 0xf3, 0xde,
2285 0x60, 0x86, 0x03, 0x97, 0x65, 0xeb, 0x1e, 0x6b, 0xdb, 0x53, 0x85, 0xad, 0x68,
2286 0x21, 0xf1, 0x5d, 0xe7, 0x1f, 0xe6, 0x53, 0xb4, 0xbb, 0x59, 0x3e, 0x14, 0x27,
2287 0xb1, 0x83, 0xa7, 0x3a, 0x54, 0xe2, 0x8f, 0x65, 0x8e, 0x6a, 0x4a, 0xcf, 0x3b,
2288 0x1f, 0x65, 0xff, 0xfe, 0xf1, 0x31, 0x3a, 0x37, 0x7a, 0x8b, 0xcb, 0xc6, 0xd4,
2289 0x98, 0x50, 0x36, 0x67, 0xe4, 0xa1, 0xe8, 0x7e, 0x8a, 0xc5, 0x23, 0xf2, 0x77,
2290 0xf5, 0x37, 0x61, 0x49, 0x72, 0x59, 0xe8, 0x3d, 0xf7, 0x60, 0xb2, 0x77, 0xca,
2291 0x78, 0x54, 0x6d, 0x65, 0x9e, 0x03, 0x97, 0x1b, 0x61, 0xbd, 0x0c, 0xd8, 0x06,
2292 0x63, 0xe2, 0xc5, 0x48, 0xef, 0xb3, 0xe2, 0x6e, 0x98, 0x7d, 0xbd, 0x4e, 0x72,
2293 0x91, 0xdb, 0x31, 0x57, 0xe3, 0x65, 0x3a, 0x49, 0xca, 0xec, 0xd2, 0x02, 0x4e,
2294 0x22, 0x7e, 0x72, 0x8e, 0xf9, 0x79, 0x84, 0x82, 0xdf, 0x7b, 0x92, 0x2d, 0xaf,
2295 0xc9, 0xe4, 0x33, 0xef, 0x89, 0x5c, 0x66, 0x99, 0xd8, 0x80, 0x81, 0x47, 0x2b,
2296 0xb1, 0x66, 0x02, 0x84, 0x59, 0x7b, 0xc3, 0xbe, 0x98, 0x45, 0x4a, 0x3d, 0xdd,
2297 0xea, 0x2b, 0xdf, 0x4e, 0xb4, 0x24, 0x6b, 0xec, 0xe7, 0xd9, 0x0c, 0x45, 0xb8,
2298 0xbe, 0xca, 0x69, 0x37, 0x92, 0x4c, 0x38, 0x6b, 0x96, 0x6d, 0xcd, 0x86, 0x67,
2299 0x5c, 0xea, 0x54, 0x94, 0xa4, 0xca, 0xa4, 0x02, 0xa5, 0x21, 0x4d, 0xae, 0x40,
2300 0x8f, 0x9d, 0x51, 0x83, 0xf2, 0x3f, 0x33, 0xc1, 0x72, 0xb4, 0x1d, 0x94, 0x6e,
2301 0x7d, 0xe4, 0x27, 0x3f, 0xea, 0xff, 0xe5, 0x9b, 0xa7, 0x5e, 0x55, 0x8e, 0x0d,
2302 0x69, 0x1c, 0x7a, 0xff, 0x81, 0x9d, 0x53, 0x52, 0x97, 0x9a, 0x76, 0x79, 0xda,
2303 0x93, 0x32, 0x16, 0xec, 0x69, 0x51, 0x1a, 0x4e, 0xc3, 0xf1, 0x72, 0x80, 0x78,
2304 0x5e, 0x66, 0x4a, 0x8d, 0x85, 0x2f, 0x3f, 0xb2, 0xa7 };
2306 static const BYTE selfSignedCert[] = {
2307 0x30, 0x82, 0x01, 0x1f, 0x30, 0x81, 0xce, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
2308 0x10, 0xeb, 0x0d, 0x57, 0x2a, 0x9c, 0x09, 0xba, 0xa4, 0x4a, 0xb7, 0x25, 0x49,
2309 0xd9, 0x3e, 0xb5, 0x73, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d,
2310 0x05, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
2311 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30,
2312 0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x36, 0x32, 0x39, 0x30, 0x35, 0x30, 0x30,
2313 0x34, 0x36, 0x5a, 0x17, 0x0d, 0x30, 0x37, 0x30, 0x36, 0x32, 0x39, 0x31, 0x31,
2314 0x30, 0x30, 0x34, 0x36, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
2315 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e,
2316 0x67, 0x00, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
2317 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
2318 0x00, 0xe2, 0x54, 0x3a, 0xa7, 0x83, 0xb1, 0x27, 0x14, 0x3e, 0x59, 0xbb, 0xb4,
2319 0x53, 0xe6, 0x1f, 0xe7, 0x5d, 0xf1, 0x21, 0x68, 0xad, 0x85, 0x53, 0xdb, 0x6b,
2320 0x1e, 0xeb, 0x65, 0x97, 0x03, 0x86, 0x60, 0xde, 0xf3, 0x6c, 0x38, 0x75, 0xe0,
2321 0x4c, 0x61, 0xbb, 0xbc, 0x62, 0x17, 0xa9, 0xcd, 0x79, 0x3f, 0x21, 0x4e, 0x96,
2322 0xcb, 0x0e, 0xdc, 0x61, 0x94, 0x30, 0x18, 0x10, 0x6b, 0xd0, 0x1c, 0x10, 0x79,
2323 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
2324 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x25, 0x90, 0x53, 0x34, 0xd9, 0x56, 0x41,
2325 0x5e, 0xdb, 0x7e, 0x01, 0x36, 0xec, 0x27, 0x61, 0x5e, 0xb7, 0x4d, 0x90, 0x66,
2326 0xa2, 0xe1, 0x9d, 0x58, 0x76, 0xd4, 0x9c, 0xba, 0x2c, 0x84, 0xc6, 0x83, 0x7a,
2327 0x22, 0x0d, 0x03, 0x69, 0x32, 0x1a, 0x6d, 0xcb, 0x0c, 0x15, 0xb3, 0x6b, 0xc7,
2328 0x0a, 0x8c, 0xb4, 0x5c, 0x34, 0x78, 0xe0, 0x3c, 0x9c, 0xe9, 0xf3, 0x30, 0x9f,
2329 0xa8, 0x76, 0x57, 0x92, 0x36 };
2331 static const BYTE exportedPublicKeyBlob[] = {
2332 0x06,0x02,0x00,0x00,0x00,0xa4,0x00,0x00,0x52,0x53,0x41,0x31,0x00,0x02,0x00,0x00,
2333 0x01,0x00,0x01,0x00,0x79,0x10,0x1c,0xd0,0x6b,0x10,0x18,0x30,0x94,0x61,0xdc,0x0e,
2334 0xcb,0x96,0x4e,0x21,0x3f,0x79,0xcd,0xa9,0x17,0x62,0xbc,0xbb,0x61,0x4c,0xe0,0x75,
2335 0x38,0x6c,0xf3,0xde,0x60,0x86,0x03,0x97,0x65,0xeb,0x1e,0x6b,0xdb,0x53,0x85,0xad,
2336 0x68,0x21,0xf1,0x5d,0xe7,0x1f,0xe6,0x53,0xb4,0xbb,0x59,0x3e,0x14,0x27,0xb1,0x83,
2337 0xa7,0x3a,0x54,0xe2 };
2339 static const BYTE asnEncodedPublicKey[] = {
2340 0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7,0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,
2341 0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21,0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,
2342 0x65,0x97,0x03,0x86,0x60,0xde,0xf3,0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,
2343 0x17,0xa9,0xcd,0x79,0x3f,0x21,0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,
2344 0x6b,0xd0,0x1c,0x10,0x79,0x02,0x03,0x01,0x00,0x01 };
2346 static void testAcquireCertPrivateKey(void)
2348 BOOL ret;
2349 PCCERT_CONTEXT cert;
2350 HCRYPTPROV csp;
2351 DWORD size, keySpec;
2352 BOOL callerFree;
2353 CRYPT_KEY_PROV_INFO keyProvInfo;
2354 HCRYPTKEY key;
2355 WCHAR ms_def_prov_w[MAX_PATH];
2357 lstrcpyW(ms_def_prov_w, MS_DEF_PROV_W);
2359 keyProvInfo.pwszContainerName = cspNameW;
2360 keyProvInfo.pwszProvName = ms_def_prov_w;
2361 keyProvInfo.dwProvType = PROV_RSA_FULL;
2362 keyProvInfo.dwFlags = 0;
2363 keyProvInfo.cProvParam = 0;
2364 keyProvInfo.rgProvParam = NULL;
2365 keyProvInfo.dwKeySpec = AT_SIGNATURE;
2367 pCryptAcquireContextW(NULL, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
2368 CRYPT_DELETEKEYSET);
2370 cert = CertCreateCertificateContext(X509_ASN_ENCODING, selfSignedCert,
2371 sizeof(selfSignedCert));
2373 /* Crash
2374 ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, NULL, NULL);
2375 ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, NULL,
2376 &callerFree);
2377 ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, &keySpec,
2378 NULL);
2379 ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, &csp, NULL, NULL);
2380 ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, &csp, &keySpec,
2381 &callerFree);
2382 ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, NULL, NULL, NULL);
2385 /* Missing private key */
2386 ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, NULL, NULL);
2387 ok(!ret && GetLastError() == CRYPT_E_NO_KEY_PROPERTY,
2388 "Expected CRYPT_E_NO_KEY_PROPERTY, got %08x\n", GetLastError());
2389 ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, &keySpec,
2390 &callerFree);
2391 ok(!ret && GetLastError() == CRYPT_E_NO_KEY_PROPERTY,
2392 "Expected CRYPT_E_NO_KEY_PROPERTY, got %08x\n", GetLastError());
2393 CertSetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, 0,
2394 &keyProvInfo);
2395 ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, &keySpec,
2396 &callerFree);
2397 ok(!ret && GetLastError() == CRYPT_E_NO_KEY_PROPERTY,
2398 "Expected CRYPT_E_NO_KEY_PROPERTY, got %08x\n", GetLastError());
2400 pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
2401 CRYPT_NEWKEYSET);
2402 ret = CryptImportKey(csp, privKey, sizeof(privKey), 0, 0, &key);
2403 ok(ret, "CryptImportKey failed: %08x\n", GetLastError());
2404 if (ret)
2406 HCRYPTPROV certCSP;
2407 DWORD size;
2408 CERT_KEY_CONTEXT keyContext;
2410 /* Don't cache provider */
2411 ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &certCSP,
2412 &keySpec, &callerFree);
2413 ok(ret, "CryptAcquireCertificatePrivateKey failed: %08x\n",
2414 GetLastError());
2415 ok(callerFree, "Expected callerFree to be TRUE\n");
2416 CryptReleaseContext(certCSP, 0);
2417 ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &certCSP,
2418 NULL, NULL);
2419 ok(ret, "CryptAcquireCertificatePrivateKey failed: %08x\n",
2420 GetLastError());
2421 CryptReleaseContext(certCSP, 0);
2423 /* Use the key prov info's caching (there shouldn't be any) */
2424 ret = CryptAcquireCertificatePrivateKey(cert,
2425 CRYPT_ACQUIRE_USE_PROV_INFO_FLAG, NULL, &certCSP, &keySpec,
2426 &callerFree);
2427 ok(ret, "CryptAcquireCertificatePrivateKey failed: %08x\n",
2428 GetLastError());
2429 ok(callerFree, "Expected callerFree to be TRUE\n");
2430 CryptReleaseContext(certCSP, 0);
2432 /* Cache it (and check that it's cached) */
2433 ret = CryptAcquireCertificatePrivateKey(cert,
2434 CRYPT_ACQUIRE_CACHE_FLAG, NULL, &certCSP, &keySpec, &callerFree);
2435 ok(ret, "CryptAcquireCertificatePrivateKey failed: %08x\n",
2436 GetLastError());
2437 ok(!callerFree, "Expected callerFree to be FALSE\n");
2438 size = sizeof(keyContext);
2439 ret = CertGetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID,
2440 &keyContext, &size);
2441 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
2442 GetLastError());
2444 /* Remove the cached provider */
2445 CryptReleaseContext(keyContext.hCryptProv, 0);
2446 CertSetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID, 0,
2447 NULL);
2448 /* Allow caching via the key prov info */
2449 keyProvInfo.dwFlags = CERT_SET_KEY_CONTEXT_PROP_ID;
2450 CertSetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, 0,
2451 &keyProvInfo);
2452 /* Now use the key prov info's caching */
2453 ret = CryptAcquireCertificatePrivateKey(cert,
2454 CRYPT_ACQUIRE_USE_PROV_INFO_FLAG, NULL, &certCSP, &keySpec,
2455 &callerFree);
2456 ok(ret, "CryptAcquireCertificatePrivateKey failed: %08x\n",
2457 GetLastError());
2458 ok(!callerFree, "Expected callerFree to be FALSE\n");
2459 size = sizeof(keyContext);
2460 ret = CertGetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID,
2461 &keyContext, &size);
2462 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
2463 GetLastError());
2465 CryptDestroyKey(key);
2468 /* Some sanity-checking on public key exporting */
2469 ret = CryptImportPublicKeyInfo(csp, X509_ASN_ENCODING,
2470 &cert->pCertInfo->SubjectPublicKeyInfo, &key);
2471 ok(ret, "CryptImportPublicKeyInfo failed: %08x\n", GetLastError());
2472 if (ret)
2474 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &size);
2475 ok(ret, "CryptExportKey failed: %08x\n", GetLastError());
2476 if (ret)
2478 LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, size), encodedKey;
2480 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, buf, &size);
2481 ok(ret, "CryptExportKey failed: %08x\n", GetLastError());
2482 ok(size == sizeof(exportedPublicKeyBlob), "Unexpected size %d\n",
2483 size);
2484 ok(!memcmp(buf, exportedPublicKeyBlob, size), "Unexpected value\n");
2485 ret = CryptEncodeObjectEx(X509_ASN_ENCODING, RSA_CSP_PUBLICKEYBLOB,
2486 buf, CRYPT_ENCODE_ALLOC_FLAG, NULL, &encodedKey, &size);
2487 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2488 if (ret)
2490 ok(size == sizeof(asnEncodedPublicKey), "Unexpected size %d\n",
2491 size);
2492 ok(!memcmp(encodedKey, asnEncodedPublicKey, size),
2493 "Unexpected value\n");
2494 LocalFree(encodedKey);
2496 HeapFree(GetProcessHeap(), 0, buf);
2498 CryptDestroyKey(key);
2500 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
2501 NULL, 0, NULL, NULL, &size);
2502 ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
2503 if (ret)
2505 PCERT_PUBLIC_KEY_INFO info = HeapAlloc(GetProcessHeap(), 0, size);
2507 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
2508 NULL, 0, NULL, info, &size);
2509 ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
2510 if (ret)
2512 ok(info->PublicKey.cbData == sizeof(asnEncodedPublicKey),
2513 "Unexpected size %d\n", info->PublicKey.cbData);
2514 ok(!memcmp(info->PublicKey.pbData, asnEncodedPublicKey,
2515 info->PublicKey.cbData), "Unexpected value\n");
2517 HeapFree(GetProcessHeap(), 0, info);
2520 CryptReleaseContext(csp, 0);
2521 pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
2522 CRYPT_DELETEKEYSET);
2524 CertFreeCertificateContext(cert);
2527 static void testGetPublicKeyLength(void)
2529 static char oid_rsa_rsa[] = szOID_RSA_RSA;
2530 static char oid_rsa_dh[] = szOID_RSA_DH;
2531 static char bogusOID[] = "1.2.3";
2532 DWORD ret;
2533 CERT_PUBLIC_KEY_INFO info = { { 0 } };
2534 BYTE bogusKey[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
2535 BYTE key[] = { 0x30,0x0f,0x02,0x08,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
2536 0x02,0x03,0x01,0x00,0x01 };
2538 /* Crashes
2539 ret = CertGetPublicKeyLength(0, NULL);
2541 /* With an empty public key info */
2542 SetLastError(0xdeadbeef);
2543 ret = CertGetPublicKeyLength(0, &info);
2544 ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
2545 "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
2546 ret, GetLastError());
2547 SetLastError(0xdeadbeef);
2548 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
2549 ok(ret == 0 && GetLastError() == CRYPT_E_ASN1_EOD,
2550 "Expected length 0 and CRYPT_E_ASN1_EOD, got length %d, %08x\n",
2551 ret, GetLastError());
2552 /* With a nearly-empty public key info */
2553 info.Algorithm.pszObjId = oid_rsa_rsa;
2554 SetLastError(0xdeadbeef);
2555 ret = CertGetPublicKeyLength(0, &info);
2556 ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
2557 "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
2558 ret, GetLastError());
2559 SetLastError(0xdeadbeef);
2560 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
2561 ok(ret == 0 && GetLastError() == CRYPT_E_ASN1_EOD,
2562 "Expected length 0 and CRYPT_E_ASN1_EOD, got length %d, %08x\n",
2563 ret, GetLastError());
2564 /* With a bogus key */
2565 info.PublicKey.cbData = sizeof(bogusKey);
2566 info.PublicKey.pbData = bogusKey;
2567 SetLastError(0xdeadbeef);
2568 ret = CertGetPublicKeyLength(0, &info);
2569 ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
2570 "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
2571 ret, GetLastError());
2572 SetLastError(0xdeadbeef);
2573 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
2574 ok(ret == 0 && GetLastError() == CRYPT_E_ASN1_BADTAG,
2575 "Expected length 0 and CRYPT_E_ASN1_BADTAGTAG, got length %d, %08x\n",
2576 ret, GetLastError());
2577 /* With a believable RSA key but a bogus OID */
2578 info.Algorithm.pszObjId = bogusOID;
2579 info.PublicKey.cbData = sizeof(key);
2580 info.PublicKey.pbData = key;
2581 SetLastError(0xdeadbeef);
2582 ret = CertGetPublicKeyLength(0, &info);
2583 ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
2584 "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
2585 ret, GetLastError());
2586 SetLastError(0xdeadbeef);
2587 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
2588 ok(ret == 56, "Expected length 56, got %d\n", ret);
2589 /* An RSA key with the DH OID */
2590 info.Algorithm.pszObjId = oid_rsa_dh;
2591 SetLastError(0xdeadbeef);
2592 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
2593 ok(ret == 0 && GetLastError() == CRYPT_E_ASN1_BADTAG,
2594 "Expected length 0 and CRYPT_E_ASN1_BADTAG, got length %d, %08x\n",
2595 ret, GetLastError());
2596 /* With the RSA OID */
2597 info.Algorithm.pszObjId = oid_rsa_rsa;
2598 SetLastError(0xdeadbeef);
2599 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
2600 ok(ret == 56, "Expected length 56, got %d\n", ret);
2603 START_TEST(cert)
2605 init_function_pointers();
2607 testAddCert();
2608 testCertProperties();
2609 testDupCert();
2610 testFindCert();
2611 testGetSubjectCert();
2612 testGetIssuerCert();
2614 testCryptHashCert();
2615 testCertSigs();
2616 testSignAndEncodeCert();
2617 testCreateSelfSignCert();
2618 testKeyUsage();
2619 testCompareCertName();
2620 testCompareIntegerBlob();
2621 testComparePublicKeyInfo();
2622 testHashPublicKeyInfo();
2623 testCompareCert();
2624 testVerifySubjectCert();
2625 testAcquireCertPrivateKey();
2626 testGetPublicKeyLength();