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