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