wined3d: Pass a wined3d_device_context to wined3d_cs_emit_blt_sub_resource().
[wine/zf.git] / dlls / crypt32 / tests / cert.c
blob745770f009562dc6135cf252a0aec0677326c10c
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 <stdio.h>
22 #include <stdarg.h>
24 #include <ntstatus.h>
25 #define WIN32_NO_STATUS
26 #include <windef.h>
27 #include <winbase.h>
28 #include <winreg.h>
29 #include <winerror.h>
30 #include <wincrypt.h>
32 #include "wine/test.h"
34 static PCCERT_CONTEXT (WINAPI *pCertCreateSelfSignCertificate)(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE,PCERT_NAME_BLOB,DWORD,PCRYPT_KEY_PROV_INFO,PCRYPT_ALGORITHM_IDENTIFIER,PSYSTEMTIME,PSYSTEMTIME,PCERT_EXTENSIONS);
35 static BOOL (WINAPI *pCertGetValidUsages)(DWORD,PCCERT_CONTEXT*,int*,LPSTR*,DWORD*);
36 static BOOL (WINAPI *pCryptAcquireCertificatePrivateKey)(PCCERT_CONTEXT,DWORD,void*,HCRYPTPROV_OR_NCRYPT_KEY_HANDLE*,DWORD*,BOOL*);
37 static BOOL (WINAPI *pCryptEncodeObjectEx)(DWORD,LPCSTR,const void*,DWORD,PCRYPT_ENCODE_PARA,void*,DWORD*);
38 static BOOL (WINAPI *pCryptHashCertificate2)(LPCWSTR, DWORD, void*, const BYTE*, DWORD, BYTE*, DWORD*);
39 static BOOL (WINAPI * pCryptVerifyCertificateSignatureEx)
40 (HCRYPTPROV, DWORD, DWORD, void *, DWORD, void *, DWORD, void *);
42 static BOOL (WINAPI * pCryptAcquireContextA)
43 (HCRYPTPROV *, LPCSTR, LPCSTR, DWORD, DWORD);
45 static void init_function_pointers(void)
47 HMODULE hCrypt32 = GetModuleHandleA("crypt32.dll");
48 HMODULE hAdvapi32 = GetModuleHandleA("advapi32.dll");
50 #define GET_PROC(dll, func) \
51 p ## func = (void *)GetProcAddress(dll, #func); \
52 if(!p ## func) \
53 trace("GetProcAddress(%s) failed\n", #func);
55 GET_PROC(hCrypt32, CertCreateSelfSignCertificate)
56 GET_PROC(hCrypt32, CertGetValidUsages)
57 GET_PROC(hCrypt32, CryptAcquireCertificatePrivateKey)
58 GET_PROC(hCrypt32, CryptEncodeObjectEx)
59 GET_PROC(hCrypt32, CryptHashCertificate2)
60 GET_PROC(hCrypt32, CryptVerifyCertificateSignatureEx)
62 GET_PROC(hAdvapi32, CryptAcquireContextA)
64 #undef GET_PROC
67 static BYTE subjectName[] = { 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
68 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
69 0x6e, 0x67, 0x00 };
70 static BYTE serialNum[] = { 1 };
71 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
72 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
73 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
74 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
75 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
76 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
77 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
78 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
79 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
80 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
81 static BYTE bigCertHash[] = { 0x6e, 0x30, 0x90, 0x71, 0x5f, 0xd9, 0x23,
82 0x56, 0xeb, 0xae, 0x25, 0x40, 0xe6, 0x22, 0xda, 0x19, 0x26, 0x02, 0xa6, 0x08 };
84 static const BYTE bigCertWithDifferentSubject[] = { 0x30, 0x7a, 0x02, 0x01, 0x02,
85 0x30, 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
86 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67,
87 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31,
88 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
89 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15,
90 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c,
91 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06,
92 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55,
93 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02,
94 0x01, 0x01 };
95 static const BYTE bigCertWithDifferentIssuer[] = { 0x30, 0x7a, 0x02, 0x01,
96 0x01, 0x30, 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
97 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e,
98 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
99 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30,
100 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30,
101 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
102 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02,
103 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03,
104 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff,
105 0x02, 0x01, 0x01 };
107 static BYTE subjectName2[] = { 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
108 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61,
109 0x6e, 0x67, 0x00 };
110 static const BYTE bigCert2[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
111 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
112 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
113 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
114 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
115 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
116 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20,
117 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
118 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
119 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
120 static const BYTE bigCert2WithDifferentSerial[] = { 0x30, 0x7a, 0x02, 0x01,
121 0x02, 0x30, 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
122 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e,
123 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
124 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30,
125 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30,
126 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41,
127 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02,
128 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03,
129 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff,
130 0x02, 0x01, 0x01 };
131 static BYTE bigCert2Hash[] = { 0x4a, 0x7f, 0x32, 0x1f, 0xcf, 0x3b, 0xc0,
132 0x87, 0x48, 0x2b, 0xa1, 0x86, 0x54, 0x18, 0xe4, 0x3a, 0x0e, 0x53, 0x7e, 0x2b };
134 static const BYTE certWithUsage[] = { 0x30, 0x81, 0x93, 0x02, 0x01, 0x01, 0x30,
135 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04,
136 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00,
137 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
138 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
139 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31,
140 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61,
141 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00,
142 0x03, 0x01, 0x00, 0xa3, 0x2f, 0x30, 0x2d, 0x30, 0x2b, 0x06, 0x03, 0x55, 0x1d,
143 0x25, 0x01, 0x01, 0xff, 0x04, 0x21, 0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01,
144 0x05, 0x05, 0x07, 0x03, 0x03, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
145 0x03, 0x02, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
147 static void testAddCert(void)
149 HCERTSTORE store;
150 HCERTSTORE collection;
151 PCCERT_CONTEXT context;
152 PCCERT_CONTEXT copyContext;
153 BOOL ret;
155 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
156 CERT_STORE_CREATE_NEW_FLAG, NULL);
157 ok(store != NULL, "CertOpenStore failed: %d\n", GetLastError());
158 if (!store)
159 return;
161 /* Weird--bad add disposition leads to an access violation in Windows.
162 * Both tests crash on some win9x boxes.
164 if (0)
166 ret = CertAddEncodedCertificateToStore(0, X509_ASN_ENCODING, bigCert,
167 sizeof(bigCert), 0, NULL);
168 ok(!ret && (GetLastError() == STATUS_ACCESS_VIOLATION ||
169 GetLastError() == E_INVALIDARG),
170 "Expected STATUS_ACCESS_VIOLATION or E_INVALIDARG, got %08x\n",
171 GetLastError());
172 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
173 bigCert, sizeof(bigCert), 0, NULL);
174 ok(!ret && (GetLastError() == STATUS_ACCESS_VIOLATION ||
175 GetLastError() == E_INVALIDARG),
176 "Expected STATUS_ACCESS_VIOLATION or E_INVALIDARG, got %08x\n",
177 GetLastError());
180 /* Weird--can add a cert to the NULL store (does this have special
181 * meaning?)
183 context = NULL;
184 ret = CertAddEncodedCertificateToStore(0, X509_ASN_ENCODING, bigCert,
185 sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
186 ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* win98 */),
187 "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
188 if (context)
189 CertFreeCertificateContext(context);
190 if (!ret && GetLastError() == OSS_DATA_ERROR)
192 skip("bigCert can't be decoded, skipping tests\n");
193 return;
196 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
197 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
198 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
199 GetLastError());
200 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
201 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, NULL);
202 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
203 GetLastError());
204 /* This has the same name as bigCert, so finding isn't done by name */
205 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
206 certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, &context);
207 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
208 GetLastError());
209 ok(context != NULL, "Expected a context\n");
210 if (context)
212 CRYPT_DATA_BLOB hash = { sizeof(bigCert2Hash), bigCert2Hash };
214 /* Duplicate (AddRef) the context so we can still use it after
215 * deleting it from the store.
217 CertDuplicateCertificateContext(context);
218 CertDeleteCertificateFromStore(context);
219 /* Set the same hash as bigCert2, and try to readd it */
220 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID,
221 0, &hash);
222 ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
223 GetLastError());
224 ret = CertAddCertificateContextToStore(store, context,
225 CERT_STORE_ADD_NEW, NULL);
226 /* The failure is a bit odd (CRYPT_E_ASN1_BADTAG), so just check
227 * that it fails.
229 ok(!ret, "Expected failure\n");
230 CertFreeCertificateContext(context);
232 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert2,
233 sizeof(bigCert2));
234 ok(context != NULL, "Expected a context\n");
235 if (context)
237 /* Try to readd bigCert2 to the store */
238 ret = CertAddCertificateContextToStore(store, context,
239 CERT_STORE_ADD_NEW, NULL);
240 ok(!ret && GetLastError() == CRYPT_E_EXISTS,
241 "Expected CRYPT_E_EXISTS, got %08x\n", GetLastError());
242 CertFreeCertificateContext(context);
245 /* Adding a cert with the same issuer name and serial number (but
246 * different subject) as an existing cert succeeds.
248 context = NULL;
249 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
250 bigCert2WithDifferentSerial, sizeof(bigCert2WithDifferentSerial),
251 CERT_STORE_ADD_NEW, &context);
252 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
253 GetLastError());
254 if (context)
255 CertDeleteCertificateFromStore(context);
257 /* Adding a cert with the same subject name and serial number (but
258 * different issuer) as an existing cert succeeds.
260 context = NULL;
261 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
262 bigCertWithDifferentSubject, sizeof(bigCertWithDifferentSubject),
263 CERT_STORE_ADD_NEW, &context);
264 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
265 GetLastError());
266 if (context)
267 CertDeleteCertificateFromStore(context);
269 /* Adding a cert with the same issuer name and serial number (but
270 * different otherwise) as an existing cert succeeds.
272 context = NULL;
273 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
274 bigCertWithDifferentIssuer, sizeof(bigCertWithDifferentIssuer),
275 CERT_STORE_ADD_NEW, &context);
276 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
277 GetLastError());
278 if (context)
279 CertDeleteCertificateFromStore(context);
281 collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
282 CERT_STORE_CREATE_NEW_FLAG, NULL);
283 ok(collection != NULL, "CertOpenStore failed: %08x\n", GetLastError());
284 if (collection)
286 /* Add store to the collection, but disable updates */
287 CertAddStoreToCollection(collection, store, 0, 0);
289 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert2,
290 sizeof(bigCert2));
291 ok(context != NULL, "Expected a context\n");
292 if (context)
294 /* Try to readd bigCert2 to the collection */
295 ret = CertAddCertificateContextToStore(collection, context,
296 CERT_STORE_ADD_NEW, NULL);
297 ok(!ret && GetLastError() == CRYPT_E_EXISTS,
298 "Expected CRYPT_E_EXISTS, got %08x\n", GetLastError());
299 /* Replacing an existing certificate context is allowed, even
300 * though updates to the collection aren't..
302 ret = CertAddCertificateContextToStore(collection, context,
303 CERT_STORE_ADD_REPLACE_EXISTING, NULL);
304 ok(ret, "CertAddCertificateContextToStore failed: %08x\n",
305 GetLastError());
306 /* use the existing certificate and ask for a copy of the context*/
307 copyContext = NULL;
308 ret = CertAddCertificateContextToStore(collection, context,
309 CERT_STORE_ADD_USE_EXISTING, &copyContext);
310 ok(ret, "CertAddCertificateContextToStore failed: %08x\n",
311 GetLastError());
312 ok(copyContext != NULL, "Expected on output a non NULL copyContext\n");
313 if (copyContext)
314 CertFreeCertificateContext(copyContext);
315 /* but adding a new certificate isn't allowed. */
316 ret = CertAddCertificateContextToStore(collection, context,
317 CERT_STORE_ADD_ALWAYS, NULL);
318 ok(!ret && GetLastError() == E_ACCESSDENIED,
319 "Expected E_ACCESSDENIED, got %08x\n", GetLastError());
320 CertFreeCertificateContext(context);
323 CertCloseStore(collection, 0);
326 CertCloseStore(store, 0);
329 static void checkHash(const BYTE *data, DWORD dataLen, ALG_ID algID,
330 PCCERT_CONTEXT context, DWORD propID)
332 BYTE hash[20] = { 0 }, hashProperty[20];
333 BOOL ret;
334 DWORD size;
335 DWORD dwSizeWithNull;
337 memset(hash, 0, sizeof(hash));
338 memset(hashProperty, 0, sizeof(hashProperty));
339 size = sizeof(hash);
340 ret = CryptHashCertificate(0, algID, 0, data, dataLen, hash, &size);
341 ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
342 ret = CertGetCertificateContextProperty(context, propID, NULL,
343 &dwSizeWithNull);
344 ok(ret, "algID %08x, propID %d: CertGetCertificateContextProperty failed: %08x\n",
345 algID, propID, GetLastError());
346 ret = CertGetCertificateContextProperty(context, propID, hashProperty,
347 &size);
348 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
349 GetLastError());
350 ok(!memcmp(hash, hashProperty, size), "Unexpected hash for property %d\n",
351 propID);
352 ok(size == dwSizeWithNull, "Unexpected length of hash for property: received %d instead of %d\n",
353 dwSizeWithNull,size);
356 static const CHAR cspNameA[] = "WineCryptTemp";
357 static WCHAR cspNameW[] = { 'W','i','n','e','C','r','y','p','t','T','e','m','p',0 };
358 static const BYTE v1CertWithPubKey[] = {
359 0x30,0x81,0x95,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
360 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
361 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
362 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
363 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
364 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
365 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
366 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
367 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,
368 0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,
369 0x01,0x01 };
370 static const BYTE v1CertWithSubjectKeyId[] = {
371 0x30,0x7b,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
372 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
373 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
374 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
375 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
376 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
377 0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x17,0x30,0x15,0x30,
378 0x13,0x06,0x03,0x55,0x1d,0x0e,0x04,0x0c,0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,
379 0x4c,0x61,0x6e,0x67,0x00 };
380 static const BYTE subjectKeyId[] = {
381 0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
382 static const BYTE selfSignedCert[] = {
383 0x30, 0x82, 0x01, 0x1f, 0x30, 0x81, 0xce, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
384 0x10, 0xeb, 0x0d, 0x57, 0x2a, 0x9c, 0x09, 0xba, 0xa4, 0x4a, 0xb7, 0x25, 0x49,
385 0xd9, 0x3e, 0xb5, 0x73, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d,
386 0x05, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
387 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30,
388 0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x36, 0x32, 0x39, 0x30, 0x35, 0x30, 0x30,
389 0x34, 0x36, 0x5a, 0x17, 0x0d, 0x30, 0x37, 0x30, 0x36, 0x32, 0x39, 0x31, 0x31,
390 0x30, 0x30, 0x34, 0x36, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
391 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e,
392 0x67, 0x00, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
393 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
394 0x00, 0xe2, 0x54, 0x3a, 0xa7, 0x83, 0xb1, 0x27, 0x14, 0x3e, 0x59, 0xbb, 0xb4,
395 0x53, 0xe6, 0x1f, 0xe7, 0x5d, 0xf1, 0x21, 0x68, 0xad, 0x85, 0x53, 0xdb, 0x6b,
396 0x1e, 0xeb, 0x65, 0x97, 0x03, 0x86, 0x60, 0xde, 0xf3, 0x6c, 0x38, 0x75, 0xe0,
397 0x4c, 0x61, 0xbb, 0xbc, 0x62, 0x17, 0xa9, 0xcd, 0x79, 0x3f, 0x21, 0x4e, 0x96,
398 0xcb, 0x0e, 0xdc, 0x61, 0x94, 0x30, 0x18, 0x10, 0x6b, 0xd0, 0x1c, 0x10, 0x79,
399 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
400 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x25, 0x90, 0x53, 0x34, 0xd9, 0x56, 0x41,
401 0x5e, 0xdb, 0x7e, 0x01, 0x36, 0xec, 0x27, 0x61, 0x5e, 0xb7, 0x4d, 0x90, 0x66,
402 0xa2, 0xe1, 0x9d, 0x58, 0x76, 0xd4, 0x9c, 0xba, 0x2c, 0x84, 0xc6, 0x83, 0x7a,
403 0x22, 0x0d, 0x03, 0x69, 0x32, 0x1a, 0x6d, 0xcb, 0x0c, 0x15, 0xb3, 0x6b, 0xc7,
404 0x0a, 0x8c, 0xb4, 0x5c, 0x34, 0x78, 0xe0, 0x3c, 0x9c, 0xe9, 0xf3, 0x30, 0x9f,
405 0xa8, 0x76, 0x57, 0x92, 0x36 };
406 static const BYTE selfSignedSignatureHash[] = { 0x07,0x5a,0x3e,0xfd,0x0d,0xf6,
407 0x88,0xeb,0x00,0x64,0xbd,0xc9,0xd6,0xea,0x0a,0x7c,0xcc,0x24,0xdb,0x5d };
409 static void testCertProperties(void)
411 PCCERT_CONTEXT context = CertCreateCertificateContext(X509_ASN_ENCODING,
412 bigCert, sizeof(bigCert));
413 DWORD propID, numProps, access, size;
414 BOOL ret;
415 BYTE hash[20] = { 0 }, hashProperty[20];
416 CRYPT_DATA_BLOB blob;
417 CERT_KEY_CONTEXT keyContext;
419 ok(context != NULL || broken(GetLastError() == OSS_DATA_ERROR /* win98 */),
420 "CertCreateCertificateContext failed: %08x\n", GetLastError());
421 if (!context)
422 return;
424 /* This crashes
425 propID = CertEnumCertificateContextProperties(NULL, 0);
428 propID = 0;
429 numProps = 0;
430 do {
431 propID = CertEnumCertificateContextProperties(context, propID);
432 if (propID)
433 numProps++;
434 } while (propID != 0);
435 ok(numProps == 0, "Expected 0 properties, got %d\n", numProps);
437 /* Tests with a NULL cert context. Prop ID 0 fails.. */
438 ret = CertSetCertificateContextProperty(NULL, 0, 0, NULL);
439 ok(!ret && GetLastError() == E_INVALIDARG,
440 "Expected E_INVALIDARG, got %08x\n", GetLastError());
441 /* while this just crashes.
442 ret = CertSetCertificateContextProperty(NULL,
443 CERT_KEY_PROV_HANDLE_PROP_ID, 0, NULL);
446 ret = CertSetCertificateContextProperty(context, 0, 0, NULL);
447 ok(!ret && GetLastError() == E_INVALIDARG,
448 "Expected E_INVALIDARG, got %08x\n", GetLastError());
449 /* Can't set the cert property directly, this crashes.
450 ret = CertSetCertificateContextProperty(context,
451 CERT_CERT_PROP_ID, 0, bigCert2);
454 /* These all crash.
455 ret = CertGetCertificateContextProperty(context,
456 CERT_ACCESS_STATE_PROP_ID, 0, NULL);
457 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
458 NULL, NULL);
459 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
460 hashProperty, NULL);
462 /* A missing prop */
463 size = 0;
464 ret = CertGetCertificateContextProperty(context,
465 CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
466 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
467 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
468 /* And, an implicit property */
469 size = sizeof(access);
470 ret = CertGetCertificateContextProperty(context,
471 CERT_ACCESS_STATE_PROP_ID, &access, &size);
472 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
473 GetLastError());
474 ok(!(access & CERT_ACCESS_STATE_WRITE_PERSIST_FLAG),
475 "Didn't expect a persisted cert\n");
476 /* Trying to set this "read only" property crashes.
477 access |= CERT_ACCESS_STATE_WRITE_PERSIST_FLAG;
478 ret = CertSetCertificateContextProperty(context,
479 CERT_ACCESS_STATE_PROP_ID, 0, &access);
482 /* Can I set the hash to an invalid hash? */
483 blob.pbData = hash;
484 blob.cbData = sizeof(hash);
485 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID, 0,
486 &blob);
487 ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
488 GetLastError());
489 size = sizeof(hashProperty);
490 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
491 hashProperty, &size);
492 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
493 GetLastError());
494 ok(!memcmp(hashProperty, hash, sizeof(hash)), "Unexpected hash\n");
495 /* Delete the (bogus) hash, and get the real one */
496 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID, 0,
497 NULL);
498 ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
499 GetLastError());
500 checkHash(bigCert, sizeof(bigCert), CALG_SHA1, context,
501 CERT_HASH_PROP_ID);
503 /* Now that the hash property is set, we should get one property when
504 * enumerating.
506 propID = 0;
507 numProps = 0;
508 do {
509 propID = CertEnumCertificateContextProperties(context, propID);
510 if (propID)
511 numProps++;
512 } while (propID != 0);
513 ok(numProps == 1, "Expected 1 properties, got %d\n", numProps);
515 /* Check a few other implicit properties */
516 checkHash(bigCert, sizeof(bigCert), CALG_MD5, context,
517 CERT_MD5_HASH_PROP_ID);
519 /* Getting the signature hash fails with this bogus certificate */
520 size = 0;
521 ret = CertGetCertificateContextProperty(context,
522 CERT_SIGNATURE_HASH_PROP_ID, NULL, &size);
523 ok(!ret &&
524 (GetLastError() == CRYPT_E_ASN1_BADTAG ||
525 GetLastError() == CRYPT_E_NOT_FOUND ||
526 GetLastError() == OSS_DATA_ERROR), /* win9x */
527 "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
529 /* Test key contexts and handles and such */
530 size = 0;
531 ret = CertGetCertificateContextProperty(context, CERT_KEY_CONTEXT_PROP_ID,
532 NULL, &size);
533 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
534 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
535 size = sizeof(CERT_KEY_CONTEXT);
536 ret = CertGetCertificateContextProperty(context, CERT_KEY_CONTEXT_PROP_ID,
537 NULL, &size);
538 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
539 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
540 ret = CertGetCertificateContextProperty(context, CERT_KEY_CONTEXT_PROP_ID,
541 &keyContext, &size);
542 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
543 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
544 /* Key context with an invalid size */
545 keyContext.cbSize = 0;
546 ret = CertSetCertificateContextProperty(context, CERT_KEY_CONTEXT_PROP_ID,
547 0, &keyContext);
548 ok(!ret && GetLastError() == E_INVALIDARG,
549 "Expected E_INVALIDARG, got %08x\n", GetLastError());
550 size = sizeof(keyContext);
551 ret = CertGetCertificateContextProperty(context, CERT_KEY_CONTEXT_PROP_ID,
552 &keyContext, &size);
553 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
554 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
555 keyContext.cbSize = sizeof(keyContext);
556 keyContext.hCryptProv = 0;
557 keyContext.dwKeySpec = AT_SIGNATURE;
558 ret = CertSetCertificateContextProperty(context, CERT_KEY_CONTEXT_PROP_ID,
559 0, &keyContext);
560 ok(ret, "CertSetCertificateContextProperty failed: %08x\n", GetLastError());
561 /* Now that that's set, the key prov handle property is also gettable.
563 size = sizeof(keyContext.hCryptProv);
564 ret = CertGetCertificateContextProperty(context,
565 CERT_KEY_PROV_HANDLE_PROP_ID, &keyContext.hCryptProv, &size);
566 ok(ret, "Expected to get the CERT_KEY_PROV_HANDLE_PROP_ID, got %08x\n",
567 GetLastError());
568 /* Remove the key prov handle property.. */
569 ret = CertSetCertificateContextProperty(context,
570 CERT_KEY_PROV_HANDLE_PROP_ID, 0, NULL);
571 ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
572 GetLastError());
573 /* and the key context's CSP is set to NULL. */
574 size = sizeof(keyContext);
575 ret = CertGetCertificateContextProperty(context,
576 CERT_KEY_CONTEXT_PROP_ID, &keyContext, &size);
577 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
578 GetLastError());
579 ok(keyContext.hCryptProv == 0, "Expected no hCryptProv\n");
581 /* According to MSDN the subject key id can be stored as a property,
582 * as a subject key extension, or as the SHA1 hash of the public key,
583 * but this cert has none of them:
585 ret = CertGetCertificateContextProperty(context,
586 CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size);
587 ok(!ret && GetLastError() == ERROR_INVALID_DATA,
588 "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
589 CertFreeCertificateContext(context);
590 /* This cert does have a public key, but its subject key identifier still
591 * isn't available: */
592 context = CertCreateCertificateContext(X509_ASN_ENCODING,
593 v1CertWithPubKey, sizeof(v1CertWithPubKey));
594 ret = CertGetCertificateContextProperty(context,
595 CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size);
596 ok(!ret && GetLastError() == ERROR_INVALID_DATA,
597 "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
598 CertFreeCertificateContext(context);
599 /* This cert with a subject key extension can have its key identifier
600 * property retrieved:
602 context = CertCreateCertificateContext(X509_ASN_ENCODING,
603 v1CertWithSubjectKeyId, sizeof(v1CertWithSubjectKeyId));
604 ret = CertGetCertificateContextProperty(context,
605 CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size);
606 ok(ret, "CertGetCertificateContextProperty failed: %08x\n", GetLastError());
607 if (ret)
609 LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, size);
611 if (buf)
613 ret = CertGetCertificateContextProperty(context,
614 CERT_KEY_IDENTIFIER_PROP_ID, buf, &size);
615 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
616 GetLastError());
617 ok(!memcmp(buf, subjectKeyId, size), "Unexpected subject key id\n");
618 HeapFree(GetProcessHeap(), 0, buf);
621 CertFreeCertificateContext(context);
623 context = CertCreateCertificateContext(X509_ASN_ENCODING,
624 selfSignedCert, sizeof(selfSignedCert));
625 /* Getting the signature hash of a valid (self-signed) cert succeeds */
626 size = 0;
627 ret = CertGetCertificateContextProperty(context,
628 CERT_SIGNATURE_HASH_PROP_ID, NULL, &size);
629 ok(ret, "CertGetCertificateContextProperty failed: %08x\n", GetLastError());
630 ok(size == sizeof(selfSignedSignatureHash), "unexpected size %d\n", size);
631 ret = CertGetCertificateContextProperty(context,
632 CERT_SIGNATURE_HASH_PROP_ID, hashProperty, &size);
633 if (ret)
634 ok(!memcmp(hashProperty, selfSignedSignatureHash, size),
635 "unexpected value\n");
636 CertFreeCertificateContext(context);
639 static void testCreateCert(void)
641 PCCERT_CONTEXT cert, enumCert;
642 DWORD count, size;
643 BOOL ret;
645 SetLastError(0xdeadbeef);
646 cert = CertCreateCertificateContext(0, NULL, 0);
647 ok(!cert && GetLastError() == E_INVALIDARG,
648 "expected E_INVALIDARG, got %08x\n", GetLastError());
649 SetLastError(0xdeadbeef);
650 cert = CertCreateCertificateContext(0, selfSignedCert,
651 sizeof(selfSignedCert));
652 ok(!cert && GetLastError() == E_INVALIDARG,
653 "expected E_INVALIDARG, got %08x\n", GetLastError());
654 SetLastError(0xdeadbeef);
655 cert = CertCreateCertificateContext(X509_ASN_ENCODING, NULL, 0);
656 ok(!cert &&
657 (GetLastError() == CRYPT_E_ASN1_EOD ||
658 broken(GetLastError() == OSS_MORE_INPUT /* NT4 */)),
659 "expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
661 cert = CertCreateCertificateContext(X509_ASN_ENCODING,
662 selfSignedCert, sizeof(selfSignedCert));
663 ok(cert != NULL, "creating cert failed: %08x\n", GetLastError());
664 /* Even in-memory certs are expected to have a store associated with them */
665 ok(cert->hCertStore != NULL, "expected created cert to have a store\n");
666 /* The cert doesn't have the archived property set (which would imply it
667 * doesn't show up in enumerations.)
669 size = 0;
670 ret = CertGetCertificateContextProperty(cert, CERT_ARCHIVED_PROP_ID,
671 NULL, &size);
672 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
673 "expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
674 /* Strangely, enumerating the certs in the store finds none. */
675 enumCert = NULL;
676 count = 0;
677 while ((enumCert = CertEnumCertificatesInStore(cert->hCertStore, enumCert)))
678 count++;
679 ok(!count, "expected 0, got %d\n", count);
680 CertFreeCertificateContext(cert);
683 static void testDupCert(void)
685 PCCERT_CONTEXT context, dupContext, storeContext, storeContext2, context2;
686 HCERTSTORE store, store2;
687 BOOL ret;
689 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
690 CERT_STORE_CREATE_NEW_FLAG, NULL);
691 ok(store != NULL, "CertOpenStore failed: %d\n", GetLastError());
692 if (!store)
693 return;
695 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
696 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
697 ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* win98 */),
698 "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
699 if (!ret && GetLastError() == OSS_DATA_ERROR)
701 skip("bigCert can't be decoded, skipping tests\n");
702 return;
704 ok(context != NULL, "Expected a valid cert context\n");
705 if (context)
707 ok(context->cbCertEncoded == sizeof(bigCert),
708 "Wrong cert size %d\n", context->cbCertEncoded);
709 ok(!memcmp(context->pbCertEncoded, bigCert, sizeof(bigCert)),
710 "Unexpected encoded cert in context\n");
711 ok(context->hCertStore == store, "Unexpected store\n");
713 dupContext = CertDuplicateCertificateContext(context);
714 ok(dupContext != NULL, "Expected valid duplicate\n");
715 /* Not only is it a duplicate, it's identical: the address is the
716 * same.
718 ok(dupContext == context, "Expected identical context addresses\n");
719 CertFreeCertificateContext(dupContext);
720 CertFreeCertificateContext(context);
722 CertCloseStore(store, 0);
724 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert, sizeof(bigCert));
725 ok(context != NULL, "CertCreateCertificateContext failed\n");
727 dupContext = CertDuplicateCertificateContext(context);
728 ok(dupContext == context, "context != dupContext\n");
730 ret = CertFreeCertificateContext(dupContext);
731 ok(ret, "CertFreeCertificateContext failed\n");
733 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL);
734 ok(store != NULL, "CertOpenStore failed: %d\n", GetLastError());
736 ret = CertAddCertificateContextToStore(store, context, CERT_STORE_ADD_NEW, &storeContext);
737 ok(ret, "CertAddCertificateContextToStore failed\n");
738 ok(storeContext != NULL && storeContext != context, "unexpected storeContext\n");
739 ok(storeContext->hCertStore == store, "unexpected hCertStore\n");
741 ok(storeContext->pbCertEncoded != context->pbCertEncoded, "unexpected pbCertEncoded\n");
742 ok(storeContext->cbCertEncoded == context->cbCertEncoded, "unexpected cbCertEncoded\n");
743 ok(storeContext->pCertInfo != context->pCertInfo, "unexpected pCertInfo\n");
745 store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL);
746 ok(store2 != NULL, "CertOpenStore failed: %d\n", GetLastError());
748 ret = CertAddCertificateContextToStore(store2, storeContext, CERT_STORE_ADD_NEW, &storeContext2);
749 ok(ret, "CertAddCertificateContextToStore failed\n");
750 ok(storeContext2 != NULL && storeContext2 != storeContext, "unexpected storeContext\n");
751 ok(storeContext2->hCertStore == store2, "unexpected hCertStore\n");
753 ok(storeContext2->pbCertEncoded != storeContext->pbCertEncoded, "unexpected pbCertEncoded\n");
754 ok(storeContext2->cbCertEncoded == storeContext->cbCertEncoded, "unexpected cbCertEncoded\n");
755 ok(storeContext2->pCertInfo != storeContext->pCertInfo, "unexpected pCertInfo\n");
757 CertFreeCertificateContext(storeContext2);
758 CertFreeCertificateContext(storeContext);
760 context2 = CertCreateCertificateContext(X509_ASN_ENCODING, certWithUsage, sizeof(certWithUsage));
761 ok(context2 != NULL, "CertCreateCertificateContext failed\n");
763 ok(context2->hCertStore == context->hCertStore, "Unexpected hCertStore\n");
765 CertFreeCertificateContext(context2);
766 ret = CertFreeCertificateContext(context);
767 ok(ret, "CertFreeCertificateContext failed\n");
769 CertCloseStore(store, 0);
770 CertCloseStore(store2, 0);
772 SetLastError(0xdeadbeef);
773 context = CertDuplicateCertificateContext(NULL);
774 ok(context == NULL, "Expected context to be NULL\n");
776 ret = CertFreeCertificateContext(NULL);
777 ok(ret, "CertFreeCertificateContext failed\n");
780 static void testLinkCert(void)
782 const CERT_CONTEXT *context, *link;
783 HCERTSTORE store;
784 BOOL ret;
786 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert, sizeof(bigCert));
787 ok(context != NULL, "CertCreateCertificateContext failed\n");
789 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL);
790 ok(store != NULL, "CertOpenStore failed: %d\n", GetLastError());
792 ret = CertAddCertificateLinkToStore(store, context, CERT_STORE_ADD_NEW, &link);
793 ok(ret, "CertAddCertificateContextToStore failed\n");
794 ok(link != NULL && link != context, "unexpected storeContext\n");
795 ok(link->hCertStore == store, "unexpected hCertStore\n");
797 ok(link->pbCertEncoded == context->pbCertEncoded, "unexpected pbCertEncoded\n");
798 ok(link->cbCertEncoded == context->cbCertEncoded, "unexpected cbCertEncoded\n");
799 ok(link->pCertInfo == context->pCertInfo, "unexpected pCertInfo\n");
801 CertFreeCertificateContext(link);
802 CertFreeCertificateContext(context);
803 CertCloseStore(store, 0);
806 static BYTE subjectName3[] = { 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
807 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x52, 0x6f, 0x62, 0x20, 0x20, 0x4c, 0x61,
808 0x6e, 0x67, 0x00 };
809 static const BYTE iTunesCert0[] = {
810 0x30,0x82,0x03,0xc4,0x30,0x82,0x03,0x2d,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,
811 0x47,0xbf,0x19,0x95,0xdf,0x8d,0x52,0x46,0x43,0xf7,0xdb,0x6d,0x48,0x0d,0x31,
812 0xa4,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,
813 0x00,0x30,0x81,0x8b,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,
814 0x5a,0x41,0x31,0x15,0x30,0x13,0x06,0x03,0x55,0x04,0x08,0x13,0x0c,0x57,0x65,
815 0x73,0x74,0x65,0x72,0x6e,0x20,0x43,0x61,0x70,0x65,0x31,0x14,0x30,0x12,0x06,
816 0x03,0x55,0x04,0x07,0x13,0x0b,0x44,0x75,0x72,0x62,0x61,0x6e,0x76,0x69,0x6c,
817 0x6c,0x65,0x31,0x0f,0x30,0x0d,0x06,0x03,0x55,0x04,0x0a,0x13,0x06,0x54,0x68,
818 0x61,0x77,0x74,0x65,0x31,0x1d,0x30,0x1b,0x06,0x03,0x55,0x04,0x0b,0x13,0x14,
819 0x54,0x68,0x61,0x77,0x74,0x65,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,
820 0x61,0x74,0x69,0x6f,0x6e,0x31,0x1f,0x30,0x1d,0x06,0x03,0x55,0x04,0x03,0x13,
821 0x16,0x54,0x68,0x61,0x77,0x74,0x65,0x20,0x54,0x69,0x6d,0x65,0x73,0x74,0x61,
822 0x6d,0x70,0x69,0x6e,0x67,0x20,0x43,0x41,0x30,0x1e,0x17,0x0d,0x30,0x33,0x31,
823 0x32,0x30,0x34,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,0x31,0x33,0x31,
824 0x32,0x30,0x33,0x32,0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x53,0x31,0x0b,0x30,
825 0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x17,0x30,0x15,0x06,
826 0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x2c,
827 0x20,0x49,0x6e,0x63,0x2e,0x31,0x2b,0x30,0x29,0x06,0x03,0x55,0x04,0x03,0x13,
828 0x22,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x54,0x69,0x6d,0x65,0x20,
829 0x53,0x74,0x61,0x6d,0x70,0x69,0x6e,0x67,0x20,0x53,0x65,0x72,0x76,0x69,0x63,
830 0x65,0x73,0x20,0x43,0x41,0x30,0x82,0x01,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,
831 0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0f,0x00,0x30,
832 0x82,0x01,0x0a,0x02,0x82,0x01,0x01,0x00,0xa9,0xca,0xb2,0xa4,0xcc,0xcd,0x20,
833 0xaf,0x0a,0x7d,0x89,0xac,0x87,0x75,0xf0,0xb4,0x4e,0xf1,0xdf,0xc1,0x0f,0xbf,
834 0x67,0x61,0xbd,0xa3,0x64,0x1c,0xda,0xbb,0xf9,0xca,0x33,0xab,0x84,0x30,0x89,
835 0x58,0x7e,0x8c,0xdb,0x6b,0xdd,0x36,0x9e,0x0f,0xbf,0xd1,0xec,0x78,0xf2,0x77,
836 0xa6,0x7e,0x6f,0x3c,0xbf,0x93,0xaf,0x0d,0xba,0x68,0xf4,0x6c,0x94,0xca,0xbd,
837 0x52,0x2d,0xab,0x48,0x3d,0xf5,0xb6,0xd5,0x5d,0x5f,0x1b,0x02,0x9f,0xfa,0x2f,
838 0x6b,0x1e,0xa4,0xf7,0xa3,0x9a,0xa6,0x1a,0xc8,0x02,0xe1,0x7f,0x4c,0x52,0xe3,
839 0x0e,0x60,0xec,0x40,0x1c,0x7e,0xb9,0x0d,0xde,0x3f,0xc7,0xb4,0xdf,0x87,0xbd,
840 0x5f,0x7a,0x6a,0x31,0x2e,0x03,0x99,0x81,0x13,0xa8,0x47,0x20,0xce,0x31,0x73,
841 0x0d,0x57,0x2d,0xcd,0x78,0x34,0x33,0x95,0x12,0x99,0x12,0xb9,0xde,0x68,0x2f,
842 0xaa,0xe6,0xe3,0xc2,0x8a,0x8c,0x2a,0xc3,0x8b,0x21,0x87,0x66,0xbd,0x83,0x58,
843 0x57,0x6f,0x75,0xbf,0x3c,0xaa,0x26,0x87,0x5d,0xca,0x10,0x15,0x3c,0x9f,0x84,
844 0xea,0x54,0xc1,0x0a,0x6e,0xc4,0xfe,0xc5,0x4a,0xdd,0xb9,0x07,0x11,0x97,0x22,
845 0x7c,0xdb,0x3e,0x27,0xd1,0x1e,0x78,0xec,0x9f,0x31,0xc9,0xf1,0xe6,0x22,0x19,
846 0xdb,0xc4,0xb3,0x47,0x43,0x9a,0x1a,0x5f,0xa0,0x1e,0x90,0xe4,0x5e,0xf5,0xee,
847 0x7c,0xf1,0x7d,0xab,0x62,0x01,0x8f,0xf5,0x4d,0x0b,0xde,0xd0,0x22,0x56,0xa8,
848 0x95,0xcd,0xae,0x88,0x76,0xae,0xee,0xba,0x0d,0xf3,0xe4,0x4d,0xd9,0xa0,0xfb,
849 0x68,0xa0,0xae,0x14,0x3b,0xb3,0x87,0xc1,0xbb,0x02,0x03,0x01,0x00,0x01,0xa3,
850 0x81,0xdb,0x30,0x81,0xd8,0x30,0x34,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,
851 0x01,0x01,0x04,0x28,0x30,0x26,0x30,0x24,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,
852 0x07,0x30,0x01,0x86,0x18,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6f,0x63,0x73,
853 0x70,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x30,
854 0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,
855 0xff,0x02,0x01,0x00,0x30,0x41,0x06,0x03,0x55,0x1d,0x1f,0x04,0x3a,0x30,0x38,
856 0x30,0x36,0xa0,0x34,0xa0,0x32,0x86,0x30,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
857 0x63,0x72,0x6c,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,
858 0x6d,0x2f,0x54,0x68,0x61,0x77,0x74,0x65,0x54,0x69,0x6d,0x65,0x73,0x74,0x61,
859 0x6d,0x70,0x69,0x6e,0x67,0x43,0x41,0x2e,0x63,0x72,0x6c,0x30,0x13,0x06,0x03,
860 0x55,0x1d,0x25,0x04,0x0c,0x30,0x0a,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,
861 0x03,0x08,0x30,0x0e,0x06,0x03,0x55,0x1d,0x0f,0x01,0x01,0xff,0x04,0x04,0x03,
862 0x02,0x01,0x06,0x30,0x24,0x06,0x03,0x55,0x1d,0x11,0x04,0x1d,0x30,0x1b,0xa4,
863 0x19,0x30,0x17,0x31,0x15,0x30,0x13,0x06,0x03,0x55,0x04,0x03,0x13,0x0c,0x54,
864 0x53,0x41,0x32,0x30,0x34,0x38,0x2d,0x31,0x2d,0x35,0x33,0x30,0x0d,0x06,0x09,
865 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x03,0x81,0x81,0x00,
866 0x4a,0x6b,0xf9,0xea,0x58,0xc2,0x44,0x1c,0x31,0x89,0x79,0x99,0x2b,0x96,0xbf,
867 0x82,0xac,0x01,0xd6,0x1c,0x4c,0xcd,0xb0,0x8a,0x58,0x6e,0xdf,0x08,0x29,0xa3,
868 0x5e,0xc8,0xca,0x93,0x13,0xe7,0x04,0x52,0x0d,0xef,0x47,0x27,0x2f,0x00,0x38,
869 0xb0,0xe4,0xc9,0x93,0x4e,0x9a,0xd4,0x22,0x62,0x15,0xf7,0x3f,0x37,0x21,0x4f,
870 0x70,0x31,0x80,0xf1,0x8b,0x38,0x87,0xb3,0xe8,0xe8,0x97,0x00,0xfe,0xcf,0x55,
871 0x96,0x4e,0x24,0xd2,0xa9,0x27,0x4e,0x7a,0xae,0xb7,0x61,0x41,0xf3,0x2a,0xce,
872 0xe7,0xc9,0xd9,0x5e,0xdd,0xbb,0x2b,0x85,0x3e,0xb5,0x9d,0xb5,0xd9,0xe1,0x57,
873 0xff,0xbe,0xb4,0xc5,0x7e,0xf5,0xcf,0x0c,0x9e,0xf0,0x97,0xfe,0x2b,0xd3,0x3b,
874 0x52,0x1b,0x1b,0x38,0x27,0xf7,0x3f,0x4a };
875 static const BYTE iTunesCert1[] = {
876 0x30,0x82,0x03,0xff,0x30,0x82,0x02,0xe7,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,
877 0x0d,0xe9,0x2b,0xf0,0xd4,0xd8,0x29,0x88,0x18,0x32,0x05,0x09,0x5e,0x9a,0x76,
878 0x88,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,
879 0x00,0x30,0x53,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,
880 0x53,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,
881 0x69,0x53,0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x2b,0x30,0x29,
882 0x06,0x03,0x55,0x04,0x03,0x13,0x22,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,
883 0x20,0x54,0x69,0x6d,0x65,0x20,0x53,0x74,0x61,0x6d,0x70,0x69,0x6e,0x67,0x20,
884 0x53,0x65,0x72,0x76,0x69,0x63,0x65,0x73,0x20,0x43,0x41,0x30,0x1e,0x17,0x0d,
885 0x30,0x33,0x31,0x32,0x30,0x34,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,
886 0x30,0x38,0x31,0x32,0x30,0x33,0x32,0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x57,
887 0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x17,
888 0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,0x69,
889 0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x2f,0x30,0x2d,0x06,0x03,0x55,
890 0x04,0x03,0x13,0x26,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x54,0x69,
891 0x6d,0x65,0x20,0x53,0x74,0x61,0x6d,0x70,0x69,0x6e,0x67,0x20,0x53,0x65,0x72,
892 0x76,0x69,0x63,0x65,0x73,0x20,0x53,0x69,0x67,0x6e,0x65,0x72,0x30,0x82,0x01,
893 0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,
894 0x00,0x03,0x82,0x01,0x0f,0x00,0x30,0x82,0x01,0x0a,0x02,0x82,0x01,0x01,0x00,
895 0xb2,0x50,0x28,0x48,0xdd,0xd3,0x68,0x7a,0x84,0x18,0x44,0x66,0x75,0x5d,0x7e,
896 0xc4,0xb8,0x9f,0x63,0x26,0xff,0x3d,0x43,0x9c,0x7c,0x11,0x38,0x10,0x25,0x55,
897 0x73,0xd9,0x75,0x27,0x69,0xfd,0x4e,0xb9,0x20,0x5c,0xd3,0x0a,0xf9,0xa0,0x1b,
898 0x2a,0xed,0x55,0x56,0x21,0x61,0xd8,0x1e,0xdb,0xe4,0xbc,0x33,0x6b,0xc7,0xef,
899 0xdd,0xa3,0x37,0x65,0x8e,0x1b,0x93,0x0c,0xb6,0x53,0x1e,0x5c,0x7c,0x66,0x35,
900 0x5f,0x05,0x8a,0x45,0xfe,0x76,0x4e,0xdf,0x53,0x80,0xa2,0x81,0x20,0x9d,0xae,
901 0x88,0x5c,0xa2,0x08,0xf7,0xe5,0x30,0xf9,0xee,0x22,0x37,0x4c,0x42,0x0a,0xce,
902 0xdf,0xc6,0x1f,0xc4,0xd6,0x55,0xe9,0x81,0x3f,0xb5,0x52,0xa3,0x2c,0xaa,0x01,
903 0x7a,0xf2,0xa2,0xaa,0x8d,0x35,0xfe,0x9f,0xe6,0x5d,0x6a,0x05,0x9f,0x3d,0x6b,
904 0xe3,0xbf,0x96,0xc0,0xfe,0xcc,0x60,0xf9,0x40,0xe7,0x07,0xa0,0x44,0xeb,0x81,
905 0x51,0x6e,0xa5,0x2a,0xf2,0xb6,0x8a,0x10,0x28,0xed,0x8f,0xdc,0x06,0xa0,0x86,
906 0x50,0x9a,0x7b,0x4a,0x08,0x0d,0x30,0x1d,0xca,0x10,0x9e,0x6b,0xf7,0xe9,0x58,
907 0xae,0x04,0xa9,0x40,0x99,0xb2,0x28,0xe8,0x8f,0x16,0xac,0x3c,0xe3,0x53,0x6f,
908 0x4b,0xd3,0x35,0x9d,0xb5,0x6f,0x64,0x1d,0xb3,0x96,0x2c,0xbb,0x3d,0xe7,0x79,
909 0xeb,0x6d,0x7a,0xf9,0x16,0xe6,0x26,0xad,0xaf,0xef,0x99,0x53,0xb7,0x40,0x2c,
910 0x95,0xb8,0x79,0xaa,0xfe,0xd4,0x52,0xab,0x29,0x74,0x7e,0x42,0xec,0x39,0x1e,
911 0xa2,0x6a,0x16,0xe6,0x59,0xbb,0x24,0x68,0xd8,0x00,0x80,0x43,0x10,0x87,0x80,
912 0x6b,0x02,0x03,0x01,0x00,0x01,0xa3,0x81,0xca,0x30,0x81,0xc7,0x30,0x34,0x06,
913 0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x28,0x30,0x26,0x30,0x24,
914 0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x18,0x68,0x74,0x74,
915 0x70,0x3a,0x2f,0x2f,0x6f,0x63,0x73,0x70,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,
916 0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x30,0x0c,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
917 0xff,0x04,0x02,0x30,0x00,0x30,0x33,0x06,0x03,0x55,0x1d,0x1f,0x04,0x2c,0x30,
918 0x2a,0x30,0x28,0xa0,0x26,0xa0,0x24,0x86,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,
919 0x2f,0x63,0x72,0x6c,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,
920 0x6f,0x6d,0x2f,0x74,0x73,0x73,0x2d,0x63,0x61,0x2e,0x63,0x72,0x6c,0x30,0x16,
921 0x06,0x03,0x55,0x1d,0x25,0x01,0x01,0xff,0x04,0x0c,0x30,0x0a,0x06,0x08,0x2b,
922 0x06,0x01,0x05,0x05,0x07,0x03,0x08,0x30,0x0e,0x06,0x03,0x55,0x1d,0x0f,0x01,
923 0x01,0xff,0x04,0x04,0x03,0x02,0x06,0xc0,0x30,0x24,0x06,0x03,0x55,0x1d,0x11,
924 0x04,0x1d,0x30,0x1b,0xa4,0x19,0x30,0x17,0x31,0x15,0x30,0x13,0x06,0x03,0x55,
925 0x04,0x03,0x13,0x0c,0x54,0x53,0x41,0x32,0x30,0x34,0x38,0x2d,0x31,0x2d,0x35,
926 0x34,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,
927 0x00,0x03,0x82,0x01,0x01,0x00,0x87,0x78,0x70,0xda,0x4e,0x52,0x01,0x20,0x5b,
928 0xe0,0x79,0xc9,0x82,0x30,0xc4,0xfd,0xb9,0x19,0x96,0xbd,0x91,0x00,0xc3,0xbd,
929 0xcd,0xcd,0xc6,0xf4,0x0e,0xd8,0xff,0xf9,0x4d,0xc0,0x33,0x62,0x30,0x11,0xc5,
930 0xf5,0x74,0x1b,0xd4,0x92,0xde,0x5f,0x9c,0x20,0x13,0xb1,0x7c,0x45,0xbe,0x50,
931 0xcd,0x83,0xe7,0x80,0x17,0x83,0xa7,0x27,0x93,0x67,0x13,0x46,0xfb,0xca,0xb8,
932 0x98,0x41,0x03,0xcc,0x9b,0x51,0x5b,0x05,0x8b,0x7f,0xa8,0x6f,0xf3,0x1b,0x50,
933 0x1b,0x24,0x2e,0xf2,0x69,0x8d,0x6c,0x22,0xf7,0xbb,0xca,0x16,0x95,0xed,0x0c,
934 0x74,0xc0,0x68,0x77,0xd9,0xeb,0x99,0x62,0x87,0xc1,0x73,0x90,0xf8,0x89,0x74,
935 0x7a,0x23,0xab,0xa3,0x98,0x7b,0x97,0xb1,0xf7,0x8f,0x29,0x71,0x4d,0x2e,0x75,
936 0x1b,0x48,0x41,0xda,0xf0,0xb5,0x0d,0x20,0x54,0xd6,0x77,0xa0,0x97,0x82,0x63,
937 0x69,0xfd,0x09,0xcf,0x8a,0xf0,0x75,0xbb,0x09,0x9b,0xd9,0xf9,0x11,0x55,0x26,
938 0x9a,0x61,0x32,0xbe,0x7a,0x02,0xb0,0x7b,0x86,0xbe,0xa2,0xc3,0x8b,0x22,0x2c,
939 0x78,0xd1,0x35,0x76,0xbc,0x92,0x73,0x5c,0xf9,0xb9,0xe6,0x4c,0x15,0x0a,0x23,
940 0xcc,0xe4,0xd2,0xd4,0x34,0x2e,0x49,0x40,0x15,0x3c,0x0f,0x60,0x7a,0x24,0xc6,
941 0xa5,0x66,0xef,0x96,0xcf,0x70,0xeb,0x3e,0xe7,0xf4,0x0d,0x7e,0xdc,0xd1,0x7c,
942 0xa3,0x76,0x71,0x69,0xc1,0x9c,0x4f,0x47,0x30,0x35,0x21,0xb1,0xa2,0xaf,0x1a,
943 0x62,0x3c,0x2b,0xd9,0x8e,0xaa,0x2a,0x07,0x7b,0xd8,0x18,0xb3,0x5c,0x7b,0xe2,
944 0x9d,0xa5,0x6f,0xfe,0x3c,0x89,0xad };
945 static const BYTE iTunesCert2[] = {
946 0x30,0x82,0x04,0xbf,0x30,0x82,0x04,0x28,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,
947 0x41,0x91,0xa1,0x5a,0x39,0x78,0xdf,0xcf,0x49,0x65,0x66,0x38,0x1d,0x4c,0x75,
948 0xc2,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,
949 0x00,0x30,0x5f,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,
950 0x53,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,
951 0x69,0x53,0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x37,0x30,0x35,
952 0x06,0x03,0x55,0x04,0x0b,0x13,0x2e,0x43,0x6c,0x61,0x73,0x73,0x20,0x33,0x20,
953 0x50,0x75,0x62,0x6c,0x69,0x63,0x20,0x50,0x72,0x69,0x6d,0x61,0x72,0x79,0x20,
954 0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x41,
955 0x75,0x74,0x68,0x6f,0x72,0x69,0x74,0x79,0x30,0x1e,0x17,0x0d,0x30,0x34,0x30,
956 0x37,0x31,0x36,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,0x31,0x34,0x30,
957 0x37,0x31,0x35,0x32,0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x81,0xb4,0x31,0x0b,
958 0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x17,0x30,0x15,
959 0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,
960 0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x1f,0x30,0x1d,0x06,0x03,0x55,0x04,0x0b,
961 0x13,0x16,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x54,0x72,0x75,0x73,
962 0x74,0x20,0x4e,0x65,0x74,0x77,0x6f,0x72,0x6b,0x31,0x3b,0x30,0x39,0x06,0x03,
963 0x55,0x04,0x0b,0x13,0x32,0x54,0x65,0x72,0x6d,0x73,0x20,0x6f,0x66,0x20,0x75,
964 0x73,0x65,0x20,0x61,0x74,0x20,0x68,0x74,0x74,0x70,0x73,0x3a,0x2f,0x2f,0x77,
965 0x77,0x77,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,
966 0x2f,0x72,0x70,0x61,0x20,0x28,0x63,0x29,0x30,0x34,0x31,0x2e,0x30,0x2c,0x06,
967 0x03,0x55,0x04,0x03,0x13,0x25,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,
968 0x43,0x6c,0x61,0x73,0x73,0x20,0x33,0x20,0x43,0x6f,0x64,0x65,0x20,0x53,0x69,
969 0x67,0x6e,0x69,0x6e,0x67,0x20,0x32,0x30,0x30,0x34,0x20,0x43,0x41,0x30,0x82,
970 0x01,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,
971 0x05,0x00,0x03,0x82,0x01,0x0f,0x00,0x30,0x82,0x01,0x0a,0x02,0x82,0x01,0x01,
972 0x00,0xbe,0xbc,0xee,0xbc,0x7e,0xef,0x83,0xeb,0xe0,0x37,0x4f,0xfb,0x03,0x10,
973 0x38,0xbe,0x08,0xd2,0x8c,0x7d,0x9d,0xfa,0x92,0x7f,0x19,0x0c,0xc2,0x6b,0xee,
974 0x42,0x52,0x8c,0xde,0xd3,0x1c,0x48,0x13,0x25,0xea,0xc1,0x63,0x7a,0xf9,0x51,
975 0x65,0xee,0xd3,0xaa,0x3b,0xf5,0xf0,0x94,0x9c,0x2b,0xfb,0xf2,0x66,0xd4,0x24,
976 0xda,0xf7,0xf5,0x9f,0x6e,0x19,0x39,0x36,0xbc,0xd0,0xa3,0x76,0x08,0x1e,0x22,
977 0x27,0x24,0x6c,0x38,0x91,0x27,0xe2,0x84,0x49,0xae,0x1b,0x8a,0xa1,0xfd,0x25,
978 0x82,0x2c,0x10,0x30,0xe8,0x71,0xab,0x28,0xe8,0x77,0x4a,0x51,0xf1,0xec,0xcd,
979 0xf8,0xf0,0x54,0xd4,0x6f,0xc0,0xe3,0x6d,0x0a,0x8f,0xd9,0xd8,0x64,0x8d,0x63,
980 0xb2,0x2d,0x4e,0x27,0xf6,0x85,0x0e,0xfe,0x6d,0xe3,0x29,0x99,0xe2,0x85,0x47,
981 0x7c,0x2d,0x86,0x7f,0xe8,0x57,0x8f,0xad,0x67,0xc2,0x33,0x32,0x91,0x13,0x20,
982 0xfc,0xa9,0x23,0x14,0x9a,0x6d,0xc2,0x84,0x4b,0x76,0x68,0x04,0xd5,0x71,0x2c,
983 0x5d,0x21,0xfa,0x88,0x0d,0x26,0xfd,0x1f,0x2d,0x91,0x2b,0xe7,0x01,0x55,0x4d,
984 0xf2,0x6d,0x35,0x28,0x82,0xdf,0xd9,0x6b,0x5c,0xb6,0xd6,0xd9,0xaa,0x81,0xfd,
985 0x5f,0xcd,0x83,0xba,0x63,0x9d,0xd0,0x22,0xfc,0xa9,0x3b,0x42,0x69,0xb2,0x8e,
986 0x3a,0xb5,0xbc,0xb4,0x9e,0x0f,0x5e,0xc4,0xea,0x2c,0x82,0x8b,0x28,0xfd,0x53,
987 0x08,0x96,0xdd,0xb5,0x01,0x20,0xd1,0xf9,0xa5,0x18,0xe7,0xc0,0xee,0x51,0x70,
988 0x37,0xe1,0xb6,0x05,0x48,0x52,0x48,0x6f,0x38,0xea,0xc3,0xe8,0x6c,0x7b,0x44,
989 0x84,0xbb,0x02,0x03,0x01,0x00,0x01,0xa3,0x82,0x01,0xa0,0x30,0x82,0x01,0x9c,
990 0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,
991 0x01,0xff,0x02,0x01,0x00,0x30,0x44,0x06,0x03,0x55,0x1d,0x20,0x04,0x3d,0x30,
992 0x3b,0x30,0x39,0x06,0x0b,0x60,0x86,0x48,0x01,0x86,0xf8,0x45,0x01,0x07,0x17,
993 0x03,0x30,0x2a,0x30,0x28,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x02,0x01,
994 0x16,0x1c,0x68,0x74,0x74,0x70,0x73,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x76,
995 0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x2f,0x72,0x70,0x61,
996 0x30,0x31,0x06,0x03,0x55,0x1d,0x1f,0x04,0x2a,0x30,0x28,0x30,0x26,0xa0,0x24,
997 0xa0,0x22,0x86,0x20,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x63,0x72,0x6c,0x2e,
998 0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x2f,0x70,0x63,
999 0x61,0x33,0x2e,0x63,0x72,0x6c,0x30,0x1d,0x06,0x03,0x55,0x1d,0x25,0x04,0x16,
1000 0x30,0x14,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x03,0x02,0x06,0x08,0x2b,
1001 0x06,0x01,0x05,0x05,0x07,0x03,0x03,0x30,0x0e,0x06,0x03,0x55,0x1d,0x0f,0x01,
1002 0x01,0xff,0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x11,0x06,0x09,0x60,0x86,0x48,
1003 0x01,0x86,0xf8,0x42,0x01,0x01,0x04,0x04,0x03,0x02,0x00,0x01,0x30,0x29,0x06,
1004 0x03,0x55,0x1d,0x11,0x04,0x22,0x30,0x20,0xa4,0x1e,0x30,0x1c,0x31,0x1a,0x30,
1005 0x18,0x06,0x03,0x55,0x04,0x03,0x13,0x11,0x43,0x6c,0x61,0x73,0x73,0x33,0x43,
1006 0x41,0x32,0x30,0x34,0x38,0x2d,0x31,0x2d,0x34,0x33,0x30,0x1d,0x06,0x03,0x55,
1007 0x1d,0x0e,0x04,0x16,0x04,0x14,0x08,0xf5,0x51,0xe8,0xfb,0xfe,0x3d,0x3d,0x64,
1008 0x36,0x7c,0x68,0xcf,0x5b,0x78,0xa8,0xdf,0xb9,0xc5,0x37,0x30,0x81,0x80,0x06,
1009 0x03,0x55,0x1d,0x23,0x04,0x79,0x30,0x77,0xa1,0x63,0xa4,0x61,0x30,0x5f,0x31,
1010 0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x17,0x30,
1011 0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,0x69,0x67,
1012 0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x37,0x30,0x35,0x06,0x03,0x55,0x04,
1013 0x0b,0x13,0x2e,0x43,0x6c,0x61,0x73,0x73,0x20,0x33,0x20,0x50,0x75,0x62,0x6c,
1014 0x69,0x63,0x20,0x50,0x72,0x69,0x6d,0x61,0x72,0x79,0x20,0x43,0x65,0x72,0x74,
1015 0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x41,0x75,0x74,0x68,0x6f,
1016 0x72,0x69,0x74,0x79,0x82,0x10,0x70,0xba,0xe4,0x1d,0x10,0xd9,0x29,0x34,0xb6,
1017 0x38,0xca,0x7b,0x03,0xcc,0xba,0xbf,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,
1018 0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x03,0x81,0x81,0x00,0xae,0x3a,0x17,0xb8,
1019 0x4a,0x7b,0x55,0xfa,0x64,0x55,0xec,0x40,0xa4,0xed,0x49,0x41,0x90,0x99,0x9c,
1020 0x89,0xbc,0xaf,0x2e,0x1d,0xca,0x78,0x23,0xf9,0x1c,0x19,0x0f,0x7f,0xeb,0x68,
1021 0xbc,0x32,0xd9,0x88,0x38,0xde,0xdc,0x3f,0xd3,0x89,0xb4,0x3f,0xb1,0x82,0x96,
1022 0xf1,0xa4,0x5a,0xba,0xed,0x2e,0x26,0xd3,0xde,0x7c,0x01,0x6e,0x00,0x0a,0x00,
1023 0xa4,0x06,0x92,0x11,0x48,0x09,0x40,0xf9,0x1c,0x18,0x79,0x67,0x23,0x24,0xe0,
1024 0xbb,0xd5,0xe1,0x50,0xae,0x1b,0xf5,0x0e,0xdd,0xe0,0x2e,0x81,0xcd,0x80,0xa3,
1025 0x6c,0x52,0x4f,0x91,0x75,0x55,0x8a,0xba,0x22,0xf2,0xd2,0xea,0x41,0x75,0x88,
1026 0x2f,0x63,0x55,0x7d,0x1e,0x54,0x5a,0x95,0x59,0xca,0xd9,0x34,0x81,0xc0,0x5f,
1027 0x5e,0xf6,0x7a,0xb5 };
1028 static const BYTE iTunesCert3[] = {
1029 0x30,0x82,0x04,0xf1,0x30,0x82,0x03,0xd9,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,
1030 0x0f,0x1a,0xa0,0xe0,0x9b,0x9b,0x61,0xa6,0xb6,0xfe,0x40,0xd2,0xdf,0x6a,0xf6,
1031 0x8d,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,
1032 0x00,0x30,0x81,0xb4,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,
1033 0x55,0x53,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,
1034 0x72,0x69,0x53,0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x1f,0x30,
1035 0x1d,0x06,0x03,0x55,0x04,0x0b,0x13,0x16,0x56,0x65,0x72,0x69,0x53,0x69,0x67,
1036 0x6e,0x20,0x54,0x72,0x75,0x73,0x74,0x20,0x4e,0x65,0x74,0x77,0x6f,0x72,0x6b,
1037 0x31,0x3b,0x30,0x39,0x06,0x03,0x55,0x04,0x0b,0x13,0x32,0x54,0x65,0x72,0x6d,
1038 0x73,0x20,0x6f,0x66,0x20,0x75,0x73,0x65,0x20,0x61,0x74,0x20,0x68,0x74,0x74,
1039 0x70,0x73,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,
1040 0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x2f,0x72,0x70,0x61,0x20,0x28,0x63,0x29,0x30,
1041 0x34,0x31,0x2e,0x30,0x2c,0x06,0x03,0x55,0x04,0x03,0x13,0x25,0x56,0x65,0x72,
1042 0x69,0x53,0x69,0x67,0x6e,0x20,0x43,0x6c,0x61,0x73,0x73,0x20,0x33,0x20,0x43,
1043 0x6f,0x64,0x65,0x20,0x53,0x69,0x67,0x6e,0x69,0x6e,0x67,0x20,0x32,0x30,0x30,
1044 0x34,0x20,0x43,0x41,0x30,0x1e,0x17,0x0d,0x30,0x36,0x30,0x31,0x31,0x37,0x30,
1045 0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,0x30,0x38,0x30,0x31,0x32,0x32,0x32,
1046 0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x81,0xb4,0x31,0x0b,0x30,0x09,0x06,0x03,
1047 0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,
1048 0x08,0x13,0x0a,0x43,0x61,0x6c,0x69,0x66,0x6f,0x72,0x6e,0x69,0x61,0x31,0x12,
1049 0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x13,0x09,0x43,0x75,0x70,0x65,0x72,0x74,
1050 0x69,0x6e,0x6f,0x31,0x1d,0x30,0x1b,0x06,0x03,0x55,0x04,0x0a,0x14,0x14,0x41,
1051 0x70,0x70,0x6c,0x65,0x20,0x43,0x6f,0x6d,0x70,0x75,0x74,0x65,0x72,0x2c,0x20,
1052 0x49,0x6e,0x63,0x2e,0x31,0x3e,0x30,0x3c,0x06,0x03,0x55,0x04,0x0b,0x13,0x35,
1053 0x44,0x69,0x67,0x69,0x74,0x61,0x6c,0x20,0x49,0x44,0x20,0x43,0x6c,0x61,0x73,
1054 0x73,0x20,0x33,0x20,0x2d,0x20,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,
1055 0x20,0x53,0x6f,0x66,0x74,0x77,0x61,0x72,0x65,0x20,0x56,0x61,0x6c,0x69,0x64,
1056 0x61,0x74,0x69,0x6f,0x6e,0x20,0x76,0x32,0x31,0x1d,0x30,0x1b,0x06,0x03,0x55,
1057 0x04,0x03,0x14,0x14,0x41,0x70,0x70,0x6c,0x65,0x20,0x43,0x6f,0x6d,0x70,0x75,
1058 0x74,0x65,0x72,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x30,0x81,0x9f,0x30,0x0d,0x06,
1059 0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x81,0x8d,
1060 0x00,0x30,0x81,0x89,0x02,0x81,0x81,0x00,0xd3,0xab,0x3b,0x7f,0xec,0x48,0x84,
1061 0xce,0xa8,0x1a,0x12,0xf3,0x3c,0x87,0xcb,0x24,0x58,0x96,0x02,0x87,0x66,0x49,
1062 0xeb,0x89,0xee,0x79,0x44,0x70,0x8d,0xe7,0xd4,0x1f,0x30,0x92,0xc0,0x9c,0x35,
1063 0x78,0xc0,0xaf,0x1c,0xb6,0x28,0xd3,0xe0,0xe0,0x9d,0xd3,0x49,0x76,0x73,0x57,
1064 0x19,0x4d,0x8d,0x70,0x85,0x64,0x4d,0x1d,0xc6,0x02,0x3e,0xe5,0x2c,0x66,0x07,
1065 0xd2,0x27,0x4b,0xd6,0xc8,0x3c,0x93,0xb6,0x15,0x0c,0xde,0x5b,0xd7,0x93,0xdd,
1066 0xbe,0x85,0x62,0x34,0x17,0x8a,0x05,0x60,0xf0,0x8a,0x1c,0x5a,0x40,0x21,0x8d,
1067 0x51,0x6c,0xb0,0x62,0xd8,0xb5,0xd4,0xf9,0xb1,0xd0,0x58,0x7a,0x7a,0x82,0x55,
1068 0xb3,0xf9,0x53,0x71,0xde,0xd2,0xc9,0x37,0x8c,0xf6,0x5a,0x1f,0x2d,0xcd,0x7c,
1069 0x67,0x02,0x03,0x01,0x00,0x01,0xa3,0x82,0x01,0x7f,0x30,0x82,0x01,0x7b,0x30,
1070 0x09,0x06,0x03,0x55,0x1d,0x13,0x04,0x02,0x30,0x00,0x30,0x0e,0x06,0x03,0x55,
1071 0x1d,0x0f,0x01,0x01,0xff,0x04,0x04,0x03,0x02,0x07,0x80,0x30,0x40,0x06,0x03,
1072 0x55,0x1d,0x1f,0x04,0x39,0x30,0x37,0x30,0x35,0xa0,0x33,0xa0,0x31,0x86,0x2f,
1073 0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x43,0x53,0x43,0x33,0x2d,0x32,0x30,0x30,
1074 0x34,0x2d,0x63,0x72,0x6c,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,
1075 0x63,0x6f,0x6d,0x2f,0x43,0x53,0x43,0x33,0x2d,0x32,0x30,0x30,0x34,0x2e,0x63,
1076 0x72,0x6c,0x30,0x44,0x06,0x03,0x55,0x1d,0x20,0x04,0x3d,0x30,0x3b,0x30,0x39,
1077 0x06,0x0b,0x60,0x86,0x48,0x01,0x86,0xf8,0x45,0x01,0x07,0x17,0x03,0x30,0x2a,
1078 0x30,0x28,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x1c,0x68,
1079 0x74,0x74,0x70,0x73,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x76,0x65,0x72,0x69,
1080 0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x2f,0x72,0x70,0x61,0x30,0x13,0x06,
1081 0x03,0x55,0x1d,0x25,0x04,0x0c,0x30,0x0a,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,
1082 0x07,0x03,0x03,0x30,0x75,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x01,0x01,
1083 0x04,0x69,0x30,0x67,0x30,0x24,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,
1084 0x01,0x86,0x18,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6f,0x63,0x73,0x70,0x2e,
1085 0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x30,0x3f,0x06,
1086 0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x33,0x68,0x74,0x74,0x70,
1087 0x3a,0x2f,0x2f,0x43,0x53,0x43,0x33,0x2d,0x32,0x30,0x30,0x34,0x2d,0x61,0x69,
1088 0x61,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x2f,
1089 0x43,0x53,0x43,0x33,0x2d,0x32,0x30,0x30,0x34,0x2d,0x61,0x69,0x61,0x2e,0x63,
1090 0x65,0x72,0x30,0x1f,0x06,0x03,0x55,0x1d,0x23,0x04,0x18,0x30,0x16,0x80,0x14,
1091 0x08,0xf5,0x51,0xe8,0xfb,0xfe,0x3d,0x3d,0x64,0x36,0x7c,0x68,0xcf,0x5b,0x78,
1092 0xa8,0xdf,0xb9,0xc5,0x37,0x30,0x11,0x06,0x09,0x60,0x86,0x48,0x01,0x86,0xf8,
1093 0x42,0x01,0x01,0x04,0x04,0x03,0x02,0x04,0x10,0x30,0x16,0x06,0x0a,0x2b,0x06,
1094 0x01,0x04,0x01,0x82,0x37,0x02,0x01,0x1b,0x04,0x08,0x30,0x06,0x01,0x01,0x00,
1095 0x01,0x01,0xff,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,
1096 0x05,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x6a,0xa6,0x06,0xd0,0x33,0x18,0x64,
1097 0xe2,0x69,0x82,0xee,0x6e,0x36,0x9e,0x9d,0x9a,0x0e,0x18,0xa8,0xac,0x9d,0x10,
1098 0xed,0x01,0x3c,0xb9,0x61,0x04,0x62,0xf3,0x85,0x8f,0xcc,0x4f,0x2c,0x66,0x35,
1099 0x54,0x25,0x45,0x8d,0x95,0x1c,0xd2,0x33,0xbe,0x2e,0xdd,0x7f,0x74,0xaf,0x03,
1100 0x7b,0x86,0x63,0xb0,0xc9,0xe6,0xbd,0xc7,0x8e,0xde,0x03,0x18,0x98,0x82,0xc3,
1101 0xbb,0xf8,0x15,0x99,0x1a,0xa9,0xdd,0xb9,0x5d,0xb9,0xbd,0x53,0x95,0x25,0x76,
1102 0xfb,0x5c,0x53,0x90,0xea,0x01,0x0a,0xa0,0xb1,0xbf,0x09,0x1b,0x97,0x8f,0x40,
1103 0xfa,0x85,0x12,0x74,0x01,0xdb,0xf6,0xdb,0x09,0xd6,0x5f,0x4f,0xd7,0x17,0xb4,
1104 0xbf,0x9e,0x2f,0x86,0x52,0x5d,0x70,0x24,0x52,0x32,0x1e,0xa5,0x1d,0x39,0x8b,
1105 0x66,0xf6,0xba,0x9b,0x69,0x8e,0x12,0x60,0xdb,0xb6,0xcf,0xe6,0x0d,0xd6,0x1c,
1106 0x8f,0xd4,0x5b,0x4b,0x00,0xde,0x21,0x93,0xfb,0x6e,0xc7,0x3d,0xb4,0x66,0x0d,
1107 0x29,0x0c,0x4e,0xe9,0x3f,0x94,0xd6,0xd6,0xdc,0xec,0xf8,0x53,0x3b,0x62,0xd5,
1108 0x97,0x50,0x53,0x84,0x17,0xfe,0xe2,0xed,0x4c,0x23,0x0a,0x49,0xce,0x5b,0xe9,
1109 0x70,0x31,0xc1,0x04,0x02,0x02,0x6c,0xb8,0x52,0xcd,0xc7,0x4e,0x70,0xb4,0x13,
1110 0xd7,0xe0,0x92,0xba,0x44,0x1a,0x10,0x4c,0x6e,0x45,0xc6,0x86,0x04,0xc6,0x64,
1111 0xd3,0x9c,0x6e,0xc1,0x9c,0xac,0x74,0x3d,0x77,0x06,0x5e,0x28,0x28,0x5c,0xf5,
1112 0xe0,0x9c,0x19,0xd8,0xba,0x74,0x81,0x2d,0x67,0x77,0x93,0x8d,0xbf,0xd2,0x52,
1113 0x00,0xe6,0xa5,0x38,0x4e,0x2e,0x73,0x66,0x7a };
1114 static BYTE iTunesIssuer[] = {
1115 0x30,0x81,0xb4,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,
1116 0x13,0x02,0x55,0x53,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,
1117 0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x2c,
1118 0x20,0x49,0x6e,0x63,0x2e,0x31,0x1f,0x30,0x1d,0x06,0x03,0x55,
1119 0x04,0x0b,0x13,0x16,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,
1120 0x20,0x54,0x72,0x75,0x73,0x74,0x20,0x4e,0x65,0x74,0x77,0x6f,
1121 0x72,0x6b,0x31,0x3b,0x30,0x39,0x06,0x03,0x55,0x04,0x0b,0x13,
1122 0x32,0x54,0x65,0x72,0x6d,0x73,0x20,0x6f,0x66,0x20,0x75,0x73,
1123 0x65,0x20,0x61,0x74,0x20,0x68,0x74,0x74,0x70,0x73,0x3a,0x2f,
1124 0x2f,0x77,0x77,0x77,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,
1125 0x6e,0x2e,0x63,0x6f,0x6d,0x2f,0x72,0x70,0x61,0x20,0x28,0x63,
1126 0x29,0x30,0x34,0x31,0x2e,0x30,0x2c,0x06,0x03,0x55,0x04,0x03,
1127 0x13,0x25,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x43,
1128 0x6c,0x61,0x73,0x73,0x20,0x33,0x20,0x43,0x6f,0x64,0x65,0x20,
1129 0x53,0x69,0x67,0x6e,0x69,0x6e,0x67,0x20,0x32,0x30,0x30,0x34,
1130 0x20,0x43,0x41 };
1131 static BYTE iTunesSerialNum[] = {
1132 0x8d,0xf6,0x6a,0xdf,0xd2,0x40,0xfe,0xb6,0xa6,0x61,0x9b,0x9b,
1133 0xe0,0xa0,0x1a,0x0f };
1135 static void testFindCert(void)
1137 HCERTSTORE store;
1138 PCCERT_CONTEXT context = NULL, subject;
1139 BOOL ret;
1140 CERT_INFO certInfo = { 0 };
1141 CRYPT_HASH_BLOB blob;
1142 BYTE otherSerialNumber[] = { 2 };
1143 DWORD count;
1144 static const WCHAR juan[] = { 'j','u','a','n',0 };
1145 static const WCHAR lang[] = { 'L','A','N','G',0 };
1146 static const WCHAR malcolm[] = { 'm','a','l','c','o','l','m',0 };
1148 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1149 CERT_STORE_CREATE_NEW_FLAG, NULL);
1150 ok(store != NULL, "CertOpenStore failed: %d\n", GetLastError());
1151 if (!store)
1152 return;
1154 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1155 bigCert, sizeof(bigCert), CERT_STORE_ADD_NEW, NULL);
1156 ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* win98 */),
1157 "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
1158 if (!ret && GetLastError() == OSS_DATA_ERROR)
1160 skip("bigCert can't be decoded, skipping tests\n");
1161 return;
1163 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1164 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, NULL);
1165 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1166 GetLastError());
1167 /* This has the same name as bigCert */
1168 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1169 certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, NULL);
1170 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1171 GetLastError());
1173 /* Crashes
1174 context = CertFindCertificateInStore(NULL, 0, 0, 0, NULL, NULL);
1177 /* Check first cert's there, by issuer */
1178 certInfo.Subject.pbData = subjectName;
1179 certInfo.Subject.cbData = sizeof(subjectName);
1180 certInfo.SerialNumber.pbData = serialNum;
1181 certInfo.SerialNumber.cbData = sizeof(serialNum);
1182 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1183 CERT_FIND_ISSUER_NAME, &certInfo.Subject, NULL);
1184 ok(context != NULL, "CertFindCertificateInStore failed: %08x\n",
1185 GetLastError());
1186 if (context)
1188 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1189 CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
1190 ok(context != NULL, "Expected more than one cert\n");
1191 if (context)
1193 context = CertFindCertificateInStore(store, X509_ASN_ENCODING,
1194 0, CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
1195 ok(context == NULL, "Expected precisely two certs\n");
1199 /* Check second cert's there as well, by subject name */
1200 certInfo.Subject.pbData = subjectName2;
1201 certInfo.Subject.cbData = sizeof(subjectName2);
1202 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1203 CERT_FIND_SUBJECT_NAME, &certInfo.Subject, NULL);
1204 ok(context != NULL, "CertFindCertificateInStore failed: %08x\n",
1205 GetLastError());
1206 if (context)
1208 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1209 CERT_FIND_SUBJECT_NAME, &certInfo.Subject, context);
1210 ok(context == NULL, "Expected one cert only\n");
1213 /* Strange but true: searching for the subject cert requires you to set
1214 * the issuer, not the subject
1216 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1217 CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
1218 ok(context == NULL, "Expected no certificate\n");
1219 certInfo.Subject.pbData = NULL;
1220 certInfo.Subject.cbData = 0;
1221 certInfo.Issuer.pbData = subjectName2;
1222 certInfo.Issuer.cbData = sizeof(subjectName2);
1223 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1224 CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
1225 ok(context != NULL, "CertFindCertificateInStore failed: %08x\n",
1226 GetLastError());
1227 if (context)
1229 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1230 CERT_FIND_SUBJECT_CERT, &certInfo, context);
1231 ok(context == NULL, "Expected one cert only\n");
1233 /* A non-matching serial number will not match. */
1234 certInfo.SerialNumber.pbData = otherSerialNumber;
1235 certInfo.SerialNumber.cbData = sizeof(otherSerialNumber);
1236 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1237 CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
1238 ok(context == NULL, "Expected no match\n");
1239 /* No serial number will not match */
1240 certInfo.SerialNumber.cbData = 0;
1241 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1242 CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
1243 ok(context == NULL, "Expected no match\n");
1244 /* A serial number still won't match if the name doesn't */
1245 certInfo.SerialNumber.pbData = serialNum;
1246 certInfo.SerialNumber.cbData = sizeof(serialNum);
1247 certInfo.Issuer.pbData = subjectName3;
1248 certInfo.Issuer.cbData = sizeof(subjectName3);
1249 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1250 CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
1251 ok(context == NULL, "Expected no match\n");
1253 /* The nice thing about hashes, they're unique */
1254 blob.pbData = bigCertHash;
1255 blob.cbData = sizeof(bigCertHash);
1256 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1257 CERT_FIND_SHA1_HASH, &blob, NULL);
1258 ok(context != NULL, "CertFindCertificateInStore failed: %08x\n",
1259 GetLastError());
1260 if (context)
1262 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1263 CERT_FIND_SHA1_HASH, &certInfo.Subject, context);
1264 ok(context == NULL, "Expected one cert only\n");
1267 /* Searching for NULL string matches any context. */
1268 count = 0;
1269 context = NULL;
1270 do {
1271 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1272 CERT_FIND_ISSUER_STR, NULL, context);
1273 if (context)
1274 count++;
1275 } while (context);
1276 ok(count == 3, "expected 3 contexts\n");
1277 count = 0;
1278 context = NULL;
1279 do {
1280 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1281 CERT_FIND_ISSUER_STR, juan, context);
1282 if (context)
1283 count++;
1284 } while (context);
1285 ok(count == 2, "expected 2 contexts\n");
1286 count = 0;
1287 context = NULL;
1288 do {
1289 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1290 CERT_FIND_ISSUER_STR, lang, context);
1291 if (context)
1292 count++;
1293 } while (context);
1294 ok(count == 3, "expected 3 contexts\n");
1295 SetLastError(0xdeadbeef);
1296 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1297 CERT_FIND_ISSUER_STR, malcolm, NULL);
1298 ok(!context, "expected no certs\n");
1299 ok(GetLastError() == CRYPT_E_NOT_FOUND,
1300 "expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1302 CertCloseStore(store, 0);
1304 /* Another subject cert search, using iTunes's certs */
1305 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1306 CERT_STORE_CREATE_NEW_FLAG, NULL);
1307 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1308 iTunesCert0, sizeof(iTunesCert0), CERT_STORE_ADD_NEW, NULL);
1309 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1310 GetLastError());
1311 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1312 iTunesCert1, sizeof(iTunesCert1), CERT_STORE_ADD_NEW, NULL);
1313 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1314 GetLastError());
1315 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1316 iTunesCert2, sizeof(iTunesCert2), CERT_STORE_ADD_NEW, NULL);
1317 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1318 GetLastError());
1319 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1320 iTunesCert3, sizeof(iTunesCert3), CERT_STORE_ADD_NEW, &subject);
1321 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1322 GetLastError());
1324 /* The certInfo's issuer does not match any subject, but the serial
1325 * number does match a cert whose issuer matches certInfo's issuer.
1326 * This yields a match.
1328 certInfo.SerialNumber.cbData = sizeof(iTunesSerialNum);
1329 certInfo.SerialNumber.pbData = iTunesSerialNum;
1330 certInfo.Issuer.cbData = sizeof(iTunesIssuer);
1331 certInfo.Issuer.pbData = iTunesIssuer;
1332 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1333 CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
1334 ok(context != NULL, "Expected a match\n");
1335 if (context)
1337 ret = CertCompareCertificateName(context->dwCertEncodingType,
1338 &certInfo.Issuer, &context->pCertInfo->Subject);
1339 ok(!ret, "Expected subject name not to match\n");
1340 ret = CertCompareCertificateName(context->dwCertEncodingType,
1341 &certInfo.Issuer, &context->pCertInfo->Issuer);
1342 ok(ret, "Expected issuer name to match\n");
1343 ret = CertCompareIntegerBlob(&certInfo.SerialNumber,
1344 &context->pCertInfo->SerialNumber);
1345 ok(ret, "Expected serial number to match\n");
1346 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1347 CERT_FIND_SUBJECT_CERT, &certInfo, context);
1348 ok(context == NULL, "Expected one cert only\n");
1351 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1352 CERT_FIND_ISSUER_OF, subject, NULL);
1353 ok(context != NULL, "Expected an issuer\n");
1354 if (context)
1356 PCCERT_CONTEXT none = CertFindCertificateInStore(store,
1357 X509_ASN_ENCODING, 0, CERT_FIND_ISSUER_OF, context, NULL);
1359 ok(!none, "Expected no parent of issuer\n");
1360 CertFreeCertificateContext(context);
1362 CertFreeCertificateContext(subject);
1363 CertCloseStore(store, 0);
1366 static void testGetSubjectCert(void)
1368 HCERTSTORE store;
1369 PCCERT_CONTEXT context1, context2;
1370 CERT_INFO info = { 0 };
1371 BOOL ret;
1373 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1374 CERT_STORE_CREATE_NEW_FLAG, NULL);
1375 ok(store != NULL, "CertOpenStore failed: %d\n", GetLastError());
1376 if (!store)
1377 return;
1379 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1380 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
1381 ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* win98 */),
1382 "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
1383 if (!ret && GetLastError() == OSS_DATA_ERROR)
1385 skip("bigCert can't be decoded, skipping tests\n");
1386 return;
1388 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1389 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, &context1);
1390 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1391 GetLastError());
1392 ok(context1 != NULL, "Expected a context\n");
1393 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1394 certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, NULL);
1395 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1396 GetLastError());
1398 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
1399 NULL);
1400 ok(!context2 && GetLastError() == E_INVALIDARG,
1401 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1402 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
1403 &info);
1404 ok(!context2 && GetLastError() == CRYPT_E_NOT_FOUND,
1405 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1406 info.SerialNumber.cbData = sizeof(serialNum);
1407 info.SerialNumber.pbData = serialNum;
1408 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
1409 &info);
1410 ok(!context2 && GetLastError() == CRYPT_E_NOT_FOUND,
1411 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1412 info.Issuer.cbData = sizeof(subjectName2);
1413 info.Issuer.pbData = subjectName2;
1414 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
1415 &info);
1416 ok(context2 != NULL,
1417 "CertGetSubjectCertificateFromStore failed: %08x\n", GetLastError());
1418 /* Not only should this find a context, but it should be the same
1419 * (same address) as context1.
1421 ok(context1 == context2, "Expected identical context addresses\n");
1422 CertFreeCertificateContext(context2);
1424 CertFreeCertificateContext(context1);
1425 CertCloseStore(store, 0);
1428 /* This expires in 1970 or so */
1429 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
1430 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
1431 0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
1432 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
1433 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
1434 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
1435 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
1436 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
1437 0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
1438 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
1439 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
1440 0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
1441 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
1442 0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
1443 0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
1444 0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
1445 0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
1446 0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
1447 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
1448 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
1449 0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
1450 0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
1451 0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
1452 0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
1453 0x49, 0xe5, 0xf9, 0x65, 0xf3 };
1455 /* This expires in 2036 or so */
1456 static const BYTE childOfExpired[] = { 0x30, 0x81, 0xcc, 0x30, 0x78, 0xa0,
1457 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
1458 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d,
1459 0x30, 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63,
1460 0x40, 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e,
1461 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x35, 0x30, 0x35,
1462 0x31, 0x37, 0x31, 0x32, 0x34, 0x39, 0x5a, 0x17, 0x0d, 0x33, 0x36, 0x30, 0x35,
1463 0x30, 0x35, 0x31, 0x37, 0x31, 0x32, 0x34, 0x39, 0x5a, 0x30, 0x15, 0x31, 0x13,
1464 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e,
1465 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03,
1466 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
1467 0x01, 0x05, 0x05, 0x00, 0x03, 0x41, 0x00, 0x20, 0x3b, 0xdb, 0x4d, 0x67, 0x50,
1468 0xec, 0x73, 0x9d, 0xf9, 0x85, 0x5d, 0x18, 0xe9, 0xb4, 0x98, 0xe3, 0x31, 0xb7,
1469 0x03, 0x0b, 0xc0, 0x39, 0x93, 0x56, 0x81, 0x0a, 0xfc, 0x78, 0xa8, 0x29, 0x42,
1470 0x5f, 0x69, 0xfb, 0xbc, 0x5b, 0xf2, 0xa6, 0x2a, 0xbe, 0x91, 0x2c, 0xfc, 0x89,
1471 0x69, 0x15, 0x18, 0x58, 0xe5, 0x02, 0x75, 0xf7, 0x2a, 0xb6, 0xa9, 0xfb, 0x47,
1472 0x6a, 0x6e, 0x0a, 0x9b, 0xe9, 0xdc };
1473 /* chain10_0 -+
1474 * +-> chain7_1
1475 * chain10_1 -+
1476 * A chain with two issuers, only one of whose dates is valid.
1478 static const BYTE chain10_0[] = {
1479 0x30,0x82,0x01,0x9b,0x30,0x82,0x01,0x08,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,
1480 0x4a,0x30,0x3a,0x42,0xa2,0x5a,0xb3,0x93,0x4d,0x94,0x06,0xad,0x6d,0x1c,0x34,
1481 0xe6,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x30,0x10,0x31,
1482 0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x03,0x13,0x05,0x43,0x65,0x72,0x74,0x31,
1483 0x30,0x1e,0x17,0x0d,0x30,0x36,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
1484 0x30,0x5a,0x17,0x0d,0x30,0x36,0x31,0x32,0x33,0x31,0x32,0x33,0x35,0x39,0x35,
1485 0x39,0x5a,0x30,0x10,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x03,0x13,0x05,
1486 0x43,0x65,0x72,0x74,0x31,0x30,0x81,0x9f,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
1487 0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x81,0x8d,0x00,0x30,0x81,0x89,
1488 0x02,0x81,0x81,0x00,0xad,0x7e,0xca,0xf3,0xe5,0x99,0xc2,0x2a,0xca,0x50,0x82,
1489 0x7c,0x2d,0xa4,0x81,0xcd,0x0d,0x0d,0x86,0xd7,0xd8,0xb2,0xde,0xc5,0xc3,0x34,
1490 0x9e,0x07,0x78,0x08,0x11,0x12,0x2d,0x21,0x0a,0x09,0x07,0x14,0x03,0x7a,0xe7,
1491 0x3b,0x58,0xf1,0xde,0x3e,0x01,0x25,0x93,0xab,0x8f,0xce,0x1f,0xc1,0x33,0x91,
1492 0xfe,0x59,0xb9,0x3b,0x9e,0x95,0x12,0x89,0x8e,0xc3,0x4b,0x98,0x1b,0x99,0xc5,
1493 0x07,0xe2,0xdf,0x15,0x4c,0x39,0x76,0x06,0xad,0xdb,0x16,0x06,0x49,0xba,0xcd,
1494 0x0f,0x07,0xd6,0xea,0x27,0xa6,0xfe,0x3d,0x88,0xe5,0x97,0x45,0x72,0xb6,0x1c,
1495 0xc0,0x1c,0xb1,0xa2,0x89,0xe8,0x37,0x9e,0xf6,0x2a,0xcf,0xd5,0x1f,0x2f,0x35,
1496 0x5e,0x8f,0x3a,0x9c,0x61,0xb1,0xf1,0x6c,0xff,0x8c,0xb2,0x2f,0x02,0x03,0x01,
1497 0x00,0x01,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x03,0x81,
1498 0x81,0x00,0x85,0x6e,0x35,0x2f,0x2c,0x51,0x4f,0xd6,0x2a,0xe4,0x9e,0xd0,0x4b,
1499 0xe6,0x90,0xfd,0xf7,0x20,0xad,0x76,0x3f,0x93,0xea,0x7f,0x0d,0x1f,0xb3,0x8e,
1500 0xfd,0xe0,0xe1,0xd6,0xd7,0x9c,0x7d,0x46,0x6b,0x15,0x5c,0xe6,0xc9,0x62,0x3b,
1501 0x70,0x4a,0x4b,0xb2,0x82,0xe3,0x55,0x0c,0xc4,0x90,0x44,0x06,0x6c,0x86,0x1c,
1502 0x6d,0x47,0x12,0xda,0x33,0x95,0x5d,0x98,0x43,0xcb,0x7c,0xfa,0x2b,0xee,0xc4,
1503 0x2d,0xc8,0x95,0x33,0x89,0x08,0x3f,0x9f,0x87,0xea,0x20,0x04,0xaf,0x58,0x4b,
1504 0x9d,0xc0,0x7c,0x0a,0x1b,0x05,0x31,0x3b,0xbb,0x13,0x58,0x2e,0x3f,0x61,0x6b,
1505 0x10,0xb4,0xeb,0xb9,0x1a,0x30,0xfd,0xea,0xca,0x29,0x99,0x5f,0x42,0x2b,0x00,
1506 0xb0,0x08,0xc3,0xf0,0xb6,0xd6,0x6b,0xf9,0x35,0x95 };
1507 static const BYTE chain10_1[] = {
1508 0x30,0x82,0x01,0x9b,0x30,0x82,0x01,0x08,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,
1509 0xbf,0x99,0x4f,0x14,0x03,0x77,0x44,0xb8,0x49,0x02,0x70,0xa1,0xb8,0x9c,0xa7,
1510 0x24,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x30,0x10,0x31,
1511 0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x03,0x13,0x05,0x43,0x65,0x72,0x74,0x31,
1512 0x30,0x1e,0x17,0x0d,0x30,0x37,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
1513 0x30,0x5a,0x17,0x0d,0x30,0x37,0x31,0x32,0x33,0x31,0x32,0x33,0x35,0x39,0x35,
1514 0x39,0x5a,0x30,0x10,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x03,0x13,0x05,
1515 0x43,0x65,0x72,0x74,0x31,0x30,0x81,0x9f,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
1516 0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x81,0x8d,0x00,0x30,0x81,0x89,
1517 0x02,0x81,0x81,0x00,0xad,0x7e,0xca,0xf3,0xe5,0x99,0xc2,0x2a,0xca,0x50,0x82,
1518 0x7c,0x2d,0xa4,0x81,0xcd,0x0d,0x0d,0x86,0xd7,0xd8,0xb2,0xde,0xc5,0xc3,0x34,
1519 0x9e,0x07,0x78,0x08,0x11,0x12,0x2d,0x21,0x0a,0x09,0x07,0x14,0x03,0x7a,0xe7,
1520 0x3b,0x58,0xf1,0xde,0x3e,0x01,0x25,0x93,0xab,0x8f,0xce,0x1f,0xc1,0x33,0x91,
1521 0xfe,0x59,0xb9,0x3b,0x9e,0x95,0x12,0x89,0x8e,0xc3,0x4b,0x98,0x1b,0x99,0xc5,
1522 0x07,0xe2,0xdf,0x15,0x4c,0x39,0x76,0x06,0xad,0xdb,0x16,0x06,0x49,0xba,0xcd,
1523 0x0f,0x07,0xd6,0xea,0x27,0xa6,0xfe,0x3d,0x88,0xe5,0x97,0x45,0x72,0xb6,0x1c,
1524 0xc0,0x1c,0xb1,0xa2,0x89,0xe8,0x37,0x9e,0xf6,0x2a,0xcf,0xd5,0x1f,0x2f,0x35,
1525 0x5e,0x8f,0x3a,0x9c,0x61,0xb1,0xf1,0x6c,0xff,0x8c,0xb2,0x2f,0x02,0x03,0x01,
1526 0x00,0x01,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x03,0x81,
1527 0x81,0x00,0xa8,0xec,0x8c,0x34,0xe7,0x2c,0xdf,0x75,0x87,0xc4,0xf7,0xda,0x71,
1528 0x72,0x29,0xb2,0x48,0xa8,0x2a,0xec,0x7b,0x7d,0x19,0xb9,0x5f,0x1d,0xd9,0x91,
1529 0x2b,0xc4,0x28,0x7e,0xd6,0xb5,0x91,0x69,0xa5,0x8a,0x1a,0x1f,0x97,0x98,0x46,
1530 0x9d,0xdf,0x12,0xf6,0x45,0x62,0xad,0x60,0xb6,0xba,0xb0,0xfd,0xf5,0x9f,0xc6,
1531 0x98,0x05,0x4f,0x4d,0x48,0xdc,0xee,0x69,0xbe,0xb8,0xc4,0xc4,0xd7,0x1b,0xb1,
1532 0x1f,0x64,0xd6,0x45,0xa7,0xdb,0xb3,0x87,0x63,0x0f,0x54,0xe1,0x3a,0x6b,0x57,
1533 0x36,0xd7,0x68,0x65,0xcf,0xda,0x57,0x8d,0xcd,0x84,0x75,0x47,0x26,0x2c,0xef,
1534 0x1e,0x8f,0xc7,0x3b,0xee,0x5d,0x03,0xa6,0xdf,0x3a,0x20,0xb2,0xcc,0xc9,0x09,
1535 0x2c,0xfe,0x2b,0x79,0xb0,0xca,0x2c,0x9a,0x81,0x6b };
1536 static const BYTE chain7_1[] = {
1537 0x30,0x82,0x01,0x93,0x30,0x81,0xfd,0xa0,0x03,0x02,0x01,0x02,0x02,0x01,0x01,
1538 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,
1539 0x30,0x10,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x03,0x13,0x05,0x43,0x65,
1540 0x72,0x74,0x31,0x30,0x1e,0x17,0x0d,0x30,0x37,0x30,0x31,0x30,0x31,0x30,0x30,
1541 0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,0x30,0x37,0x31,0x32,0x33,0x31,0x32,0x33,
1542 0x35,0x39,0x35,0x39,0x5a,0x30,0x10,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,
1543 0x03,0x13,0x05,0x43,0x65,0x72,0x74,0x32,0x30,0x81,0x9f,0x30,0x0d,0x06,0x09,
1544 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x81,0x8d,0x00,
1545 0x30,0x81,0x89,0x02,0x81,0x81,0x00,0xb8,0x52,0xda,0xc5,0x4b,0x3f,0xe5,0x33,
1546 0x0e,0x67,0x5f,0x48,0x21,0xdc,0x7e,0xef,0x37,0x33,0xba,0xff,0xb4,0xc6,0xdc,
1547 0xb6,0x17,0x8e,0x20,0x55,0x07,0x12,0xd2,0x7b,0x3c,0xce,0x30,0xc5,0xa7,0x48,
1548 0x9f,0x6e,0xfe,0xb8,0xbe,0xdb,0x9f,0x9b,0x17,0x60,0x16,0xde,0xc6,0x8b,0x47,
1549 0xd1,0x57,0x71,0x3c,0x93,0xfc,0xbd,0xec,0x44,0x32,0x3b,0xb9,0xcf,0x6b,0x05,
1550 0x72,0xa7,0x87,0x8e,0x7e,0xd4,0x9a,0x87,0x1c,0x2f,0xb7,0x82,0x40,0xfc,0x6a,
1551 0x80,0x83,0x68,0x28,0xce,0x84,0xf4,0x0b,0x2e,0x44,0xcb,0x53,0xac,0x85,0x85,
1552 0xb5,0x46,0x36,0x98,0x3c,0x10,0x02,0xaa,0x02,0xbc,0x8b,0xa2,0x23,0xb2,0xd3,
1553 0x51,0x9a,0x22,0x4a,0xe3,0xaa,0x4e,0x7c,0xda,0x38,0xcf,0x49,0x98,0x72,0xa3,
1554 0x02,0x03,0x01,0x00,0x01,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
1555 0x01,0x01,0x05,0x05,0x00,0x03,0x81,0x81,0x00,0x9f,0x69,0xfd,0x26,0xd5,0x4b,
1556 0xe0,0xab,0x12,0x21,0xb9,0xfc,0xf7,0xe0,0x0c,0x09,0x94,0xad,0x27,0xd7,0x9d,
1557 0xa3,0xcc,0x46,0x2a,0x25,0x9a,0x24,0xa7,0x31,0x58,0x78,0xf5,0xfc,0x30,0xe1,
1558 0x6d,0xfd,0x59,0xab,0xbe,0x69,0xa0,0xea,0xe3,0x7d,0x7a,0x7b,0xe5,0x85,0xeb,
1559 0x86,0x6a,0x84,0x3c,0x96,0x01,0x1a,0x70,0xa7,0xb8,0xcb,0xf2,0x11,0xe7,0x52,
1560 0x9c,0x58,0x2d,0xac,0x63,0xce,0x72,0x4b,0xad,0x62,0xa8,0x1d,0x75,0x96,0xe2,
1561 0x27,0xf5,0x6f,0xba,0x91,0xf8,0xf1,0xb0,0xbf,0x90,0x24,0x6d,0xba,0x5d,0xd7,
1562 0x39,0x63,0x3b,0x7c,0x04,0x5d,0x89,0x9d,0x1c,0xf2,0xf7,0xcc,0xdf,0x6e,0x8a,
1563 0x43,0xa9,0xdd,0x86,0x05,0xa2,0xf3,0x22,0x2d,0x1e,0x70,0xa1,0x59,0xd7,0xa5,
1564 0x94,0x7d };
1566 static void testGetIssuerCert(void)
1568 BOOL ret;
1569 PCCERT_CONTEXT parent, child, cert1, cert2, cert3;
1570 DWORD flags = 0xffffffff, size;
1571 CERT_NAME_BLOB certsubject;
1572 BYTE *certencoded;
1573 WCHAR rootW[] = {'R', 'O', 'O', 'T', '\0'},
1574 certname[] = {'C', 'N', '=', 'd', 'u', 'm', 'm', 'y', ',', ' ', 'T', '=', 'T', 'e', 's', 't', '\0'};
1575 HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1576 CERT_STORE_CREATE_NEW_FLAG, NULL);
1578 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1580 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1581 expiredCert, sizeof(expiredCert), CERT_STORE_ADD_ALWAYS, NULL);
1582 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1583 GetLastError());
1585 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1586 childOfExpired, sizeof(childOfExpired), CERT_STORE_ADD_ALWAYS, &child);
1587 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1588 GetLastError());
1590 /* These crash:
1591 parent = CertGetIssuerCertificateFromStore(NULL, NULL, NULL, NULL);
1592 parent = CertGetIssuerCertificateFromStore(store, NULL, NULL, NULL);
1594 parent = CertGetIssuerCertificateFromStore(NULL, NULL, NULL, &flags);
1595 ok(!parent && GetLastError() == E_INVALIDARG,
1596 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1597 parent = CertGetIssuerCertificateFromStore(store, NULL, NULL, &flags);
1598 ok(!parent && GetLastError() == E_INVALIDARG,
1599 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1600 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1601 ok(!parent && GetLastError() == E_INVALIDARG,
1602 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1603 /* Confusing: the caller cannot set either of the
1604 * CERT_STORE_NO_*_FLAGs, as these are not checks,
1605 * they're results:
1607 flags = CERT_STORE_NO_CRL_FLAG | CERT_STORE_NO_ISSUER_FLAG;
1608 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1609 ok(!parent && GetLastError() == E_INVALIDARG,
1610 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1611 /* Perform no checks */
1612 flags = 0;
1613 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1614 ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08x\n",
1615 GetLastError());
1616 if (parent)
1617 CertFreeCertificateContext(parent);
1618 /* Check revocation and signature only */
1619 flags = CERT_STORE_REVOCATION_FLAG | CERT_STORE_SIGNATURE_FLAG;
1620 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1621 ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08x\n",
1622 GetLastError());
1623 /* Confusing: CERT_STORE_REVOCATION_FLAG succeeds when there is no CRL by
1624 * setting CERT_STORE_NO_CRL_FLAG.
1626 ok(flags == (CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG),
1627 "Expected CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG, got %08x\n",
1628 flags);
1629 if (parent)
1630 CertFreeCertificateContext(parent);
1631 /* Checking time validity is not productive, because while most Windows
1632 * versions return 0 (time valid) because the child is not expired,
1633 * Windows 2003 SP1 returns that it is expired. Thus the range of
1634 * possibilities is covered, and a test verifies nothing.
1637 CertFreeCertificateContext(child);
1638 CertCloseStore(store, 0);
1640 flags = 0;
1641 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1642 CERT_STORE_CREATE_NEW_FLAG, NULL);
1643 /* With only the child certificate, no issuer will be found */
1644 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1645 chain7_1, sizeof(chain7_1), CERT_STORE_ADD_ALWAYS, &child);
1646 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
1647 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1648 ok(parent == NULL, "Expected no issuer\n");
1649 ok(GetLastError() == CRYPT_E_NOT_FOUND, "Expected CRYPT_E_NOT_FOUND, got %08X\n", GetLastError());
1650 /* Adding an issuer allows one (and only one) issuer to be found */
1651 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1652 chain10_1, sizeof(chain10_1), CERT_STORE_ADD_ALWAYS, &cert1);
1653 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
1654 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1655 ok(parent == cert1, "Expected cert1 to be the issuer\n");
1656 parent = CertGetIssuerCertificateFromStore(store, child, parent, &flags);
1657 ok(parent == NULL, "Expected only one issuer\n");
1658 ok(GetLastError() == CRYPT_E_NOT_FOUND, "Expected CRYPT_E_NOT_FOUND, got %08X\n", GetLastError());
1659 /* Adding a second issuer allows two issuers to be found - and the second
1660 * issuer is found before the first, implying certs are added to the head
1661 * of a list.
1663 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1664 chain10_0, sizeof(chain10_0), CERT_STORE_ADD_ALWAYS, &cert2);
1665 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
1666 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1667 ok(parent == cert2, "Expected cert2 to be the first issuer\n");
1668 parent = CertGetIssuerCertificateFromStore(store, child, parent, &flags);
1669 ok(parent == cert1, "Expected cert1 to be the second issuer\n");
1670 parent = CertGetIssuerCertificateFromStore(store, child, parent, &flags);
1671 ok(parent == NULL, "Expected no more than two issuers\n");
1672 ok(GetLastError() == CRYPT_E_NOT_FOUND, "Expected CRYPT_E_NOT_FOUND, got %08X\n", GetLastError());
1673 CertFreeCertificateContext(child);
1674 CertFreeCertificateContext(cert1);
1675 CertFreeCertificateContext(cert2);
1676 CertCloseStore(store, 0);
1678 /* Repeat the test, reversing the order in which issuers are added,
1679 * to show it's order-dependent.
1681 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1682 CERT_STORE_CREATE_NEW_FLAG, NULL);
1683 /* With only the child certificate, no issuer will be found */
1684 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1685 chain7_1, sizeof(chain7_1), CERT_STORE_ADD_ALWAYS, &child);
1686 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
1687 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1688 ok(parent == NULL, "Expected no issuer\n");
1689 ok(GetLastError() == CRYPT_E_NOT_FOUND, "Expected CRYPT_E_NOT_FOUND, got %08X\n", GetLastError());
1690 /* Adding an issuer allows one (and only one) issuer to be found */
1691 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1692 chain10_0, sizeof(chain10_0), CERT_STORE_ADD_ALWAYS, &cert1);
1693 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
1694 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1695 ok(parent == cert1, "Expected cert1 to be the issuer\n");
1696 parent = CertGetIssuerCertificateFromStore(store, child, parent, &flags);
1697 ok(parent == NULL, "Expected only one issuer\n");
1698 ok(GetLastError() == CRYPT_E_NOT_FOUND, "Expected CRYPT_E_NOT_FOUND, got %08X\n", GetLastError());
1699 /* Adding a second issuer allows two issuers to be found - and the second
1700 * issuer is found before the first, implying certs are added to the head
1701 * of a list.
1703 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1704 chain10_1, sizeof(chain10_1), CERT_STORE_ADD_ALWAYS, &cert2);
1705 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
1706 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1707 ok(parent == cert2, "Expected cert2 to be the first issuer\n");
1708 parent = CertGetIssuerCertificateFromStore(store, child, parent, &flags);
1709 ok(parent == cert1, "Expected cert1 to be the second issuer\n");
1710 parent = CertGetIssuerCertificateFromStore(store, child, parent, &flags);
1711 ok(parent == NULL, "Expected no more than two issuers\n");
1712 ok(GetLastError() == CRYPT_E_NOT_FOUND, "Expected CRYPT_E_NOT_FOUND, got %08X\n", GetLastError());
1714 /* Self-sign a certificate, add to the store and test getting the issuer */
1715 size = 0;
1716 ok(CertStrToNameW(X509_ASN_ENCODING, certname, CERT_X500_NAME_STR, NULL, NULL, &size, NULL),
1717 "CertStrToName should have worked\n");
1718 certencoded = HeapAlloc(GetProcessHeap(), 0, size);
1719 ok(CertStrToNameW(X509_ASN_ENCODING, certname, CERT_X500_NAME_STR, NULL, certencoded, &size, NULL),
1720 "CertStrToName should have worked\n");
1721 certsubject.pbData = certencoded;
1722 certsubject.cbData = size;
1723 cert3 = CertCreateSelfSignCertificate(0, &certsubject, 0, NULL, NULL, NULL, NULL, NULL);
1724 ok(cert3 != NULL, "CertCreateSelfSignCertificate should have worked\n");
1725 ret = CertAddCertificateContextToStore(store, cert3, CERT_STORE_ADD_REPLACE_EXISTING, 0);
1726 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
1727 CertFreeCertificateContext(cert3);
1728 cert3 = CertEnumCertificatesInStore(store, NULL);
1729 ok(cert3 != NULL, "CertEnumCertificatesInStore should have worked\n");
1730 SetLastError(0xdeadbeef);
1731 flags = 0;
1732 parent = CertGetIssuerCertificateFromStore(store, cert3, NULL, &flags);
1733 ok(!parent, "Expected NULL\n");
1734 ok(GetLastError() == CRYPT_E_SELF_SIGNED,
1735 "Expected CRYPT_E_SELF_SIGNED, got %08X\n", GetLastError());
1736 CertFreeCertificateContext(child);
1737 CertFreeCertificateContext(cert1);
1738 CertFreeCertificateContext(cert2);
1739 CertFreeCertificateContext(cert3);
1740 CertCloseStore(store, 0);
1741 HeapFree(GetProcessHeap(), 0, certencoded);
1743 /* Test root storage self-signed certificate */
1744 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, CERT_SYSTEM_STORE_CURRENT_USER, rootW);
1745 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1746 flags = 0;
1747 cert1 = CertEnumCertificatesInStore(store, NULL);
1748 ok(cert1 != NULL, "CertEnumCertificatesInStore should have worked\n");
1749 SetLastError(0xdeadbeef);
1750 parent = CertGetIssuerCertificateFromStore(store, cert1, NULL, &flags);
1751 ok(!parent, "Expected NULL\n");
1752 ok(GetLastError() == CRYPT_E_SELF_SIGNED,
1753 "Expected CRYPT_E_SELF_SIGNED, got %08X\n", GetLastError());
1754 CertFreeCertificateContext(cert1);
1755 CertCloseStore(store, 0);
1758 static void testCryptHashCert(void)
1760 static const BYTE emptyHash[] = { 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b,
1761 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07,
1762 0x09 };
1763 static const BYTE knownHash[] = { 0xae, 0x9d, 0xbf, 0x6d, 0xf5, 0x46, 0xee,
1764 0x8b, 0xc5, 0x7a, 0x13, 0xba, 0xc2, 0xb1, 0x04, 0xf2, 0xbf, 0x52, 0xa8,
1765 0xa2 };
1766 static const BYTE toHash[] = "abcdefghijklmnopqrstuvwxyz0123456789.,;!?:";
1767 BOOL ret;
1768 BYTE hash[20];
1769 DWORD hashLen = sizeof(hash);
1771 /* NULL buffer and nonzero length crashes
1772 ret = CryptHashCertificate(0, 0, 0, NULL, size, hash, &hashLen);
1773 empty hash length also crashes
1774 ret = CryptHashCertificate(0, 0, 0, buf, size, hash, NULL);
1776 /* Test empty hash */
1777 ret = CryptHashCertificate(0, 0, 0, toHash, sizeof(toHash), NULL,
1778 &hashLen);
1779 ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
1780 ok(hashLen == sizeof(hash), "Got unexpected size of hash %d\n", hashLen);
1781 /* Test with empty buffer */
1782 ret = CryptHashCertificate(0, 0, 0, NULL, 0, hash, &hashLen);
1783 ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
1784 ok(!memcmp(hash, emptyHash, sizeof(emptyHash)),
1785 "Unexpected hash of nothing\n");
1786 /* Test a known value */
1787 ret = CryptHashCertificate(0, 0, 0, toHash, sizeof(toHash), hash,
1788 &hashLen);
1789 ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
1790 ok(!memcmp(hash, knownHash, sizeof(knownHash)), "Unexpected hash\n");
1793 static void testCryptHashCert2(void)
1795 static const BYTE emptyHash[] = { 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b,
1796 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07,
1797 0x09 };
1798 static const BYTE knownHash[] = { 0xae, 0x9d, 0xbf, 0x6d, 0xf5, 0x46, 0xee,
1799 0x8b, 0xc5, 0x7a, 0x13, 0xba, 0xc2, 0xb1, 0x04, 0xf2, 0xbf, 0x52, 0xa8,
1800 0xa2 };
1801 static const BYTE toHash[] = "abcdefghijklmnopqrstuvwxyz0123456789.,;!?:";
1802 BOOL ret;
1803 BYTE hash[20];
1804 DWORD hashLen;
1805 const WCHAR SHA1[] = { 'S', 'H', 'A', '1', '\0' };
1806 const WCHAR invalidAlgorithm[] = { '_', 'S', 'H', 'O', 'U', 'L', 'D',
1807 'N', 'O', 'T',
1808 'E', 'X', 'I', 'S', 'T', '_', '\0' };
1810 if (!pCryptHashCertificate2)
1812 win_skip("CryptHashCertificate2() is not available\n");
1813 return;
1816 /* Test empty hash */
1817 hashLen = sizeof(hash);
1818 ret = pCryptHashCertificate2(SHA1, 0, NULL, NULL, 0, hash, &hashLen);
1819 ok(ret, "CryptHashCertificate2 failed: %08x\n", GetLastError());
1820 ok(hashLen == sizeof(hash), "Got unexpected size of hash %d\n", hashLen);
1821 ok(!memcmp(hash, emptyHash, sizeof(emptyHash)), "Unexpected hash of nothing\n");
1823 /* Test known hash */
1824 hashLen = sizeof(hash);
1825 ret = pCryptHashCertificate2(SHA1, 0, NULL, toHash, sizeof(toHash), hash, &hashLen);
1826 ok(ret, "CryptHashCertificate2 failed: %08x\n", GetLastError());
1827 ok(hashLen == sizeof(hash), "Got unexpected size of hash %d\n", hashLen);
1828 ok(!memcmp(hash, knownHash, sizeof(knownHash)), "Unexpected hash\n");
1830 /* Test null hash size pointer just sets hash size */
1831 hashLen = 0;
1832 ret = pCryptHashCertificate2(SHA1, 0, NULL, toHash, sizeof(toHash), NULL, &hashLen);
1833 ok(ret, "CryptHashCertificate2 failed: %08x\n", GetLastError());
1834 ok(hashLen == sizeof(hash), "Hash size not set correctly (%d)\n", hashLen);
1836 /* Null algorithm ID crashes Windows implementations */
1837 if (0) {
1838 /* Test null algorithm ID */
1839 hashLen = sizeof(hash);
1840 ret = pCryptHashCertificate2(NULL, 0, NULL, toHash, sizeof(toHash), hash, &hashLen);
1843 /* Test invalid algorithm */
1844 hashLen = sizeof(hash);
1845 SetLastError(0xdeadbeef);
1846 ret = pCryptHashCertificate2(invalidAlgorithm, 0, NULL, toHash, sizeof(toHash), hash, &hashLen);
1847 ok(!ret && GetLastError() == STATUS_NOT_FOUND,
1848 "Expected STATUS_NOT_FOUND (0x%08x), got 0x%08x\n", STATUS_NOT_FOUND, GetLastError());
1850 /* Test hash buffer too small */
1851 hashLen = sizeof(hash) / 2;
1852 SetLastError(0xdeadbeef);
1853 ret = pCryptHashCertificate2(SHA1, 0, NULL, toHash, sizeof(toHash), hash, &hashLen);
1854 ok(!ret && GetLastError() == ERROR_MORE_DATA,
1855 "Expected ERROR_MORE_DATA (%d), got %d\n", ERROR_MORE_DATA, GetLastError());
1857 /* Null hash length crashes Windows implementations */
1858 if (0) {
1859 /* Test hashLen null with hash */
1860 ret = pCryptHashCertificate2(SHA1, 0, NULL, toHash, sizeof(toHash), hash, NULL);
1862 /* Test hashLen null with no hash */
1863 ret = pCryptHashCertificate2(SHA1, 0, NULL, toHash, sizeof(toHash), NULL, NULL);
1867 static void verifySig(HCRYPTPROV csp, const BYTE *toSign, size_t toSignLen,
1868 const BYTE *sig, unsigned int sigLen)
1870 HCRYPTHASH hash;
1871 BOOL ret = CryptCreateHash(csp, CALG_SHA1, 0, 0, &hash);
1873 ok(ret, "CryptCreateHash failed: %08x\n", GetLastError());
1874 if (ret)
1876 BYTE mySig[64];
1877 DWORD mySigSize = sizeof(mySig);
1879 ret = CryptHashData(hash, toSign, toSignLen, 0);
1880 ok(ret, "CryptHashData failed: %08x\n", GetLastError());
1881 /* use the A variant so the test can run on Win9x */
1882 ret = CryptSignHashA(hash, AT_SIGNATURE, NULL, 0, mySig, &mySigSize);
1883 ok(ret, "CryptSignHash failed: %08x\n", GetLastError());
1884 if (ret)
1886 ok(mySigSize == sigLen, "Expected sig length %d, got %d\n",
1887 sigLen, mySigSize);
1888 ok(!memcmp(mySig, sig, sigLen), "Unexpected signature\n");
1890 CryptDestroyHash(hash);
1894 /* Tests signing the certificate described by toBeSigned with the CSP passed in,
1895 * using the algorithm with OID sigOID. The CSP is assumed to be empty, and a
1896 * keyset named AT_SIGNATURE will be added to it. The signature will be stored
1897 * in sig. sigLen should be at least 64 bytes.
1899 static void testSignCert(HCRYPTPROV csp, const CRYPT_DATA_BLOB *toBeSigned,
1900 LPCSTR sigOID, BYTE *sig, DWORD *sigLen)
1902 BOOL ret;
1903 DWORD size = 0;
1904 CRYPT_ALGORITHM_IDENTIFIER algoID = { NULL, { 0, NULL } };
1905 HCRYPTKEY key;
1907 /* These all crash
1908 ret = CryptSignCertificate(0, 0, 0, NULL, 0, NULL, NULL, NULL, NULL);
1909 ret = CryptSignCertificate(0, 0, 0, NULL, 0, NULL, NULL, NULL, &size);
1910 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
1911 NULL, NULL, NULL, &size);
1913 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
1914 &algoID, NULL, NULL, &size);
1915 ok(!ret && GetLastError() == NTE_BAD_ALGID,
1916 "Expected NTE_BAD_ALGID, got %08x\n", GetLastError());
1917 algoID.pszObjId = (LPSTR)sigOID;
1918 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
1919 &algoID, NULL, NULL, &size);
1920 ok(!ret &&
1921 (GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == NTE_BAD_ALGID),
1922 "Expected ERROR_INVALID_PARAMETER or NTE_BAD_ALGID, got %08x\n",
1923 GetLastError());
1924 ret = CryptSignCertificate(0, AT_SIGNATURE, 0, toBeSigned->pbData,
1925 toBeSigned->cbData, &algoID, NULL, NULL, &size);
1926 ok(!ret &&
1927 (GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == NTE_BAD_ALGID),
1928 "Expected ERROR_INVALID_PARAMETER or NTE_BAD_ALGID, got %08x\n",
1929 GetLastError());
1931 /* No keys exist in the new CSP yet.. */
1932 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
1933 toBeSigned->cbData, &algoID, NULL, NULL, &size);
1934 ok(!ret && (GetLastError() == NTE_BAD_KEYSET || GetLastError() ==
1935 NTE_NO_KEY), "Expected NTE_BAD_KEYSET or NTE_NO_KEY, got %08x\n",
1936 GetLastError());
1937 ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
1938 ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
1939 if (ret)
1941 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
1942 toBeSigned->cbData, &algoID, NULL, NULL, &size);
1943 ok(ret, "CryptSignCertificate failed: %08x\n", GetLastError());
1944 ok(size <= *sigLen, "Expected size <= %d, got %d\n", *sigLen, size);
1945 if (ret)
1947 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
1948 toBeSigned->cbData, &algoID, NULL, sig, &size);
1949 ok(ret, "CryptSignCertificate failed: %08x\n", GetLastError());
1950 if (ret)
1952 *sigLen = size;
1953 verifySig(csp, toBeSigned->pbData, toBeSigned->cbData, sig,
1954 size);
1957 CryptDestroyKey(key);
1961 static void testVerifyCertSig(HCRYPTPROV csp, const CRYPT_DATA_BLOB *toBeSigned,
1962 LPCSTR sigOID, const BYTE *sig, DWORD sigLen)
1964 CERT_SIGNED_CONTENT_INFO info;
1965 LPBYTE cert = NULL;
1966 DWORD size = 0;
1967 BOOL ret;
1969 if (!pCryptEncodeObjectEx)
1971 win_skip("no CryptEncodeObjectEx support\n");
1972 return;
1974 ret = CryptVerifyCertificateSignature(0, 0, NULL, 0, NULL);
1975 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1976 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1977 ret = CryptVerifyCertificateSignature(csp, 0, NULL, 0, NULL);
1978 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1979 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1980 ret = CryptVerifyCertificateSignature(csp, X509_ASN_ENCODING, NULL, 0,
1981 NULL);
1982 ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
1983 GetLastError() == OSS_BAD_ARG),
1984 "Expected CRYPT_E_ASN1_EOD or OSS_BAD_ARG, got %08x\n", GetLastError());
1985 info.ToBeSigned.cbData = toBeSigned->cbData;
1986 info.ToBeSigned.pbData = toBeSigned->pbData;
1987 info.SignatureAlgorithm.pszObjId = (LPSTR)sigOID;
1988 info.SignatureAlgorithm.Parameters.cbData = 0;
1989 info.Signature.cbData = sigLen;
1990 info.Signature.pbData = (BYTE *)sig;
1991 info.Signature.cUnusedBits = 0;
1992 ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, X509_CERT, &info,
1993 CRYPT_ENCODE_ALLOC_FLAG, NULL, &cert, &size);
1994 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1995 if (cert)
1997 PCERT_PUBLIC_KEY_INFO pubKeyInfo = NULL;
1998 DWORD pubKeySize;
2000 if (0)
2002 /* Crashes prior to Vista */
2003 ret = CryptVerifyCertificateSignature(csp, X509_ASN_ENCODING,
2004 cert, size, NULL);
2006 CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
2007 (LPSTR)sigOID, 0, NULL, NULL, &pubKeySize);
2008 pubKeyInfo = HeapAlloc(GetProcessHeap(), 0, pubKeySize);
2009 if (pubKeyInfo)
2011 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
2012 X509_ASN_ENCODING, (LPSTR)sigOID, 0, NULL, pubKeyInfo,
2013 &pubKeySize);
2014 ok(ret, "CryptExportKey failed: %08x\n", GetLastError());
2015 if (ret)
2017 ret = CryptVerifyCertificateSignature(csp, X509_ASN_ENCODING,
2018 cert, size, pubKeyInfo);
2019 ok(ret, "CryptVerifyCertificateSignature failed: %08x\n",
2020 GetLastError());
2022 HeapFree(GetProcessHeap(), 0, pubKeyInfo);
2024 LocalFree(cert);
2028 static void testVerifyCertSigEx(HCRYPTPROV csp, const CRYPT_DATA_BLOB *toBeSigned,
2029 LPCSTR sigOID, const BYTE *sig, DWORD sigLen)
2031 CERT_SIGNED_CONTENT_INFO info;
2032 LPBYTE cert = NULL;
2033 DWORD size = 0;
2034 BOOL ret;
2036 if (!pCryptVerifyCertificateSignatureEx)
2038 win_skip("no CryptVerifyCertificateSignatureEx support\n");
2039 return;
2041 if (!pCryptEncodeObjectEx)
2043 win_skip("no CryptEncodeObjectEx support\n");
2044 return;
2046 ret = pCryptVerifyCertificateSignatureEx(0, 0, 0, NULL, 0, NULL, 0, NULL);
2047 ok(!ret && GetLastError() == E_INVALIDARG,
2048 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2049 ret = pCryptVerifyCertificateSignatureEx(csp, 0, 0, NULL, 0, NULL, 0, NULL);
2050 ok(!ret && GetLastError() == E_INVALIDARG,
2051 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2052 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING, 0, NULL, 0,
2053 NULL, 0, NULL);
2054 ok(!ret && GetLastError() == E_INVALIDARG,
2055 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2056 /* This crashes
2057 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
2058 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, NULL, 0, NULL, 0, NULL);
2060 info.ToBeSigned.cbData = toBeSigned->cbData;
2061 info.ToBeSigned.pbData = toBeSigned->pbData;
2062 info.SignatureAlgorithm.pszObjId = (LPSTR)sigOID;
2063 info.SignatureAlgorithm.Parameters.cbData = 0;
2064 info.Signature.cbData = sigLen;
2065 info.Signature.pbData = (BYTE *)sig;
2066 info.Signature.cUnusedBits = 0;
2067 ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, X509_CERT, &info,
2068 CRYPT_ENCODE_ALLOC_FLAG, NULL, &cert, &size);
2069 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2070 if (cert)
2072 CRYPT_DATA_BLOB certBlob = { 0, NULL };
2073 PCERT_PUBLIC_KEY_INFO pubKeyInfo = NULL;
2075 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
2076 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
2077 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
2078 "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
2079 certBlob.cbData = 1;
2080 certBlob.pbData = (void *)0xdeadbeef;
2081 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
2082 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
2083 ok(!ret && (GetLastError() == STATUS_ACCESS_VIOLATION ||
2084 GetLastError() == CRYPT_E_ASN1_EOD /* Win9x */ ||
2085 GetLastError() == CRYPT_E_ASN1_BADTAG /* Win98 */),
2086 "Expected STATUS_ACCESS_VIOLATION, CRYPT_E_ASN1_EOD, OR CRYPT_E_ASN1_BADTAG, got %08x\n",
2087 GetLastError());
2089 certBlob.cbData = size;
2090 certBlob.pbData = cert;
2091 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
2092 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
2093 ok(!ret && GetLastError() == E_INVALIDARG,
2094 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2095 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
2096 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
2097 CRYPT_VERIFY_CERT_SIGN_ISSUER_NULL, NULL, 0, NULL);
2098 ok(!ret && GetLastError() == E_INVALIDARG,
2099 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2100 /* This crashes
2101 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
2102 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
2103 CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY, NULL, 0, NULL);
2105 CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
2106 (LPSTR)sigOID, 0, NULL, NULL, &size);
2107 pubKeyInfo = HeapAlloc(GetProcessHeap(), 0, size);
2108 if (pubKeyInfo)
2110 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
2111 X509_ASN_ENCODING, (LPSTR)sigOID, 0, NULL, pubKeyInfo, &size);
2112 ok(ret, "CryptExportKey failed: %08x\n", GetLastError());
2113 if (ret)
2115 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
2116 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
2117 CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY, pubKeyInfo, 0, NULL);
2118 ok(ret, "CryptVerifyCertificateSignatureEx failed: %08x\n",
2119 GetLastError());
2121 HeapFree(GetProcessHeap(), 0, pubKeyInfo);
2123 LocalFree(cert);
2127 static BYTE emptyCert[] = { 0x30, 0x00 };
2129 static void testCertSigs(void)
2131 HCRYPTPROV csp;
2132 CRYPT_DATA_BLOB toBeSigned = { sizeof(emptyCert), emptyCert };
2133 BOOL ret;
2134 BYTE sig[64];
2135 DWORD sigSize = sizeof(sig);
2137 /* Just in case a previous run failed, delete this thing */
2138 pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
2139 CRYPT_DELETEKEYSET);
2140 ret = pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
2141 CRYPT_NEWKEYSET);
2142 ok(ret, "CryptAcquireContext failed: %08x\n", GetLastError());
2144 testSignCert(csp, &toBeSigned, szOID_RSA_SHA1RSA, sig, &sigSize);
2145 testVerifyCertSig(csp, &toBeSigned, szOID_RSA_SHA1RSA, sig, sigSize);
2146 testVerifyCertSigEx(csp, &toBeSigned, szOID_RSA_SHA1RSA, sig, sigSize);
2148 CryptReleaseContext(csp, 0);
2149 ret = pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
2150 CRYPT_DELETEKEYSET);
2151 ok(ret, "CryptAcquireContext failed: %08x\n", GetLastError());
2154 static const BYTE md5SignedEmptyCert[] = {
2155 0x30,0x56,0x30,0x33,0x02,0x00,0x30,0x02,0x06,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,
2156 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,
2157 0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x07,
2158 0x30,0x02,0x06,0x00,0x03,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,
2159 0x0d,0x02,0x05,0x05,0x00,0x03,0x11,0x00,0xfb,0x0f,0x66,0x82,0x66,0xd9,0xe5,0xf8,
2160 0xd8,0xa2,0x55,0x2b,0xe1,0xa5,0xd9,0x04 };
2161 static const BYTE md5SignedEmptyCertNoNull[] = {
2162 0x30,0x54,0x30,0x33,0x02,0x00,0x30,0x02,0x06,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,
2163 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,
2164 0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x07,
2165 0x30,0x02,0x06,0x00,0x03,0x01,0x00,0x30,0x0a,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,
2166 0x0d,0x02,0x05,0x03,0x11,0x00,0x04,0xd9,0xa5,0xe1,0x2b,0x55,0xa2,0xd8,0xf8,0xe5,
2167 0xd9,0x66,0x82,0x66,0x0f,0xfb };
2169 static void testSignAndEncodeCert(void)
2171 static char oid_rsa_md5rsa[] = szOID_RSA_MD5RSA;
2172 static char oid_rsa_md5[] = szOID_RSA_MD5;
2173 BOOL ret;
2174 DWORD size;
2175 CRYPT_ALGORITHM_IDENTIFIER algID = { 0 };
2176 CERT_INFO info = { 0 };
2178 /* Crash
2179 ret = CryptSignAndEncodeCertificate(0, 0, 0, NULL, NULL, NULL, NULL, NULL,
2180 NULL);
2181 ret = CryptSignAndEncodeCertificate(0, 0, 0, NULL, NULL, NULL, NULL, NULL,
2182 &size);
2184 ret = CryptSignAndEncodeCertificate(0, 0, 0, NULL, NULL, &algID, NULL, NULL,
2185 &size);
2186 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2187 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2188 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING, NULL, NULL,
2189 &algID, NULL, NULL, &size);
2190 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2191 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2192 ret = CryptSignAndEncodeCertificate(0, 0, 0, X509_CERT_TO_BE_SIGNED, NULL,
2193 &algID, NULL, NULL, &size);
2194 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2195 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2196 /* Crashes on some win9x boxes */
2197 if (0)
2199 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
2200 X509_CERT_TO_BE_SIGNED, NULL, &algID, NULL, NULL, &size);
2201 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2202 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
2204 /* Crashes
2205 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
2206 X509_CERT_TO_BE_SIGNED, &info, NULL, NULL, NULL, &size);
2208 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
2209 X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, NULL, &size);
2210 ok(!ret &&
2211 (GetLastError() == NTE_BAD_ALGID ||
2212 GetLastError() == OSS_BAD_PTR), /* win9x */
2213 "Expected NTE_BAD_ALGID, got %08x\n", GetLastError());
2214 algID.pszObjId = oid_rsa_md5rsa;
2215 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
2216 X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, NULL, &size);
2217 ok(!ret &&
2218 (GetLastError() == ERROR_INVALID_PARAMETER ||
2219 GetLastError() == NTE_BAD_ALGID ||
2220 GetLastError() == OSS_BAD_PTR), /* Win9x */
2221 "Expected ERROR_INVALID_PARAMETER or NTE_BAD_ALGID, got %08x\n",
2222 GetLastError());
2223 algID.pszObjId = oid_rsa_md5;
2224 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
2225 X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, NULL, &size);
2226 /* oid_rsa_md5 not present in some win2k */
2227 if (ret)
2229 LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, size);
2231 if (buf)
2233 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
2234 X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, buf, &size);
2235 ok(ret, "CryptSignAndEncodeCertificate failed: %08x\n",
2236 GetLastError());
2237 /* Tricky: because the NULL parameters may either be omitted or
2238 * included as an asn.1-encoded NULL (0x05,0x00), two different
2239 * values are allowed.
2241 ok(size == sizeof(md5SignedEmptyCert) ||
2242 size == sizeof(md5SignedEmptyCertNoNull), "Unexpected size %d\n",
2243 size);
2244 if (size == sizeof(md5SignedEmptyCert))
2245 ok(!memcmp(buf, md5SignedEmptyCert, size),
2246 "Unexpected value\n");
2247 else if (size == sizeof(md5SignedEmptyCertNoNull))
2248 ok(!memcmp(buf, md5SignedEmptyCertNoNull, size),
2249 "Unexpected value\n");
2250 HeapFree(GetProcessHeap(), 0, buf);
2255 static void testCreateSelfSignCert(void)
2257 PCCERT_CONTEXT context;
2258 CERT_NAME_BLOB name = { sizeof(subjectName), subjectName };
2259 HCRYPTPROV csp;
2260 BOOL ret;
2261 HCRYPTKEY key;
2262 CRYPT_KEY_PROV_INFO info;
2264 if (!pCertCreateSelfSignCertificate)
2266 win_skip("CertCreateSelfSignCertificate() is not available\n");
2267 return;
2270 /* This crashes:
2271 context = pCertCreateSelfSignCertificate(0, NULL, 0, NULL, NULL, NULL, NULL,
2272 NULL);
2273 * Calling this with no first parameter creates a new key container, which
2274 * lasts beyond the test, so I don't test that. Nb: the generated key
2275 * name is a GUID.
2276 context = pCertCreateSelfSignCertificate(0, &name, 0, NULL, NULL, NULL, NULL,
2277 NULL);
2280 /* Acquire a CSP */
2281 pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
2282 CRYPT_DELETEKEYSET);
2283 ret = pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
2284 CRYPT_NEWKEYSET);
2285 ok(ret, "CryptAcquireContext failed: %08x\n", GetLastError());
2287 context = pCertCreateSelfSignCertificate(csp, &name, 0, NULL, NULL, NULL,
2288 NULL, NULL);
2289 ok(!context && GetLastError() == NTE_NO_KEY,
2290 "Expected NTE_NO_KEY, got %08x\n", GetLastError());
2291 ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
2292 ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
2293 if (ret)
2295 context = pCertCreateSelfSignCertificate(csp, &name, 0, NULL, NULL, NULL,
2296 NULL, NULL);
2297 ok(context != NULL, "CertCreateSelfSignCertificate failed: %08x\n",
2298 GetLastError());
2299 if (context)
2301 DWORD size = 0;
2303 /* The context must have a key provider info property */
2304 ret = CertGetCertificateContextProperty(context,
2305 CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
2306 ok(ret && size, "Expected non-zero key provider info\n");
2307 if (size)
2309 PCRYPT_KEY_PROV_INFO pInfo = HeapAlloc(GetProcessHeap(), 0, size);
2311 if (pInfo)
2313 ret = CertGetCertificateContextProperty(context,
2314 CERT_KEY_PROV_INFO_PROP_ID, pInfo, &size);
2315 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
2316 GetLastError());
2317 if (ret)
2319 /* Sanity-check the key provider */
2320 ok(!lstrcmpW(pInfo->pwszContainerName, cspNameW),
2321 "Unexpected key container\n");
2322 ok(!lstrcmpW(pInfo->pwszProvName, MS_DEF_PROV_W),
2323 "Unexpected provider\n");
2324 ok(pInfo->dwKeySpec == AT_SIGNATURE,
2325 "Expected AT_SIGNATURE, got %d\n", pInfo->dwKeySpec);
2327 HeapFree(GetProcessHeap(), 0, pInfo);
2331 CertFreeCertificateContext(context);
2334 CryptDestroyKey(key);
2337 CryptReleaseContext(csp, 0);
2338 ret = pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
2339 CRYPT_DELETEKEYSET);
2340 ok(ret, "CryptAcquireContext failed: %08x\n", GetLastError());
2342 /* Do the same test with a CSP, AT_KEYEXCHANGE and key info */
2343 pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
2344 CRYPT_DELETEKEYSET);
2345 ret = pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
2346 CRYPT_NEWKEYSET);
2347 ok(ret, "CryptAcquireContext failed: %08x\n", GetLastError());
2348 ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
2349 ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
2351 memset(&info,0,sizeof(info));
2352 info.dwProvType = PROV_RSA_FULL;
2353 info.dwKeySpec = AT_KEYEXCHANGE;
2354 info.pwszProvName = (LPWSTR) MS_DEF_PROV_W;
2355 info.pwszContainerName = cspNameW;
2356 /* This should fail because the CSP doesn't have the specified key. */
2357 SetLastError(0xdeadbeef);
2358 context = pCertCreateSelfSignCertificate(csp, &name, 0, &info, NULL, NULL,
2359 NULL, NULL);
2360 ok(context == NULL, "expected failure\n");
2361 if (context != NULL)
2362 CertFreeCertificateContext(context);
2363 else
2364 ok(GetLastError() == NTE_NO_KEY, "expected NTE_NO_KEY, got %08x\n",
2365 GetLastError());
2366 /* Again, with a CSP, AT_SIGNATURE and key info */
2367 info.dwKeySpec = AT_SIGNATURE;
2368 SetLastError(0xdeadbeef);
2369 context = pCertCreateSelfSignCertificate(csp, &name, 0, &info, NULL, NULL,
2370 NULL, NULL);
2371 ok(context != NULL,
2372 "CertCreateSelfSignCertificate failed: %08x\n", GetLastError());
2373 if (context)
2375 DWORD size = 0;
2377 /* The context must have a key provider info property */
2378 ret = CertGetCertificateContextProperty(context,
2379 CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
2380 ok(ret && size, "Expected non-zero key provider info\n");
2381 if (size)
2383 PCRYPT_KEY_PROV_INFO pInfo = HeapAlloc(GetProcessHeap(), 0, size);
2385 if (pInfo)
2387 ret = CertGetCertificateContextProperty(context,
2388 CERT_KEY_PROV_INFO_PROP_ID, pInfo, &size);
2389 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
2390 GetLastError());
2391 if (ret)
2393 /* Sanity-check the key provider */
2394 ok(!lstrcmpW(pInfo->pwszContainerName, cspNameW),
2395 "Unexpected key container\n");
2396 ok(!lstrcmpW(pInfo->pwszProvName, MS_DEF_PROV_W),
2397 "Unexpected provider\n");
2398 ok(pInfo->dwKeySpec == AT_SIGNATURE,
2399 "Expected AT_SIGNATURE, got %d\n", pInfo->dwKeySpec);
2401 HeapFree(GetProcessHeap(), 0, pInfo);
2405 CertFreeCertificateContext(context);
2407 CryptDestroyKey(key);
2409 CryptReleaseContext(csp, 0);
2410 ret = pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
2411 CRYPT_DELETEKEYSET);
2412 ok(ret, "CryptAcquireContext failed: %08x\n", GetLastError());
2414 /* Do the same test with no CSP, AT_KEYEXCHANGE and key info */
2415 info.dwKeySpec = AT_KEYEXCHANGE;
2416 context = pCertCreateSelfSignCertificate(0, &name, 0, &info, NULL, NULL,
2417 NULL, NULL);
2418 ok(context != NULL, "CertCreateSelfSignCertificate failed: %08x\n",
2419 GetLastError());
2420 if (context)
2422 DWORD size = 0;
2424 /* The context must have a key provider info property */
2425 ret = CertGetCertificateContextProperty(context,
2426 CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
2427 ok(ret && size, "Expected non-zero key provider info\n");
2428 if (size)
2430 PCRYPT_KEY_PROV_INFO pInfo = HeapAlloc(GetProcessHeap(), 0, size);
2432 if (pInfo)
2434 ret = CertGetCertificateContextProperty(context,
2435 CERT_KEY_PROV_INFO_PROP_ID, pInfo, &size);
2436 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
2437 GetLastError());
2438 if (ret)
2440 /* Sanity-check the key provider */
2441 ok(!lstrcmpW(pInfo->pwszContainerName, cspNameW),
2442 "Unexpected key container\n");
2443 ok(!lstrcmpW(pInfo->pwszProvName, MS_DEF_PROV_W),
2444 "Unexpected provider\n");
2445 ok(pInfo->dwKeySpec == AT_KEYEXCHANGE,
2446 "Expected AT_KEYEXCHANGE, got %d\n", pInfo->dwKeySpec);
2448 HeapFree(GetProcessHeap(), 0, pInfo);
2452 CertFreeCertificateContext(context);
2455 pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
2456 CRYPT_DELETEKEYSET);
2458 /* Acquire a CSP and generate an AT_KEYEXCHANGE key in it. */
2459 pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
2460 CRYPT_DELETEKEYSET);
2461 ret = pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
2462 CRYPT_NEWKEYSET);
2463 ok(ret, "CryptAcquireContext failed: %08x\n", GetLastError());
2465 context = pCertCreateSelfSignCertificate(csp, &name, 0, NULL, NULL, NULL,
2466 NULL, NULL);
2467 ok(!context && GetLastError() == NTE_NO_KEY,
2468 "Expected NTE_NO_KEY, got %08x\n", GetLastError());
2469 ret = CryptGenKey(csp, AT_KEYEXCHANGE, 0, &key);
2470 ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
2471 CryptDestroyKey(key);
2473 memset(&info,0,sizeof(info));
2474 info.dwProvType = PROV_RSA_FULL;
2475 info.dwKeySpec = AT_SIGNATURE;
2476 info.pwszProvName = (LPWSTR) MS_DEF_PROV_W;
2477 info.pwszContainerName = cspNameW;
2478 /* This should fail because the CSP doesn't have the specified key. */
2479 SetLastError(0xdeadbeef);
2480 context = pCertCreateSelfSignCertificate(csp, &name, 0, &info, NULL, NULL,
2481 NULL, NULL);
2482 ok(context == NULL, "expected failure\n");
2483 if (context != NULL)
2484 CertFreeCertificateContext(context);
2485 else
2486 ok(GetLastError() == NTE_NO_KEY, "expected NTE_NO_KEY, got %08x\n",
2487 GetLastError());
2488 /* Again, with a CSP, AT_KEYEXCHANGE and key info. This succeeds because the
2489 * CSP has an AT_KEYEXCHANGE key in it.
2491 info.dwKeySpec = AT_KEYEXCHANGE;
2492 SetLastError(0xdeadbeef);
2493 context = pCertCreateSelfSignCertificate(csp, &name, 0, &info, NULL, NULL,
2494 NULL, NULL);
2495 ok(context != NULL,
2496 "CertCreateSelfSignCertificate failed: %08x\n", GetLastError());
2497 if (context)
2499 DWORD size = 0;
2501 /* The context must have a key provider info property */
2502 ret = CertGetCertificateContextProperty(context,
2503 CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
2504 ok(ret && size, "Expected non-zero key provider info\n");
2505 if (size)
2507 PCRYPT_KEY_PROV_INFO pInfo = HeapAlloc(GetProcessHeap(), 0, size);
2509 if (pInfo)
2511 ret = CertGetCertificateContextProperty(context,
2512 CERT_KEY_PROV_INFO_PROP_ID, pInfo, &size);
2513 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
2514 GetLastError());
2515 if (ret)
2517 /* Sanity-check the key provider */
2518 ok(!lstrcmpW(pInfo->pwszContainerName, cspNameW),
2519 "Unexpected key container\n");
2520 ok(!lstrcmpW(pInfo->pwszProvName, MS_DEF_PROV_W),
2521 "Unexpected provider\n");
2522 ok(pInfo->dwKeySpec == AT_KEYEXCHANGE,
2523 "Expected AT_KEYEXCHANGE, got %d\n", pInfo->dwKeySpec);
2525 HeapFree(GetProcessHeap(), 0, pInfo);
2529 CertFreeCertificateContext(context);
2532 CryptReleaseContext(csp, 0);
2533 ret = pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
2534 CRYPT_DELETEKEYSET);
2535 ok(ret, "CryptAcquireContext failed: %08x\n", GetLastError());
2539 static void testIntendedKeyUsage(void)
2541 BOOL ret;
2542 CERT_INFO info = { 0 };
2543 static char oid_key_usage[] = szOID_KEY_USAGE;
2544 /* A couple "key usages". Really they're just encoded bits which aren't
2545 * necessarily restricted to the defined key usage values.
2547 static BYTE usage1[] = { 0x03,0x03,0x00,0xff,0xff };
2548 static BYTE usage2[] = { 0x03,0x03,0x01,0xff,0xfe };
2549 static const BYTE expected_usage1[] = { 0xff,0xff,0x00,0x00 };
2550 static const BYTE expected_usage2[] = { 0xff,0xfe,0x00,0x00 };
2551 CERT_EXTENSION ext = { oid_key_usage, TRUE, { sizeof(usage1), usage1 } };
2552 BYTE usage_bytes[4];
2554 if (0)
2556 /* Crash */
2557 CertGetIntendedKeyUsage(0, NULL, NULL, 0);
2559 ret = CertGetIntendedKeyUsage(0, &info, NULL, 0);
2560 ok(!ret, "expected failure\n");
2561 ret = CertGetIntendedKeyUsage(0, &info, usage_bytes, sizeof(usage_bytes));
2562 ok(!ret, "expected failure\n");
2563 ret = CertGetIntendedKeyUsage(X509_ASN_ENCODING, &info, NULL, 0);
2564 ok(!ret, "expected failure\n");
2565 ret = CertGetIntendedKeyUsage(X509_ASN_ENCODING, &info, usage_bytes,
2566 sizeof(usage_bytes));
2567 ok(!ret, "expected failure\n");
2568 info.cExtension = 1;
2569 info.rgExtension = &ext;
2570 ret = CertGetIntendedKeyUsage(X509_ASN_ENCODING, &info, NULL, 0);
2571 ok(!ret, "expected failure\n");
2572 /* The unused bytes are filled with 0. */
2573 ret = CertGetIntendedKeyUsage(X509_ASN_ENCODING, &info, usage_bytes,
2574 sizeof(usage_bytes));
2575 ok(ret, "CertGetIntendedKeyUsage failed: %08x\n", GetLastError());
2576 ok(!memcmp(usage_bytes, expected_usage1, sizeof(expected_usage1)),
2577 "unexpected value\n");
2578 /* The usage bytes are copied in big-endian order. */
2579 ext.Value.cbData = sizeof(usage2);
2580 ext.Value.pbData = usage2;
2581 ret = CertGetIntendedKeyUsage(X509_ASN_ENCODING, &info, usage_bytes,
2582 sizeof(usage_bytes));
2583 ok(ret, "CertGetIntendedKeyUsage failed: %08x\n", GetLastError());
2584 ok(!memcmp(usage_bytes, expected_usage2, sizeof(expected_usage2)),
2585 "unexpected value\n");
2588 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
2589 szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
2591 static void testKeyUsage(void)
2593 BOOL ret;
2594 PCCERT_CONTEXT context;
2595 DWORD size;
2597 /* Test base cases */
2598 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, NULL);
2599 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2600 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
2601 size = 1;
2602 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, &size);
2603 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2604 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
2605 size = 0;
2606 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, &size);
2607 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2608 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
2609 /* These crash
2610 ret = CertSetEnhancedKeyUsage(NULL, NULL);
2611 usage.cUsageIdentifier = 0;
2612 ret = CertSetEnhancedKeyUsage(NULL, &usage);
2614 /* Test with a cert with no enhanced key usage extension */
2615 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
2616 sizeof(bigCert));
2617 ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
2618 GetLastError());
2619 if (context)
2621 static const char oid[] = "1.2.3.4";
2622 BYTE buf[sizeof(CERT_ENHKEY_USAGE) + 2 * (sizeof(LPSTR) + sizeof(oid))];
2623 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
2625 ret = CertGetEnhancedKeyUsage(context, 0, NULL, NULL);
2626 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2627 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
2628 size = 1;
2629 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &size);
2630 if (ret)
2632 /* Windows 2000, ME, or later: even though it succeeded, we expect
2633 * CRYPT_E_NOT_FOUND, which indicates there is no enhanced key
2634 * usage set for this cert (which implies it's valid for all uses.)
2636 ok(GetLastError() == CRYPT_E_NOT_FOUND,
2637 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
2638 ok(size == sizeof(CERT_ENHKEY_USAGE), "Wrong size %d\n", size);
2639 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2640 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2641 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %d\n",
2642 pUsage->cUsageIdentifier);
2644 else
2646 /* Windows NT, 95, or 98: it fails, and the last error is
2647 * CRYPT_E_NOT_FOUND.
2649 ok(GetLastError() == CRYPT_E_NOT_FOUND,
2650 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
2652 /* I can add a usage identifier when no key usage has been set */
2653 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
2654 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
2655 GetLastError());
2656 size = sizeof(buf);
2657 ret = CertGetEnhancedKeyUsage(context,
2658 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
2659 ok(ret && GetLastError() == 0,
2660 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2661 ok(pUsage->cUsageIdentifier == 1, "Expected 1 usage, got %d\n",
2662 pUsage->cUsageIdentifier);
2663 if (pUsage->cUsageIdentifier)
2664 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
2665 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
2666 /* Now set an empty key usage */
2667 pUsage->cUsageIdentifier = 0;
2668 ret = CertSetEnhancedKeyUsage(context, pUsage);
2669 ok(ret, "CertSetEnhancedKeyUsage failed: %08x\n", GetLastError());
2670 /* Shouldn't find it in the cert */
2671 size = sizeof(buf);
2672 ret = CertGetEnhancedKeyUsage(context,
2673 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
2674 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
2675 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
2676 /* Should find it as an extended property */
2677 ret = CertGetEnhancedKeyUsage(context,
2678 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
2679 ok(ret && GetLastError() == 0,
2680 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2681 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %d\n",
2682 pUsage->cUsageIdentifier);
2683 /* Should find it as either */
2684 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2685 ok(ret && GetLastError() == 0,
2686 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2687 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %d\n",
2688 pUsage->cUsageIdentifier);
2689 /* Add a usage identifier */
2690 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
2691 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
2692 GetLastError());
2693 size = sizeof(buf);
2694 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2695 ok(ret && GetLastError() == 0,
2696 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2697 ok(pUsage->cUsageIdentifier == 1, "Expected 1 identifier, got %d\n",
2698 pUsage->cUsageIdentifier);
2699 if (pUsage->cUsageIdentifier)
2700 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
2701 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
2702 /* Re-adding the same usage identifier succeeds, though it only adds
2703 * a duplicate usage identifier on versions prior to Vista
2705 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
2706 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
2707 GetLastError());
2708 size = sizeof(buf);
2709 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2710 ok(ret && GetLastError() == 0,
2711 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2712 ok(pUsage->cUsageIdentifier == 1 || pUsage->cUsageIdentifier == 2,
2713 "Expected 1 or 2 identifiers, got %d\n", pUsage->cUsageIdentifier);
2714 if (pUsage->cUsageIdentifier)
2715 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
2716 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
2717 if (pUsage->cUsageIdentifier >= 2)
2718 ok(!strcmp(pUsage->rgpszUsageIdentifier[1], oid),
2719 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[1]);
2720 /* Now set a NULL extended property--this deletes the property. */
2721 ret = CertSetEnhancedKeyUsage(context, NULL);
2722 ok(ret, "CertSetEnhancedKeyUsage failed: %08x\n", GetLastError());
2723 SetLastError(0xbaadcafe);
2724 size = sizeof(buf);
2725 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2726 ok(ret || broken(!ret && GetLastError() == CRYPT_E_NOT_FOUND /* NT4 */),
2727 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2728 ok(GetLastError() == CRYPT_E_NOT_FOUND,
2729 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
2731 CertFreeCertificateContext(context);
2733 /* Now test with a cert with an enhanced key usage extension */
2734 context = CertCreateCertificateContext(X509_ASN_ENCODING, certWithUsage,
2735 sizeof(certWithUsage));
2736 ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
2737 GetLastError());
2738 if (context)
2740 LPBYTE buf = NULL;
2741 DWORD bufSize = 0, i;
2743 /* The size may depend on what flags are used to query it, so I
2744 * realloc the buffer for each test.
2746 ret = CertGetEnhancedKeyUsage(context,
2747 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, NULL, &bufSize);
2748 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2749 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
2750 if (buf)
2752 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
2754 /* Should find it in the cert */
2755 size = bufSize;
2756 ret = CertGetEnhancedKeyUsage(context,
2757 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
2758 ok(ret && GetLastError() == 0,
2759 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2760 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
2761 pUsage->cUsageIdentifier);
2762 for (i = 0; i < pUsage->cUsageIdentifier; i++)
2763 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
2764 "Expected %s, got %s\n", keyUsages[i],
2765 pUsage->rgpszUsageIdentifier[i]);
2766 HeapFree(GetProcessHeap(), 0, buf);
2768 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
2769 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2770 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
2771 if (buf)
2773 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
2775 /* Should find it as either */
2776 size = bufSize;
2777 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2778 /* In Windows, GetLastError returns CRYPT_E_NOT_FOUND not found
2779 * here, even though the return is successful and the usage id
2780 * count is positive. I don't enforce that here.
2782 ok(ret,
2783 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2784 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
2785 pUsage->cUsageIdentifier);
2786 for (i = 0; i < pUsage->cUsageIdentifier; i++)
2787 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
2788 "Expected %s, got %s\n", keyUsages[i],
2789 pUsage->rgpszUsageIdentifier[i]);
2790 HeapFree(GetProcessHeap(), 0, buf);
2792 /* Shouldn't find it as an extended property */
2793 ret = CertGetEnhancedKeyUsage(context,
2794 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, NULL, &size);
2795 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
2796 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
2797 /* Adding a usage identifier overrides the cert's usage!? */
2798 ret = CertAddEnhancedKeyUsageIdentifier(context, szOID_RSA_RSA);
2799 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
2800 GetLastError());
2801 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
2802 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2803 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
2804 if (buf)
2806 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
2808 /* Should find it as either */
2809 size = bufSize;
2810 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2811 ok(ret,
2812 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2813 ok(pUsage->cUsageIdentifier == 1, "Expected 1 usage, got %d\n",
2814 pUsage->cUsageIdentifier);
2815 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], szOID_RSA_RSA),
2816 "Expected %s, got %s\n", szOID_RSA_RSA,
2817 pUsage->rgpszUsageIdentifier[0]);
2818 HeapFree(GetProcessHeap(), 0, buf);
2820 /* But querying the cert directly returns its usage */
2821 ret = CertGetEnhancedKeyUsage(context,
2822 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, NULL, &bufSize);
2823 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2824 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
2825 if (buf)
2827 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
2829 size = bufSize;
2830 ret = CertGetEnhancedKeyUsage(context,
2831 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
2832 ok(ret,
2833 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2834 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
2835 pUsage->cUsageIdentifier);
2836 for (i = 0; i < pUsage->cUsageIdentifier; i++)
2837 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
2838 "Expected %s, got %s\n", keyUsages[i],
2839 pUsage->rgpszUsageIdentifier[i]);
2840 HeapFree(GetProcessHeap(), 0, buf);
2842 /* And removing the only usage identifier in the extended property
2843 * results in the cert's key usage being found.
2845 ret = CertRemoveEnhancedKeyUsageIdentifier(context, szOID_RSA_RSA);
2846 ok(ret, "CertRemoveEnhancedKeyUsage failed: %08x\n", GetLastError());
2847 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
2848 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2849 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
2850 if (buf)
2852 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
2854 /* Should find it as either */
2855 size = bufSize;
2856 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2857 ok(ret,
2858 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2859 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
2860 pUsage->cUsageIdentifier);
2861 for (i = 0; i < pUsage->cUsageIdentifier; i++)
2862 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
2863 "Expected %s, got %s\n", keyUsages[i],
2864 pUsage->rgpszUsageIdentifier[i]);
2865 HeapFree(GetProcessHeap(), 0, buf);
2868 CertFreeCertificateContext(context);
2872 static const BYTE cert2WithUsage[] = {
2873 0x30,0x81,0x89,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2874 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2875 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2876 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2877 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2878 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2879 0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x25,0x30,0x23,
2880 0x30,0x21,0x06,0x03,0x55,0x1d,0x25,0x01,0x01,0xff,0x04,0x17,0x30,0x15,0x06,
2881 0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x03,0x02,0x06,0x09,0x2a,0x86,0x48,0x86,
2882 0xf7,0x0d,0x01,0x01,0x01 };
2884 static void testGetValidUsages(void)
2886 static const LPCSTR expectedOIDs[] = {
2887 "1.3.6.1.5.5.7.3.3",
2888 "1.3.6.1.5.5.7.3.2",
2889 "1.2.840.113549.1.1.1",
2891 static const LPCSTR expectedOIDs2[] = {
2892 "1.3.6.1.5.5.7.3.2",
2893 "1.2.840.113549.1.1.1",
2895 BOOL ret;
2896 int numOIDs;
2897 DWORD size;
2898 LPSTR *oids = NULL;
2899 PCCERT_CONTEXT contexts[3];
2901 if (!pCertGetValidUsages)
2903 win_skip("CertGetValidUsages() is not available\n");
2904 return;
2907 /* Crash
2908 ret = pCertGetValidUsages(0, NULL, NULL, NULL, NULL);
2909 ret = pCertGetValidUsages(0, NULL, NULL, NULL, &size);
2911 contexts[0] = NULL;
2912 size = numOIDs = 0xdeadbeef;
2913 SetLastError(0xdeadbeef);
2914 ret = pCertGetValidUsages(1, &contexts[0], &numOIDs, NULL, &size);
2915 ok(ret, "CertGetValidUsages failed: %d\n", GetLastError());
2916 ok(numOIDs == -1, "Expected -1, got %d\n", numOIDs);
2917 ok(size == 0, "Expected size 0, got %d\n", size);
2918 contexts[0] = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
2919 sizeof(bigCert));
2920 contexts[1] = CertCreateCertificateContext(X509_ASN_ENCODING, certWithUsage,
2921 sizeof(certWithUsage));
2922 contexts[2] = CertCreateCertificateContext(X509_ASN_ENCODING,
2923 cert2WithUsage, sizeof(cert2WithUsage));
2924 size = numOIDs = 0xdeadbeef;
2925 ret = pCertGetValidUsages(0, NULL, &numOIDs, NULL, &size);
2926 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2927 ok(numOIDs == -1, "Expected -1, got %d\n", numOIDs);
2928 ok(size == 0, "Expected size 0, got %d\n", size);
2929 size = numOIDs = 0xdeadbeef;
2930 ret = pCertGetValidUsages(1, contexts, &numOIDs, NULL, &size);
2931 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2932 ok(numOIDs == -1, "Expected -1, got %d\n", numOIDs);
2933 ok(size == 0, "Expected size 0, got %d\n", size);
2934 ret = pCertGetValidUsages(1, &contexts[1], &numOIDs, NULL, &size);
2935 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2936 ok(numOIDs == 3, "Expected 3, got %d\n", numOIDs);
2937 ok(size, "Expected non-zero size\n");
2938 oids = HeapAlloc(GetProcessHeap(), 0, size);
2939 if (oids)
2941 int i;
2942 DWORD smallSize = 1;
2944 SetLastError(0xdeadbeef);
2945 ret = pCertGetValidUsages(1, &contexts[1], &numOIDs, oids, &smallSize);
2946 ok(!ret && GetLastError() == ERROR_MORE_DATA,
2947 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
2948 ret = pCertGetValidUsages(1, &contexts[1], &numOIDs, oids, &size);
2949 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2950 for (i = 0; i < numOIDs; i++)
2951 ok(!lstrcmpA(oids[i], expectedOIDs[i]), "unexpected OID %s\n",
2952 oids[i]);
2953 HeapFree(GetProcessHeap(), 0, oids);
2955 numOIDs = 0xdeadbeef;
2956 /* Oddly enough, this crashes when the number of contexts is not 1:
2957 ret = pCertGetValidUsages(2, contexts, &numOIDs, NULL, &size);
2958 * but setting size to 0 allows it to succeed:
2960 size = 0;
2961 ret = pCertGetValidUsages(2, contexts, &numOIDs, NULL, &size);
2962 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2963 ok(numOIDs == 3, "Expected 3, got %d\n", numOIDs);
2964 ok(size, "Expected non-zero size\n");
2965 oids = HeapAlloc(GetProcessHeap(), 0, size);
2966 if (oids)
2968 int i;
2970 ret = pCertGetValidUsages(1, &contexts[1], &numOIDs, oids, &size);
2971 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2972 for (i = 0; i < numOIDs; i++)
2973 ok(!lstrcmpA(oids[i], expectedOIDs[i]), "unexpected OID %s\n",
2974 oids[i]);
2975 HeapFree(GetProcessHeap(), 0, oids);
2977 numOIDs = 0xdeadbeef;
2978 size = 0;
2979 ret = pCertGetValidUsages(1, &contexts[2], &numOIDs, NULL, &size);
2980 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2981 ok(numOIDs == 2, "Expected 2, got %d\n", numOIDs);
2982 ok(size, "Expected non-zero size\n");
2983 oids = HeapAlloc(GetProcessHeap(), 0, size);
2984 if (oids)
2986 int i;
2988 ret = pCertGetValidUsages(1, &contexts[2], &numOIDs, oids, &size);
2989 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2990 for (i = 0; i < numOIDs; i++)
2991 ok(!lstrcmpA(oids[i], expectedOIDs2[i]), "unexpected OID %s\n",
2992 oids[i]);
2993 HeapFree(GetProcessHeap(), 0, oids);
2995 numOIDs = 0xdeadbeef;
2996 size = 0;
2997 ret = pCertGetValidUsages(3, contexts, &numOIDs, NULL, &size);
2998 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2999 ok(numOIDs == 2, "Expected 2, got %d\n", numOIDs);
3000 ok(size, "Expected non-zero size\n");
3001 oids = HeapAlloc(GetProcessHeap(), 0, size);
3002 if (oids)
3004 int i;
3006 ret = pCertGetValidUsages(3, contexts, &numOIDs, oids, &size);
3007 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
3008 for (i = 0; i < numOIDs; i++)
3009 ok(!lstrcmpA(oids[i], expectedOIDs2[i]), "unexpected OID %s\n",
3010 oids[i]);
3011 HeapFree(GetProcessHeap(), 0, oids);
3013 CertFreeCertificateContext(contexts[0]);
3014 CertFreeCertificateContext(contexts[1]);
3015 CertFreeCertificateContext(contexts[2]);
3018 static BYTE cn[] = {
3019 0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,
3020 0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67 };
3021 static BYTE cnWithLeadingSpace[] = {
3022 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x20,0x4a,
3023 0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67 };
3024 static BYTE cnWithTrailingSpace[] = {
3025 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,
3026 0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x20 };
3027 static BYTE cnWithIntermediateSpace[] = {
3028 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,
3029 0x61,0x6e,0x20,0x20,0x4c,0x61,0x6e,0x67 };
3030 static BYTE cnThenO[] = {
3031 0x30,0x2d,0x31,0x2b,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,
3032 0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x30,0x17,0x06,0x03,0x55,0x04,0x0a,0x13,
3033 0x10,0x54,0x68,0x65,0x20,0x57,0x69,0x6e,0x65,0x20,0x50,0x72,0x6f,0x6a,0x65,
3034 0x63,0x74 };
3035 static BYTE oThenCN[] = {
3036 0x30,0x2d,0x31,0x2b,0x30,0x10,0x06,0x03,0x55,0x04,0x0a,0x13,0x09,0x4a,0x75,
3037 0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x30,0x17,0x06,0x03,0x55,0x04,0x03,0x13,
3038 0x10,0x54,0x68,0x65,0x20,0x57,0x69,0x6e,0x65,0x20,0x50,0x72,0x6f,0x6a,0x65,
3039 0x63,0x74 };
3041 static void testCompareCertName(void)
3043 static BYTE bogus[] = { 1, 2, 3, 4 };
3044 static BYTE bogusPrime[] = { 0, 1, 2, 3, 4 };
3045 static BYTE emptyPrime[] = { 0x30, 0x00, 0x01 };
3046 BOOL ret;
3047 CERT_NAME_BLOB blob1, blob2;
3049 /* crashes
3050 ret = CertCompareCertificateName(0, NULL, NULL);
3052 /* An empty name checks against itself.. */
3053 blob1.pbData = emptyCert;
3054 blob1.cbData = sizeof(emptyCert);
3055 ret = CertCompareCertificateName(0, &blob1, &blob1);
3056 ok(ret, "CertCompareCertificateName failed: %08x\n", GetLastError());
3057 /* It doesn't have to be a valid encoded name.. */
3058 blob1.pbData = bogus;
3059 blob1.cbData = sizeof(bogus);
3060 ret = CertCompareCertificateName(0, &blob1, &blob1);
3061 ok(ret, "CertCompareCertificateName failed: %08x\n", GetLastError());
3062 /* Leading zeroes matter.. */
3063 blob2.pbData = bogusPrime;
3064 blob2.cbData = sizeof(bogusPrime);
3065 ret = CertCompareCertificateName(0, &blob1, &blob2);
3066 ok(!ret, "Expected failure\n");
3067 /* As do trailing extra bytes. */
3068 blob2.pbData = emptyPrime;
3069 blob2.cbData = sizeof(emptyPrime);
3070 ret = CertCompareCertificateName(0, &blob1, &blob2);
3071 ok(!ret, "Expected failure\n");
3072 /* Tests to show that CertCompareCertificateName doesn't decode the name
3073 * to remove spaces, or to do an order-independent comparison.
3075 /* Compare CN="Juan Lang" with CN=" Juan Lang" */
3076 blob1.pbData = cn;
3077 blob1.cbData = sizeof(cn);
3078 blob2.pbData = cnWithLeadingSpace;
3079 blob2.cbData = sizeof(cnWithLeadingSpace);
3080 ret = CertCompareCertificateName(0, &blob1, &blob2);
3081 ok(!ret, "Expected failure\n");
3082 ret = CertCompareCertificateName(X509_ASN_ENCODING, &blob1, &blob2);
3083 ok(!ret, "Expected failure\n");
3084 /* Compare CN="Juan Lang" with CN="Juan Lang " */
3085 blob2.pbData = cnWithTrailingSpace;
3086 blob2.cbData = sizeof(cnWithTrailingSpace);
3087 ret = CertCompareCertificateName(0, &blob1, &blob2);
3088 ok(!ret, "Expected failure\n");
3089 ret = CertCompareCertificateName(X509_ASN_ENCODING, &blob1, &blob2);
3090 ok(!ret, "Expected failure\n");
3091 /* Compare CN="Juan Lang" with CN="Juan Lang" */
3092 blob2.pbData = cnWithIntermediateSpace;
3093 blob2.cbData = sizeof(cnWithIntermediateSpace);
3094 ret = CertCompareCertificateName(0, &blob1, &blob2);
3095 ok(!ret, "Expected failure\n");
3096 ret = CertCompareCertificateName(X509_ASN_ENCODING, &blob1, &blob2);
3097 ok(!ret, "Expected failure\n");
3098 /* Compare 'CN="Juan Lang", O="The Wine Project"' with
3099 * 'O="The Wine Project", CN="Juan Lang"'
3101 blob1.pbData = cnThenO;
3102 blob1.cbData = sizeof(cnThenO);
3103 blob2.pbData = oThenCN;
3104 blob2.cbData = sizeof(oThenCN);
3105 ret = CertCompareCertificateName(0, &blob1, &blob2);
3106 ok(!ret, "Expected failure\n");
3107 ret = CertCompareCertificateName(X509_ASN_ENCODING, &blob1, &blob2);
3108 ok(!ret, "Expected failure\n");
3111 static void testIsRDNAttrsInCertificateName(void)
3113 static char oid_1_2_3[] = "1.2.3";
3114 static char oid_common_name[] = szOID_COMMON_NAME;
3115 static char oid_organization[] = szOID_ORGANIZATION_NAME;
3116 static char juan[] = "Juan Lang";
3117 static char juan_with_leading_space[] = " Juan Lang";
3118 static char juan_with_intermediate_space[] = "Juan Lang";
3119 static char juan_with_trailing_space[] = "Juan Lang ";
3120 static char juan_lower_case[] = "juan lang";
3121 static WCHAR juanW[] = { 'J','u','a','n',' ','L','a','n','g',0 };
3122 static char the_wine_project[] = "The Wine Project";
3123 BOOL ret;
3124 CERT_NAME_BLOB name;
3125 CERT_RDN_ATTR attr[2];
3126 CERT_RDN rdn = { 0, NULL };
3128 name.cbData = sizeof(cn);
3129 name.pbData = cn;
3130 if (0)
3132 /* Crash */
3133 CertIsRDNAttrsInCertificateName(0, 0, NULL, NULL);
3134 CertIsRDNAttrsInCertificateName(X509_ASN_ENCODING, 0, &name, NULL);
3136 SetLastError(0xdeadbeef);
3137 ret = CertIsRDNAttrsInCertificateName(0, 0, &name, NULL);
3138 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
3139 "expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
3140 ret = CertIsRDNAttrsInCertificateName(X509_ASN_ENCODING, 0, &name, &rdn);
3141 ok(ret, "CertIsRDNAttrsInCertificateName failed: %08x\n", GetLastError());
3142 attr[0].pszObjId = oid_1_2_3;
3143 rdn.rgRDNAttr = attr;
3144 rdn.cRDNAttr = 1;
3145 SetLastError(0xdeadbeef);
3146 ret = CertIsRDNAttrsInCertificateName(X509_ASN_ENCODING, 0, &name, &rdn);
3147 ok(!ret && GetLastError() == CRYPT_E_NO_MATCH,
3148 "expected CRYPT_E_NO_MATCH, got %08x\n", GetLastError());
3149 attr[0].pszObjId = oid_common_name;
3150 attr[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
3151 attr[0].Value.cbData = strlen(juan);
3152 attr[0].Value.pbData = (BYTE *)juan;
3153 ret = CertIsRDNAttrsInCertificateName(X509_ASN_ENCODING, 0, &name, &rdn);
3154 ok(ret, "CertIsRDNAttrsInCertificateName failed: %08x\n", GetLastError());
3155 /* Again, spaces are not removed for name comparison. */
3156 attr[0].Value.cbData = strlen(juan_with_leading_space);
3157 attr[0].Value.pbData = (BYTE *)juan_with_leading_space;
3158 SetLastError(0xdeadbeef);
3159 ret = CertIsRDNAttrsInCertificateName(X509_ASN_ENCODING, 0, &name, &rdn);
3160 ok(!ret && GetLastError() == CRYPT_E_NO_MATCH,
3161 "expected CRYPT_E_NO_MATCH, got %08x\n", GetLastError());
3162 attr[0].Value.cbData = strlen(juan_with_intermediate_space);
3163 attr[0].Value.pbData = (BYTE *)juan_with_intermediate_space;
3164 SetLastError(0xdeadbeef);
3165 ret = CertIsRDNAttrsInCertificateName(X509_ASN_ENCODING, 0, &name, &rdn);
3166 ok(!ret && GetLastError() == CRYPT_E_NO_MATCH,
3167 "expected CRYPT_E_NO_MATCH, got %08x\n", GetLastError());
3168 attr[0].Value.cbData = strlen(juan_with_trailing_space);
3169 attr[0].Value.pbData = (BYTE *)juan_with_trailing_space;
3170 SetLastError(0xdeadbeef);
3171 ret = CertIsRDNAttrsInCertificateName(X509_ASN_ENCODING, 0, &name, &rdn);
3172 ok(!ret && GetLastError() == CRYPT_E_NO_MATCH,
3173 "expected CRYPT_E_NO_MATCH, got %08x\n", GetLastError());
3174 /* The lower case name isn't matched unless a case insensitive match is
3175 * specified.
3177 attr[0].Value.cbData = strlen(juan_lower_case);
3178 attr[0].Value.pbData = (BYTE *)juan_lower_case;
3179 SetLastError(0xdeadbeef);
3180 ret = CertIsRDNAttrsInCertificateName(X509_ASN_ENCODING, 0, &name, &rdn);
3181 ok(!ret && GetLastError() == CRYPT_E_NO_MATCH,
3182 "expected CRYPT_E_NO_MATCH, got %08x\n", GetLastError());
3183 ret = CertIsRDNAttrsInCertificateName(X509_ASN_ENCODING,
3184 CERT_CASE_INSENSITIVE_IS_RDN_ATTRS_FLAG, &name, &rdn);
3185 ok(ret ||
3186 broken(!ret && GetLastError() == CRYPT_E_NO_MATCH), /* Older crypt32 */
3187 "CertIsRDNAttrsInCertificateName failed: %08x\n", GetLastError());
3188 /* The values don't match unless they have the same RDN type */
3189 attr[0].dwValueType = CERT_RDN_UNICODE_STRING;
3190 attr[0].Value.cbData = lstrlenW(juanW) * sizeof(WCHAR);
3191 attr[0].Value.pbData = (BYTE *)juanW;
3192 SetLastError(0xdeadbeef);
3193 ret = CertIsRDNAttrsInCertificateName(X509_ASN_ENCODING, 0, &name, &rdn);
3194 ok(!ret && GetLastError() == CRYPT_E_NO_MATCH,
3195 "expected CRYPT_E_NO_MATCH, got %08x\n", GetLastError());
3196 SetLastError(0xdeadbeef);
3197 ret = CertIsRDNAttrsInCertificateName(X509_ASN_ENCODING,
3198 CERT_UNICODE_IS_RDN_ATTRS_FLAG, &name, &rdn);
3199 ok(!ret && GetLastError() == CRYPT_E_NO_MATCH,
3200 "expected CRYPT_E_NO_MATCH, got %08x\n", GetLastError());
3201 attr[0].dwValueType = CERT_RDN_IA5_STRING;
3202 attr[0].Value.cbData = strlen(juan);
3203 attr[0].Value.pbData = (BYTE *)juan;
3204 SetLastError(0xdeadbeef);
3205 ret = CertIsRDNAttrsInCertificateName(X509_ASN_ENCODING, 0, &name, &rdn);
3206 ok(!ret && GetLastError() == CRYPT_E_NO_MATCH,
3207 "expected CRYPT_E_NO_MATCH, got %08x\n", GetLastError());
3208 /* All attributes must be present */
3209 attr[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
3210 attr[0].Value.cbData = strlen(juan);
3211 attr[0].Value.pbData = (BYTE *)juan;
3212 attr[1].pszObjId = oid_organization;
3213 attr[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
3214 attr[1].Value.cbData = strlen(the_wine_project);
3215 attr[1].Value.pbData = (BYTE *)the_wine_project;
3216 rdn.cRDNAttr = 2;
3217 SetLastError(0xdeadbeef);
3218 ret = CertIsRDNAttrsInCertificateName(X509_ASN_ENCODING, 0, &name, &rdn);
3219 ok(!ret && GetLastError() == CRYPT_E_NO_MATCH,
3220 "expected CRYPT_E_NO_MATCH, got %08x\n", GetLastError());
3221 /* Order also matters */
3222 name.pbData = cnThenO;
3223 name.cbData = sizeof(cnThenO);
3224 ret = CertIsRDNAttrsInCertificateName(X509_ASN_ENCODING, 0, &name, &rdn);
3225 ok(ret, "CertIsRDNAttrsInCertificateName failed: %08x\n", GetLastError());
3226 name.pbData = oThenCN;
3227 name.cbData = sizeof(oThenCN);
3228 SetLastError(0xdeadbeef);
3229 ret = CertIsRDNAttrsInCertificateName(X509_ASN_ENCODING, 0, &name, &rdn);
3230 ok(!ret && GetLastError() == CRYPT_E_NO_MATCH,
3231 "expected CRYPT_E_NO_MATCH, got %08x\n", GetLastError());
3234 static BYTE int1[] = { 0x88, 0xff, 0xff, 0xff };
3235 static BYTE int2[] = { 0x88, 0xff };
3236 static BYTE int3[] = { 0x23, 0xff };
3237 static BYTE int4[] = { 0x7f, 0x00 };
3238 static BYTE int5[] = { 0x7f };
3239 static BYTE int6[] = { 0x80, 0x00, 0x00, 0x00 };
3240 static BYTE int7[] = { 0x80, 0x00 };
3242 static struct IntBlobTest
3244 CRYPT_INTEGER_BLOB blob1;
3245 CRYPT_INTEGER_BLOB blob2;
3246 BOOL areEqual;
3247 } intBlobs[] = {
3248 { { sizeof(int1), int1 }, { sizeof(int2), int2 }, TRUE },
3249 { { sizeof(int3), int3 }, { sizeof(int3), int3 }, TRUE },
3250 { { sizeof(int4), int4 }, { sizeof(int5), int5 }, TRUE },
3251 { { sizeof(int6), int6 }, { sizeof(int7), int7 }, TRUE },
3252 { { sizeof(int1), int1 }, { sizeof(int7), int7 }, FALSE },
3255 static void testCompareIntegerBlob(void)
3257 DWORD i;
3258 BOOL ret;
3260 for (i = 0; i < ARRAY_SIZE(intBlobs); i++)
3262 ret = CertCompareIntegerBlob(&intBlobs[i].blob1, &intBlobs[i].blob2);
3263 ok(ret == intBlobs[i].areEqual,
3264 "%d: expected blobs %s compare\n", i, intBlobs[i].areEqual ?
3265 "to" : "not to");
3269 static void testComparePublicKeyInfo(void)
3271 BOOL ret;
3272 CERT_PUBLIC_KEY_INFO info1 = { { 0 } }, info2 = { { 0 } };
3273 static CHAR oid_rsa_rsa[] = szOID_RSA_RSA;
3274 static CHAR oid_rsa_sha1rsa[] = szOID_RSA_SHA1RSA;
3275 static CHAR oid_x957_dsa[] = szOID_X957_DSA;
3276 static BYTE bits1[] = { 1, 0 };
3277 static BYTE bits2[] = { 0 };
3278 static BYTE bits3[] = { 1 };
3279 static BYTE bits4[] = { 0x30,8, 2,1,0x81, 2,3,1,0,1 }; /* ASN_SEQUENCE */
3280 static BYTE bits5[] = { 0x30,9, 2,2,0,0x81, 2,3,1,0,1 }; /* ASN_SEQUENCE */
3281 static BYTE bits6[] = { 0x30,9, 2,2,0,0x82, 2,3,1,0,1 }; /* ASN_SEQUENCE */
3282 static BYTE bits7[] = { 0x04,8, 2,1,0x81, 2,3,1,0,1 }; /* ASN_OCTETSTRING */
3283 static BYTE bits8[] = { 0x04,9, 2,2,0,0x81, 2,3,1,0,1 }; /* ASN_OCTETSTRING */
3284 static BYTE bits9[] = { 0x04,9, 2,2,0,0x82, 2,3,1,0,1 }; /* ASN_OCTETSTRING */
3286 /* crashes
3287 ret = CertComparePublicKeyInfo(0, NULL, NULL);
3289 /* Empty public keys compare */
3290 ret = CertComparePublicKeyInfo(0, &info1, &info2);
3291 ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
3292 ret = CertComparePublicKeyInfo(X509_ASN_ENCODING, &info1, &info2);
3293 ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
3295 /* Different OIDs appear to compare */
3296 info1.Algorithm.pszObjId = oid_rsa_rsa;
3297 info2.Algorithm.pszObjId = oid_rsa_sha1rsa;
3298 ret = CertComparePublicKeyInfo(0, &info1, &info2);
3299 ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
3300 ret = CertComparePublicKeyInfo(X509_ASN_ENCODING, &info1, &info2);
3301 ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
3303 info2.Algorithm.pszObjId = oid_x957_dsa;
3304 ret = CertComparePublicKeyInfo(0, &info1, &info2);
3305 ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
3306 ret = CertComparePublicKeyInfo(X509_ASN_ENCODING, &info1, &info2);
3307 ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
3309 info1.PublicKey.cbData = sizeof(bits1);
3310 info1.PublicKey.pbData = bits1;
3311 info1.PublicKey.cUnusedBits = 0;
3312 info2.PublicKey.cbData = sizeof(bits1);
3313 info2.PublicKey.pbData = bits1;
3314 info2.PublicKey.cUnusedBits = 0;
3315 ret = CertComparePublicKeyInfo(0, &info1, &info2);
3316 ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
3317 ret = CertComparePublicKeyInfo(X509_ASN_ENCODING, &info1, &info2);
3318 ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
3320 info2.Algorithm.pszObjId = oid_rsa_rsa;
3321 info1.PublicKey.cbData = sizeof(bits4);
3322 info1.PublicKey.pbData = bits4;
3323 info1.PublicKey.cUnusedBits = 0;
3324 info2.PublicKey.cbData = sizeof(bits5);
3325 info2.PublicKey.pbData = bits5;
3326 info2.PublicKey.cUnusedBits = 0;
3327 ret = CertComparePublicKeyInfo(0, &info1, &info2);
3328 ok(!ret, "CertComparePublicKeyInfo: as raw binary: keys should be unequal\n");
3329 ret = CertComparePublicKeyInfo(X509_ASN_ENCODING, &info1, &info2);
3330 ok(ret, "CertComparePublicKeyInfo: as ASN.1 encoded: keys should be equal\n");
3332 info1.PublicKey.cUnusedBits = 1;
3333 info2.PublicKey.cUnusedBits = 5;
3334 ret = CertComparePublicKeyInfo(X509_ASN_ENCODING, &info1, &info2);
3335 ok(ret, "CertComparePublicKeyInfo: ASN.1 encoding should ignore cUnusedBits\n");
3336 info1.PublicKey.cUnusedBits = 0;
3337 info2.PublicKey.cUnusedBits = 0;
3338 info1.PublicKey.cbData--; /* kill one byte, make ASN.1 encoded data invalid */
3339 ret = CertComparePublicKeyInfo(X509_ASN_ENCODING, &info1, &info2);
3340 ok(!ret, "CertComparePublicKeyInfo: comparing bad ASN.1 encoded key should fail\n");
3341 /* Even though they compare in their used bits, these do not compare */
3342 info1.PublicKey.cbData = sizeof(bits2);
3343 info1.PublicKey.pbData = bits2;
3344 info1.PublicKey.cUnusedBits = 0;
3345 info2.PublicKey.cbData = sizeof(bits3);
3346 info2.PublicKey.pbData = bits3;
3347 info2.PublicKey.cUnusedBits = 1;
3348 ret = CertComparePublicKeyInfo(0, &info1, &info2);
3349 /* Simple (non-comparing) case */
3350 ok(!ret, "Expected keys not to compare\n");
3351 ret = CertComparePublicKeyInfo(X509_ASN_ENCODING, &info1, &info2);
3352 ok(!ret, "Expected keys not to compare\n");
3354 info2.PublicKey.cbData = sizeof(bits1);
3355 info2.PublicKey.pbData = bits1;
3356 info2.PublicKey.cUnusedBits = 0;
3357 ret = CertComparePublicKeyInfo(0, &info1, &info2);
3358 ok(!ret, "Expected keys not to compare\n");
3359 ret = CertComparePublicKeyInfo(X509_ASN_ENCODING, &info1, &info2);
3360 ok(!ret, "Expected keys not to compare\n");
3362 info1.PublicKey.cbData = sizeof(bits7);
3363 info1.PublicKey.pbData = bits7;
3364 info1.PublicKey.cUnusedBits = 0;
3365 info2.PublicKey.cbData = sizeof(bits8);
3366 info2.PublicKey.pbData = bits8;
3367 info2.PublicKey.cUnusedBits = 0;
3368 ret = CertComparePublicKeyInfo(0, &info1, &info2);
3369 ok(!ret, "CertComparePublicKeyInfo: as raw binary: keys should be unequal\n");
3370 ret = CertComparePublicKeyInfo(X509_ASN_ENCODING, &info1, &info2);
3371 ok(!ret, "CertComparePublicKeyInfo: as ASN.1 encoded: keys should be unequal\n");
3373 ret = CertComparePublicKeyInfo(0, &info1, &info1);
3374 ok(ret, "CertComparePublicKeyInfo: as raw binary: keys should be equal\n");
3375 ret = CertComparePublicKeyInfo(X509_ASN_ENCODING, &info1, &info1);
3376 ok(ret, "CertComparePublicKeyInfo: as ASN.1 encoded: keys should be equal\n");
3377 info1.PublicKey.cbData--; /* kill one byte, make ASN.1 encoded data invalid */
3378 ret = CertComparePublicKeyInfo(X509_ASN_ENCODING, &info1, &info1);
3379 ok(ret, "CertComparePublicKeyInfo: as ASN.1 encoded: keys should be equal\n");
3381 /* ASN.1 encoded non-comparing case */
3382 info1.PublicKey.cbData = sizeof(bits5);
3383 info1.PublicKey.pbData = bits5;
3384 info1.PublicKey.cUnusedBits = 0;
3385 info2.PublicKey.cbData = sizeof(bits6);
3386 info2.PublicKey.pbData = bits6;
3387 info2.PublicKey.cUnusedBits = 0;
3388 ret = CertComparePublicKeyInfo(X509_ASN_ENCODING, &info1, &info2);
3389 ok(!ret, "CertComparePublicKeyInfo: different keys should be unequal\n");
3391 /* ASN.1 encoded non-comparing case */
3392 info1.PublicKey.cbData = sizeof(bits8);
3393 info1.PublicKey.pbData = bits8;
3394 info1.PublicKey.cUnusedBits = 0;
3395 info2.PublicKey.cbData = sizeof(bits9);
3396 info2.PublicKey.pbData = bits9;
3397 info2.PublicKey.cUnusedBits = 0;
3398 ret = CertComparePublicKeyInfo(X509_ASN_ENCODING, &info1, &info2);
3399 ok(!ret, "CertComparePublicKeyInfo: different keys should be unequal\n");
3402 static void testHashPublicKeyInfo(void)
3404 BOOL ret;
3405 CERT_PUBLIC_KEY_INFO info = { { 0 } };
3406 DWORD len;
3408 /* Crash
3409 ret = CryptHashPublicKeyInfo(0, 0, 0, 0, NULL, NULL, NULL);
3410 ret = CryptHashPublicKeyInfo(0, 0, 0, 0, &info, NULL, NULL);
3412 ret = CryptHashPublicKeyInfo(0, 0, 0, 0, NULL, NULL, &len);
3413 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
3414 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
3415 /* Crashes on some win9x boxes */
3416 if (0)
3418 ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, NULL, NULL, &len);
3419 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3420 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3422 ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, &info, NULL, &len);
3423 ok(ret ||
3424 broken(!ret), /* win9x */
3425 "CryptHashPublicKeyInfo failed: %08x\n", GetLastError());
3426 if (ret)
3428 ok(len == 16, "Expected hash size 16, got %d\n", len);
3429 if (len == 16)
3431 static const BYTE emptyHash[] = { 0xb8,0x51,0x3a,0x31,0x0e,0x9f,0x40,
3432 0x36,0x9c,0x92,0x45,0x1b,0x9d,0xc8,0xf9,0xf6 };
3433 BYTE buf[16];
3435 ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, &info, buf,
3436 &len);
3437 ok(ret, "CryptHashPublicKeyInfo failed: %08x\n", GetLastError());
3438 ok(!memcmp(buf, emptyHash, len), "Unexpected hash\n");
3443 static const BYTE md5SignedEmptyCertHash[] = { 0xfb,0x0f,0x66,0x82,0x66,0xd9,
3444 0xe5,0xf8,0xd8,0xa2,0x55,0x2b,0xe1,0xa5,0xd9,0x04 };
3446 static void testHashToBeSigned(void)
3448 BOOL ret;
3449 DWORD size;
3450 BYTE hash[16];
3452 /* Crash */
3453 if (0)
3455 CryptHashToBeSigned(0, 0, NULL, 0, NULL, NULL);
3457 SetLastError(0xdeadbeef);
3458 ret = CryptHashToBeSigned(0, 0, NULL, 0, NULL, &size);
3459 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
3460 "expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
3461 SetLastError(0xdeadbeef);
3462 ret = CryptHashToBeSigned(0, X509_ASN_ENCODING, NULL, 0, NULL, &size);
3463 ok(!ret &&
3464 (GetLastError() == CRYPT_E_ASN1_EOD ||
3465 GetLastError() == OSS_BAD_ARG), /* win9x */
3466 "expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
3467 /* Can't sign anything: has to be asn.1 encoded, at least */
3468 SetLastError(0xdeadbeef);
3469 ret = CryptHashToBeSigned(0, X509_ASN_ENCODING, int1, sizeof(int1),
3470 NULL, &size);
3471 ok(!ret &&
3472 (GetLastError() == CRYPT_E_ASN1_BADTAG ||
3473 GetLastError() == OSS_MORE_INPUT), /* win9x */
3474 "expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
3475 /* Can't be empty, either */
3476 SetLastError(0xdeadbeef);
3477 ret = CryptHashToBeSigned(0, X509_ASN_ENCODING, emptyCert,
3478 sizeof(emptyCert), NULL, &size);
3479 ok(!ret &&
3480 (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
3481 GetLastError() == OSS_DATA_ERROR), /* win9x */
3482 "expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
3483 /* Signing a cert works */
3484 ret = CryptHashToBeSigned(0, X509_ASN_ENCODING, md5SignedEmptyCert,
3485 sizeof(md5SignedEmptyCert), NULL, &size);
3486 ok(ret ||
3487 broken(!ret), /* win9x */
3488 "CryptHashToBeSigned failed: %08x\n", GetLastError());
3489 if (ret)
3491 ok(size == sizeof(md5SignedEmptyCertHash), "unexpected size %d\n", size);
3494 ret = CryptHashToBeSigned(0, X509_ASN_ENCODING, md5SignedEmptyCert,
3495 sizeof(md5SignedEmptyCert), hash, &size);
3496 ok(ret || broken(!ret && GetLastError() == NTE_BAD_ALGID) /* NT4 */,
3497 "CryptHashToBeSigned failed: %08x\n", GetLastError());
3499 ok(!memcmp(hash, md5SignedEmptyCertHash, size), "unexpected value\n");
3502 static void testCompareCert(void)
3504 CERT_INFO info1 = { 0 }, info2 = { 0 };
3505 BOOL ret;
3507 /* Crashes */
3508 if (0)
3509 CertCompareCertificate(X509_ASN_ENCODING, NULL, NULL);
3511 /* Certs with the same issuer and serial number are equal, even if they
3512 * differ in other respects (like subject).
3514 info1.SerialNumber.pbData = serialNum;
3515 info1.SerialNumber.cbData = sizeof(serialNum);
3516 info1.Issuer.pbData = subjectName;
3517 info1.Issuer.cbData = sizeof(subjectName);
3518 info1.Subject.pbData = subjectName2;
3519 info1.Subject.cbData = sizeof(subjectName2);
3520 info2.SerialNumber.pbData = serialNum;
3521 info2.SerialNumber.cbData = sizeof(serialNum);
3522 info2.Issuer.pbData = subjectName;
3523 info2.Issuer.cbData = sizeof(subjectName);
3524 info2.Subject.pbData = subjectName;
3525 info2.Subject.cbData = sizeof(subjectName);
3526 ret = CertCompareCertificate(X509_ASN_ENCODING, &info1, &info2);
3527 ok(ret, "Expected certs to be equal\n");
3529 info2.Issuer.pbData = subjectName2;
3530 info2.Issuer.cbData = sizeof(subjectName2);
3531 ret = CertCompareCertificate(X509_ASN_ENCODING, &info1, &info2);
3532 ok(!ret, "Expected certs not to be equal\n");
3535 static void testVerifySubjectCert(void)
3537 BOOL ret;
3538 DWORD flags;
3539 PCCERT_CONTEXT context1, context2;
3541 /* Crashes
3542 ret = CertVerifySubjectCertificateContext(NULL, NULL, NULL);
3544 flags = 0;
3545 ret = CertVerifySubjectCertificateContext(NULL, NULL, &flags);
3546 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
3547 GetLastError());
3548 flags = CERT_STORE_NO_CRL_FLAG;
3549 ret = CertVerifySubjectCertificateContext(NULL, NULL, &flags);
3550 ok(!ret && GetLastError() == E_INVALIDARG,
3551 "Expected E_INVALIDARG, got %08x\n", GetLastError());
3553 flags = 0;
3554 context1 = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
3555 sizeof(bigCert));
3556 ret = CertVerifySubjectCertificateContext(NULL, context1, &flags);
3557 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
3558 GetLastError());
3559 ret = CertVerifySubjectCertificateContext(context1, NULL, &flags);
3560 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
3561 GetLastError());
3562 ret = CertVerifySubjectCertificateContext(context1, context1, &flags);
3563 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
3564 GetLastError());
3566 context2 = CertCreateCertificateContext(X509_ASN_ENCODING,
3567 bigCertWithDifferentSubject, sizeof(bigCertWithDifferentSubject));
3568 SetLastError(0xdeadbeef);
3569 ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
3570 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
3571 GetLastError());
3572 flags = CERT_STORE_REVOCATION_FLAG;
3573 ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
3574 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
3575 GetLastError());
3576 ok(flags == (CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG),
3577 "Expected CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG, got %08x\n",
3578 flags);
3579 flags = CERT_STORE_SIGNATURE_FLAG;
3580 ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
3581 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
3582 GetLastError());
3583 ok(flags == CERT_STORE_SIGNATURE_FLAG,
3584 "Expected CERT_STORE_SIGNATURE_FLAG, got %08x\n", flags);
3585 CertFreeCertificateContext(context2);
3587 CertFreeCertificateContext(context1);
3590 static const BYTE rootWithKeySignAndCRLSign[] = {
3591 0x30,0x82,0x01,0xdf,0x30,0x82,0x01,0x4c,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,
3592 0x5b,0xc7,0x0b,0x27,0x99,0xbb,0x2e,0x99,0x47,0x9d,0x45,0x4e,0x7c,0x1a,0xca,
3593 0xe8,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x30,0x10,0x31,
3594 0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x03,0x13,0x05,0x43,0x65,0x72,0x74,0x31,
3595 0x30,0x1e,0x17,0x0d,0x30,0x37,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
3596 0x30,0x5a,0x17,0x0d,0x30,0x37,0x31,0x32,0x33,0x31,0x32,0x33,0x35,0x39,0x35,
3597 0x39,0x5a,0x30,0x10,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x03,0x13,0x05,
3598 0x43,0x65,0x72,0x74,0x31,0x30,0x81,0x9f,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
3599 0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x81,0x8d,0x00,0x30,0x81,0x89,
3600 0x02,0x81,0x81,0x00,0xad,0x7e,0xca,0xf3,0xe5,0x99,0xc2,0x2a,0xca,0x50,0x82,
3601 0x7c,0x2d,0xa4,0x81,0xcd,0x0d,0x0d,0x86,0xd7,0xd8,0xb2,0xde,0xc5,0xc3,0x34,
3602 0x9e,0x07,0x78,0x08,0x11,0x12,0x2d,0x21,0x0a,0x09,0x07,0x14,0x03,0x7a,0xe7,
3603 0x3b,0x58,0xf1,0xde,0x3e,0x01,0x25,0x93,0xab,0x8f,0xce,0x1f,0xc1,0x33,0x91,
3604 0xfe,0x59,0xb9,0x3b,0x9e,0x95,0x12,0x89,0x8e,0xc3,0x4b,0x98,0x1b,0x99,0xc5,
3605 0x07,0xe2,0xdf,0x15,0x4c,0x39,0x76,0x06,0xad,0xdb,0x16,0x06,0x49,0xba,0xcd,
3606 0x0f,0x07,0xd6,0xea,0x27,0xa6,0xfe,0x3d,0x88,0xe5,0x97,0x45,0x72,0xb6,0x1c,
3607 0xc0,0x1c,0xb1,0xa2,0x89,0xe8,0x37,0x9e,0xf6,0x2a,0xcf,0xd5,0x1f,0x2f,0x35,
3608 0x5e,0x8f,0x3a,0x9c,0x61,0xb1,0xf1,0x6c,0xff,0x8c,0xb2,0x2f,0x02,0x03,0x01,
3609 0x00,0x01,0xa3,0x42,0x30,0x40,0x30,0x0e,0x06,0x03,0x55,0x1d,0x0f,0x01,0x01,
3610 0xff,0x04,0x04,0x03,0x02,0x00,0x06,0x30,0x0f,0x06,0x03,0x55,0x1d,0x13,0x01,
3611 0x01,0xff,0x04,0x05,0x30,0x03,0x01,0x01,0xff,0x30,0x1d,0x06,0x03,0x55,0x1d,
3612 0x0e,0x04,0x16,0x04,0x14,0x14,0x8c,0x16,0xbb,0xbe,0x70,0xa2,0x28,0x89,0xa0,
3613 0x58,0xff,0x98,0xbd,0xa8,0x24,0x2b,0x8a,0xe9,0x9a,0x30,0x09,0x06,0x05,0x2b,
3614 0x0e,0x03,0x02,0x1d,0x05,0x00,0x03,0x81,0x81,0x00,0x74,0xcb,0x21,0xfd,0x2d,
3615 0x25,0xdc,0xa5,0xaa,0xa1,0x26,0xdc,0x8b,0x40,0x11,0x64,0xae,0x5c,0x71,0x3c,
3616 0x28,0xbc,0xf9,0xb3,0xcb,0xa5,0x94,0xb2,0x8d,0x4c,0x23,0x2b,0x9b,0xde,0x2c,
3617 0x4c,0x30,0x04,0xc6,0x88,0x10,0x2f,0x53,0xfd,0x6c,0x82,0xf1,0x13,0xfb,0xda,
3618 0x27,0x75,0x25,0x48,0xe4,0x72,0x09,0x2a,0xee,0xb4,0x1e,0xc9,0x55,0xf5,0xf7,
3619 0x82,0x91,0xd8,0x4b,0xe4,0x3a,0xfe,0x97,0x87,0xdf,0xfb,0x15,0x5a,0x12,0x3e,
3620 0x12,0xe6,0xad,0x40,0x0b,0xcf,0xee,0x1a,0x44,0xe0,0x83,0xb2,0x67,0x94,0xd4,
3621 0x2e,0x7c,0xf2,0x06,0x9d,0xb3,0x3b,0x7e,0x2f,0xda,0x25,0x66,0x7e,0xa7,0x1f,
3622 0x45,0xd4,0xf5,0xe3,0xdf,0x2a,0xf1,0x18,0x28,0x20,0xb5,0xf8,0xf5,0x8d,0x7a,
3623 0x2e,0x84,0xee };
3624 static const BYTE eeCert[] = {
3625 0x30,0x82,0x01,0xb9,0x30,0x82,0x01,0x22,0xa0,0x03,0x02,0x01,0x02,0x02,0x01,
3626 0x01,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,
3627 0x00,0x30,0x10,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x03,0x13,0x05,0x43,
3628 0x65,0x72,0x74,0x31,0x30,0x1e,0x17,0x0d,0x30,0x37,0x30,0x35,0x30,0x31,0x30,
3629 0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,0x30,0x37,0x31,0x30,0x30,0x31,0x30,
3630 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x10,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,
3631 0x04,0x03,0x13,0x05,0x43,0x65,0x72,0x74,0x32,0x30,0x81,0x9f,0x30,0x0d,0x06,
3632 0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x81,0x8d,
3633 0x00,0x30,0x81,0x89,0x02,0x81,0x81,0x00,0xb8,0x52,0xda,0xc5,0x4b,0x3f,0xe5,
3634 0x33,0x0e,0x67,0x5f,0x48,0x21,0xdc,0x7e,0xef,0x37,0x33,0xba,0xff,0xb4,0xc6,
3635 0xdc,0xb6,0x17,0x8e,0x20,0x55,0x07,0x12,0xd2,0x7b,0x3c,0xce,0x30,0xc5,0xa7,
3636 0x48,0x9f,0x6e,0xfe,0xb8,0xbe,0xdb,0x9f,0x9b,0x17,0x60,0x16,0xde,0xc6,0x8b,
3637 0x47,0xd1,0x57,0x71,0x3c,0x93,0xfc,0xbd,0xec,0x44,0x32,0x3b,0xb9,0xcf,0x6b,
3638 0x05,0x72,0xa7,0x87,0x8e,0x7e,0xd4,0x9a,0x87,0x1c,0x2f,0xb7,0x82,0x40,0xfc,
3639 0x6a,0x80,0x83,0x68,0x28,0xce,0x84,0xf4,0x0b,0x2e,0x44,0xcb,0x53,0xac,0x85,
3640 0x85,0xb5,0x46,0x36,0x98,0x3c,0x10,0x02,0xaa,0x02,0xbc,0x8b,0xa2,0x23,0xb2,
3641 0xd3,0x51,0x9a,0x22,0x4a,0xe3,0xaa,0x4e,0x7c,0xda,0x38,0xcf,0x49,0x98,0x72,
3642 0xa3,0x02,0x03,0x01,0x00,0x01,0xa3,0x23,0x30,0x21,0x30,0x1f,0x06,0x03,0x55,
3643 0x1d,0x23,0x04,0x18,0x30,0x18,0x80,0x14,0x14,0x8c,0x16,0xbb,0xbe,0x70,0xa2,
3644 0x28,0x89,0xa0,0x58,0xff,0x98,0xbd,0xa8,0x24,0x2b,0x8a,0xe9,0x9a,0x30,0x0d,
3645 0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x03,0x81,
3646 0x81,0x00,0x8a,0x49,0xa9,0x86,0x5e,0xc9,0x33,0x7e,0xfd,0xab,0x64,0x1f,0x6d,
3647 0x00,0xd7,0x9b,0xec,0xd1,0x5b,0x38,0xcc,0xd6,0xf3,0xf2,0xb4,0x75,0x70,0x00,
3648 0x82,0x9d,0x37,0x58,0xe1,0xcd,0x2c,0x61,0xb3,0x28,0xe7,0x8a,0x00,0xbe,0x6e,
3649 0xca,0xe8,0x55,0xd5,0xad,0x3a,0xea,0xaf,0x13,0x20,0x1c,0x44,0xfc,0xb4,0xf9,
3650 0x29,0x2b,0xdc,0x8a,0x2d,0x1b,0x27,0x9e,0xb9,0x3b,0x4a,0x71,0x9d,0x47,0x7d,
3651 0xf7,0x92,0x6b,0x21,0x7f,0xfa,0x88,0x79,0x94,0x33,0xf6,0xdd,0x92,0x04,0x92,
3652 0xd6,0x5e,0x0a,0x74,0xf2,0x85,0xa6,0xd5,0x3c,0x28,0xc0,0x89,0x5d,0xda,0xf3,
3653 0xa6,0x01,0xc2,0xe9,0xa3,0xc1,0xb7,0x21,0x08,0xba,0x18,0x07,0x45,0xeb,0x77,
3654 0x7d,0xcd,0xc6,0xe7,0x2a,0x7b,0x46,0xd2,0x3d,0xb5 };
3655 static const BYTE rootSignedCRL[] = {
3656 0x30,0x82,0x01,0x1f,0x30,0x81,0x89,0x02,0x01,0x01,0x30,0x0d,0x06,0x09,0x2a,
3657 0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x30,0x10,0x31,0x0e,0x30,
3658 0x0c,0x06,0x03,0x55,0x04,0x03,0x13,0x05,0x43,0x65,0x72,0x74,0x31,0x17,0x0d,
3659 0x30,0x37,0x30,0x39,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,
3660 0x30,0x37,0x31,0x32,0x33,0x31,0x32,0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x14,
3661 0x30,0x12,0x02,0x01,0x01,0x17,0x0d,0x30,0x37,0x30,0x39,0x30,0x31,0x30,0x30,
3662 0x30,0x30,0x30,0x30,0x5a,0xa0,0x2f,0x30,0x2d,0x30,0x0a,0x06,0x03,0x55,0x1d,
3663 0x14,0x04,0x03,0x02,0x01,0x01,0x30,0x1f,0x06,0x03,0x55,0x1d,0x23,0x04,0x18,
3664 0x30,0x18,0x80,0x14,0x14,0x8c,0x16,0xbb,0xbe,0x70,0xa2,0x28,0x89,0xa0,0x58,
3665 0xff,0x98,0xbd,0xa8,0x24,0x2b,0x8a,0xe9,0x9a,0x30,0x0d,0x06,0x09,0x2a,0x86,
3666 0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x03,0x81,0x81,0x00,0xa3,0xcf,
3667 0x17,0x5d,0x7a,0x08,0xab,0x11,0x1a,0xbd,0x5c,0xde,0x9a,0x22,0x92,0x38,0xe6,
3668 0x96,0xcc,0xb1,0xc5,0x42,0x86,0xa6,0xae,0xad,0xa3,0x1a,0x2b,0xa0,0xb0,0x65,
3669 0xaa,0x9c,0xd7,0x2d,0x44,0x8c,0xae,0x61,0xc7,0x30,0x17,0x89,0x84,0x3b,0x4a,
3670 0x8f,0x17,0x08,0x06,0x37,0x1c,0xf7,0x2d,0x4e,0x47,0x07,0x61,0x50,0xd9,0x06,
3671 0xd1,0x46,0xed,0x0a,0xbb,0xc3,0x9b,0x36,0x0b,0xa7,0x27,0x2f,0x2b,0x55,0xce,
3672 0x2a,0xa5,0x60,0xc6,0x53,0x28,0xe8,0xee,0xad,0x0e,0x2b,0xe8,0xd7,0x5f,0xc9,
3673 0xa5,0xed,0xf9,0x77,0xb0,0x3c,0x81,0xcf,0xcc,0x49,0xb2,0x1a,0xc3,0xfd,0x34,
3674 0xd5,0xbc,0xb0,0xd5,0xa5,0x9c,0x1b,0x72,0xc3,0x0f,0xa3,0xe3,0x3c,0xf0,0xc3,
3675 0x91,0xe8,0x93,0x4f,0xd4,0x2f };
3677 static void testVerifyRevocation(void)
3679 BOOL ret;
3680 CERT_REVOCATION_STATUS status = { 0 };
3681 PCCERT_CONTEXT certs[2];
3682 CERT_REVOCATION_PARA revPara = { sizeof(revPara), 0 };
3684 /* Crash
3685 ret = CertVerifyRevocation(0, 0, 0, NULL, 0, NULL, NULL);
3687 SetLastError(0xdeadbeef);
3688 ret = CertVerifyRevocation(0, 0, 0, NULL, 0, NULL, &status);
3689 ok(!ret && GetLastError() == E_INVALIDARG,
3690 "Expected E_INVALIDARG, got %08x\n", GetLastError());
3691 status.cbSize = sizeof(status);
3692 ret = CertVerifyRevocation(0, 0, 0, NULL, 0, NULL, &status);
3693 ok(ret, "CertVerifyRevocation failed: %08x\n", GetLastError());
3694 ret = CertVerifyRevocation(0, 2, 0, NULL, 0, NULL, &status);
3695 ok(ret, "CertVerifyRevocation failed: %08x\n", GetLastError());
3696 ret = CertVerifyRevocation(2, 0, 0, NULL, 0, NULL, &status);
3697 ok(ret, "CertVerifyRevocation failed: %08x\n", GetLastError());
3698 certs[0] = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
3699 sizeof(bigCert));
3700 SetLastError(0xdeadbeef);
3701 ret = CertVerifyRevocation(0, 0, 1, (void **)certs, 0, NULL, &status);
3702 ok(!ret && GetLastError() == CRYPT_E_NO_REVOCATION_DLL,
3703 "Expected CRYPT_E_NO_REVOCATION_DLL, got %08x\n", GetLastError());
3704 SetLastError(0xdeadbeef);
3705 ret = CertVerifyRevocation(0, 2, 1, (void **)certs, 0, NULL, &status);
3706 ok(!ret && GetLastError() == CRYPT_E_NO_REVOCATION_DLL,
3707 "Expected CRYPT_E_NO_REVOCATION_DLL, got %08x\n", GetLastError());
3709 CertFreeCertificateContext(certs[0]);
3711 certs[0] = CertCreateCertificateContext(X509_ASN_ENCODING,
3712 rootWithKeySignAndCRLSign, sizeof(rootWithKeySignAndCRLSign));
3713 certs[1] = CertCreateCertificateContext(X509_ASN_ENCODING,
3714 eeCert, sizeof(eeCert));
3715 /* The root cert itself can't be checked for revocation */
3716 SetLastError(0xdeadbeef);
3717 ret = CertVerifyRevocation(X509_ASN_ENCODING, CERT_CONTEXT_REVOCATION_TYPE,
3718 1, (void **)certs, 0, NULL, &status);
3719 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3721 win_skip("CERT_CONTEXT_REVOCATION_TYPE unsupported, skipping\n");
3722 return;
3724 ok(!ret && GetLastError() == CRYPT_E_NO_REVOCATION_CHECK,
3725 "expected CRYPT_E_NO_REVOCATION_CHECK, got %08x\n", GetLastError());
3726 ok(status.dwError == CRYPT_E_NO_REVOCATION_CHECK,
3727 "expected CRYPT_E_NO_REVOCATION_CHECK, got %08x\n", status.dwError);
3728 ok(status.dwIndex == 0, "expected index 0, got %d\n", status.dwIndex);
3729 /* Neither can the end cert */
3730 SetLastError(0xdeadbeef);
3731 ret = CertVerifyRevocation(X509_ASN_ENCODING, CERT_CONTEXT_REVOCATION_TYPE,
3732 1, (void **)&certs[1], 0, NULL, &status);
3733 ok(!ret && (GetLastError() == CRYPT_E_NO_REVOCATION_CHECK /* Win9x */ ||
3734 GetLastError() == CRYPT_E_REVOCATION_OFFLINE),
3735 "expected CRYPT_E_NO_REVOCATION_CHECK or CRYPT_E_REVOCATION_OFFLINE, got %08x\n",
3736 GetLastError());
3737 ok(status.dwError == CRYPT_E_NO_REVOCATION_CHECK /* Win9x */ ||
3738 status.dwError == CRYPT_E_REVOCATION_OFFLINE,
3739 "expected CRYPT_E_NO_REVOCATION_CHECK or CRYPT_E_REVOCATION_OFFLINE, got %08x\n",
3740 status.dwError);
3741 ok(status.dwIndex == 0, "expected index 0, got %d\n", status.dwIndex);
3742 /* Both certs together can't, either (they're not CRLs) */
3743 SetLastError(0xdeadbeef);
3744 ret = CertVerifyRevocation(X509_ASN_ENCODING, CERT_CONTEXT_REVOCATION_TYPE,
3745 2, (void **)certs, 0, NULL, &status);
3746 ok(!ret && (GetLastError() == CRYPT_E_NO_REVOCATION_CHECK ||
3747 GetLastError() == CRYPT_E_REVOCATION_OFFLINE /* WinME */),
3748 "expected CRYPT_E_NO_REVOCATION_CHECK or CRYPT_E_REVOCATION_OFFLINE, got %08x\n",
3749 GetLastError());
3750 ok(status.dwError == CRYPT_E_NO_REVOCATION_CHECK ||
3751 status.dwError == CRYPT_E_REVOCATION_OFFLINE /* WinME */,
3752 "expected CRYPT_E_NO_REVOCATION_CHECK or CRYPT_E_REVOCATION_OFFLINE, got %08x\n",
3753 status.dwError);
3754 ok(status.dwIndex == 0, "expected index 0, got %d\n", status.dwIndex);
3755 /* Now add a CRL to the hCrlStore */
3756 revPara.hCrlStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
3757 CERT_STORE_CREATE_NEW_FLAG, NULL);
3758 CertAddEncodedCRLToStore(revPara.hCrlStore, X509_ASN_ENCODING,
3759 rootSignedCRL, sizeof(rootSignedCRL), CERT_STORE_ADD_ALWAYS, NULL);
3760 SetLastError(0xdeadbeef);
3761 ret = CertVerifyRevocation(X509_ASN_ENCODING, CERT_CONTEXT_REVOCATION_TYPE,
3762 2, (void **)certs, 0, &revPara, &status);
3763 ok(!ret && (GetLastError() == CRYPT_E_NO_REVOCATION_CHECK ||
3764 GetLastError() == CRYPT_E_REVOCATION_OFFLINE /* WinME */),
3765 "expected CRYPT_E_NO_REVOCATION_CHECK or CRYPT_E_REVOCATION_OFFLINE, got %08x\n",
3766 GetLastError());
3767 ok(status.dwError == CRYPT_E_NO_REVOCATION_CHECK ||
3768 status.dwError == CRYPT_E_REVOCATION_OFFLINE /* WinME */,
3769 "expected CRYPT_E_NO_REVOCATION_CHECK or CRYPT_E_REVOCATION_OFFLINE, got %08x\n",
3770 status.dwError);
3771 ok(status.dwIndex == 0, "expected index 0, got %d\n", status.dwIndex);
3772 /* Specifying CERT_VERIFY_REV_CHAIN_FLAG doesn't change things either */
3773 SetLastError(0xdeadbeef);
3774 ret = CertVerifyRevocation(X509_ASN_ENCODING, CERT_CONTEXT_REVOCATION_TYPE,
3775 2, (void **)certs, CERT_VERIFY_REV_CHAIN_FLAG, &revPara, &status);
3776 ok(!ret && GetLastError() == CRYPT_E_NO_REVOCATION_CHECK,
3777 "expected CRYPT_E_NO_REVOCATION_CHECK, got %08x\n", GetLastError());
3778 ok(status.dwError == CRYPT_E_NO_REVOCATION_CHECK,
3779 "expected CRYPT_E_NO_REVOCATION_CHECK, got %08x\n", status.dwError);
3780 ok(status.dwIndex == 0, "expected index 0, got %d\n", status.dwIndex);
3781 /* Again, specifying the issuer cert: no change */
3782 revPara.pIssuerCert = certs[0];
3783 SetLastError(0xdeadbeef);
3784 ret = CertVerifyRevocation(X509_ASN_ENCODING, CERT_CONTEXT_REVOCATION_TYPE,
3785 1, (void **)&certs[1], 0, &revPara, &status);
3786 /* Win2k thinks the cert is revoked, and it is, except the CRL is out of
3787 * date, hence the revocation status should be unknown.
3789 ok(!ret && (GetLastError() == CRYPT_E_NO_REVOCATION_CHECK ||
3790 broken(GetLastError() == CRYPT_E_REVOKED /* Win2k */)),
3791 "expected CRYPT_E_NO_REVOCATION_CHECK, got %08x\n", GetLastError());
3792 ok(status.dwError == CRYPT_E_NO_REVOCATION_CHECK ||
3793 broken(status.dwError == CRYPT_E_REVOKED /* Win2k */),
3794 "expected CRYPT_E_NO_REVOCATION_CHECK, got %08x\n", status.dwError);
3795 ok(status.dwIndex == 0, "expected index 0, got %d\n", status.dwIndex);
3796 CertCloseStore(revPara.hCrlStore, 0);
3797 CertFreeCertificateContext(certs[1]);
3798 CertFreeCertificateContext(certs[0]);
3801 static BYTE privKey[] = {
3802 0x07, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x52, 0x53, 0x41, 0x32, 0x00,
3803 0x02, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x79, 0x10, 0x1c, 0xd0, 0x6b, 0x10,
3804 0x18, 0x30, 0x94, 0x61, 0xdc, 0x0e, 0xcb, 0x96, 0x4e, 0x21, 0x3f, 0x79, 0xcd,
3805 0xa9, 0x17, 0x62, 0xbc, 0xbb, 0x61, 0x4c, 0xe0, 0x75, 0x38, 0x6c, 0xf3, 0xde,
3806 0x60, 0x86, 0x03, 0x97, 0x65, 0xeb, 0x1e, 0x6b, 0xdb, 0x53, 0x85, 0xad, 0x68,
3807 0x21, 0xf1, 0x5d, 0xe7, 0x1f, 0xe6, 0x53, 0xb4, 0xbb, 0x59, 0x3e, 0x14, 0x27,
3808 0xb1, 0x83, 0xa7, 0x3a, 0x54, 0xe2, 0x8f, 0x65, 0x8e, 0x6a, 0x4a, 0xcf, 0x3b,
3809 0x1f, 0x65, 0xff, 0xfe, 0xf1, 0x31, 0x3a, 0x37, 0x7a, 0x8b, 0xcb, 0xc6, 0xd4,
3810 0x98, 0x50, 0x36, 0x67, 0xe4, 0xa1, 0xe8, 0x7e, 0x8a, 0xc5, 0x23, 0xf2, 0x77,
3811 0xf5, 0x37, 0x61, 0x49, 0x72, 0x59, 0xe8, 0x3d, 0xf7, 0x60, 0xb2, 0x77, 0xca,
3812 0x78, 0x54, 0x6d, 0x65, 0x9e, 0x03, 0x97, 0x1b, 0x61, 0xbd, 0x0c, 0xd8, 0x06,
3813 0x63, 0xe2, 0xc5, 0x48, 0xef, 0xb3, 0xe2, 0x6e, 0x98, 0x7d, 0xbd, 0x4e, 0x72,
3814 0x91, 0xdb, 0x31, 0x57, 0xe3, 0x65, 0x3a, 0x49, 0xca, 0xec, 0xd2, 0x02, 0x4e,
3815 0x22, 0x7e, 0x72, 0x8e, 0xf9, 0x79, 0x84, 0x82, 0xdf, 0x7b, 0x92, 0x2d, 0xaf,
3816 0xc9, 0xe4, 0x33, 0xef, 0x89, 0x5c, 0x66, 0x99, 0xd8, 0x80, 0x81, 0x47, 0x2b,
3817 0xb1, 0x66, 0x02, 0x84, 0x59, 0x7b, 0xc3, 0xbe, 0x98, 0x45, 0x4a, 0x3d, 0xdd,
3818 0xea, 0x2b, 0xdf, 0x4e, 0xb4, 0x24, 0x6b, 0xec, 0xe7, 0xd9, 0x0c, 0x45, 0xb8,
3819 0xbe, 0xca, 0x69, 0x37, 0x92, 0x4c, 0x38, 0x6b, 0x96, 0x6d, 0xcd, 0x86, 0x67,
3820 0x5c, 0xea, 0x54, 0x94, 0xa4, 0xca, 0xa4, 0x02, 0xa5, 0x21, 0x4d, 0xae, 0x40,
3821 0x8f, 0x9d, 0x51, 0x83, 0xf2, 0x3f, 0x33, 0xc1, 0x72, 0xb4, 0x1d, 0x94, 0x6e,
3822 0x7d, 0xe4, 0x27, 0x3f, 0xea, 0xff, 0xe5, 0x9b, 0xa7, 0x5e, 0x55, 0x8e, 0x0d,
3823 0x69, 0x1c, 0x7a, 0xff, 0x81, 0x9d, 0x53, 0x52, 0x97, 0x9a, 0x76, 0x79, 0xda,
3824 0x93, 0x32, 0x16, 0xec, 0x69, 0x51, 0x1a, 0x4e, 0xc3, 0xf1, 0x72, 0x80, 0x78,
3825 0x5e, 0x66, 0x4a, 0x8d, 0x85, 0x2f, 0x3f, 0xb2, 0xa7 };
3827 static const BYTE exportedPublicKeyBlob[] = {
3828 0x06,0x02,0x00,0x00,0x00,0xa4,0x00,0x00,0x52,0x53,0x41,0x31,0x00,0x02,0x00,0x00,
3829 0x01,0x00,0x01,0x00,0x79,0x10,0x1c,0xd0,0x6b,0x10,0x18,0x30,0x94,0x61,0xdc,0x0e,
3830 0xcb,0x96,0x4e,0x21,0x3f,0x79,0xcd,0xa9,0x17,0x62,0xbc,0xbb,0x61,0x4c,0xe0,0x75,
3831 0x38,0x6c,0xf3,0xde,0x60,0x86,0x03,0x97,0x65,0xeb,0x1e,0x6b,0xdb,0x53,0x85,0xad,
3832 0x68,0x21,0xf1,0x5d,0xe7,0x1f,0xe6,0x53,0xb4,0xbb,0x59,0x3e,0x14,0x27,0xb1,0x83,
3833 0xa7,0x3a,0x54,0xe2 };
3835 static const BYTE asnEncodedPublicKey[] = {
3836 0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7,0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,
3837 0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21,0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,
3838 0x65,0x97,0x03,0x86,0x60,0xde,0xf3,0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,
3839 0x17,0xa9,0xcd,0x79,0x3f,0x21,0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,
3840 0x6b,0xd0,0x1c,0x10,0x79,0x02,0x03,0x01,0x00,0x01 };
3842 static void testAcquireCertPrivateKey(void)
3844 BOOL ret;
3845 PCCERT_CONTEXT cert;
3846 HCRYPTPROV csp;
3847 DWORD size, keySpec;
3848 BOOL callerFree;
3849 CRYPT_KEY_PROV_INFO keyProvInfo;
3850 HCRYPTKEY key;
3851 WCHAR ms_def_prov_w[MAX_PATH];
3853 if (!pCryptAcquireCertificatePrivateKey)
3855 win_skip("CryptAcquireCertificatePrivateKey() is not available\n");
3856 return;
3859 lstrcpyW(ms_def_prov_w, MS_DEF_PROV_W);
3861 keyProvInfo.pwszContainerName = cspNameW;
3862 keyProvInfo.pwszProvName = ms_def_prov_w;
3863 keyProvInfo.dwProvType = PROV_RSA_FULL;
3864 keyProvInfo.dwFlags = 0;
3865 keyProvInfo.cProvParam = 0;
3866 keyProvInfo.rgProvParam = NULL;
3867 keyProvInfo.dwKeySpec = AT_SIGNATURE;
3869 pCryptAcquireContextA(NULL, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
3870 CRYPT_DELETEKEYSET);
3872 cert = CertCreateCertificateContext(X509_ASN_ENCODING, selfSignedCert,
3873 sizeof(selfSignedCert));
3875 /* Crash
3876 ret = pCryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, NULL, NULL);
3877 ret = pCryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, NULL,
3878 &callerFree);
3879 ret = pCryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, &keySpec,
3880 NULL);
3881 ret = pCryptAcquireCertificatePrivateKey(NULL, 0, NULL, &csp, NULL, NULL);
3882 ret = pCryptAcquireCertificatePrivateKey(NULL, 0, NULL, &csp, &keySpec,
3883 &callerFree);
3884 ret = pCryptAcquireCertificatePrivateKey(cert, 0, NULL, NULL, NULL, NULL);
3887 /* Missing private key */
3888 ret = pCryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, NULL, NULL);
3889 ok(!ret && (GetLastError() == CRYPT_E_NO_KEY_PROPERTY || GetLastError() == NTE_BAD_PROV_TYPE /* win10 */),
3890 "Expected CRYPT_E_NO_KEY_PROPERTY, got %08x\n", GetLastError());
3891 ret = pCryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, &keySpec,
3892 &callerFree);
3893 ok(!ret && (GetLastError() == CRYPT_E_NO_KEY_PROPERTY || GetLastError() == NTE_BAD_PROV_TYPE /* win10 */),
3894 "Expected CRYPT_E_NO_KEY_PROPERTY, got %08x\n", GetLastError());
3895 CertSetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, 0,
3896 &keyProvInfo);
3897 ret = pCryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, &keySpec,
3898 &callerFree);
3899 ok(!ret && (GetLastError() == CRYPT_E_NO_KEY_PROPERTY ||
3900 GetLastError() == NTE_BAD_KEYSET /* win8 */ ||
3901 GetLastError() == NTE_BAD_PROV_TYPE /* win10 */),
3902 "Expected CRYPT_E_NO_KEY_PROPERTY, got %08x\n", GetLastError());
3904 pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
3905 CRYPT_NEWKEYSET);
3906 ret = CryptImportKey(csp, privKey, sizeof(privKey), 0, 0, &key);
3907 ok(ret, "CryptImportKey failed: %08x\n", GetLastError());
3908 if (ret)
3910 HCRYPTPROV certCSP;
3911 DWORD size;
3912 CERT_KEY_CONTEXT keyContext;
3914 /* Don't cache provider */
3915 ret = pCryptAcquireCertificatePrivateKey(cert, 0, NULL, &certCSP,
3916 &keySpec, &callerFree);
3917 ok(ret ||
3918 broken(!ret), /* win95 */
3919 "CryptAcquireCertificatePrivateKey failed: %08x\n",
3920 GetLastError());
3921 if (ret)
3923 ok(callerFree, "Expected callerFree to be TRUE\n");
3924 CryptReleaseContext(certCSP, 0);
3927 ret = pCryptAcquireCertificatePrivateKey(cert, 0, NULL, &certCSP,
3928 NULL, NULL);
3929 ok(ret ||
3930 broken(!ret), /* win95 */
3931 "CryptAcquireCertificatePrivateKey failed: %08x\n",
3932 GetLastError());
3933 CryptReleaseContext(certCSP, 0);
3935 /* Use the key prov info's caching (there shouldn't be any) */
3936 ret = pCryptAcquireCertificatePrivateKey(cert,
3937 CRYPT_ACQUIRE_USE_PROV_INFO_FLAG, NULL, &certCSP, &keySpec,
3938 &callerFree);
3939 ok(ret ||
3940 broken(!ret), /* win95 */
3941 "CryptAcquireCertificatePrivateKey failed: %08x\n",
3942 GetLastError());
3943 if (ret)
3945 ok(callerFree, "Expected callerFree to be TRUE\n");
3946 CryptReleaseContext(certCSP, 0);
3949 /* Cache it (and check that it's cached) */
3950 ret = pCryptAcquireCertificatePrivateKey(cert,
3951 CRYPT_ACQUIRE_CACHE_FLAG, NULL, &certCSP, &keySpec, &callerFree);
3952 ok(ret ||
3953 broken(!ret), /* win95 */
3954 "CryptAcquireCertificatePrivateKey failed: %08x\n",
3955 GetLastError());
3956 ok(!callerFree, "Expected callerFree to be FALSE\n");
3957 size = sizeof(keyContext);
3958 ret = CertGetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID,
3959 &keyContext, &size);
3960 ok(ret ||
3961 broken(!ret), /* win95 */
3962 "CertGetCertificateContextProperty failed: %08x\n",
3963 GetLastError());
3965 /* Remove the cached provider */
3966 CryptReleaseContext(keyContext.hCryptProv, 0);
3967 CertSetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID, 0,
3968 NULL);
3969 /* Allow caching via the key prov info */
3970 keyProvInfo.dwFlags = CERT_SET_KEY_CONTEXT_PROP_ID;
3971 CertSetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, 0,
3972 &keyProvInfo);
3973 /* Now use the key prov info's caching */
3974 ret = pCryptAcquireCertificatePrivateKey(cert,
3975 CRYPT_ACQUIRE_USE_PROV_INFO_FLAG, NULL, &certCSP, &keySpec,
3976 &callerFree);
3977 ok(ret ||
3978 broken(!ret), /* win95 */
3979 "CryptAcquireCertificatePrivateKey failed: %08x\n",
3980 GetLastError());
3981 ok(!callerFree, "Expected callerFree to be FALSE\n");
3982 size = sizeof(keyContext);
3983 ret = CertGetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID,
3984 &keyContext, &size);
3985 ok(ret ||
3986 broken(!ret), /* win95 */
3987 "CertGetCertificateContextProperty failed: %08x\n",
3988 GetLastError());
3989 CryptReleaseContext(certCSP, 0);
3991 CryptDestroyKey(key);
3994 /* Some sanity-checking on public key exporting */
3995 ret = CryptImportPublicKeyInfo(csp, X509_ASN_ENCODING,
3996 &cert->pCertInfo->SubjectPublicKeyInfo, &key);
3997 ok(ret, "CryptImportPublicKeyInfo failed: %08x\n", GetLastError());
3998 if (ret)
4000 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &size);
4001 ok(ret, "CryptExportKey failed: %08x\n", GetLastError());
4002 if (ret)
4004 LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, size), encodedKey;
4006 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, buf, &size);
4007 ok(ret, "CryptExportKey failed: %08x\n", GetLastError());
4008 ok(size == sizeof(exportedPublicKeyBlob), "Unexpected size %d\n",
4009 size);
4010 ok(!memcmp(buf, exportedPublicKeyBlob, size), "Unexpected value\n");
4011 ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, RSA_CSP_PUBLICKEYBLOB,
4012 buf, CRYPT_ENCODE_ALLOC_FLAG, NULL, &encodedKey, &size);
4013 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4014 if (ret)
4016 ok(size == sizeof(asnEncodedPublicKey), "Unexpected size %d\n",
4017 size);
4018 ok(!memcmp(encodedKey, asnEncodedPublicKey, size),
4019 "Unexpected value\n");
4020 LocalFree(encodedKey);
4022 HeapFree(GetProcessHeap(), 0, buf);
4024 CryptDestroyKey(key);
4026 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
4027 NULL, 0, NULL, NULL, &size);
4028 ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
4029 if (ret)
4031 PCERT_PUBLIC_KEY_INFO info = HeapAlloc(GetProcessHeap(), 0, size);
4033 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
4034 NULL, 0, NULL, info, &size);
4035 ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
4036 if (ret)
4038 ok(info->PublicKey.cbData == sizeof(asnEncodedPublicKey),
4039 "Unexpected size %d\n", info->PublicKey.cbData);
4040 ok(!memcmp(info->PublicKey.pbData, asnEncodedPublicKey,
4041 info->PublicKey.cbData), "Unexpected value\n");
4043 HeapFree(GetProcessHeap(), 0, info);
4046 CryptReleaseContext(csp, 0);
4047 pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
4048 CRYPT_DELETEKEYSET);
4050 CertFreeCertificateContext(cert);
4053 static void testGetPublicKeyLength(void)
4055 static char oid_rsa_rsa[] = szOID_RSA_RSA;
4056 static char oid_rsa_dh[] = szOID_RSA_DH;
4057 static char bogusOID[] = "1.2.3";
4058 DWORD ret;
4059 CERT_PUBLIC_KEY_INFO info = { { 0 } };
4060 BYTE bogusKey[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
4061 BYTE key[] = { 0x30,0x0f,0x02,0x08,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
4062 0x02,0x03,0x01,0x00,0x01 };
4064 /* Crashes
4065 ret = CertGetPublicKeyLength(0, NULL);
4067 /* With an empty public key info */
4068 SetLastError(0xdeadbeef);
4069 ret = CertGetPublicKeyLength(0, &info);
4070 ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
4071 "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
4072 ret, GetLastError());
4073 SetLastError(0xdeadbeef);
4074 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
4075 ok(ret == 0 &&
4076 (GetLastError() == CRYPT_E_ASN1_EOD ||
4077 GetLastError() == OSS_BAD_ARG), /* win9x */
4078 "Expected length 0 and CRYPT_E_ASN1_EOD, got length %d, %08x\n",
4079 ret, GetLastError());
4080 /* With a nearly-empty public key info */
4081 info.Algorithm.pszObjId = oid_rsa_rsa;
4082 SetLastError(0xdeadbeef);
4083 ret = CertGetPublicKeyLength(0, &info);
4084 ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
4085 "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
4086 ret, GetLastError());
4087 SetLastError(0xdeadbeef);
4088 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
4089 ok(ret == 0 &&
4090 (GetLastError() == CRYPT_E_ASN1_EOD ||
4091 GetLastError() == OSS_BAD_ARG), /* win9x */
4092 "Expected length 0 and CRYPT_E_ASN1_EOD, got length %d, %08x\n",
4093 ret, GetLastError());
4094 /* With a bogus key */
4095 info.PublicKey.cbData = sizeof(bogusKey);
4096 info.PublicKey.pbData = bogusKey;
4097 SetLastError(0xdeadbeef);
4098 ret = CertGetPublicKeyLength(0, &info);
4099 ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
4100 "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
4101 ret, GetLastError());
4102 SetLastError(0xdeadbeef);
4103 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
4104 ok(ret == 0 &&
4105 (GetLastError() == CRYPT_E_ASN1_BADTAG ||
4106 GetLastError() == OSS_PDU_MISMATCH), /* win9x */
4107 "Expected length 0 and CRYPT_E_ASN1_BADTAGTAG, got length %d, %08x\n",
4108 ret, GetLastError());
4109 /* With a believable RSA key but a bogus OID */
4110 info.Algorithm.pszObjId = bogusOID;
4111 info.PublicKey.cbData = sizeof(key);
4112 info.PublicKey.pbData = key;
4113 SetLastError(0xdeadbeef);
4114 ret = CertGetPublicKeyLength(0, &info);
4115 ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
4116 "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
4117 ret, GetLastError());
4118 SetLastError(0xdeadbeef);
4119 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
4120 ok(ret == 56 || broken(ret == 0 && GetLastError() == NTE_BAD_LEN) /* Win7 */,
4121 "Expected length 56, got %d\n", ret);
4122 /* An RSA key with the DH OID */
4123 info.Algorithm.pszObjId = oid_rsa_dh;
4124 SetLastError(0xdeadbeef);
4125 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
4126 ok(ret == 0 &&
4127 (GetLastError() == CRYPT_E_ASN1_BADTAG ||
4128 GetLastError() == E_INVALIDARG), /* win9x */
4129 "Expected length 0 and CRYPT_E_ASN1_BADTAG, got length %d, %08x\n",
4130 ret, GetLastError());
4131 /* With the RSA OID */
4132 info.Algorithm.pszObjId = oid_rsa_rsa;
4133 SetLastError(0xdeadbeef);
4134 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
4135 ok(ret == 56 || broken(ret == 0 && GetLastError() == NTE_BAD_LEN) /* Win7 */,
4136 "Expected length 56, got %d\n", ret);
4137 /* With the RSA OID and a message encoding */
4138 info.Algorithm.pszObjId = oid_rsa_rsa;
4139 SetLastError(0xdeadbeef);
4140 ret = CertGetPublicKeyLength(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, &info);
4141 ok(ret == 56 || broken(ret == 0 && GetLastError() == NTE_BAD_LEN) /* Win7 */,
4142 "Expected length 56, got %d\n", ret);
4145 static void testKeyProvInfo(void)
4147 static WCHAR containerW[] = L"Wine Test Container";
4148 static WCHAR providerW[] = L"Hello World CSP";
4149 static CRYPT_KEY_PROV_PARAM param[2] = { { 0x4444, (BYTE *)"param", 6, 0x5555 }, { 0x7777, (BYTE *)"param2", 7, 0x8888 } };
4150 HCERTSTORE store;
4151 const CERT_CONTEXT *cert;
4152 CERT_NAME_BLOB name;
4153 CRYPT_KEY_PROV_INFO *info, info2;
4154 BOOL ret;
4155 DWORD size;
4157 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, 0,
4158 CERT_SYSTEM_STORE_CURRENT_USER, "My");
4159 ok(store != NULL, "CertOpenStore error %u\n", GetLastError());
4161 cert = CertCreateCertificateContext(X509_ASN_ENCODING, selfSignedCert, sizeof(selfSignedCert));
4162 ok(cert != NULL, "CertCreateCertificateContext error %#x\n", GetLastError());
4164 info2.pwszContainerName = containerW;
4165 info2.pwszProvName = providerW;
4166 info2.dwProvType = 0x12345678;
4167 info2.dwFlags = 0x87654321;
4168 info2.cProvParam = ARRAY_SIZE(param);
4169 info2.rgProvParam = param;
4170 info2.dwKeySpec = 0x11223344;
4171 ret = CertSetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, 0, &info2);
4172 ok(ret, "CertSetCertificateContextProperty error %#x\n", GetLastError());
4174 ret = CertGetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
4175 ok(ret, "CertGetCertificateContextProperty error %#x\n", GetLastError());
4176 info = HeapAlloc(GetProcessHeap(), 0, size);
4177 ret = CertGetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, info, &size);
4178 ok(ret, "CertGetCertificateContextProperty error %#x\n", GetLastError());
4179 ok(!lstrcmpW(info->pwszContainerName, containerW), "got %s\n", wine_dbgstr_w(info->pwszContainerName));
4180 ok(!lstrcmpW(info->pwszProvName, providerW), "got %s\n", wine_dbgstr_w(info->pwszProvName));
4181 ok(info->dwProvType == 0x12345678, "got %#x\n", info->dwProvType);
4182 ok(info->dwFlags == 0x87654321, "got %#x\n", info->dwFlags);
4183 ok(info->dwKeySpec == 0x11223344, "got %#x\n", info->dwKeySpec);
4184 ok(info->cProvParam == 2, "got %#x\n", info->cProvParam);
4185 ok(info->rgProvParam != NULL, "got %p\n", info->rgProvParam);
4186 ok(info->rgProvParam[0].dwParam == param[0].dwParam, "got %#x\n", info->rgProvParam[0].dwParam);
4187 ok(info->rgProvParam[0].cbData == param[0].cbData, "got %#x\n", info->rgProvParam[0].cbData);
4188 ok(!memcmp(info->rgProvParam[0].pbData, param[0].pbData, param[0].cbData), "param1 mismatch\n");
4189 ok(info->rgProvParam[0].dwFlags == param[0].dwFlags, "got %#x\n", info->rgProvParam[1].dwFlags);
4190 ok(info->rgProvParam[1].dwParam == param[1].dwParam, "got %#x\n", info->rgProvParam[1].dwParam);
4191 ok(info->rgProvParam[1].cbData == param[1].cbData, "got %#x\n", info->rgProvParam[1].cbData);
4192 ok(!memcmp(info->rgProvParam[1].pbData, param[1].pbData, param[1].cbData), "param2 mismatch\n");
4193 ok(info->rgProvParam[1].dwFlags == param[1].dwFlags, "got %#x\n", info->rgProvParam[1].dwFlags);
4194 HeapFree(GetProcessHeap(), 0, info);
4196 ret = CertAddCertificateContextToStore(store, cert, CERT_STORE_ADD_NEW, NULL);
4197 ok(ret, "CertAddCertificateContextToStore error %#x\n", GetLastError());
4199 CertFreeCertificateContext(cert);
4200 CertCloseStore(store, 0);
4202 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, 0,
4203 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, "My");
4204 ok(store != NULL, "CertOpenStore error %u\n", GetLastError());
4206 name.pbData = subjectName;
4207 name.cbData = sizeof(subjectName);
4208 cert = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0, CERT_FIND_SUBJECT_NAME, &name, NULL);
4209 ok(cert != NULL, "certificate should exist in My store\n");
4211 ret = CertGetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
4212 ok(ret, "CertGetCertificateContextProperty error %#x\n", GetLastError());
4213 info = HeapAlloc(GetProcessHeap(), 0, size);
4214 ret = CertGetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, info, &size);
4215 ok(ret, "CertGetCertificateContextProperty error %#x\n", GetLastError());
4216 ok(!lstrcmpW(info->pwszContainerName, containerW), "got %s\n", wine_dbgstr_w(info->pwszContainerName));
4217 ok(!lstrcmpW(info->pwszProvName, providerW), "got %s\n", wine_dbgstr_w(info->pwszProvName));
4218 ok(info->dwProvType == 0x12345678, "got %#x\n", info->dwProvType);
4219 ok(info->dwFlags == 0x87654321, "got %#x\n", info->dwFlags);
4220 ok(info->dwKeySpec == 0x11223344, "got %#x\n", info->dwKeySpec);
4221 ok(info->cProvParam == 2, "got %#x\n", info->cProvParam);
4222 ok(info->rgProvParam != NULL, "got %p\n", info->rgProvParam);
4223 ok(info->rgProvParam[0].dwParam == param[0].dwParam, "got %#x\n", info->rgProvParam[0].dwParam);
4224 ok(info->rgProvParam[0].cbData == param[0].cbData, "got %#x\n", info->rgProvParam[0].cbData);
4225 ok(!memcmp(info->rgProvParam[0].pbData, param[0].pbData, param[0].cbData), "param1 mismatch\n");
4226 ok(info->rgProvParam[0].dwFlags == param[0].dwFlags, "got %#x\n", info->rgProvParam[1].dwFlags);
4227 ok(info->rgProvParam[1].dwParam == param[1].dwParam, "got %#x\n", info->rgProvParam[1].dwParam);
4228 ok(info->rgProvParam[1].cbData == param[1].cbData, "got %#x\n", info->rgProvParam[1].cbData);
4229 ok(!memcmp(info->rgProvParam[1].pbData, param[1].pbData, param[1].cbData), "param2 mismatch\n");
4230 ok(info->rgProvParam[1].dwFlags == param[1].dwFlags, "got %#x\n", info->rgProvParam[1].dwFlags);
4231 HeapFree(GetProcessHeap(), 0, info);
4233 ret = CertDeleteCertificateFromStore(cert);
4234 ok(ret, "CertDeleteCertificateFromStore error %#x\n", GetLastError());
4236 CertFreeCertificateContext(cert);
4237 CertCloseStore(store, 0);
4240 START_TEST(cert)
4242 init_function_pointers();
4244 testAddCert();
4245 testCertProperties();
4246 testCreateCert();
4247 testDupCert();
4248 testFindCert();
4249 testGetSubjectCert();
4250 testGetIssuerCert();
4251 testLinkCert();
4252 testKeyProvInfo();
4254 testCryptHashCert();
4255 testCryptHashCert2();
4256 testCertSigs();
4257 testSignAndEncodeCert();
4258 testCreateSelfSignCert();
4259 testIntendedKeyUsage();
4260 testKeyUsage();
4261 testGetValidUsages();
4262 testCompareCertName();
4263 testCompareIntegerBlob();
4264 testComparePublicKeyInfo();
4265 testHashPublicKeyInfo();
4266 testHashToBeSigned();
4267 testCompareCert();
4268 testVerifySubjectCert();
4269 testVerifyRevocation();
4270 testAcquireCertPrivateKey();
4271 testGetPublicKeyLength();
4272 testIsRDNAttrsInCertificateName();