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