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