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