crypt32/tests: Fix a test failure on Win9x.
[wine/multimedia.git] / dlls / crypt32 / tests / cert.c
blob415f9c78dd4699d6bccf77457deadd795679f9ec
1 /*
2 * crypt32 cert functions tests
4 * Copyright 2005-2006 Juan Lang
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <assert.h>
22 #include <stdio.h>
23 #include <stdarg.h>
24 #include <windef.h>
25 #include <winbase.h>
26 #include <winreg.h>
27 #include <winerror.h>
28 #include <wincrypt.h>
30 #include "wine/test.h"
32 static BOOL (WINAPI *pCertAddStoreToCollection)(HCERTSTORE,HCERTSTORE,DWORD,DWORD);
33 static PCCERT_CONTEXT (WINAPI *pCertCreateSelfSignCertificate)(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE,PCERT_NAME_BLOB,DWORD,PCRYPT_KEY_PROV_INFO,PCRYPT_ALGORITHM_IDENTIFIER,PSYSTEMTIME,PSYSTEMTIME,PCERT_EXTENSIONS);
34 static BOOL (WINAPI *pCertGetValidUsages)(DWORD,PCCERT_CONTEXT*,int*,LPSTR*,DWORD*);
35 static BOOL (WINAPI *pCryptAcquireCertificatePrivateKey)(PCCERT_CONTEXT,DWORD,void*,HCRYPTPROV_OR_NCRYPT_KEY_HANDLE*,DWORD*,BOOL*);
36 static BOOL (WINAPI *pCryptEncodeObjectEx)(DWORD,LPCSTR,const void*,DWORD,PCRYPT_ENCODE_PARA,void*,DWORD*);
37 static BOOL (WINAPI * pCryptVerifyCertificateSignatureEx)
38 (HCRYPTPROV, DWORD, DWORD, void *, DWORD, void *, DWORD, void *);
40 static BOOL (WINAPI * pCryptAcquireContextA)
41 (HCRYPTPROV *, LPCSTR, LPCSTR, DWORD, DWORD);
43 static void init_function_pointers(void)
45 HMODULE hCrypt32 = GetModuleHandleA("crypt32.dll");
46 HMODULE hAdvapi32 = GetModuleHandleA("advapi32.dll");
48 #define GET_PROC(dll, func) \
49 p ## func = (void *)GetProcAddress(dll, #func); \
50 if(!p ## func) \
51 trace("GetProcAddress(%s) failed\n", #func);
53 GET_PROC(hCrypt32, CertAddStoreToCollection)
54 GET_PROC(hCrypt32, CertCreateSelfSignCertificate)
55 GET_PROC(hCrypt32, CertGetValidUsages)
56 GET_PROC(hCrypt32, CryptAcquireCertificatePrivateKey)
57 GET_PROC(hCrypt32, CryptEncodeObjectEx)
58 GET_PROC(hCrypt32, CryptVerifyCertificateSignatureEx)
60 GET_PROC(hAdvapi32, CryptAcquireContextA)
62 #undef GET_PROC
65 static BYTE subjectName[] = { 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
66 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
67 0x6e, 0x67, 0x00 };
68 static BYTE serialNum[] = { 1 };
69 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
70 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
71 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
72 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
73 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
74 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
75 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
76 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
77 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
78 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
79 static BYTE bigCertHash[] = { 0x6e, 0x30, 0x90, 0x71, 0x5f, 0xd9, 0x23,
80 0x56, 0xeb, 0xae, 0x25, 0x40, 0xe6, 0x22, 0xda, 0x19, 0x26, 0x02, 0xa6, 0x08 };
82 static const BYTE bigCertWithDifferentSubject[] = { 0x30, 0x7a, 0x02, 0x01, 0x02,
83 0x30, 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
84 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67,
85 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31,
86 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
87 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15,
88 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c,
89 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06,
90 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55,
91 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02,
92 0x01, 0x01 };
93 static const BYTE bigCertWithDifferentIssuer[] = { 0x30, 0x7a, 0x02, 0x01,
94 0x01, 0x30, 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
95 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e,
96 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
97 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30,
98 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30,
99 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
100 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02,
101 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03,
102 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff,
103 0x02, 0x01, 0x01 };
105 static BYTE subjectName2[] = { 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
106 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61,
107 0x6e, 0x67, 0x00 };
108 static const BYTE bigCert2[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
109 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
110 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
111 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
112 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
113 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
114 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20,
115 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
116 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
117 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
118 static const BYTE bigCert2WithDifferentSerial[] = { 0x30, 0x7a, 0x02, 0x01,
119 0x02, 0x30, 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
120 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e,
121 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
122 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30,
123 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30,
124 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41,
125 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02,
126 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03,
127 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff,
128 0x02, 0x01, 0x01 };
129 static BYTE bigCert2Hash[] = { 0x4a, 0x7f, 0x32, 0x1f, 0xcf, 0x3b, 0xc0,
130 0x87, 0x48, 0x2b, 0xa1, 0x86, 0x54, 0x18, 0xe4, 0x3a, 0x0e, 0x53, 0x7e, 0x2b };
132 static const BYTE certWithUsage[] = { 0x30, 0x81, 0x93, 0x02, 0x01, 0x01, 0x30,
133 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04,
134 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00,
135 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
136 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
137 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31,
138 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61,
139 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00,
140 0x03, 0x01, 0x00, 0xa3, 0x2f, 0x30, 0x2d, 0x30, 0x2b, 0x06, 0x03, 0x55, 0x1d,
141 0x25, 0x01, 0x01, 0xff, 0x04, 0x21, 0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01,
142 0x05, 0x05, 0x07, 0x03, 0x03, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
143 0x03, 0x02, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
145 static void testAddCert(void)
147 HCERTSTORE store;
148 HCERTSTORE collection;
149 PCCERT_CONTEXT context;
150 PCCERT_CONTEXT copyContext;
151 BOOL ret;
153 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
154 CERT_STORE_CREATE_NEW_FLAG, NULL);
155 ok(store != NULL, "CertOpenStore failed: %d\n", GetLastError());
156 if (!store)
157 return;
159 /* Weird--bad add disposition leads to an access violation in Windows.
160 * Both tests crash on some win9x boxes.
162 if (0)
164 ret = CertAddEncodedCertificateToStore(0, X509_ASN_ENCODING, bigCert,
165 sizeof(bigCert), 0, NULL);
166 ok(!ret && (GetLastError() == STATUS_ACCESS_VIOLATION ||
167 GetLastError() == E_INVALIDARG),
168 "Expected STATUS_ACCESS_VIOLATION or E_INVALIDARG, got %08x\n",
169 GetLastError());
170 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
171 bigCert, sizeof(bigCert), 0, NULL);
172 ok(!ret && (GetLastError() == STATUS_ACCESS_VIOLATION ||
173 GetLastError() == E_INVALIDARG),
174 "Expected STATUS_ACCESS_VIOLATION or E_INVALIDARG, got %08x\n",
175 GetLastError());
178 /* Weird--can add a cert to the NULL store (does this have special
179 * meaning?)
181 context = NULL;
182 ret = CertAddEncodedCertificateToStore(0, X509_ASN_ENCODING, bigCert,
183 sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
184 ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* win98 */),
185 "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
186 if (context)
187 CertFreeCertificateContext(context);
188 if (!ret && GetLastError() == OSS_DATA_ERROR)
190 skip("bigCert can't be decoded, skipping tests\n");
191 return;
194 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
195 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
196 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
197 GetLastError());
198 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
199 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, NULL);
200 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
201 GetLastError());
202 /* This has the same name as bigCert, so finding isn't done by name */
203 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
204 certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, &context);
205 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
206 GetLastError());
207 ok(context != NULL, "Expected a context\n");
208 if (context)
210 CRYPT_DATA_BLOB hash = { sizeof(bigCert2Hash), bigCert2Hash };
212 /* Duplicate (AddRef) the context so we can still use it after
213 * deleting it from the store.
215 CertDuplicateCertificateContext(context);
216 CertDeleteCertificateFromStore(context);
217 /* Set the same hash as bigCert2, and try to readd it */
218 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID,
219 0, &hash);
220 ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
221 GetLastError());
222 ret = CertAddCertificateContextToStore(store, context,
223 CERT_STORE_ADD_NEW, NULL);
224 /* The failure is a bit odd (CRYPT_E_ASN1_BADTAG), so just check
225 * that it fails.
227 ok(!ret, "Expected failure\n");
228 CertFreeCertificateContext(context);
230 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert2,
231 sizeof(bigCert2));
232 ok(context != NULL, "Expected a context\n");
233 if (context)
235 /* Try to readd bigCert2 to the store */
236 ret = CertAddCertificateContextToStore(store, context,
237 CERT_STORE_ADD_NEW, NULL);
238 ok(!ret && GetLastError() == CRYPT_E_EXISTS,
239 "Expected CRYPT_E_EXISTS, got %08x\n", GetLastError());
240 CertFreeCertificateContext(context);
243 /* Adding a cert with the same issuer name and serial number (but
244 * different subject) as an existing cert succeeds.
246 context = NULL;
247 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
248 bigCert2WithDifferentSerial, sizeof(bigCert2WithDifferentSerial),
249 CERT_STORE_ADD_NEW, &context);
250 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
251 GetLastError());
252 if (context)
253 CertDeleteCertificateFromStore(context);
255 /* Adding a cert with the same subject name and serial number (but
256 * different issuer) as an existing cert succeeds.
258 context = NULL;
259 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
260 bigCertWithDifferentSubject, sizeof(bigCertWithDifferentSubject),
261 CERT_STORE_ADD_NEW, &context);
262 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
263 GetLastError());
264 if (context)
265 CertDeleteCertificateFromStore(context);
267 /* Adding a cert with the same issuer name and serial number (but
268 * different otherwise) as an existing cert succeeds.
270 context = NULL;
271 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
272 bigCertWithDifferentIssuer, sizeof(bigCertWithDifferentIssuer),
273 CERT_STORE_ADD_NEW, &context);
274 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
275 GetLastError());
276 if (context)
277 CertDeleteCertificateFromStore(context);
279 collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
280 CERT_STORE_CREATE_NEW_FLAG, NULL);
281 ok(collection != NULL, "CertOpenStore failed: %08x\n", GetLastError());
282 if (collection && pCertAddStoreToCollection)
284 /* Add store to the collection, but disable updates */
285 pCertAddStoreToCollection(collection, store, 0, 0);
287 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert2,
288 sizeof(bigCert2));
289 ok(context != NULL, "Expected a context\n");
290 if (context)
292 /* Try to readd bigCert2 to the collection */
293 ret = CertAddCertificateContextToStore(collection, context,
294 CERT_STORE_ADD_NEW, NULL);
295 ok(!ret && GetLastError() == CRYPT_E_EXISTS,
296 "Expected CRYPT_E_EXISTS, got %08x\n", GetLastError());
297 /* Replacing an existing certificate context is allowed, even
298 * though updates to the collection aren't..
300 ret = CertAddCertificateContextToStore(collection, context,
301 CERT_STORE_ADD_REPLACE_EXISTING, NULL);
302 ok(ret, "CertAddCertificateContextToStore failed: %08x\n",
303 GetLastError());
304 /* use the existing certificate and ask for a copy of the context*/
305 copyContext = NULL;
306 ret = CertAddCertificateContextToStore(collection, context,
307 CERT_STORE_ADD_USE_EXISTING, &copyContext);
308 ok(ret, "CertAddCertificateContextToStore failed: %08x\n",
309 GetLastError());
310 ok(copyContext != NULL, "Expected on output a non NULL copyContext\n");
311 if (copyContext)
312 CertFreeCertificateContext(copyContext);
313 /* but adding a new certificate isn't allowed. */
314 ret = CertAddCertificateContextToStore(collection, context,
315 CERT_STORE_ADD_ALWAYS, NULL);
316 ok(!ret && GetLastError() == E_ACCESSDENIED,
317 "Expected E_ACCESSDENIED, got %08x\n", GetLastError());
318 CertFreeCertificateContext(context);
321 CertCloseStore(collection, 0);
324 CertCloseStore(store, 0);
327 static void checkHash(const BYTE *data, DWORD dataLen, ALG_ID algID,
328 PCCERT_CONTEXT context, DWORD propID)
330 BYTE hash[20] = { 0 }, hashProperty[20];
331 BOOL ret;
332 DWORD size;
333 DWORD dwSizeWithNull;
335 memset(hash, 0, sizeof(hash));
336 memset(hashProperty, 0, sizeof(hashProperty));
337 size = sizeof(hash);
338 ret = CryptHashCertificate(0, algID, 0, data, dataLen, hash, &size);
339 ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
340 ret = CertGetCertificateContextProperty(context, propID, NULL,
341 &dwSizeWithNull);
342 ok(ret, "algID %08x, propID %d: CertGetCertificateContextProperty failed: %08x\n",
343 algID, propID, GetLastError());
344 ret = CertGetCertificateContextProperty(context, propID, hashProperty,
345 &size);
346 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
347 GetLastError());
348 ok(!memcmp(hash, hashProperty, size), "Unexpected hash for property %d\n",
349 propID);
350 ok(size == dwSizeWithNull, "Unexpected length of hash for property: received %d instead of %d\n",
351 dwSizeWithNull,size);
354 static CHAR cspNameA[] = "WineCryptTemp";
355 static WCHAR cspNameW[] = { 'W','i','n','e','C','r','y','p','t','T','e','m','p',0 };
356 static const BYTE v1CertWithPubKey[] = {
357 0x30,0x81,0x95,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
358 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
359 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
360 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
361 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
362 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
363 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
364 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
365 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,
366 0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,
367 0x01,0x01 };
368 static const BYTE v1CertWithSubjectKeyId[] = {
369 0x30,0x7b,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
370 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
371 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
372 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
373 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
374 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
375 0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x17,0x30,0x15,0x30,
376 0x13,0x06,0x03,0x55,0x1d,0x0e,0x04,0x0c,0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,
377 0x4c,0x61,0x6e,0x67,0x00 };
378 static const BYTE subjectKeyId[] = {
379 0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
380 static const BYTE selfSignedCert[] = {
381 0x30, 0x82, 0x01, 0x1f, 0x30, 0x81, 0xce, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
382 0x10, 0xeb, 0x0d, 0x57, 0x2a, 0x9c, 0x09, 0xba, 0xa4, 0x4a, 0xb7, 0x25, 0x49,
383 0xd9, 0x3e, 0xb5, 0x73, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d,
384 0x05, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
385 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30,
386 0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x36, 0x32, 0x39, 0x30, 0x35, 0x30, 0x30,
387 0x34, 0x36, 0x5a, 0x17, 0x0d, 0x30, 0x37, 0x30, 0x36, 0x32, 0x39, 0x31, 0x31,
388 0x30, 0x30, 0x34, 0x36, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
389 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e,
390 0x67, 0x00, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
391 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
392 0x00, 0xe2, 0x54, 0x3a, 0xa7, 0x83, 0xb1, 0x27, 0x14, 0x3e, 0x59, 0xbb, 0xb4,
393 0x53, 0xe6, 0x1f, 0xe7, 0x5d, 0xf1, 0x21, 0x68, 0xad, 0x85, 0x53, 0xdb, 0x6b,
394 0x1e, 0xeb, 0x65, 0x97, 0x03, 0x86, 0x60, 0xde, 0xf3, 0x6c, 0x38, 0x75, 0xe0,
395 0x4c, 0x61, 0xbb, 0xbc, 0x62, 0x17, 0xa9, 0xcd, 0x79, 0x3f, 0x21, 0x4e, 0x96,
396 0xcb, 0x0e, 0xdc, 0x61, 0x94, 0x30, 0x18, 0x10, 0x6b, 0xd0, 0x1c, 0x10, 0x79,
397 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
398 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x25, 0x90, 0x53, 0x34, 0xd9, 0x56, 0x41,
399 0x5e, 0xdb, 0x7e, 0x01, 0x36, 0xec, 0x27, 0x61, 0x5e, 0xb7, 0x4d, 0x90, 0x66,
400 0xa2, 0xe1, 0x9d, 0x58, 0x76, 0xd4, 0x9c, 0xba, 0x2c, 0x84, 0xc6, 0x83, 0x7a,
401 0x22, 0x0d, 0x03, 0x69, 0x32, 0x1a, 0x6d, 0xcb, 0x0c, 0x15, 0xb3, 0x6b, 0xc7,
402 0x0a, 0x8c, 0xb4, 0x5c, 0x34, 0x78, 0xe0, 0x3c, 0x9c, 0xe9, 0xf3, 0x30, 0x9f,
403 0xa8, 0x76, 0x57, 0x92, 0x36 };
404 static const BYTE selfSignedSignatureHash[] = { 0x07,0x5a,0x3e,0xfd,0x0d,0xf6,
405 0x88,0xeb,0x00,0x64,0xbd,0xc9,0xd6,0xea,0x0a,0x7c,0xcc,0x24,0xdb,0x5d };
407 static void testCertProperties(void)
409 PCCERT_CONTEXT context = CertCreateCertificateContext(X509_ASN_ENCODING,
410 bigCert, sizeof(bigCert));
411 DWORD propID, numProps, access, size;
412 BOOL ret;
413 BYTE hash[20] = { 0 }, hashProperty[20];
414 CRYPT_DATA_BLOB blob;
415 CERT_KEY_CONTEXT keyContext;
417 ok(context != NULL || broken(GetLastError() == OSS_DATA_ERROR /* win98 */),
418 "CertCreateCertificateContext failed: %08x\n", GetLastError());
419 if (!context)
420 return;
422 /* This crashes
423 propID = CertEnumCertificateContextProperties(NULL, 0);
426 propID = 0;
427 numProps = 0;
428 do {
429 propID = CertEnumCertificateContextProperties(context, propID);
430 if (propID)
431 numProps++;
432 } while (propID != 0);
433 ok(numProps == 0, "Expected 0 properties, got %d\n", numProps);
435 /* Tests with a NULL cert context. Prop ID 0 fails.. */
436 ret = CertSetCertificateContextProperty(NULL, 0, 0, NULL);
437 ok(!ret && GetLastError() == E_INVALIDARG,
438 "Expected E_INVALIDARG, got %08x\n", GetLastError());
439 /* while this just crashes.
440 ret = CertSetCertificateContextProperty(NULL,
441 CERT_KEY_PROV_HANDLE_PROP_ID, 0, NULL);
444 ret = CertSetCertificateContextProperty(context, 0, 0, NULL);
445 ok(!ret && GetLastError() == E_INVALIDARG,
446 "Expected E_INVALIDARG, got %08x\n", GetLastError());
447 /* Can't set the cert property directly, this crashes.
448 ret = CertSetCertificateContextProperty(context,
449 CERT_CERT_PROP_ID, 0, bigCert2);
452 /* These all crash.
453 ret = CertGetCertificateContextProperty(context,
454 CERT_ACCESS_STATE_PROP_ID, 0, NULL);
455 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
456 NULL, NULL);
457 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
458 hashProperty, NULL);
460 /* A missing prop */
461 size = 0;
462 ret = CertGetCertificateContextProperty(context,
463 CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
464 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
465 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
466 /* And, an implicit property */
467 size = sizeof(access);
468 ret = CertGetCertificateContextProperty(context,
469 CERT_ACCESS_STATE_PROP_ID, &access, &size);
470 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
471 GetLastError());
472 ok(!(access & CERT_ACCESS_STATE_WRITE_PERSIST_FLAG),
473 "Didn't expect a persisted cert\n");
474 /* Trying to set this "read only" property crashes.
475 access |= CERT_ACCESS_STATE_WRITE_PERSIST_FLAG;
476 ret = CertSetCertificateContextProperty(context,
477 CERT_ACCESS_STATE_PROP_ID, 0, &access);
480 /* Can I set the hash to an invalid hash? */
481 blob.pbData = hash;
482 blob.cbData = sizeof(hash);
483 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID, 0,
484 &blob);
485 ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
486 GetLastError());
487 size = sizeof(hashProperty);
488 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
489 hashProperty, &size);
490 ok(!memcmp(hashProperty, hash, sizeof(hash)), "Unexpected hash\n");
491 /* Delete the (bogus) hash, and get the real one */
492 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID, 0,
493 NULL);
494 ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
495 GetLastError());
496 checkHash(bigCert, sizeof(bigCert), CALG_SHA1, context,
497 CERT_HASH_PROP_ID);
499 /* Now that the hash property is set, we should get one property when
500 * enumerating.
502 propID = 0;
503 numProps = 0;
504 do {
505 propID = CertEnumCertificateContextProperties(context, propID);
506 if (propID)
507 numProps++;
508 } while (propID != 0);
509 ok(numProps == 1, "Expected 1 properties, got %d\n", numProps);
511 /* Check a few other implicit properties */
512 checkHash(bigCert, sizeof(bigCert), CALG_MD5, context,
513 CERT_MD5_HASH_PROP_ID);
515 /* Getting the signature hash fails with this bogus certificate */
516 size = 0;
517 ret = CertGetCertificateContextProperty(context,
518 CERT_SIGNATURE_HASH_PROP_ID, NULL, &size);
519 ok(!ret &&
520 (GetLastError() == CRYPT_E_ASN1_BADTAG ||
521 GetLastError() == CRYPT_E_NOT_FOUND ||
522 GetLastError() == OSS_DATA_ERROR), /* win9x */
523 "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
525 /* Test key contexts and handles and such */
526 size = 0;
527 ret = CertGetCertificateContextProperty(context, CERT_KEY_CONTEXT_PROP_ID,
528 NULL, &size);
529 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
530 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
531 size = sizeof(CERT_KEY_CONTEXT);
532 ret = CertGetCertificateContextProperty(context, CERT_KEY_CONTEXT_PROP_ID,
533 NULL, &size);
534 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
535 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
536 ret = CertGetCertificateContextProperty(context, CERT_KEY_CONTEXT_PROP_ID,
537 &keyContext, &size);
538 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
539 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
540 /* Key context with an invalid size */
541 keyContext.cbSize = 0;
542 ret = CertSetCertificateContextProperty(context, CERT_KEY_CONTEXT_PROP_ID,
543 0, &keyContext);
544 ok(!ret && GetLastError() == E_INVALIDARG,
545 "Expected E_INVALIDARG, got %08x\n", GetLastError());
546 size = sizeof(keyContext);
547 ret = CertGetCertificateContextProperty(context, CERT_KEY_CONTEXT_PROP_ID,
548 &keyContext, &size);
549 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
550 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
551 keyContext.cbSize = sizeof(keyContext);
552 keyContext.hCryptProv = 0;
553 keyContext.dwKeySpec = AT_SIGNATURE;
554 ret = CertSetCertificateContextProperty(context, CERT_KEY_CONTEXT_PROP_ID,
555 0, &keyContext);
556 ok(ret, "CertSetCertificateContextProperty failed: %08x\n", GetLastError());
557 /* Now that that's set, the key prov handle property is also gettable.
559 size = sizeof(keyContext.hCryptProv);
560 ret = CertGetCertificateContextProperty(context,
561 CERT_KEY_PROV_HANDLE_PROP_ID, &keyContext.hCryptProv, &size);
562 ok(ret, "Expected to get the CERT_KEY_PROV_HANDLE_PROP_ID, got %08x\n",
563 GetLastError());
564 /* Remove the key prov handle property.. */
565 ret = CertSetCertificateContextProperty(context,
566 CERT_KEY_PROV_HANDLE_PROP_ID, 0, NULL);
567 ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
568 GetLastError());
569 /* and the key context's CSP is set to NULL. */
570 size = sizeof(keyContext);
571 ret = CertGetCertificateContextProperty(context,
572 CERT_KEY_CONTEXT_PROP_ID, &keyContext, &size);
573 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
574 GetLastError());
575 ok(keyContext.hCryptProv == 0, "Expected no hCryptProv\n");
577 /* According to MSDN the subject key id can be stored as a property,
578 * as a subject key extension, or as the SHA1 hash of the public key,
579 * but this cert has none of them:
581 ret = CertGetCertificateContextProperty(context,
582 CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size);
583 ok(!ret && GetLastError() == ERROR_INVALID_DATA,
584 "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
585 CertFreeCertificateContext(context);
586 /* This cert does have a public key, but its subject key identifier still
587 * isn't available: */
588 context = CertCreateCertificateContext(X509_ASN_ENCODING,
589 v1CertWithPubKey, sizeof(v1CertWithPubKey));
590 ret = CertGetCertificateContextProperty(context,
591 CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size);
592 ok(!ret && GetLastError() == ERROR_INVALID_DATA,
593 "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
594 CertFreeCertificateContext(context);
595 /* This cert with a subject key extension can have its key identifier
596 * property retrieved:
598 context = CertCreateCertificateContext(X509_ASN_ENCODING,
599 v1CertWithSubjectKeyId, sizeof(v1CertWithSubjectKeyId));
600 ret = CertGetCertificateContextProperty(context,
601 CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size);
602 ok(ret, "CertGetCertificateContextProperty failed: %08x\n", GetLastError());
603 if (ret)
605 LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, size);
607 if (buf)
609 ret = CertGetCertificateContextProperty(context,
610 CERT_KEY_IDENTIFIER_PROP_ID, buf, &size);
611 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
612 GetLastError());
613 ok(!memcmp(buf, subjectKeyId, size), "Unexpected subject key id\n");
614 HeapFree(GetProcessHeap(), 0, buf);
617 CertFreeCertificateContext(context);
619 context = CertCreateCertificateContext(X509_ASN_ENCODING,
620 selfSignedCert, sizeof(selfSignedCert));
621 /* Getting the signature hash of a valid (self-signed) cert succeeds */
622 size = 0;
623 ret = CertGetCertificateContextProperty(context,
624 CERT_SIGNATURE_HASH_PROP_ID, NULL, &size);
625 ok(ret, "CertGetCertificateContextProperty failed: %08x\n", GetLastError());
626 ok(size == sizeof(selfSignedSignatureHash), "unexpected size %d\n", size);
627 ret = CertGetCertificateContextProperty(context,
628 CERT_SIGNATURE_HASH_PROP_ID, hashProperty, &size);
629 if (ret)
630 ok(!memcmp(hashProperty, selfSignedSignatureHash, size),
631 "unexpected value\n");
632 CertFreeCertificateContext(context);
635 static void testDupCert(void)
637 HCERTSTORE store;
638 PCCERT_CONTEXT context, dupContext;
639 BOOL ret;
641 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
642 CERT_STORE_CREATE_NEW_FLAG, NULL);
643 ok(store != NULL, "CertOpenStore failed: %d\n", GetLastError());
644 if (!store)
645 return;
647 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
648 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
649 ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* win98 */),
650 "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
651 if (!ret && GetLastError() == OSS_DATA_ERROR)
653 skip("bigCert can't be decoded, skipping tests\n");
654 return;
656 ok(context != NULL, "Expected a valid cert context\n");
657 if (context)
659 ok(context->cbCertEncoded == sizeof(bigCert),
660 "Wrong cert size %d\n", context->cbCertEncoded);
661 ok(!memcmp(context->pbCertEncoded, bigCert, sizeof(bigCert)),
662 "Unexpected encoded cert in context\n");
663 ok(context->hCertStore == store, "Unexpected store\n");
665 dupContext = CertDuplicateCertificateContext(context);
666 ok(dupContext != NULL, "Expected valid duplicate\n");
667 /* Not only is it a duplicate, it's identical: the address is the
668 * same.
670 ok(dupContext == context, "Expected identical context addresses\n");
671 CertFreeCertificateContext(dupContext);
672 CertFreeCertificateContext(context);
674 CertCloseStore(store, 0);
676 SetLastError(0xdeadbeef);
677 context = CertDuplicateCertificateContext(NULL);
678 ok(context == NULL, "Expected context to be NULL\n");
681 static BYTE subjectName3[] = { 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
682 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x52, 0x6f, 0x62, 0x20, 0x20, 0x4c, 0x61,
683 0x6e, 0x67, 0x00 };
684 static const BYTE iTunesCert0[] = {
685 0x30,0x82,0x03,0xc4,0x30,0x82,0x03,0x2d,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,
686 0x47,0xbf,0x19,0x95,0xdf,0x8d,0x52,0x46,0x43,0xf7,0xdb,0x6d,0x48,0x0d,0x31,
687 0xa4,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,
688 0x00,0x30,0x81,0x8b,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,
689 0x5a,0x41,0x31,0x15,0x30,0x13,0x06,0x03,0x55,0x04,0x08,0x13,0x0c,0x57,0x65,
690 0x73,0x74,0x65,0x72,0x6e,0x20,0x43,0x61,0x70,0x65,0x31,0x14,0x30,0x12,0x06,
691 0x03,0x55,0x04,0x07,0x13,0x0b,0x44,0x75,0x72,0x62,0x61,0x6e,0x76,0x69,0x6c,
692 0x6c,0x65,0x31,0x0f,0x30,0x0d,0x06,0x03,0x55,0x04,0x0a,0x13,0x06,0x54,0x68,
693 0x61,0x77,0x74,0x65,0x31,0x1d,0x30,0x1b,0x06,0x03,0x55,0x04,0x0b,0x13,0x14,
694 0x54,0x68,0x61,0x77,0x74,0x65,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,
695 0x61,0x74,0x69,0x6f,0x6e,0x31,0x1f,0x30,0x1d,0x06,0x03,0x55,0x04,0x03,0x13,
696 0x16,0x54,0x68,0x61,0x77,0x74,0x65,0x20,0x54,0x69,0x6d,0x65,0x73,0x74,0x61,
697 0x6d,0x70,0x69,0x6e,0x67,0x20,0x43,0x41,0x30,0x1e,0x17,0x0d,0x30,0x33,0x31,
698 0x32,0x30,0x34,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,0x31,0x33,0x31,
699 0x32,0x30,0x33,0x32,0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x53,0x31,0x0b,0x30,
700 0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x17,0x30,0x15,0x06,
701 0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x2c,
702 0x20,0x49,0x6e,0x63,0x2e,0x31,0x2b,0x30,0x29,0x06,0x03,0x55,0x04,0x03,0x13,
703 0x22,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x54,0x69,0x6d,0x65,0x20,
704 0x53,0x74,0x61,0x6d,0x70,0x69,0x6e,0x67,0x20,0x53,0x65,0x72,0x76,0x69,0x63,
705 0x65,0x73,0x20,0x43,0x41,0x30,0x82,0x01,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,
706 0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0f,0x00,0x30,
707 0x82,0x01,0x0a,0x02,0x82,0x01,0x01,0x00,0xa9,0xca,0xb2,0xa4,0xcc,0xcd,0x20,
708 0xaf,0x0a,0x7d,0x89,0xac,0x87,0x75,0xf0,0xb4,0x4e,0xf1,0xdf,0xc1,0x0f,0xbf,
709 0x67,0x61,0xbd,0xa3,0x64,0x1c,0xda,0xbb,0xf9,0xca,0x33,0xab,0x84,0x30,0x89,
710 0x58,0x7e,0x8c,0xdb,0x6b,0xdd,0x36,0x9e,0x0f,0xbf,0xd1,0xec,0x78,0xf2,0x77,
711 0xa6,0x7e,0x6f,0x3c,0xbf,0x93,0xaf,0x0d,0xba,0x68,0xf4,0x6c,0x94,0xca,0xbd,
712 0x52,0x2d,0xab,0x48,0x3d,0xf5,0xb6,0xd5,0x5d,0x5f,0x1b,0x02,0x9f,0xfa,0x2f,
713 0x6b,0x1e,0xa4,0xf7,0xa3,0x9a,0xa6,0x1a,0xc8,0x02,0xe1,0x7f,0x4c,0x52,0xe3,
714 0x0e,0x60,0xec,0x40,0x1c,0x7e,0xb9,0x0d,0xde,0x3f,0xc7,0xb4,0xdf,0x87,0xbd,
715 0x5f,0x7a,0x6a,0x31,0x2e,0x03,0x99,0x81,0x13,0xa8,0x47,0x20,0xce,0x31,0x73,
716 0x0d,0x57,0x2d,0xcd,0x78,0x34,0x33,0x95,0x12,0x99,0x12,0xb9,0xde,0x68,0x2f,
717 0xaa,0xe6,0xe3,0xc2,0x8a,0x8c,0x2a,0xc3,0x8b,0x21,0x87,0x66,0xbd,0x83,0x58,
718 0x57,0x6f,0x75,0xbf,0x3c,0xaa,0x26,0x87,0x5d,0xca,0x10,0x15,0x3c,0x9f,0x84,
719 0xea,0x54,0xc1,0x0a,0x6e,0xc4,0xfe,0xc5,0x4a,0xdd,0xb9,0x07,0x11,0x97,0x22,
720 0x7c,0xdb,0x3e,0x27,0xd1,0x1e,0x78,0xec,0x9f,0x31,0xc9,0xf1,0xe6,0x22,0x19,
721 0xdb,0xc4,0xb3,0x47,0x43,0x9a,0x1a,0x5f,0xa0,0x1e,0x90,0xe4,0x5e,0xf5,0xee,
722 0x7c,0xf1,0x7d,0xab,0x62,0x01,0x8f,0xf5,0x4d,0x0b,0xde,0xd0,0x22,0x56,0xa8,
723 0x95,0xcd,0xae,0x88,0x76,0xae,0xee,0xba,0x0d,0xf3,0xe4,0x4d,0xd9,0xa0,0xfb,
724 0x68,0xa0,0xae,0x14,0x3b,0xb3,0x87,0xc1,0xbb,0x02,0x03,0x01,0x00,0x01,0xa3,
725 0x81,0xdb,0x30,0x81,0xd8,0x30,0x34,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,
726 0x01,0x01,0x04,0x28,0x30,0x26,0x30,0x24,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,
727 0x07,0x30,0x01,0x86,0x18,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6f,0x63,0x73,
728 0x70,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x30,
729 0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,
730 0xff,0x02,0x01,0x00,0x30,0x41,0x06,0x03,0x55,0x1d,0x1f,0x04,0x3a,0x30,0x38,
731 0x30,0x36,0xa0,0x34,0xa0,0x32,0x86,0x30,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
732 0x63,0x72,0x6c,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,
733 0x6d,0x2f,0x54,0x68,0x61,0x77,0x74,0x65,0x54,0x69,0x6d,0x65,0x73,0x74,0x61,
734 0x6d,0x70,0x69,0x6e,0x67,0x43,0x41,0x2e,0x63,0x72,0x6c,0x30,0x13,0x06,0x03,
735 0x55,0x1d,0x25,0x04,0x0c,0x30,0x0a,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,
736 0x03,0x08,0x30,0x0e,0x06,0x03,0x55,0x1d,0x0f,0x01,0x01,0xff,0x04,0x04,0x03,
737 0x02,0x01,0x06,0x30,0x24,0x06,0x03,0x55,0x1d,0x11,0x04,0x1d,0x30,0x1b,0xa4,
738 0x19,0x30,0x17,0x31,0x15,0x30,0x13,0x06,0x03,0x55,0x04,0x03,0x13,0x0c,0x54,
739 0x53,0x41,0x32,0x30,0x34,0x38,0x2d,0x31,0x2d,0x35,0x33,0x30,0x0d,0x06,0x09,
740 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x03,0x81,0x81,0x00,
741 0x4a,0x6b,0xf9,0xea,0x58,0xc2,0x44,0x1c,0x31,0x89,0x79,0x99,0x2b,0x96,0xbf,
742 0x82,0xac,0x01,0xd6,0x1c,0x4c,0xcd,0xb0,0x8a,0x58,0x6e,0xdf,0x08,0x29,0xa3,
743 0x5e,0xc8,0xca,0x93,0x13,0xe7,0x04,0x52,0x0d,0xef,0x47,0x27,0x2f,0x00,0x38,
744 0xb0,0xe4,0xc9,0x93,0x4e,0x9a,0xd4,0x22,0x62,0x15,0xf7,0x3f,0x37,0x21,0x4f,
745 0x70,0x31,0x80,0xf1,0x8b,0x38,0x87,0xb3,0xe8,0xe8,0x97,0x00,0xfe,0xcf,0x55,
746 0x96,0x4e,0x24,0xd2,0xa9,0x27,0x4e,0x7a,0xae,0xb7,0x61,0x41,0xf3,0x2a,0xce,
747 0xe7,0xc9,0xd9,0x5e,0xdd,0xbb,0x2b,0x85,0x3e,0xb5,0x9d,0xb5,0xd9,0xe1,0x57,
748 0xff,0xbe,0xb4,0xc5,0x7e,0xf5,0xcf,0x0c,0x9e,0xf0,0x97,0xfe,0x2b,0xd3,0x3b,
749 0x52,0x1b,0x1b,0x38,0x27,0xf7,0x3f,0x4a };
750 static const BYTE iTunesCert1[] = {
751 0x30,0x82,0x03,0xff,0x30,0x82,0x02,0xe7,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,
752 0x0d,0xe9,0x2b,0xf0,0xd4,0xd8,0x29,0x88,0x18,0x32,0x05,0x09,0x5e,0x9a,0x76,
753 0x88,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,
754 0x00,0x30,0x53,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,
755 0x53,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,
756 0x69,0x53,0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x2b,0x30,0x29,
757 0x06,0x03,0x55,0x04,0x03,0x13,0x22,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,
758 0x20,0x54,0x69,0x6d,0x65,0x20,0x53,0x74,0x61,0x6d,0x70,0x69,0x6e,0x67,0x20,
759 0x53,0x65,0x72,0x76,0x69,0x63,0x65,0x73,0x20,0x43,0x41,0x30,0x1e,0x17,0x0d,
760 0x30,0x33,0x31,0x32,0x30,0x34,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,
761 0x30,0x38,0x31,0x32,0x30,0x33,0x32,0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x57,
762 0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x17,
763 0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,0x69,
764 0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x2f,0x30,0x2d,0x06,0x03,0x55,
765 0x04,0x03,0x13,0x26,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x54,0x69,
766 0x6d,0x65,0x20,0x53,0x74,0x61,0x6d,0x70,0x69,0x6e,0x67,0x20,0x53,0x65,0x72,
767 0x76,0x69,0x63,0x65,0x73,0x20,0x53,0x69,0x67,0x6e,0x65,0x72,0x30,0x82,0x01,
768 0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,
769 0x00,0x03,0x82,0x01,0x0f,0x00,0x30,0x82,0x01,0x0a,0x02,0x82,0x01,0x01,0x00,
770 0xb2,0x50,0x28,0x48,0xdd,0xd3,0x68,0x7a,0x84,0x18,0x44,0x66,0x75,0x5d,0x7e,
771 0xc4,0xb8,0x9f,0x63,0x26,0xff,0x3d,0x43,0x9c,0x7c,0x11,0x38,0x10,0x25,0x55,
772 0x73,0xd9,0x75,0x27,0x69,0xfd,0x4e,0xb9,0x20,0x5c,0xd3,0x0a,0xf9,0xa0,0x1b,
773 0x2a,0xed,0x55,0x56,0x21,0x61,0xd8,0x1e,0xdb,0xe4,0xbc,0x33,0x6b,0xc7,0xef,
774 0xdd,0xa3,0x37,0x65,0x8e,0x1b,0x93,0x0c,0xb6,0x53,0x1e,0x5c,0x7c,0x66,0x35,
775 0x5f,0x05,0x8a,0x45,0xfe,0x76,0x4e,0xdf,0x53,0x80,0xa2,0x81,0x20,0x9d,0xae,
776 0x88,0x5c,0xa2,0x08,0xf7,0xe5,0x30,0xf9,0xee,0x22,0x37,0x4c,0x42,0x0a,0xce,
777 0xdf,0xc6,0x1f,0xc4,0xd6,0x55,0xe9,0x81,0x3f,0xb5,0x52,0xa3,0x2c,0xaa,0x01,
778 0x7a,0xf2,0xa2,0xaa,0x8d,0x35,0xfe,0x9f,0xe6,0x5d,0x6a,0x05,0x9f,0x3d,0x6b,
779 0xe3,0xbf,0x96,0xc0,0xfe,0xcc,0x60,0xf9,0x40,0xe7,0x07,0xa0,0x44,0xeb,0x81,
780 0x51,0x6e,0xa5,0x2a,0xf2,0xb6,0x8a,0x10,0x28,0xed,0x8f,0xdc,0x06,0xa0,0x86,
781 0x50,0x9a,0x7b,0x4a,0x08,0x0d,0x30,0x1d,0xca,0x10,0x9e,0x6b,0xf7,0xe9,0x58,
782 0xae,0x04,0xa9,0x40,0x99,0xb2,0x28,0xe8,0x8f,0x16,0xac,0x3c,0xe3,0x53,0x6f,
783 0x4b,0xd3,0x35,0x9d,0xb5,0x6f,0x64,0x1d,0xb3,0x96,0x2c,0xbb,0x3d,0xe7,0x79,
784 0xeb,0x6d,0x7a,0xf9,0x16,0xe6,0x26,0xad,0xaf,0xef,0x99,0x53,0xb7,0x40,0x2c,
785 0x95,0xb8,0x79,0xaa,0xfe,0xd4,0x52,0xab,0x29,0x74,0x7e,0x42,0xec,0x39,0x1e,
786 0xa2,0x6a,0x16,0xe6,0x59,0xbb,0x24,0x68,0xd8,0x00,0x80,0x43,0x10,0x87,0x80,
787 0x6b,0x02,0x03,0x01,0x00,0x01,0xa3,0x81,0xca,0x30,0x81,0xc7,0x30,0x34,0x06,
788 0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x28,0x30,0x26,0x30,0x24,
789 0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x18,0x68,0x74,0x74,
790 0x70,0x3a,0x2f,0x2f,0x6f,0x63,0x73,0x70,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,
791 0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x30,0x0c,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
792 0xff,0x04,0x02,0x30,0x00,0x30,0x33,0x06,0x03,0x55,0x1d,0x1f,0x04,0x2c,0x30,
793 0x2a,0x30,0x28,0xa0,0x26,0xa0,0x24,0x86,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,
794 0x2f,0x63,0x72,0x6c,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,
795 0x6f,0x6d,0x2f,0x74,0x73,0x73,0x2d,0x63,0x61,0x2e,0x63,0x72,0x6c,0x30,0x16,
796 0x06,0x03,0x55,0x1d,0x25,0x01,0x01,0xff,0x04,0x0c,0x30,0x0a,0x06,0x08,0x2b,
797 0x06,0x01,0x05,0x05,0x07,0x03,0x08,0x30,0x0e,0x06,0x03,0x55,0x1d,0x0f,0x01,
798 0x01,0xff,0x04,0x04,0x03,0x02,0x06,0xc0,0x30,0x24,0x06,0x03,0x55,0x1d,0x11,
799 0x04,0x1d,0x30,0x1b,0xa4,0x19,0x30,0x17,0x31,0x15,0x30,0x13,0x06,0x03,0x55,
800 0x04,0x03,0x13,0x0c,0x54,0x53,0x41,0x32,0x30,0x34,0x38,0x2d,0x31,0x2d,0x35,
801 0x34,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,
802 0x00,0x03,0x82,0x01,0x01,0x00,0x87,0x78,0x70,0xda,0x4e,0x52,0x01,0x20,0x5b,
803 0xe0,0x79,0xc9,0x82,0x30,0xc4,0xfd,0xb9,0x19,0x96,0xbd,0x91,0x00,0xc3,0xbd,
804 0xcd,0xcd,0xc6,0xf4,0x0e,0xd8,0xff,0xf9,0x4d,0xc0,0x33,0x62,0x30,0x11,0xc5,
805 0xf5,0x74,0x1b,0xd4,0x92,0xde,0x5f,0x9c,0x20,0x13,0xb1,0x7c,0x45,0xbe,0x50,
806 0xcd,0x83,0xe7,0x80,0x17,0x83,0xa7,0x27,0x93,0x67,0x13,0x46,0xfb,0xca,0xb8,
807 0x98,0x41,0x03,0xcc,0x9b,0x51,0x5b,0x05,0x8b,0x7f,0xa8,0x6f,0xf3,0x1b,0x50,
808 0x1b,0x24,0x2e,0xf2,0x69,0x8d,0x6c,0x22,0xf7,0xbb,0xca,0x16,0x95,0xed,0x0c,
809 0x74,0xc0,0x68,0x77,0xd9,0xeb,0x99,0x62,0x87,0xc1,0x73,0x90,0xf8,0x89,0x74,
810 0x7a,0x23,0xab,0xa3,0x98,0x7b,0x97,0xb1,0xf7,0x8f,0x29,0x71,0x4d,0x2e,0x75,
811 0x1b,0x48,0x41,0xda,0xf0,0xb5,0x0d,0x20,0x54,0xd6,0x77,0xa0,0x97,0x82,0x63,
812 0x69,0xfd,0x09,0xcf,0x8a,0xf0,0x75,0xbb,0x09,0x9b,0xd9,0xf9,0x11,0x55,0x26,
813 0x9a,0x61,0x32,0xbe,0x7a,0x02,0xb0,0x7b,0x86,0xbe,0xa2,0xc3,0x8b,0x22,0x2c,
814 0x78,0xd1,0x35,0x76,0xbc,0x92,0x73,0x5c,0xf9,0xb9,0xe6,0x4c,0x15,0x0a,0x23,
815 0xcc,0xe4,0xd2,0xd4,0x34,0x2e,0x49,0x40,0x15,0x3c,0x0f,0x60,0x7a,0x24,0xc6,
816 0xa5,0x66,0xef,0x96,0xcf,0x70,0xeb,0x3e,0xe7,0xf4,0x0d,0x7e,0xdc,0xd1,0x7c,
817 0xa3,0x76,0x71,0x69,0xc1,0x9c,0x4f,0x47,0x30,0x35,0x21,0xb1,0xa2,0xaf,0x1a,
818 0x62,0x3c,0x2b,0xd9,0x8e,0xaa,0x2a,0x07,0x7b,0xd8,0x18,0xb3,0x5c,0x7b,0xe2,
819 0x9d,0xa5,0x6f,0xfe,0x3c,0x89,0xad };
820 static const BYTE iTunesCert2[] = {
821 0x30,0x82,0x04,0xbf,0x30,0x82,0x04,0x28,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,
822 0x41,0x91,0xa1,0x5a,0x39,0x78,0xdf,0xcf,0x49,0x65,0x66,0x38,0x1d,0x4c,0x75,
823 0xc2,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,
824 0x00,0x30,0x5f,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,
825 0x53,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,
826 0x69,0x53,0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x37,0x30,0x35,
827 0x06,0x03,0x55,0x04,0x0b,0x13,0x2e,0x43,0x6c,0x61,0x73,0x73,0x20,0x33,0x20,
828 0x50,0x75,0x62,0x6c,0x69,0x63,0x20,0x50,0x72,0x69,0x6d,0x61,0x72,0x79,0x20,
829 0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x41,
830 0x75,0x74,0x68,0x6f,0x72,0x69,0x74,0x79,0x30,0x1e,0x17,0x0d,0x30,0x34,0x30,
831 0x37,0x31,0x36,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,0x31,0x34,0x30,
832 0x37,0x31,0x35,0x32,0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x81,0xb4,0x31,0x0b,
833 0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x17,0x30,0x15,
834 0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,
835 0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x1f,0x30,0x1d,0x06,0x03,0x55,0x04,0x0b,
836 0x13,0x16,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x54,0x72,0x75,0x73,
837 0x74,0x20,0x4e,0x65,0x74,0x77,0x6f,0x72,0x6b,0x31,0x3b,0x30,0x39,0x06,0x03,
838 0x55,0x04,0x0b,0x13,0x32,0x54,0x65,0x72,0x6d,0x73,0x20,0x6f,0x66,0x20,0x75,
839 0x73,0x65,0x20,0x61,0x74,0x20,0x68,0x74,0x74,0x70,0x73,0x3a,0x2f,0x2f,0x77,
840 0x77,0x77,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,
841 0x2f,0x72,0x70,0x61,0x20,0x28,0x63,0x29,0x30,0x34,0x31,0x2e,0x30,0x2c,0x06,
842 0x03,0x55,0x04,0x03,0x13,0x25,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,
843 0x43,0x6c,0x61,0x73,0x73,0x20,0x33,0x20,0x43,0x6f,0x64,0x65,0x20,0x53,0x69,
844 0x67,0x6e,0x69,0x6e,0x67,0x20,0x32,0x30,0x30,0x34,0x20,0x43,0x41,0x30,0x82,
845 0x01,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,
846 0x05,0x00,0x03,0x82,0x01,0x0f,0x00,0x30,0x82,0x01,0x0a,0x02,0x82,0x01,0x01,
847 0x00,0xbe,0xbc,0xee,0xbc,0x7e,0xef,0x83,0xeb,0xe0,0x37,0x4f,0xfb,0x03,0x10,
848 0x38,0xbe,0x08,0xd2,0x8c,0x7d,0x9d,0xfa,0x92,0x7f,0x19,0x0c,0xc2,0x6b,0xee,
849 0x42,0x52,0x8c,0xde,0xd3,0x1c,0x48,0x13,0x25,0xea,0xc1,0x63,0x7a,0xf9,0x51,
850 0x65,0xee,0xd3,0xaa,0x3b,0xf5,0xf0,0x94,0x9c,0x2b,0xfb,0xf2,0x66,0xd4,0x24,
851 0xda,0xf7,0xf5,0x9f,0x6e,0x19,0x39,0x36,0xbc,0xd0,0xa3,0x76,0x08,0x1e,0x22,
852 0x27,0x24,0x6c,0x38,0x91,0x27,0xe2,0x84,0x49,0xae,0x1b,0x8a,0xa1,0xfd,0x25,
853 0x82,0x2c,0x10,0x30,0xe8,0x71,0xab,0x28,0xe8,0x77,0x4a,0x51,0xf1,0xec,0xcd,
854 0xf8,0xf0,0x54,0xd4,0x6f,0xc0,0xe3,0x6d,0x0a,0x8f,0xd9,0xd8,0x64,0x8d,0x63,
855 0xb2,0x2d,0x4e,0x27,0xf6,0x85,0x0e,0xfe,0x6d,0xe3,0x29,0x99,0xe2,0x85,0x47,
856 0x7c,0x2d,0x86,0x7f,0xe8,0x57,0x8f,0xad,0x67,0xc2,0x33,0x32,0x91,0x13,0x20,
857 0xfc,0xa9,0x23,0x14,0x9a,0x6d,0xc2,0x84,0x4b,0x76,0x68,0x04,0xd5,0x71,0x2c,
858 0x5d,0x21,0xfa,0x88,0x0d,0x26,0xfd,0x1f,0x2d,0x91,0x2b,0xe7,0x01,0x55,0x4d,
859 0xf2,0x6d,0x35,0x28,0x82,0xdf,0xd9,0x6b,0x5c,0xb6,0xd6,0xd9,0xaa,0x81,0xfd,
860 0x5f,0xcd,0x83,0xba,0x63,0x9d,0xd0,0x22,0xfc,0xa9,0x3b,0x42,0x69,0xb2,0x8e,
861 0x3a,0xb5,0xbc,0xb4,0x9e,0x0f,0x5e,0xc4,0xea,0x2c,0x82,0x8b,0x28,0xfd,0x53,
862 0x08,0x96,0xdd,0xb5,0x01,0x20,0xd1,0xf9,0xa5,0x18,0xe7,0xc0,0xee,0x51,0x70,
863 0x37,0xe1,0xb6,0x05,0x48,0x52,0x48,0x6f,0x38,0xea,0xc3,0xe8,0x6c,0x7b,0x44,
864 0x84,0xbb,0x02,0x03,0x01,0x00,0x01,0xa3,0x82,0x01,0xa0,0x30,0x82,0x01,0x9c,
865 0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,
866 0x01,0xff,0x02,0x01,0x00,0x30,0x44,0x06,0x03,0x55,0x1d,0x20,0x04,0x3d,0x30,
867 0x3b,0x30,0x39,0x06,0x0b,0x60,0x86,0x48,0x01,0x86,0xf8,0x45,0x01,0x07,0x17,
868 0x03,0x30,0x2a,0x30,0x28,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x02,0x01,
869 0x16,0x1c,0x68,0x74,0x74,0x70,0x73,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x76,
870 0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x2f,0x72,0x70,0x61,
871 0x30,0x31,0x06,0x03,0x55,0x1d,0x1f,0x04,0x2a,0x30,0x28,0x30,0x26,0xa0,0x24,
872 0xa0,0x22,0x86,0x20,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x63,0x72,0x6c,0x2e,
873 0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x2f,0x70,0x63,
874 0x61,0x33,0x2e,0x63,0x72,0x6c,0x30,0x1d,0x06,0x03,0x55,0x1d,0x25,0x04,0x16,
875 0x30,0x14,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x03,0x02,0x06,0x08,0x2b,
876 0x06,0x01,0x05,0x05,0x07,0x03,0x03,0x30,0x0e,0x06,0x03,0x55,0x1d,0x0f,0x01,
877 0x01,0xff,0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x11,0x06,0x09,0x60,0x86,0x48,
878 0x01,0x86,0xf8,0x42,0x01,0x01,0x04,0x04,0x03,0x02,0x00,0x01,0x30,0x29,0x06,
879 0x03,0x55,0x1d,0x11,0x04,0x22,0x30,0x20,0xa4,0x1e,0x30,0x1c,0x31,0x1a,0x30,
880 0x18,0x06,0x03,0x55,0x04,0x03,0x13,0x11,0x43,0x6c,0x61,0x73,0x73,0x33,0x43,
881 0x41,0x32,0x30,0x34,0x38,0x2d,0x31,0x2d,0x34,0x33,0x30,0x1d,0x06,0x03,0x55,
882 0x1d,0x0e,0x04,0x16,0x04,0x14,0x08,0xf5,0x51,0xe8,0xfb,0xfe,0x3d,0x3d,0x64,
883 0x36,0x7c,0x68,0xcf,0x5b,0x78,0xa8,0xdf,0xb9,0xc5,0x37,0x30,0x81,0x80,0x06,
884 0x03,0x55,0x1d,0x23,0x04,0x79,0x30,0x77,0xa1,0x63,0xa4,0x61,0x30,0x5f,0x31,
885 0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x17,0x30,
886 0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,0x69,0x67,
887 0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x37,0x30,0x35,0x06,0x03,0x55,0x04,
888 0x0b,0x13,0x2e,0x43,0x6c,0x61,0x73,0x73,0x20,0x33,0x20,0x50,0x75,0x62,0x6c,
889 0x69,0x63,0x20,0x50,0x72,0x69,0x6d,0x61,0x72,0x79,0x20,0x43,0x65,0x72,0x74,
890 0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x41,0x75,0x74,0x68,0x6f,
891 0x72,0x69,0x74,0x79,0x82,0x10,0x70,0xba,0xe4,0x1d,0x10,0xd9,0x29,0x34,0xb6,
892 0x38,0xca,0x7b,0x03,0xcc,0xba,0xbf,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,
893 0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x03,0x81,0x81,0x00,0xae,0x3a,0x17,0xb8,
894 0x4a,0x7b,0x55,0xfa,0x64,0x55,0xec,0x40,0xa4,0xed,0x49,0x41,0x90,0x99,0x9c,
895 0x89,0xbc,0xaf,0x2e,0x1d,0xca,0x78,0x23,0xf9,0x1c,0x19,0x0f,0x7f,0xeb,0x68,
896 0xbc,0x32,0xd9,0x88,0x38,0xde,0xdc,0x3f,0xd3,0x89,0xb4,0x3f,0xb1,0x82,0x96,
897 0xf1,0xa4,0x5a,0xba,0xed,0x2e,0x26,0xd3,0xde,0x7c,0x01,0x6e,0x00,0x0a,0x00,
898 0xa4,0x06,0x92,0x11,0x48,0x09,0x40,0xf9,0x1c,0x18,0x79,0x67,0x23,0x24,0xe0,
899 0xbb,0xd5,0xe1,0x50,0xae,0x1b,0xf5,0x0e,0xdd,0xe0,0x2e,0x81,0xcd,0x80,0xa3,
900 0x6c,0x52,0x4f,0x91,0x75,0x55,0x8a,0xba,0x22,0xf2,0xd2,0xea,0x41,0x75,0x88,
901 0x2f,0x63,0x55,0x7d,0x1e,0x54,0x5a,0x95,0x59,0xca,0xd9,0x34,0x81,0xc0,0x5f,
902 0x5e,0xf6,0x7a,0xb5 };
903 static const BYTE iTunesCert3[] = {
904 0x30,0x82,0x04,0xf1,0x30,0x82,0x03,0xd9,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,
905 0x0f,0x1a,0xa0,0xe0,0x9b,0x9b,0x61,0xa6,0xb6,0xfe,0x40,0xd2,0xdf,0x6a,0xf6,
906 0x8d,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,
907 0x00,0x30,0x81,0xb4,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,
908 0x55,0x53,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,
909 0x72,0x69,0x53,0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x1f,0x30,
910 0x1d,0x06,0x03,0x55,0x04,0x0b,0x13,0x16,0x56,0x65,0x72,0x69,0x53,0x69,0x67,
911 0x6e,0x20,0x54,0x72,0x75,0x73,0x74,0x20,0x4e,0x65,0x74,0x77,0x6f,0x72,0x6b,
912 0x31,0x3b,0x30,0x39,0x06,0x03,0x55,0x04,0x0b,0x13,0x32,0x54,0x65,0x72,0x6d,
913 0x73,0x20,0x6f,0x66,0x20,0x75,0x73,0x65,0x20,0x61,0x74,0x20,0x68,0x74,0x74,
914 0x70,0x73,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,
915 0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x2f,0x72,0x70,0x61,0x20,0x28,0x63,0x29,0x30,
916 0x34,0x31,0x2e,0x30,0x2c,0x06,0x03,0x55,0x04,0x03,0x13,0x25,0x56,0x65,0x72,
917 0x69,0x53,0x69,0x67,0x6e,0x20,0x43,0x6c,0x61,0x73,0x73,0x20,0x33,0x20,0x43,
918 0x6f,0x64,0x65,0x20,0x53,0x69,0x67,0x6e,0x69,0x6e,0x67,0x20,0x32,0x30,0x30,
919 0x34,0x20,0x43,0x41,0x30,0x1e,0x17,0x0d,0x30,0x36,0x30,0x31,0x31,0x37,0x30,
920 0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,0x30,0x38,0x30,0x31,0x32,0x32,0x32,
921 0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x81,0xb4,0x31,0x0b,0x30,0x09,0x06,0x03,
922 0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,
923 0x08,0x13,0x0a,0x43,0x61,0x6c,0x69,0x66,0x6f,0x72,0x6e,0x69,0x61,0x31,0x12,
924 0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x13,0x09,0x43,0x75,0x70,0x65,0x72,0x74,
925 0x69,0x6e,0x6f,0x31,0x1d,0x30,0x1b,0x06,0x03,0x55,0x04,0x0a,0x14,0x14,0x41,
926 0x70,0x70,0x6c,0x65,0x20,0x43,0x6f,0x6d,0x70,0x75,0x74,0x65,0x72,0x2c,0x20,
927 0x49,0x6e,0x63,0x2e,0x31,0x3e,0x30,0x3c,0x06,0x03,0x55,0x04,0x0b,0x13,0x35,
928 0x44,0x69,0x67,0x69,0x74,0x61,0x6c,0x20,0x49,0x44,0x20,0x43,0x6c,0x61,0x73,
929 0x73,0x20,0x33,0x20,0x2d,0x20,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,
930 0x20,0x53,0x6f,0x66,0x74,0x77,0x61,0x72,0x65,0x20,0x56,0x61,0x6c,0x69,0x64,
931 0x61,0x74,0x69,0x6f,0x6e,0x20,0x76,0x32,0x31,0x1d,0x30,0x1b,0x06,0x03,0x55,
932 0x04,0x03,0x14,0x14,0x41,0x70,0x70,0x6c,0x65,0x20,0x43,0x6f,0x6d,0x70,0x75,
933 0x74,0x65,0x72,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x30,0x81,0x9f,0x30,0x0d,0x06,
934 0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x81,0x8d,
935 0x00,0x30,0x81,0x89,0x02,0x81,0x81,0x00,0xd3,0xab,0x3b,0x7f,0xec,0x48,0x84,
936 0xce,0xa8,0x1a,0x12,0xf3,0x3c,0x87,0xcb,0x24,0x58,0x96,0x02,0x87,0x66,0x49,
937 0xeb,0x89,0xee,0x79,0x44,0x70,0x8d,0xe7,0xd4,0x1f,0x30,0x92,0xc0,0x9c,0x35,
938 0x78,0xc0,0xaf,0x1c,0xb6,0x28,0xd3,0xe0,0xe0,0x9d,0xd3,0x49,0x76,0x73,0x57,
939 0x19,0x4d,0x8d,0x70,0x85,0x64,0x4d,0x1d,0xc6,0x02,0x3e,0xe5,0x2c,0x66,0x07,
940 0xd2,0x27,0x4b,0xd6,0xc8,0x3c,0x93,0xb6,0x15,0x0c,0xde,0x5b,0xd7,0x93,0xdd,
941 0xbe,0x85,0x62,0x34,0x17,0x8a,0x05,0x60,0xf0,0x8a,0x1c,0x5a,0x40,0x21,0x8d,
942 0x51,0x6c,0xb0,0x62,0xd8,0xb5,0xd4,0xf9,0xb1,0xd0,0x58,0x7a,0x7a,0x82,0x55,
943 0xb3,0xf9,0x53,0x71,0xde,0xd2,0xc9,0x37,0x8c,0xf6,0x5a,0x1f,0x2d,0xcd,0x7c,
944 0x67,0x02,0x03,0x01,0x00,0x01,0xa3,0x82,0x01,0x7f,0x30,0x82,0x01,0x7b,0x30,
945 0x09,0x06,0x03,0x55,0x1d,0x13,0x04,0x02,0x30,0x00,0x30,0x0e,0x06,0x03,0x55,
946 0x1d,0x0f,0x01,0x01,0xff,0x04,0x04,0x03,0x02,0x07,0x80,0x30,0x40,0x06,0x03,
947 0x55,0x1d,0x1f,0x04,0x39,0x30,0x37,0x30,0x35,0xa0,0x33,0xa0,0x31,0x86,0x2f,
948 0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x43,0x53,0x43,0x33,0x2d,0x32,0x30,0x30,
949 0x34,0x2d,0x63,0x72,0x6c,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,
950 0x63,0x6f,0x6d,0x2f,0x43,0x53,0x43,0x33,0x2d,0x32,0x30,0x30,0x34,0x2e,0x63,
951 0x72,0x6c,0x30,0x44,0x06,0x03,0x55,0x1d,0x20,0x04,0x3d,0x30,0x3b,0x30,0x39,
952 0x06,0x0b,0x60,0x86,0x48,0x01,0x86,0xf8,0x45,0x01,0x07,0x17,0x03,0x30,0x2a,
953 0x30,0x28,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x1c,0x68,
954 0x74,0x74,0x70,0x73,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x76,0x65,0x72,0x69,
955 0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x2f,0x72,0x70,0x61,0x30,0x13,0x06,
956 0x03,0x55,0x1d,0x25,0x04,0x0c,0x30,0x0a,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,
957 0x07,0x03,0x03,0x30,0x75,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x01,0x01,
958 0x04,0x69,0x30,0x67,0x30,0x24,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,
959 0x01,0x86,0x18,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6f,0x63,0x73,0x70,0x2e,
960 0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x30,0x3f,0x06,
961 0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x33,0x68,0x74,0x74,0x70,
962 0x3a,0x2f,0x2f,0x43,0x53,0x43,0x33,0x2d,0x32,0x30,0x30,0x34,0x2d,0x61,0x69,
963 0x61,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x2f,
964 0x43,0x53,0x43,0x33,0x2d,0x32,0x30,0x30,0x34,0x2d,0x61,0x69,0x61,0x2e,0x63,
965 0x65,0x72,0x30,0x1f,0x06,0x03,0x55,0x1d,0x23,0x04,0x18,0x30,0x16,0x80,0x14,
966 0x08,0xf5,0x51,0xe8,0xfb,0xfe,0x3d,0x3d,0x64,0x36,0x7c,0x68,0xcf,0x5b,0x78,
967 0xa8,0xdf,0xb9,0xc5,0x37,0x30,0x11,0x06,0x09,0x60,0x86,0x48,0x01,0x86,0xf8,
968 0x42,0x01,0x01,0x04,0x04,0x03,0x02,0x04,0x10,0x30,0x16,0x06,0x0a,0x2b,0x06,
969 0x01,0x04,0x01,0x82,0x37,0x02,0x01,0x1b,0x04,0x08,0x30,0x06,0x01,0x01,0x00,
970 0x01,0x01,0xff,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,
971 0x05,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x6a,0xa6,0x06,0xd0,0x33,0x18,0x64,
972 0xe2,0x69,0x82,0xee,0x6e,0x36,0x9e,0x9d,0x9a,0x0e,0x18,0xa8,0xac,0x9d,0x10,
973 0xed,0x01,0x3c,0xb9,0x61,0x04,0x62,0xf3,0x85,0x8f,0xcc,0x4f,0x2c,0x66,0x35,
974 0x54,0x25,0x45,0x8d,0x95,0x1c,0xd2,0x33,0xbe,0x2e,0xdd,0x7f,0x74,0xaf,0x03,
975 0x7b,0x86,0x63,0xb0,0xc9,0xe6,0xbd,0xc7,0x8e,0xde,0x03,0x18,0x98,0x82,0xc3,
976 0xbb,0xf8,0x15,0x99,0x1a,0xa9,0xdd,0xb9,0x5d,0xb9,0xbd,0x53,0x95,0x25,0x76,
977 0xfb,0x5c,0x53,0x90,0xea,0x01,0x0a,0xa0,0xb1,0xbf,0x09,0x1b,0x97,0x8f,0x40,
978 0xfa,0x85,0x12,0x74,0x01,0xdb,0xf6,0xdb,0x09,0xd6,0x5f,0x4f,0xd7,0x17,0xb4,
979 0xbf,0x9e,0x2f,0x86,0x52,0x5d,0x70,0x24,0x52,0x32,0x1e,0xa5,0x1d,0x39,0x8b,
980 0x66,0xf6,0xba,0x9b,0x69,0x8e,0x12,0x60,0xdb,0xb6,0xcf,0xe6,0x0d,0xd6,0x1c,
981 0x8f,0xd4,0x5b,0x4b,0x00,0xde,0x21,0x93,0xfb,0x6e,0xc7,0x3d,0xb4,0x66,0x0d,
982 0x29,0x0c,0x4e,0xe9,0x3f,0x94,0xd6,0xd6,0xdc,0xec,0xf8,0x53,0x3b,0x62,0xd5,
983 0x97,0x50,0x53,0x84,0x17,0xfe,0xe2,0xed,0x4c,0x23,0x0a,0x49,0xce,0x5b,0xe9,
984 0x70,0x31,0xc1,0x04,0x02,0x02,0x6c,0xb8,0x52,0xcd,0xc7,0x4e,0x70,0xb4,0x13,
985 0xd7,0xe0,0x92,0xba,0x44,0x1a,0x10,0x4c,0x6e,0x45,0xc6,0x86,0x04,0xc6,0x64,
986 0xd3,0x9c,0x6e,0xc1,0x9c,0xac,0x74,0x3d,0x77,0x06,0x5e,0x28,0x28,0x5c,0xf5,
987 0xe0,0x9c,0x19,0xd8,0xba,0x74,0x81,0x2d,0x67,0x77,0x93,0x8d,0xbf,0xd2,0x52,
988 0x00,0xe6,0xa5,0x38,0x4e,0x2e,0x73,0x66,0x7a };
989 static BYTE iTunesIssuer[] = {
990 0x30,0x81,0xb4,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,
991 0x13,0x02,0x55,0x53,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,
992 0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x2c,
993 0x20,0x49,0x6e,0x63,0x2e,0x31,0x1f,0x30,0x1d,0x06,0x03,0x55,
994 0x04,0x0b,0x13,0x16,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,
995 0x20,0x54,0x72,0x75,0x73,0x74,0x20,0x4e,0x65,0x74,0x77,0x6f,
996 0x72,0x6b,0x31,0x3b,0x30,0x39,0x06,0x03,0x55,0x04,0x0b,0x13,
997 0x32,0x54,0x65,0x72,0x6d,0x73,0x20,0x6f,0x66,0x20,0x75,0x73,
998 0x65,0x20,0x61,0x74,0x20,0x68,0x74,0x74,0x70,0x73,0x3a,0x2f,
999 0x2f,0x77,0x77,0x77,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,
1000 0x6e,0x2e,0x63,0x6f,0x6d,0x2f,0x72,0x70,0x61,0x20,0x28,0x63,
1001 0x29,0x30,0x34,0x31,0x2e,0x30,0x2c,0x06,0x03,0x55,0x04,0x03,
1002 0x13,0x25,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x43,
1003 0x6c,0x61,0x73,0x73,0x20,0x33,0x20,0x43,0x6f,0x64,0x65,0x20,
1004 0x53,0x69,0x67,0x6e,0x69,0x6e,0x67,0x20,0x32,0x30,0x30,0x34,
1005 0x20,0x43,0x41 };
1006 static BYTE iTunesSerialNum[] = {
1007 0x8d,0xf6,0x6a,0xdf,0xd2,0x40,0xfe,0xb6,0xa6,0x61,0x9b,0x9b,
1008 0xe0,0xa0,0x1a,0x0f };
1010 static void testFindCert(void)
1012 HCERTSTORE store;
1013 PCCERT_CONTEXT context = NULL, subject;
1014 BOOL ret;
1015 CERT_INFO certInfo = { 0 };
1016 CRYPT_HASH_BLOB blob;
1017 BYTE otherSerialNumber[] = { 2 };
1019 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1020 CERT_STORE_CREATE_NEW_FLAG, NULL);
1021 ok(store != NULL, "CertOpenStore failed: %d\n", GetLastError());
1022 if (!store)
1023 return;
1025 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1026 bigCert, sizeof(bigCert), CERT_STORE_ADD_NEW, NULL);
1027 ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* win98 */),
1028 "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
1029 if (!ret && GetLastError() == OSS_DATA_ERROR)
1031 skip("bigCert can't be decoded, skipping tests\n");
1032 return;
1034 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1035 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, NULL);
1036 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1037 GetLastError());
1038 /* This has the same name as bigCert */
1039 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1040 certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, NULL);
1041 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1042 GetLastError());
1044 /* Crashes
1045 context = CertFindCertificateInStore(NULL, 0, 0, 0, NULL, NULL);
1048 /* Check first cert's there, by issuer */
1049 certInfo.Subject.pbData = subjectName;
1050 certInfo.Subject.cbData = sizeof(subjectName);
1051 certInfo.SerialNumber.pbData = serialNum;
1052 certInfo.SerialNumber.cbData = sizeof(serialNum);
1053 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1054 CERT_FIND_ISSUER_NAME, &certInfo.Subject, NULL);
1055 ok(context != NULL, "CertFindCertificateInStore failed: %08x\n",
1056 GetLastError());
1057 if (context)
1059 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1060 CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
1061 ok(context != NULL, "Expected more than one cert\n");
1062 if (context)
1064 context = CertFindCertificateInStore(store, X509_ASN_ENCODING,
1065 0, CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
1066 ok(context == NULL, "Expected precisely two certs\n");
1070 /* Check second cert's there as well, by subject name */
1071 certInfo.Subject.pbData = subjectName2;
1072 certInfo.Subject.cbData = sizeof(subjectName2);
1073 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1074 CERT_FIND_SUBJECT_NAME, &certInfo.Subject, NULL);
1075 ok(context != NULL, "CertFindCertificateInStore failed: %08x\n",
1076 GetLastError());
1077 if (context)
1079 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1080 CERT_FIND_SUBJECT_NAME, &certInfo.Subject, context);
1081 ok(context == NULL, "Expected one cert only\n");
1084 /* Strange but true: searching for the subject cert requires you to set
1085 * the issuer, not the subject
1087 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1088 CERT_FIND_SUBJECT_CERT, &certInfo.Subject, NULL);
1089 ok(context == NULL, "Expected no certificate\n");
1090 certInfo.Subject.pbData = NULL;
1091 certInfo.Subject.cbData = 0;
1092 certInfo.Issuer.pbData = subjectName2;
1093 certInfo.Issuer.cbData = sizeof(subjectName2);
1094 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1095 CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
1096 ok(context != NULL, "CertFindCertificateInStore failed: %08x\n",
1097 GetLastError());
1098 if (context)
1100 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1101 CERT_FIND_SUBJECT_CERT, &certInfo.Subject, context);
1102 ok(context == NULL, "Expected one cert only\n");
1104 /* A non-matching serial number will not match. */
1105 certInfo.SerialNumber.pbData = otherSerialNumber;
1106 certInfo.SerialNumber.cbData = sizeof(otherSerialNumber);
1107 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1108 CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
1109 ok(context == NULL, "Expected no match\n");
1110 /* No serial number will not match */
1111 certInfo.SerialNumber.cbData = 0;
1112 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1113 CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
1114 ok(context == NULL, "Expected no match\n");
1115 /* A serial number still won't match if the name doesn't */
1116 certInfo.SerialNumber.pbData = serialNum;
1117 certInfo.SerialNumber.cbData = sizeof(serialNum);
1118 certInfo.Issuer.pbData = subjectName3;
1119 certInfo.Issuer.cbData = sizeof(subjectName3);
1120 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1121 CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
1122 ok(context == NULL, "Expected no match\n");
1124 /* The nice thing about hashes, they're unique */
1125 blob.pbData = bigCertHash;
1126 blob.cbData = sizeof(bigCertHash);
1127 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1128 CERT_FIND_SHA1_HASH, &blob, NULL);
1129 ok(context != NULL, "CertFindCertificateInStore failed: %08x\n",
1130 GetLastError());
1131 if (context)
1133 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1134 CERT_FIND_SHA1_HASH, &certInfo.Subject, context);
1135 ok(context == NULL, "Expected one cert only\n");
1138 CertCloseStore(store, 0);
1140 /* Another subject cert search, using iTunes's certs */
1141 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1142 CERT_STORE_CREATE_NEW_FLAG, NULL);
1143 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1144 iTunesCert0, sizeof(iTunesCert0), CERT_STORE_ADD_NEW, NULL);
1145 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1146 GetLastError());
1147 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1148 iTunesCert1, sizeof(iTunesCert1), CERT_STORE_ADD_NEW, NULL);
1149 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1150 GetLastError());
1151 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1152 iTunesCert2, sizeof(iTunesCert2), CERT_STORE_ADD_NEW, NULL);
1153 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1154 GetLastError());
1155 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1156 iTunesCert3, sizeof(iTunesCert3), CERT_STORE_ADD_NEW, &subject);
1157 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1158 GetLastError());
1160 /* The certInfo's issuer does not match any subject, but the serial
1161 * number does match a cert whose issuer matches certInfo's issuer.
1162 * This yields a match.
1164 certInfo.SerialNumber.cbData = sizeof(iTunesSerialNum);
1165 certInfo.SerialNumber.pbData = iTunesSerialNum;
1166 certInfo.Issuer.cbData = sizeof(iTunesIssuer);
1167 certInfo.Issuer.pbData = iTunesIssuer;
1168 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1169 CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
1170 ok(context != NULL, "Expected a match\n");
1171 if (context)
1173 ret = CertCompareCertificateName(context->dwCertEncodingType,
1174 &certInfo.Issuer, &context->pCertInfo->Subject);
1175 ok(!ret, "Expected subject name not to match\n");
1176 ret = CertCompareCertificateName(context->dwCertEncodingType,
1177 &certInfo.Issuer, &context->pCertInfo->Issuer);
1178 ok(ret, "Expected issuer name to match\n");
1179 ret = CertCompareIntegerBlob(&certInfo.SerialNumber,
1180 &context->pCertInfo->SerialNumber);
1181 ok(ret, "Expected serial number to match\n");
1182 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1183 CERT_FIND_SUBJECT_CERT, &certInfo, context);
1184 ok(context == NULL, "Expected one cert only\n");
1187 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1188 CERT_FIND_ISSUER_OF, subject, NULL);
1189 ok(context != NULL, "Expected an issuer\n");
1190 if (context)
1192 PCCERT_CONTEXT none = CertFindCertificateInStore(store,
1193 X509_ASN_ENCODING, 0, CERT_FIND_ISSUER_OF, context, NULL);
1195 ok(!none, "Expected no parent of issuer\n");
1196 CertFreeCertificateContext(context);
1198 CertFreeCertificateContext(subject);
1199 CertCloseStore(store, 0);
1202 static void testGetSubjectCert(void)
1204 HCERTSTORE store;
1205 PCCERT_CONTEXT context1, context2;
1206 CERT_INFO info = { 0 };
1207 BOOL ret;
1209 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1210 CERT_STORE_CREATE_NEW_FLAG, NULL);
1211 ok(store != NULL, "CertOpenStore failed: %d\n", GetLastError());
1212 if (!store)
1213 return;
1215 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1216 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
1217 ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* win98 */),
1218 "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
1219 if (!ret && GetLastError() == OSS_DATA_ERROR)
1221 skip("bigCert can't be decoded, skipping tests\n");
1222 return;
1224 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1225 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, &context1);
1226 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1227 GetLastError());
1228 ok(context1 != NULL, "Expected a context\n");
1229 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1230 certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, NULL);
1231 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1232 GetLastError());
1234 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
1235 NULL);
1236 ok(!context2 && GetLastError() == E_INVALIDARG,
1237 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1238 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
1239 &info);
1240 ok(!context2 && GetLastError() == CRYPT_E_NOT_FOUND,
1241 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1242 info.SerialNumber.cbData = sizeof(serialNum);
1243 info.SerialNumber.pbData = serialNum;
1244 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
1245 &info);
1246 ok(!context2 && GetLastError() == CRYPT_E_NOT_FOUND,
1247 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1248 info.Issuer.cbData = sizeof(subjectName2);
1249 info.Issuer.pbData = subjectName2;
1250 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
1251 &info);
1252 ok(context2 != NULL,
1253 "CertGetSubjectCertificateFromStore failed: %08x\n", GetLastError());
1254 /* Not only should this find a context, but it should be the same
1255 * (same address) as context1.
1257 ok(context1 == context2, "Expected identical context addresses\n");
1258 CertFreeCertificateContext(context2);
1260 CertFreeCertificateContext(context1);
1261 CertCloseStore(store, 0);
1264 /* This expires in 1970 or so */
1265 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
1266 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
1267 0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
1268 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
1269 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
1270 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
1271 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
1272 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
1273 0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
1274 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
1275 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
1276 0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
1277 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
1278 0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
1279 0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
1280 0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
1281 0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
1282 0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
1283 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
1284 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
1285 0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
1286 0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
1287 0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
1288 0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
1289 0x49, 0xe5, 0xf9, 0x65, 0xf3 };
1291 /* This expires in 2036 or so */
1292 static const BYTE childOfExpired[] = { 0x30, 0x81, 0xcc, 0x30, 0x78, 0xa0,
1293 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
1294 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d,
1295 0x30, 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63,
1296 0x40, 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e,
1297 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x35, 0x30, 0x35,
1298 0x31, 0x37, 0x31, 0x32, 0x34, 0x39, 0x5a, 0x17, 0x0d, 0x33, 0x36, 0x30, 0x35,
1299 0x30, 0x35, 0x31, 0x37, 0x31, 0x32, 0x34, 0x39, 0x5a, 0x30, 0x15, 0x31, 0x13,
1300 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e,
1301 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03,
1302 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
1303 0x01, 0x05, 0x05, 0x00, 0x03, 0x41, 0x00, 0x20, 0x3b, 0xdb, 0x4d, 0x67, 0x50,
1304 0xec, 0x73, 0x9d, 0xf9, 0x85, 0x5d, 0x18, 0xe9, 0xb4, 0x98, 0xe3, 0x31, 0xb7,
1305 0x03, 0x0b, 0xc0, 0x39, 0x93, 0x56, 0x81, 0x0a, 0xfc, 0x78, 0xa8, 0x29, 0x42,
1306 0x5f, 0x69, 0xfb, 0xbc, 0x5b, 0xf2, 0xa6, 0x2a, 0xbe, 0x91, 0x2c, 0xfc, 0x89,
1307 0x69, 0x15, 0x18, 0x58, 0xe5, 0x02, 0x75, 0xf7, 0x2a, 0xb6, 0xa9, 0xfb, 0x47,
1308 0x6a, 0x6e, 0x0a, 0x9b, 0xe9, 0xdc };
1309 /* chain10_0 -+
1310 * +-> chain7_1
1311 * chain10_1 -+
1312 * A chain with two issuers, only one of whose dates is valid.
1314 static const BYTE chain10_0[] = {
1315 0x30,0x82,0x01,0x9b,0x30,0x82,0x01,0x08,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,
1316 0x4a,0x30,0x3a,0x42,0xa2,0x5a,0xb3,0x93,0x4d,0x94,0x06,0xad,0x6d,0x1c,0x34,
1317 0xe6,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x30,0x10,0x31,
1318 0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x03,0x13,0x05,0x43,0x65,0x72,0x74,0x31,
1319 0x30,0x1e,0x17,0x0d,0x30,0x36,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
1320 0x30,0x5a,0x17,0x0d,0x30,0x36,0x31,0x32,0x33,0x31,0x32,0x33,0x35,0x39,0x35,
1321 0x39,0x5a,0x30,0x10,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x03,0x13,0x05,
1322 0x43,0x65,0x72,0x74,0x31,0x30,0x81,0x9f,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
1323 0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x81,0x8d,0x00,0x30,0x81,0x89,
1324 0x02,0x81,0x81,0x00,0xad,0x7e,0xca,0xf3,0xe5,0x99,0xc2,0x2a,0xca,0x50,0x82,
1325 0x7c,0x2d,0xa4,0x81,0xcd,0x0d,0x0d,0x86,0xd7,0xd8,0xb2,0xde,0xc5,0xc3,0x34,
1326 0x9e,0x07,0x78,0x08,0x11,0x12,0x2d,0x21,0x0a,0x09,0x07,0x14,0x03,0x7a,0xe7,
1327 0x3b,0x58,0xf1,0xde,0x3e,0x01,0x25,0x93,0xab,0x8f,0xce,0x1f,0xc1,0x33,0x91,
1328 0xfe,0x59,0xb9,0x3b,0x9e,0x95,0x12,0x89,0x8e,0xc3,0x4b,0x98,0x1b,0x99,0xc5,
1329 0x07,0xe2,0xdf,0x15,0x4c,0x39,0x76,0x06,0xad,0xdb,0x16,0x06,0x49,0xba,0xcd,
1330 0x0f,0x07,0xd6,0xea,0x27,0xa6,0xfe,0x3d,0x88,0xe5,0x97,0x45,0x72,0xb6,0x1c,
1331 0xc0,0x1c,0xb1,0xa2,0x89,0xe8,0x37,0x9e,0xf6,0x2a,0xcf,0xd5,0x1f,0x2f,0x35,
1332 0x5e,0x8f,0x3a,0x9c,0x61,0xb1,0xf1,0x6c,0xff,0x8c,0xb2,0x2f,0x02,0x03,0x01,
1333 0x00,0x01,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x03,0x81,
1334 0x81,0x00,0x85,0x6e,0x35,0x2f,0x2c,0x51,0x4f,0xd6,0x2a,0xe4,0x9e,0xd0,0x4b,
1335 0xe6,0x90,0xfd,0xf7,0x20,0xad,0x76,0x3f,0x93,0xea,0x7f,0x0d,0x1f,0xb3,0x8e,
1336 0xfd,0xe0,0xe1,0xd6,0xd7,0x9c,0x7d,0x46,0x6b,0x15,0x5c,0xe6,0xc9,0x62,0x3b,
1337 0x70,0x4a,0x4b,0xb2,0x82,0xe3,0x55,0x0c,0xc4,0x90,0x44,0x06,0x6c,0x86,0x1c,
1338 0x6d,0x47,0x12,0xda,0x33,0x95,0x5d,0x98,0x43,0xcb,0x7c,0xfa,0x2b,0xee,0xc4,
1339 0x2d,0xc8,0x95,0x33,0x89,0x08,0x3f,0x9f,0x87,0xea,0x20,0x04,0xaf,0x58,0x4b,
1340 0x9d,0xc0,0x7c,0x0a,0x1b,0x05,0x31,0x3b,0xbb,0x13,0x58,0x2e,0x3f,0x61,0x6b,
1341 0x10,0xb4,0xeb,0xb9,0x1a,0x30,0xfd,0xea,0xca,0x29,0x99,0x5f,0x42,0x2b,0x00,
1342 0xb0,0x08,0xc3,0xf0,0xb6,0xd6,0x6b,0xf9,0x35,0x95 };
1343 static const BYTE chain10_1[] = {
1344 0x30,0x82,0x01,0x9b,0x30,0x82,0x01,0x08,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,
1345 0xbf,0x99,0x4f,0x14,0x03,0x77,0x44,0xb8,0x49,0x02,0x70,0xa1,0xb8,0x9c,0xa7,
1346 0x24,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x30,0x10,0x31,
1347 0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x03,0x13,0x05,0x43,0x65,0x72,0x74,0x31,
1348 0x30,0x1e,0x17,0x0d,0x30,0x37,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
1349 0x30,0x5a,0x17,0x0d,0x30,0x37,0x31,0x32,0x33,0x31,0x32,0x33,0x35,0x39,0x35,
1350 0x39,0x5a,0x30,0x10,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x03,0x13,0x05,
1351 0x43,0x65,0x72,0x74,0x31,0x30,0x81,0x9f,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
1352 0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x81,0x8d,0x00,0x30,0x81,0x89,
1353 0x02,0x81,0x81,0x00,0xad,0x7e,0xca,0xf3,0xe5,0x99,0xc2,0x2a,0xca,0x50,0x82,
1354 0x7c,0x2d,0xa4,0x81,0xcd,0x0d,0x0d,0x86,0xd7,0xd8,0xb2,0xde,0xc5,0xc3,0x34,
1355 0x9e,0x07,0x78,0x08,0x11,0x12,0x2d,0x21,0x0a,0x09,0x07,0x14,0x03,0x7a,0xe7,
1356 0x3b,0x58,0xf1,0xde,0x3e,0x01,0x25,0x93,0xab,0x8f,0xce,0x1f,0xc1,0x33,0x91,
1357 0xfe,0x59,0xb9,0x3b,0x9e,0x95,0x12,0x89,0x8e,0xc3,0x4b,0x98,0x1b,0x99,0xc5,
1358 0x07,0xe2,0xdf,0x15,0x4c,0x39,0x76,0x06,0xad,0xdb,0x16,0x06,0x49,0xba,0xcd,
1359 0x0f,0x07,0xd6,0xea,0x27,0xa6,0xfe,0x3d,0x88,0xe5,0x97,0x45,0x72,0xb6,0x1c,
1360 0xc0,0x1c,0xb1,0xa2,0x89,0xe8,0x37,0x9e,0xf6,0x2a,0xcf,0xd5,0x1f,0x2f,0x35,
1361 0x5e,0x8f,0x3a,0x9c,0x61,0xb1,0xf1,0x6c,0xff,0x8c,0xb2,0x2f,0x02,0x03,0x01,
1362 0x00,0x01,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x03,0x81,
1363 0x81,0x00,0xa8,0xec,0x8c,0x34,0xe7,0x2c,0xdf,0x75,0x87,0xc4,0xf7,0xda,0x71,
1364 0x72,0x29,0xb2,0x48,0xa8,0x2a,0xec,0x7b,0x7d,0x19,0xb9,0x5f,0x1d,0xd9,0x91,
1365 0x2b,0xc4,0x28,0x7e,0xd6,0xb5,0x91,0x69,0xa5,0x8a,0x1a,0x1f,0x97,0x98,0x46,
1366 0x9d,0xdf,0x12,0xf6,0x45,0x62,0xad,0x60,0xb6,0xba,0xb0,0xfd,0xf5,0x9f,0xc6,
1367 0x98,0x05,0x4f,0x4d,0x48,0xdc,0xee,0x69,0xbe,0xb8,0xc4,0xc4,0xd7,0x1b,0xb1,
1368 0x1f,0x64,0xd6,0x45,0xa7,0xdb,0xb3,0x87,0x63,0x0f,0x54,0xe1,0x3a,0x6b,0x57,
1369 0x36,0xd7,0x68,0x65,0xcf,0xda,0x57,0x8d,0xcd,0x84,0x75,0x47,0x26,0x2c,0xef,
1370 0x1e,0x8f,0xc7,0x3b,0xee,0x5d,0x03,0xa6,0xdf,0x3a,0x20,0xb2,0xcc,0xc9,0x09,
1371 0x2c,0xfe,0x2b,0x79,0xb0,0xca,0x2c,0x9a,0x81,0x6b };
1372 static const BYTE chain7_1[] = {
1373 0x30,0x82,0x01,0x93,0x30,0x81,0xfd,0xa0,0x03,0x02,0x01,0x02,0x02,0x01,0x01,
1374 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,
1375 0x30,0x10,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x03,0x13,0x05,0x43,0x65,
1376 0x72,0x74,0x31,0x30,0x1e,0x17,0x0d,0x30,0x37,0x30,0x31,0x30,0x31,0x30,0x30,
1377 0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,0x30,0x37,0x31,0x32,0x33,0x31,0x32,0x33,
1378 0x35,0x39,0x35,0x39,0x5a,0x30,0x10,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,
1379 0x03,0x13,0x05,0x43,0x65,0x72,0x74,0x32,0x30,0x81,0x9f,0x30,0x0d,0x06,0x09,
1380 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x81,0x8d,0x00,
1381 0x30,0x81,0x89,0x02,0x81,0x81,0x00,0xb8,0x52,0xda,0xc5,0x4b,0x3f,0xe5,0x33,
1382 0x0e,0x67,0x5f,0x48,0x21,0xdc,0x7e,0xef,0x37,0x33,0xba,0xff,0xb4,0xc6,0xdc,
1383 0xb6,0x17,0x8e,0x20,0x55,0x07,0x12,0xd2,0x7b,0x3c,0xce,0x30,0xc5,0xa7,0x48,
1384 0x9f,0x6e,0xfe,0xb8,0xbe,0xdb,0x9f,0x9b,0x17,0x60,0x16,0xde,0xc6,0x8b,0x47,
1385 0xd1,0x57,0x71,0x3c,0x93,0xfc,0xbd,0xec,0x44,0x32,0x3b,0xb9,0xcf,0x6b,0x05,
1386 0x72,0xa7,0x87,0x8e,0x7e,0xd4,0x9a,0x87,0x1c,0x2f,0xb7,0x82,0x40,0xfc,0x6a,
1387 0x80,0x83,0x68,0x28,0xce,0x84,0xf4,0x0b,0x2e,0x44,0xcb,0x53,0xac,0x85,0x85,
1388 0xb5,0x46,0x36,0x98,0x3c,0x10,0x02,0xaa,0x02,0xbc,0x8b,0xa2,0x23,0xb2,0xd3,
1389 0x51,0x9a,0x22,0x4a,0xe3,0xaa,0x4e,0x7c,0xda,0x38,0xcf,0x49,0x98,0x72,0xa3,
1390 0x02,0x03,0x01,0x00,0x01,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
1391 0x01,0x01,0x05,0x05,0x00,0x03,0x81,0x81,0x00,0x9f,0x69,0xfd,0x26,0xd5,0x4b,
1392 0xe0,0xab,0x12,0x21,0xb9,0xfc,0xf7,0xe0,0x0c,0x09,0x94,0xad,0x27,0xd7,0x9d,
1393 0xa3,0xcc,0x46,0x2a,0x25,0x9a,0x24,0xa7,0x31,0x58,0x78,0xf5,0xfc,0x30,0xe1,
1394 0x6d,0xfd,0x59,0xab,0xbe,0x69,0xa0,0xea,0xe3,0x7d,0x7a,0x7b,0xe5,0x85,0xeb,
1395 0x86,0x6a,0x84,0x3c,0x96,0x01,0x1a,0x70,0xa7,0xb8,0xcb,0xf2,0x11,0xe7,0x52,
1396 0x9c,0x58,0x2d,0xac,0x63,0xce,0x72,0x4b,0xad,0x62,0xa8,0x1d,0x75,0x96,0xe2,
1397 0x27,0xf5,0x6f,0xba,0x91,0xf8,0xf1,0xb0,0xbf,0x90,0x24,0x6d,0xba,0x5d,0xd7,
1398 0x39,0x63,0x3b,0x7c,0x04,0x5d,0x89,0x9d,0x1c,0xf2,0xf7,0xcc,0xdf,0x6e,0x8a,
1399 0x43,0xa9,0xdd,0x86,0x05,0xa2,0xf3,0x22,0x2d,0x1e,0x70,0xa1,0x59,0xd7,0xa5,
1400 0x94,0x7d };
1402 static void testGetIssuerCert(void)
1404 BOOL ret;
1405 PCCERT_CONTEXT parent, child, cert1, cert2;
1406 DWORD flags = 0xffffffff;
1407 HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1408 CERT_STORE_CREATE_NEW_FLAG, NULL);
1410 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1412 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1413 expiredCert, sizeof(expiredCert), CERT_STORE_ADD_ALWAYS, NULL);
1414 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1415 GetLastError());
1417 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1418 childOfExpired, sizeof(childOfExpired), CERT_STORE_ADD_ALWAYS, &child);
1419 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1420 GetLastError());
1422 /* These crash:
1423 parent = CertGetIssuerCertificateFromStore(NULL, NULL, NULL, NULL);
1424 parent = CertGetIssuerCertificateFromStore(store, NULL, NULL, NULL);
1426 parent = CertGetIssuerCertificateFromStore(NULL, NULL, NULL, &flags);
1427 ok(!parent && GetLastError() == E_INVALIDARG,
1428 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1429 parent = CertGetIssuerCertificateFromStore(store, NULL, NULL, &flags);
1430 ok(!parent && GetLastError() == E_INVALIDARG,
1431 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1432 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1433 ok(!parent && GetLastError() == E_INVALIDARG,
1434 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1435 /* Confusing: the caller cannot set either of the
1436 * CERT_STORE_NO_*_FLAGs, as these are not checks,
1437 * they're results:
1439 flags = CERT_STORE_NO_CRL_FLAG | CERT_STORE_NO_ISSUER_FLAG;
1440 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1441 ok(!parent && GetLastError() == E_INVALIDARG,
1442 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1443 /* Perform no checks */
1444 flags = 0;
1445 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1446 ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08x\n",
1447 GetLastError());
1448 if (parent)
1449 CertFreeCertificateContext(parent);
1450 /* Check revocation and signature only */
1451 flags = CERT_STORE_REVOCATION_FLAG | CERT_STORE_SIGNATURE_FLAG;
1452 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1453 ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08x\n",
1454 GetLastError());
1455 /* Confusing: CERT_STORE_REVOCATION_FLAG succeeds when there is no CRL by
1456 * setting CERT_STORE_NO_CRL_FLAG.
1458 ok(flags == (CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG),
1459 "Expected CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG, got %08x\n",
1460 flags);
1461 if (parent)
1462 CertFreeCertificateContext(parent);
1463 /* Checking time validity is not productive, because while most Windows
1464 * versions return 0 (time valid) because the child is not expired,
1465 * Windows 2003 SP1 returns that it is expired. Thus the range of
1466 * possibilities is covered, and a test verifies nothing.
1469 CertFreeCertificateContext(child);
1470 CertCloseStore(store, 0);
1472 flags = 0;
1473 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1474 CERT_STORE_CREATE_NEW_FLAG, NULL);
1475 /* With only the child certificate, no issuer will be found */
1476 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1477 chain7_1, sizeof(chain7_1), CERT_STORE_ADD_ALWAYS, &child);
1478 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1479 ok(parent == NULL, "Expected no issuer\n");
1480 /* Adding an issuer allows one (and only one) issuer to be found */
1481 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1482 chain10_1, sizeof(chain10_1), CERT_STORE_ADD_ALWAYS, &cert1);
1483 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1484 ok(parent == cert1, "Expected cert1 to be the issuer\n");
1485 parent = CertGetIssuerCertificateFromStore(store, child, parent, &flags);
1486 ok(parent == NULL, "Expected only one issuer\n");
1487 /* Adding a second issuer allows two issuers to be found - and the second
1488 * issuer is found before the first, implying certs are added to the head
1489 * of a list.
1491 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1492 chain10_0, sizeof(chain10_0), CERT_STORE_ADD_ALWAYS, &cert2);
1493 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1494 ok(parent == cert2, "Expected cert2 to be the first issuer\n");
1495 parent = CertGetIssuerCertificateFromStore(store, child, parent, &flags);
1496 ok(parent == cert1, "Expected cert1 to be the second issuer\n");
1497 parent = CertGetIssuerCertificateFromStore(store, child, parent, &flags);
1498 ok(parent == NULL, "Expected no more than two issuers\n");
1499 CertFreeCertificateContext(child);
1500 CertFreeCertificateContext(cert1);
1501 CertFreeCertificateContext(cert2);
1502 CertCloseStore(store, 0);
1504 /* Repeat the test, reversing the order in which issuers are added,
1505 * to show it's order-dependent.
1507 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1508 CERT_STORE_CREATE_NEW_FLAG, NULL);
1509 /* With only the child certificate, no issuer will be found */
1510 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1511 chain7_1, sizeof(chain7_1), CERT_STORE_ADD_ALWAYS, &child);
1512 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1513 ok(parent == NULL, "Expected no issuer\n");
1514 /* Adding an issuer allows one (and only one) issuer to be found */
1515 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1516 chain10_0, sizeof(chain10_0), CERT_STORE_ADD_ALWAYS, &cert1);
1517 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1518 ok(parent == cert1, "Expected cert1 to be the issuer\n");
1519 parent = CertGetIssuerCertificateFromStore(store, child, parent, &flags);
1520 ok(parent == NULL, "Expected only one issuer\n");
1521 /* Adding a second issuer allows two issuers to be found - and the second
1522 * issuer is found before the first, implying certs are added to the head
1523 * of a list.
1525 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1526 chain10_1, sizeof(chain10_1), CERT_STORE_ADD_ALWAYS, &cert2);
1527 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1528 ok(parent == cert2, "Expected cert2 to be the first issuer\n");
1529 parent = CertGetIssuerCertificateFromStore(store, child, parent, &flags);
1530 ok(parent == cert1, "Expected cert1 to be the second issuer\n");
1531 parent = CertGetIssuerCertificateFromStore(store, child, parent, &flags);
1532 ok(parent == NULL, "Expected no more than two issuers\n");
1533 CertFreeCertificateContext(child);
1534 CertFreeCertificateContext(cert1);
1535 CertFreeCertificateContext(cert2);
1536 CertCloseStore(store, 0);
1539 static void testCryptHashCert(void)
1541 static const BYTE emptyHash[] = { 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b,
1542 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07,
1543 0x09 };
1544 static const BYTE knownHash[] = { 0xae, 0x9d, 0xbf, 0x6d, 0xf5, 0x46, 0xee,
1545 0x8b, 0xc5, 0x7a, 0x13, 0xba, 0xc2, 0xb1, 0x04, 0xf2, 0xbf, 0x52, 0xa8,
1546 0xa2 };
1547 static const BYTE toHash[] = "abcdefghijklmnopqrstuvwxyz0123456789.,;!?:";
1548 BOOL ret;
1549 BYTE hash[20];
1550 DWORD hashLen = sizeof(hash);
1552 /* NULL buffer and nonzero length crashes
1553 ret = CryptHashCertificate(0, 0, 0, NULL, size, hash, &hashLen);
1554 empty hash length also crashes
1555 ret = CryptHashCertificate(0, 0, 0, buf, size, hash, NULL);
1557 /* Test empty hash */
1558 ret = CryptHashCertificate(0, 0, 0, toHash, sizeof(toHash), NULL,
1559 &hashLen);
1560 ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
1561 ok(hashLen == sizeof(hash), "Got unexpected size of hash %d\n", hashLen);
1562 /* Test with empty buffer */
1563 ret = CryptHashCertificate(0, 0, 0, NULL, 0, hash, &hashLen);
1564 ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
1565 ok(!memcmp(hash, emptyHash, sizeof(emptyHash)),
1566 "Unexpected hash of nothing\n");
1567 /* Test a known value */
1568 ret = CryptHashCertificate(0, 0, 0, toHash, sizeof(toHash), hash,
1569 &hashLen);
1570 ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
1571 ok(!memcmp(hash, knownHash, sizeof(knownHash)), "Unexpected hash\n");
1574 static void verifySig(HCRYPTPROV csp, const BYTE *toSign, size_t toSignLen,
1575 const BYTE *sig, unsigned int sigLen)
1577 HCRYPTHASH hash;
1578 BOOL ret = CryptCreateHash(csp, CALG_SHA1, 0, 0, &hash);
1580 ok(ret, "CryptCreateHash failed: %08x\n", GetLastError());
1581 if (ret)
1583 BYTE mySig[64];
1584 DWORD mySigSize = sizeof(mySig);
1586 ret = CryptHashData(hash, toSign, toSignLen, 0);
1587 ok(ret, "CryptHashData failed: %08x\n", GetLastError());
1588 /* use the A variant so the test can run on Win9x */
1589 ret = CryptSignHashA(hash, AT_SIGNATURE, NULL, 0, mySig, &mySigSize);
1590 ok(ret, "CryptSignHash failed: %08x\n", GetLastError());
1591 if (ret)
1593 ok(mySigSize == sigLen, "Expected sig length %d, got %d\n",
1594 sigLen, mySigSize);
1595 ok(!memcmp(mySig, sig, sigLen), "Unexpected signature\n");
1597 CryptDestroyHash(hash);
1601 /* Tests signing the certificate described by toBeSigned with the CSP passed in,
1602 * using the algorithm with OID sigOID. The CSP is assumed to be empty, and a
1603 * keyset named AT_SIGNATURE will be added to it. The signing key will be
1604 * stored in *key, and the signature will be stored in sig. sigLen should be
1605 * at least 64 bytes.
1607 static void testSignCert(HCRYPTPROV csp, const CRYPT_DATA_BLOB *toBeSigned,
1608 LPCSTR sigOID, HCRYPTKEY *key, BYTE *sig, DWORD *sigLen)
1610 BOOL ret;
1611 DWORD size = 0;
1612 CRYPT_ALGORITHM_IDENTIFIER algoID = { NULL, { 0, NULL } };
1614 /* These all crash
1615 ret = CryptSignCertificate(0, 0, 0, NULL, 0, NULL, NULL, NULL, NULL);
1616 ret = CryptSignCertificate(0, 0, 0, NULL, 0, NULL, NULL, NULL, &size);
1617 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
1618 NULL, NULL, NULL, &size);
1620 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
1621 &algoID, NULL, NULL, &size);
1622 ok(!ret && GetLastError() == NTE_BAD_ALGID,
1623 "Expected NTE_BAD_ALGID, got %08x\n", GetLastError());
1624 algoID.pszObjId = (LPSTR)sigOID;
1625 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
1626 &algoID, NULL, NULL, &size);
1627 ok(!ret &&
1628 (GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == NTE_BAD_ALGID),
1629 "Expected ERROR_INVALID_PARAMETER or NTE_BAD_ALGID, got %08x\n",
1630 GetLastError());
1631 ret = CryptSignCertificate(0, AT_SIGNATURE, 0, toBeSigned->pbData,
1632 toBeSigned->cbData, &algoID, NULL, NULL, &size);
1633 ok(!ret &&
1634 (GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == NTE_BAD_ALGID),
1635 "Expected ERROR_INVALID_PARAMETER or NTE_BAD_ALGID, got %08x\n",
1636 GetLastError());
1638 /* No keys exist in the new CSP yet.. */
1639 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
1640 toBeSigned->cbData, &algoID, NULL, NULL, &size);
1641 ok(!ret && (GetLastError() == NTE_BAD_KEYSET || GetLastError() ==
1642 NTE_NO_KEY), "Expected NTE_BAD_KEYSET or NTE_NO_KEY, got %08x\n",
1643 GetLastError());
1644 ret = CryptGenKey(csp, AT_SIGNATURE, 0, key);
1645 ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
1646 if (ret)
1648 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
1649 toBeSigned->cbData, &algoID, NULL, NULL, &size);
1650 ok(ret, "CryptSignCertificate failed: %08x\n", GetLastError());
1651 ok(size <= *sigLen, "Expected size <= %d, got %d\n", *sigLen, size);
1652 if (ret)
1654 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
1655 toBeSigned->cbData, &algoID, NULL, sig, &size);
1656 ok(ret, "CryptSignCertificate failed: %08x\n", GetLastError());
1657 if (ret)
1659 *sigLen = size;
1660 verifySig(csp, toBeSigned->pbData, toBeSigned->cbData, sig,
1661 size);
1667 static void testVerifyCertSig(HCRYPTPROV csp, const CRYPT_DATA_BLOB *toBeSigned,
1668 LPCSTR sigOID, const BYTE *sig, DWORD sigLen)
1670 CERT_SIGNED_CONTENT_INFO info;
1671 LPBYTE cert = NULL;
1672 DWORD size = 0;
1673 BOOL ret;
1675 if (!pCryptVerifyCertificateSignatureEx)
1677 win_skip("no CryptVerifyCertificateSignatureEx support\n");
1678 return;
1680 if (!pCryptEncodeObjectEx)
1682 win_skip("no CryptEncodeObjectEx support\n");
1683 return;
1685 ret = pCryptVerifyCertificateSignatureEx(0, 0, 0, NULL, 0, NULL, 0, NULL);
1686 ok(!ret && GetLastError() == E_INVALIDARG,
1687 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1688 ret = pCryptVerifyCertificateSignatureEx(csp, 0, 0, NULL, 0, NULL, 0, NULL);
1689 ok(!ret && GetLastError() == E_INVALIDARG,
1690 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1691 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING, 0, NULL, 0,
1692 NULL, 0, NULL);
1693 ok(!ret && GetLastError() == E_INVALIDARG,
1694 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1695 /* This crashes
1696 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1697 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, NULL, 0, NULL, 0, NULL);
1699 info.ToBeSigned.cbData = toBeSigned->cbData;
1700 info.ToBeSigned.pbData = toBeSigned->pbData;
1701 info.SignatureAlgorithm.pszObjId = (LPSTR)sigOID;
1702 info.SignatureAlgorithm.Parameters.cbData = 0;
1703 info.Signature.cbData = sigLen;
1704 info.Signature.pbData = (BYTE *)sig;
1705 info.Signature.cUnusedBits = 0;
1706 ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, X509_CERT, &info,
1707 CRYPT_ENCODE_ALLOC_FLAG, NULL, &cert, &size);
1708 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1709 if (cert)
1711 CRYPT_DATA_BLOB certBlob = { 0, NULL };
1712 PCERT_PUBLIC_KEY_INFO pubKeyInfo = NULL;
1714 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1715 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
1716 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
1717 "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
1718 certBlob.cbData = 1;
1719 certBlob.pbData = (void *)0xdeadbeef;
1720 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1721 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
1722 ok(!ret && (GetLastError() == STATUS_ACCESS_VIOLATION ||
1723 GetLastError() == CRYPT_E_ASN1_EOD /* Win9x */ ||
1724 GetLastError() == CRYPT_E_ASN1_BADTAG /* Win98 */),
1725 "Expected STATUS_ACCESS_VIOLATION, CRYPT_E_ASN1_EOD, OR CRYPT_E_ASN1_BADTAG, got %08x\n",
1726 GetLastError());
1728 certBlob.cbData = size;
1729 certBlob.pbData = cert;
1730 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1731 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
1732 ok(!ret && GetLastError() == E_INVALIDARG,
1733 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1734 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1735 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
1736 CRYPT_VERIFY_CERT_SIGN_ISSUER_NULL, NULL, 0, NULL);
1737 ok(!ret && GetLastError() == E_INVALIDARG,
1738 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1739 /* This crashes
1740 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1741 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
1742 CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY, NULL, 0, NULL);
1744 CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
1745 (LPSTR)sigOID, 0, NULL, NULL, &size);
1746 pubKeyInfo = HeapAlloc(GetProcessHeap(), 0, size);
1747 if (pubKeyInfo)
1749 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
1750 X509_ASN_ENCODING, (LPSTR)sigOID, 0, NULL, pubKeyInfo, &size);
1751 ok(ret, "CryptExportKey failed: %08x\n", GetLastError());
1752 if (ret)
1754 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1755 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
1756 CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY, pubKeyInfo, 0, NULL);
1757 ok(ret, "CryptVerifyCertificateSignatureEx failed: %08x\n",
1758 GetLastError());
1760 HeapFree(GetProcessHeap(), 0, pubKeyInfo);
1762 LocalFree(cert);
1766 static BYTE emptyCert[] = { 0x30, 0x00 };
1768 static void testCertSigs(void)
1770 HCRYPTPROV csp;
1771 CRYPT_DATA_BLOB toBeSigned = { sizeof(emptyCert), emptyCert };
1772 BOOL ret;
1773 HCRYPTKEY key;
1774 BYTE sig[64];
1775 DWORD sigSize = sizeof(sig);
1777 /* Just in case a previous run failed, delete this thing */
1778 pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
1779 CRYPT_DELETEKEYSET);
1780 ret = pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
1781 CRYPT_NEWKEYSET);
1782 ok(ret, "CryptAcquireContext failed: %08x\n", GetLastError());
1784 testSignCert(csp, &toBeSigned, szOID_RSA_SHA1RSA, &key, sig, &sigSize);
1785 testVerifyCertSig(csp, &toBeSigned, szOID_RSA_SHA1RSA, sig, sigSize);
1787 CryptDestroyKey(key);
1788 CryptReleaseContext(csp, 0);
1789 ret = pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
1790 CRYPT_DELETEKEYSET);
1793 static const BYTE md5SignedEmptyCert[] = {
1794 0x30,0x56,0x30,0x33,0x02,0x00,0x30,0x02,0x06,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,
1795 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,
1796 0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x07,
1797 0x30,0x02,0x06,0x00,0x03,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,
1798 0x0d,0x02,0x05,0x05,0x00,0x03,0x11,0x00,0xfb,0x0f,0x66,0x82,0x66,0xd9,0xe5,0xf8,
1799 0xd8,0xa2,0x55,0x2b,0xe1,0xa5,0xd9,0x04 };
1800 static const BYTE md5SignedEmptyCertNoNull[] = {
1801 0x30,0x54,0x30,0x33,0x02,0x00,0x30,0x02,0x06,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,
1802 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,
1803 0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x07,
1804 0x30,0x02,0x06,0x00,0x03,0x01,0x00,0x30,0x0a,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,
1805 0x0d,0x02,0x05,0x03,0x11,0x00,0x04,0xd9,0xa5,0xe1,0x2b,0x55,0xa2,0xd8,0xf8,0xe5,
1806 0xd9,0x66,0x82,0x66,0x0f,0xfb };
1808 static void testSignAndEncodeCert(void)
1810 static char oid_rsa_md5rsa[] = szOID_RSA_MD5RSA;
1811 static char oid_rsa_md5[] = szOID_RSA_MD5;
1812 BOOL ret;
1813 DWORD size;
1814 CRYPT_ALGORITHM_IDENTIFIER algID = { 0 };
1815 CERT_INFO info = { 0 };
1817 /* Crash
1818 ret = CryptSignAndEncodeCertificate(0, 0, 0, NULL, NULL, NULL, NULL, NULL,
1819 NULL);
1820 ret = CryptSignAndEncodeCertificate(0, 0, 0, NULL, NULL, NULL, NULL, NULL,
1821 &size);
1823 ret = CryptSignAndEncodeCertificate(0, 0, 0, NULL, NULL, &algID, NULL, NULL,
1824 &size);
1825 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1826 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1827 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING, NULL, NULL,
1828 &algID, NULL, NULL, &size);
1829 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1830 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1831 ret = CryptSignAndEncodeCertificate(0, 0, 0, X509_CERT_TO_BE_SIGNED, NULL,
1832 &algID, NULL, NULL, &size);
1833 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1834 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1835 /* Crashes on some win9x boxes */
1836 if (0)
1838 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1839 X509_CERT_TO_BE_SIGNED, NULL, &algID, NULL, NULL, &size);
1840 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1841 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1843 /* Crashes
1844 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1845 X509_CERT_TO_BE_SIGNED, &info, NULL, NULL, NULL, &size);
1847 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1848 X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, NULL, &size);
1849 ok(!ret &&
1850 (GetLastError() == NTE_BAD_ALGID ||
1851 GetLastError() == OSS_BAD_PTR), /* win9x */
1852 "Expected NTE_BAD_ALGID, got %08x\n", GetLastError());
1853 algID.pszObjId = oid_rsa_md5rsa;
1854 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1855 X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, NULL, &size);
1856 ok(!ret &&
1857 (GetLastError() == ERROR_INVALID_PARAMETER ||
1858 GetLastError() == NTE_BAD_ALGID ||
1859 GetLastError() == OSS_BAD_PTR), /* Win9x */
1860 "Expected ERROR_INVALID_PARAMETER or NTE_BAD_ALGID, got %08x\n",
1861 GetLastError());
1862 algID.pszObjId = oid_rsa_md5;
1863 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1864 X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, NULL, &size);
1865 /* oid_rsa_md5 not present in some win2k */
1866 if (ret)
1868 LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, size);
1870 if (buf)
1872 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1873 X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, buf, &size);
1874 ok(ret, "CryptSignAndEncodeCertificate failed: %08x\n",
1875 GetLastError());
1876 /* Tricky: because the NULL parameters may either be omitted or
1877 * included as an asn.1-encoded NULL (0x05,0x00), two different
1878 * values are allowed.
1880 ok(size == sizeof(md5SignedEmptyCert) ||
1881 size == sizeof(md5SignedEmptyCertNoNull), "Unexpected size %d\n",
1882 size);
1883 if (size == sizeof(md5SignedEmptyCert))
1884 ok(!memcmp(buf, md5SignedEmptyCert, size),
1885 "Unexpected value\n");
1886 else if (size == sizeof(md5SignedEmptyCertNoNull))
1887 ok(!memcmp(buf, md5SignedEmptyCertNoNull, size),
1888 "Unexpected value\n");
1889 HeapFree(GetProcessHeap(), 0, buf);
1894 static void testCreateSelfSignCert(void)
1896 PCCERT_CONTEXT context;
1897 CERT_NAME_BLOB name = { sizeof(subjectName), subjectName };
1898 HCRYPTPROV csp;
1899 BOOL ret;
1900 HCRYPTKEY key;
1901 CRYPT_KEY_PROV_INFO info;
1903 if (!pCertCreateSelfSignCertificate)
1905 win_skip("CertCreateSelfSignCertificate() is not available\n");
1906 return;
1909 /* This crashes:
1910 context = pCertCreateSelfSignCertificate(0, NULL, 0, NULL, NULL, NULL, NULL,
1911 NULL);
1912 * Calling this with no first parameter creates a new key container, which
1913 * lasts beyond the test, so I don't test that. Nb: the generated key
1914 * name is a GUID.
1915 context = pCertCreateSelfSignCertificate(0, &name, 0, NULL, NULL, NULL, NULL,
1916 NULL);
1919 /* Acquire a CSP */
1920 pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
1921 CRYPT_DELETEKEYSET);
1922 ret = pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
1923 CRYPT_NEWKEYSET);
1924 ok(ret, "CryptAcquireContext failed: %08x\n", GetLastError());
1926 context = pCertCreateSelfSignCertificate(csp, &name, 0, NULL, NULL, NULL,
1927 NULL, NULL);
1928 ok(!context && GetLastError() == NTE_NO_KEY,
1929 "Expected NTE_NO_KEY, got %08x\n", GetLastError());
1930 ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
1931 ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
1932 if (ret)
1934 context = pCertCreateSelfSignCertificate(csp, &name, 0, NULL, NULL, NULL,
1935 NULL, NULL);
1936 ok(context != NULL, "CertCreateSelfSignCertificate failed: %08x\n",
1937 GetLastError());
1938 if (context)
1940 DWORD size = 0;
1941 PCRYPT_KEY_PROV_INFO info;
1943 /* The context must have a key provider info property */
1944 ret = CertGetCertificateContextProperty(context,
1945 CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
1946 ok(ret && size, "Expected non-zero key provider info\n");
1947 if (size)
1949 info = HeapAlloc(GetProcessHeap(), 0, size);
1950 if (info)
1952 ret = CertGetCertificateContextProperty(context,
1953 CERT_KEY_PROV_INFO_PROP_ID, info, &size);
1954 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
1955 GetLastError());
1956 if (ret)
1958 /* Sanity-check the key provider */
1959 ok(!lstrcmpW(info->pwszContainerName, cspNameW),
1960 "Unexpected key container\n");
1961 ok(!lstrcmpW(info->pwszProvName, MS_DEF_PROV_W),
1962 "Unexpected provider\n");
1963 ok(info->dwKeySpec == AT_SIGNATURE,
1964 "Expected AT_SIGNATURE, got %d\n", info->dwKeySpec);
1966 HeapFree(GetProcessHeap(), 0, info);
1970 CertFreeCertificateContext(context);
1973 CryptDestroyKey(key);
1976 CryptReleaseContext(csp, 0);
1977 ret = pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
1978 CRYPT_DELETEKEYSET);
1980 /* do the same test with AT_KEYEXCHANGE and key info*/
1981 memset(&info,0,sizeof(info));
1982 info.dwProvType = PROV_RSA_FULL;
1983 info.dwKeySpec = AT_KEYEXCHANGE;
1984 info.pwszProvName = (LPWSTR) MS_DEF_PROV_W;
1985 info.pwszContainerName = cspNameW;
1986 context = pCertCreateSelfSignCertificate(0, &name, 0, &info, NULL, NULL,
1987 NULL, NULL);
1988 ok(context != NULL, "CertCreateSelfSignCertificate failed: %08x\n",
1989 GetLastError());
1990 if (context)
1992 DWORD size = 0;
1993 PCRYPT_KEY_PROV_INFO info;
1995 /* The context must have a key provider info property */
1996 ret = CertGetCertificateContextProperty(context,
1997 CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
1998 ok(ret && size, "Expected non-zero key provider info\n");
1999 if (size)
2001 info = HeapAlloc(GetProcessHeap(), 0, size);
2002 if (info)
2004 ret = CertGetCertificateContextProperty(context,
2005 CERT_KEY_PROV_INFO_PROP_ID, info, &size);
2006 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
2007 GetLastError());
2008 if (ret)
2010 /* Sanity-check the key provider */
2011 ok(!lstrcmpW(info->pwszContainerName, cspNameW),
2012 "Unexpected key container\n");
2013 ok(!lstrcmpW(info->pwszProvName, MS_DEF_PROV_W),
2014 "Unexpected provider\n");
2015 ok(info->dwKeySpec == AT_KEYEXCHANGE,
2016 "Expected AT_KEYEXCHANGE, got %d\n", info->dwKeySpec);
2018 HeapFree(GetProcessHeap(), 0, info);
2022 CertFreeCertificateContext(context);
2025 pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
2026 CRYPT_DELETEKEYSET);
2029 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
2030 szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
2032 static void testKeyUsage(void)
2034 BOOL ret;
2035 PCCERT_CONTEXT context;
2036 DWORD size;
2038 /* Test base cases */
2039 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, NULL);
2040 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2041 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
2042 size = 1;
2043 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, &size);
2044 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2045 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
2046 size = 0;
2047 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, &size);
2048 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2049 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
2050 /* These crash
2051 ret = CertSetEnhancedKeyUsage(NULL, NULL);
2052 usage.cUsageIdentifier = 0;
2053 ret = CertSetEnhancedKeyUsage(NULL, &usage);
2055 /* Test with a cert with no enhanced key usage extension */
2056 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
2057 sizeof(bigCert));
2058 ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
2059 GetLastError());
2060 if (context)
2062 static const char oid[] = "1.2.3.4";
2063 BYTE buf[sizeof(CERT_ENHKEY_USAGE) + 2 * (sizeof(LPSTR) + sizeof(oid))];
2064 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
2066 ret = CertGetEnhancedKeyUsage(context, 0, NULL, NULL);
2067 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2068 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
2069 size = 1;
2070 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &size);
2071 if (ret)
2073 /* Windows 2000, ME, or later: even though it succeeded, we expect
2074 * CRYPT_E_NOT_FOUND, which indicates there is no enhanced key
2075 * usage set for this cert (which implies it's valid for all uses.)
2077 ok(GetLastError() == CRYPT_E_NOT_FOUND,
2078 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
2079 ok(size == sizeof(CERT_ENHKEY_USAGE), "Wrong size %d\n", size);
2080 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2081 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2082 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %d\n",
2083 pUsage->cUsageIdentifier);
2085 else
2087 /* Windows NT, 95, or 98: it fails, and the last error is
2088 * CRYPT_E_NOT_FOUND.
2090 ok(GetLastError() == CRYPT_E_NOT_FOUND,
2091 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
2093 /* I can add a usage identifier when no key usage has been set */
2094 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
2095 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
2096 GetLastError());
2097 size = sizeof(buf);
2098 ret = CertGetEnhancedKeyUsage(context,
2099 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
2100 ok(ret && GetLastError() == 0,
2101 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2102 ok(pUsage->cUsageIdentifier == 1, "Expected 1 usage, got %d\n",
2103 pUsage->cUsageIdentifier);
2104 if (pUsage->cUsageIdentifier)
2105 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
2106 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
2107 /* Now set an empty key usage */
2108 pUsage->cUsageIdentifier = 0;
2109 ret = CertSetEnhancedKeyUsage(context, pUsage);
2110 ok(ret, "CertSetEnhancedKeyUsage failed: %08x\n", GetLastError());
2111 /* Shouldn't find it in the cert */
2112 size = sizeof(buf);
2113 ret = CertGetEnhancedKeyUsage(context,
2114 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
2115 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
2116 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
2117 /* Should find it as an extended property */
2118 ret = CertGetEnhancedKeyUsage(context,
2119 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
2120 ok(ret && GetLastError() == 0,
2121 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2122 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %d\n",
2123 pUsage->cUsageIdentifier);
2124 /* Should find it as either */
2125 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2126 ok(ret && GetLastError() == 0,
2127 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2128 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %d\n",
2129 pUsage->cUsageIdentifier);
2130 /* Add a usage identifier */
2131 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
2132 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
2133 GetLastError());
2134 size = sizeof(buf);
2135 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2136 ok(ret && GetLastError() == 0,
2137 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2138 ok(pUsage->cUsageIdentifier == 1, "Expected 1 identifier, got %d\n",
2139 pUsage->cUsageIdentifier);
2140 if (pUsage->cUsageIdentifier)
2141 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
2142 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
2143 /* Re-adding the same usage identifier succeeds, though it only adds
2144 * a duplicate usage identifier on versions prior to Vista
2146 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
2147 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
2148 GetLastError());
2149 size = sizeof(buf);
2150 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2151 ok(ret && GetLastError() == 0,
2152 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2153 ok(pUsage->cUsageIdentifier == 1 || pUsage->cUsageIdentifier == 2,
2154 "Expected 1 or 2 identifiers, got %d\n", pUsage->cUsageIdentifier);
2155 if (pUsage->cUsageIdentifier)
2156 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
2157 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
2158 if (pUsage->cUsageIdentifier >= 2)
2159 ok(!strcmp(pUsage->rgpszUsageIdentifier[1], oid),
2160 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[1]);
2161 /* Now set a NULL extended property--this deletes the property. */
2162 ret = CertSetEnhancedKeyUsage(context, NULL);
2163 ok(ret, "CertSetEnhancedKeyUsage failed: %08x\n", GetLastError());
2164 SetLastError(0xbaadcafe);
2165 size = sizeof(buf);
2166 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2167 ok(GetLastError() == CRYPT_E_NOT_FOUND,
2168 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
2170 CertFreeCertificateContext(context);
2172 /* Now test with a cert with an enhanced key usage extension */
2173 context = CertCreateCertificateContext(X509_ASN_ENCODING, certWithUsage,
2174 sizeof(certWithUsage));
2175 ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
2176 GetLastError());
2177 if (context)
2179 LPBYTE buf = NULL;
2180 DWORD bufSize = 0, i;
2182 /* The size may depend on what flags are used to query it, so I
2183 * realloc the buffer for each test.
2185 ret = CertGetEnhancedKeyUsage(context,
2186 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, NULL, &bufSize);
2187 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2188 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
2189 if (buf)
2191 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
2193 /* Should find it in the cert */
2194 size = bufSize;
2195 ret = CertGetEnhancedKeyUsage(context,
2196 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
2197 ok(ret && GetLastError() == 0,
2198 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2199 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
2200 pUsage->cUsageIdentifier);
2201 for (i = 0; i < pUsage->cUsageIdentifier; i++)
2202 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
2203 "Expected %s, got %s\n", keyUsages[i],
2204 pUsage->rgpszUsageIdentifier[i]);
2205 HeapFree(GetProcessHeap(), 0, buf);
2207 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
2208 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2209 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
2210 if (buf)
2212 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
2214 /* Should find it as either */
2215 size = bufSize;
2216 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2217 /* In Windows, GetLastError returns CRYPT_E_NOT_FOUND not found
2218 * here, even though the return is successful and the usage id
2219 * count is positive. I don't enforce that here.
2221 ok(ret,
2222 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2223 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
2224 pUsage->cUsageIdentifier);
2225 for (i = 0; i < pUsage->cUsageIdentifier; i++)
2226 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
2227 "Expected %s, got %s\n", keyUsages[i],
2228 pUsage->rgpszUsageIdentifier[i]);
2229 HeapFree(GetProcessHeap(), 0, buf);
2231 /* Shouldn't find it as an extended property */
2232 ret = CertGetEnhancedKeyUsage(context,
2233 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, NULL, &size);
2234 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
2235 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
2236 /* Adding a usage identifier overrides the cert's usage!? */
2237 ret = CertAddEnhancedKeyUsageIdentifier(context, szOID_RSA_RSA);
2238 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
2239 GetLastError());
2240 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
2241 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2242 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
2243 if (buf)
2245 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
2247 /* Should find it as either */
2248 size = bufSize;
2249 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2250 ok(ret,
2251 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2252 ok(pUsage->cUsageIdentifier == 1, "Expected 1 usage, got %d\n",
2253 pUsage->cUsageIdentifier);
2254 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], szOID_RSA_RSA),
2255 "Expected %s, got %s\n", szOID_RSA_RSA,
2256 pUsage->rgpszUsageIdentifier[0]);
2257 HeapFree(GetProcessHeap(), 0, buf);
2259 /* But querying the cert directly returns its usage */
2260 ret = CertGetEnhancedKeyUsage(context,
2261 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, NULL, &bufSize);
2262 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2263 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
2264 if (buf)
2266 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
2268 size = bufSize;
2269 ret = CertGetEnhancedKeyUsage(context,
2270 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
2271 ok(ret,
2272 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2273 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
2274 pUsage->cUsageIdentifier);
2275 for (i = 0; i < pUsage->cUsageIdentifier; i++)
2276 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
2277 "Expected %s, got %s\n", keyUsages[i],
2278 pUsage->rgpszUsageIdentifier[i]);
2279 HeapFree(GetProcessHeap(), 0, buf);
2281 /* And removing the only usage identifier in the extended property
2282 * results in the cert's key usage being found.
2284 ret = CertRemoveEnhancedKeyUsageIdentifier(context, szOID_RSA_RSA);
2285 ok(ret, "CertRemoveEnhancedKeyUsage failed: %08x\n", GetLastError());
2286 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
2287 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2288 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
2289 if (buf)
2291 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
2293 /* Should find it as either */
2294 size = bufSize;
2295 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2296 ok(ret,
2297 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2298 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
2299 pUsage->cUsageIdentifier);
2300 for (i = 0; i < pUsage->cUsageIdentifier; i++)
2301 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
2302 "Expected %s, got %s\n", keyUsages[i],
2303 pUsage->rgpszUsageIdentifier[i]);
2304 HeapFree(GetProcessHeap(), 0, buf);
2307 CertFreeCertificateContext(context);
2311 static const BYTE cert2WithUsage[] = {
2312 0x30,0x81,0x89,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2313 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2314 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2315 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2316 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2317 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2318 0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x25,0x30,0x23,
2319 0x30,0x21,0x06,0x03,0x55,0x1d,0x25,0x01,0x01,0xff,0x04,0x17,0x30,0x15,0x06,
2320 0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x03,0x02,0x06,0x09,0x2a,0x86,0x48,0x86,
2321 0xf7,0x0d,0x01,0x01,0x01 };
2323 static void testGetValidUsages(void)
2325 static const LPCSTR expectedOIDs[] = {
2326 "1.3.6.1.5.5.7.3.3",
2327 "1.3.6.1.5.5.7.3.2",
2328 "1.2.840.113549.1.1.1",
2330 static const LPCSTR expectedOIDs2[] = {
2331 "1.3.6.1.5.5.7.3.2",
2332 "1.2.840.113549.1.1.1",
2334 BOOL ret;
2335 int numOIDs;
2336 DWORD size;
2337 LPSTR *oids = NULL;
2338 PCCERT_CONTEXT contexts[3];
2340 if (!pCertGetValidUsages)
2342 win_skip("CertGetValidUsages() is not available\n");
2343 return;
2346 /* Crash
2347 ret = pCertGetValidUsages(0, NULL, NULL, NULL, NULL);
2348 ret = pCertGetValidUsages(0, NULL, NULL, NULL, &size);
2350 contexts[0] = NULL;
2351 numOIDs = size = 0xdeadbeef;
2352 SetLastError(0xdeadbeef);
2353 ret = pCertGetValidUsages(1, &contexts[0], &numOIDs, NULL, &size);
2354 ok(ret, "CertGetValidUsages failed: %d\n", GetLastError());
2355 ok(numOIDs == -1, "Expected -1, got %d\n", numOIDs);
2356 ok(size == 0, "Expected size 0, got %d\n", size);
2357 contexts[0] = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
2358 sizeof(bigCert));
2359 contexts[1] = CertCreateCertificateContext(X509_ASN_ENCODING, certWithUsage,
2360 sizeof(certWithUsage));
2361 contexts[2] = CertCreateCertificateContext(X509_ASN_ENCODING,
2362 cert2WithUsage, sizeof(cert2WithUsage));
2363 numOIDs = size = 0xdeadbeef;
2364 ret = pCertGetValidUsages(0, NULL, &numOIDs, NULL, &size);
2365 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2366 ok(numOIDs == -1, "Expected -1, got %d\n", numOIDs);
2367 ok(size == 0, "Expected size 0, got %d\n", size);
2368 numOIDs = size = 0xdeadbeef;
2369 ret = pCertGetValidUsages(1, contexts, &numOIDs, NULL, &size);
2370 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2371 ok(numOIDs == -1, "Expected -1, got %d\n", numOIDs);
2372 ok(size == 0, "Expected size 0, got %d\n", size);
2373 ret = pCertGetValidUsages(1, &contexts[1], &numOIDs, NULL, &size);
2374 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2375 ok(numOIDs == 3, "Expected 3, got %d\n", numOIDs);
2376 ok(size, "Expected non-zero size\n");
2377 oids = HeapAlloc(GetProcessHeap(), 0, size);
2378 if (oids)
2380 int i;
2381 DWORD smallSize = 1;
2383 SetLastError(0xdeadbeef);
2384 ret = pCertGetValidUsages(1, &contexts[1], &numOIDs, oids, &smallSize);
2385 ok(!ret && GetLastError() == ERROR_MORE_DATA,
2386 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
2387 ret = pCertGetValidUsages(1, &contexts[1], &numOIDs, oids, &size);
2388 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2389 for (i = 0; i < numOIDs; i++)
2390 ok(!lstrcmpA(oids[i], expectedOIDs[i]), "unexpected OID %s\n",
2391 oids[i]);
2392 HeapFree(GetProcessHeap(), 0, oids);
2394 numOIDs = size = 0xdeadbeef;
2395 /* Oddly enough, this crashes when the number of contexts is not 1:
2396 ret = pCertGetValidUsages(2, contexts, &numOIDs, NULL, &size);
2397 * but setting size to 0 allows it to succeed:
2399 size = 0;
2400 ret = pCertGetValidUsages(2, contexts, &numOIDs, NULL, &size);
2401 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2402 ok(numOIDs == 3, "Expected 3, got %d\n", numOIDs);
2403 ok(size, "Expected non-zero size\n");
2404 oids = HeapAlloc(GetProcessHeap(), 0, size);
2405 if (oids)
2407 int i;
2409 ret = pCertGetValidUsages(1, &contexts[1], &numOIDs, oids, &size);
2410 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2411 for (i = 0; i < numOIDs; i++)
2412 ok(!lstrcmpA(oids[i], expectedOIDs[i]), "unexpected OID %s\n",
2413 oids[i]);
2414 HeapFree(GetProcessHeap(), 0, oids);
2416 numOIDs = 0xdeadbeef;
2417 size = 0;
2418 ret = pCertGetValidUsages(1, &contexts[2], &numOIDs, NULL, &size);
2419 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2420 ok(numOIDs == 2, "Expected 2, got %d\n", numOIDs);
2421 ok(size, "Expected non-zero size\n");
2422 oids = HeapAlloc(GetProcessHeap(), 0, size);
2423 if (oids)
2425 int i;
2427 ret = pCertGetValidUsages(1, &contexts[2], &numOIDs, oids, &size);
2428 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2429 for (i = 0; i < numOIDs; i++)
2430 ok(!lstrcmpA(oids[i], expectedOIDs2[i]), "unexpected OID %s\n",
2431 oids[i]);
2432 HeapFree(GetProcessHeap(), 0, oids);
2434 numOIDs = 0xdeadbeef;
2435 size = 0;
2436 ret = pCertGetValidUsages(3, contexts, &numOIDs, NULL, &size);
2437 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2438 ok(numOIDs == 2, "Expected 2, got %d\n", numOIDs);
2439 ok(size, "Expected non-zero size\n");
2440 oids = HeapAlloc(GetProcessHeap(), 0, size);
2441 if (oids)
2443 int i;
2445 ret = pCertGetValidUsages(3, contexts, &numOIDs, oids, &size);
2446 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2447 for (i = 0; i < numOIDs; i++)
2448 ok(!lstrcmpA(oids[i], expectedOIDs2[i]), "unexpected OID %s\n",
2449 oids[i]);
2450 HeapFree(GetProcessHeap(), 0, oids);
2452 CertFreeCertificateContext(contexts[0]);
2453 CertFreeCertificateContext(contexts[1]);
2454 CertFreeCertificateContext(contexts[2]);
2457 static void testCompareCertName(void)
2459 static BYTE bogus[] = { 1, 2, 3, 4 };
2460 static BYTE bogusPrime[] = { 0, 1, 2, 3, 4 };
2461 static BYTE emptyPrime[] = { 0x30, 0x00, 0x01 };
2462 BOOL ret;
2463 CERT_NAME_BLOB blob1, blob2;
2465 /* crashes
2466 ret = CertCompareCertificateName(0, NULL, NULL);
2468 /* An empty name checks against itself.. */
2469 blob1.pbData = emptyCert;
2470 blob1.cbData = sizeof(emptyCert);
2471 ret = CertCompareCertificateName(0, &blob1, &blob1);
2472 ok(ret, "CertCompareCertificateName failed: %08x\n", GetLastError());
2473 /* It doesn't have to be a valid encoded name.. */
2474 blob1.pbData = bogus;
2475 blob1.cbData = sizeof(bogus);
2476 ret = CertCompareCertificateName(0, &blob1, &blob1);
2477 ok(ret, "CertCompareCertificateName failed: %08x\n", GetLastError());
2478 /* Leading zeroes matter.. */
2479 blob2.pbData = bogusPrime;
2480 blob2.cbData = sizeof(bogusPrime);
2481 ret = CertCompareCertificateName(0, &blob1, &blob2);
2482 ok(!ret, "Expected failure\n");
2483 /* As do trailing extra bytes. */
2484 blob2.pbData = emptyPrime;
2485 blob2.cbData = sizeof(emptyPrime);
2486 ret = CertCompareCertificateName(0, &blob1, &blob2);
2487 ok(!ret, "Expected failure\n");
2490 static BYTE int1[] = { 0x88, 0xff, 0xff, 0xff };
2491 static BYTE int2[] = { 0x88, 0xff };
2492 static BYTE int3[] = { 0x23, 0xff };
2493 static BYTE int4[] = { 0x7f, 0x00 };
2494 static BYTE int5[] = { 0x7f };
2495 static BYTE int6[] = { 0x80, 0x00, 0x00, 0x00 };
2496 static BYTE int7[] = { 0x80, 0x00 };
2498 static struct IntBlobTest
2500 CRYPT_INTEGER_BLOB blob1;
2501 CRYPT_INTEGER_BLOB blob2;
2502 BOOL areEqual;
2503 } intBlobs[] = {
2504 { { sizeof(int1), int1 }, { sizeof(int2), int2 }, TRUE },
2505 { { sizeof(int3), int3 }, { sizeof(int3), int3 }, TRUE },
2506 { { sizeof(int4), int4 }, { sizeof(int5), int5 }, TRUE },
2507 { { sizeof(int6), int6 }, { sizeof(int7), int7 }, TRUE },
2508 { { sizeof(int1), int1 }, { sizeof(int7), int7 }, FALSE },
2511 static void testCompareIntegerBlob(void)
2513 DWORD i;
2514 BOOL ret;
2516 for (i = 0; i < sizeof(intBlobs) / sizeof(intBlobs[0]); i++)
2518 ret = CertCompareIntegerBlob(&intBlobs[i].blob1, &intBlobs[i].blob2);
2519 ok(ret == intBlobs[i].areEqual,
2520 "%d: expected blobs %s compare\n", i, intBlobs[i].areEqual ?
2521 "to" : "not to");
2525 static void testComparePublicKeyInfo(void)
2527 BOOL ret;
2528 CERT_PUBLIC_KEY_INFO info1 = { { 0 } }, info2 = { { 0 } };
2529 static CHAR oid_rsa_rsa[] = szOID_RSA_RSA;
2530 static CHAR oid_rsa_sha1rsa[] = szOID_RSA_SHA1RSA;
2531 static CHAR oid_x957_dsa[] = szOID_X957_DSA;
2532 static BYTE bits1[] = { 1, 0 };
2533 static BYTE bits2[] = { 0 };
2534 static BYTE bits3[] = { 1 };
2535 static BYTE bits4[] = { 0x30,8, 2,1,0x81, 2,3,1,0,1 };
2536 static BYTE bits5[] = { 0x30,9, 2,2,0,0x81, 2,3,1,0,1 };
2537 static BYTE bits6[] = { 0x30,9, 2,2,0,0x82, 2,3,1,0,1 };
2539 /* crashes
2540 ret = CertComparePublicKeyInfo(0, NULL, NULL);
2542 /* Empty public keys compare */
2543 ret = CertComparePublicKeyInfo(0, &info1, &info2);
2544 ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
2545 /* Different OIDs appear to compare */
2546 info1.Algorithm.pszObjId = oid_rsa_rsa;
2547 info2.Algorithm.pszObjId = oid_rsa_sha1rsa;
2548 ret = CertComparePublicKeyInfo(0, &info1, &info2);
2549 ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
2550 info2.Algorithm.pszObjId = oid_x957_dsa;
2551 ret = CertComparePublicKeyInfo(0, &info1, &info2);
2552 ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
2553 info1.PublicKey.cbData = sizeof(bits1);
2554 info1.PublicKey.pbData = bits1;
2555 info1.PublicKey.cUnusedBits = 0;
2556 info2.PublicKey.cbData = sizeof(bits1);
2557 info2.PublicKey.pbData = bits1;
2558 info2.PublicKey.cUnusedBits = 0;
2559 ret = CertComparePublicKeyInfo(0, &info1, &info2);
2560 ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
2561 info2.Algorithm.pszObjId = oid_rsa_rsa;
2562 info1.PublicKey.cbData = sizeof(bits4);
2563 info1.PublicKey.pbData = bits4;
2564 info1.PublicKey.cUnusedBits = 0;
2565 info2.PublicKey.cbData = sizeof(bits5);
2566 info2.PublicKey.pbData = bits5;
2567 info2.PublicKey.cUnusedBits = 0;
2568 ret = CertComparePublicKeyInfo(0, &info1, &info2);
2569 ok(!ret, "CertComparePublicKeyInfo: as raw binary: keys should be unequal\n");
2570 ret = CertComparePublicKeyInfo(X509_ASN_ENCODING, &info1, &info2);
2571 ok(ret ||
2572 broken(!ret), /* win9x */
2573 "CertComparePublicKeyInfo: as ASN.1 encoded: keys should be equal\n");
2574 info1.PublicKey.cUnusedBits = 1;
2575 info2.PublicKey.cUnusedBits = 5;
2576 ret = CertComparePublicKeyInfo(X509_ASN_ENCODING, &info1, &info2);
2577 ok(ret ||
2578 broken(!ret), /* win9x */
2579 "CertComparePublicKeyInfo: ASN.1 encoding should ignore cUnusedBits\n");
2580 info1.PublicKey.cUnusedBits = 0;
2581 info2.PublicKey.cUnusedBits = 0;
2582 info1.PublicKey.cbData--; /* kill one byte, make ASN.1 encoded data invalid */
2583 ret = CertComparePublicKeyInfo(X509_ASN_ENCODING, &info1, &info2);
2584 ok(!ret, "CertComparePublicKeyInfo: comparing bad ASN.1 encoded key should fail\n");
2585 /* Even though they compare in their used bits, these do not compare */
2586 info1.PublicKey.cbData = sizeof(bits2);
2587 info1.PublicKey.pbData = bits2;
2588 info1.PublicKey.cUnusedBits = 0;
2589 info2.PublicKey.cbData = sizeof(bits3);
2590 info2.PublicKey.pbData = bits3;
2591 info2.PublicKey.cUnusedBits = 1;
2592 ret = CertComparePublicKeyInfo(0, &info1, &info2);
2593 /* Simple (non-comparing) case */
2594 ok(!ret, "Expected keys not to compare\n");
2595 info2.PublicKey.cbData = sizeof(bits1);
2596 info2.PublicKey.pbData = bits1;
2597 info2.PublicKey.cUnusedBits = 0;
2598 ret = CertComparePublicKeyInfo(0, &info1, &info2);
2599 ok(!ret, "Expected keys not to compare\n");
2600 /* ASN.1 encoded non-comparing case */
2601 info1.PublicKey.cbData = sizeof(bits5);
2602 info1.PublicKey.pbData = bits5;
2603 info1.PublicKey.cUnusedBits = 0;
2604 info2.PublicKey.cbData = sizeof(bits6);
2605 info2.PublicKey.pbData = bits6;
2606 info2.PublicKey.cUnusedBits = 0;
2607 ret = CertComparePublicKeyInfo(X509_ASN_ENCODING, &info1, &info2);
2608 ok(!ret, "CertComparePublicKeyInfo: different keys should be unequal\n");
2611 static void testHashPublicKeyInfo(void)
2613 BOOL ret;
2614 CERT_PUBLIC_KEY_INFO info = { { 0 } };
2615 DWORD len;
2617 /* Crash
2618 ret = CryptHashPublicKeyInfo(0, 0, 0, 0, NULL, NULL, NULL);
2619 ret = CryptHashPublicKeyInfo(0, 0, 0, 0, &info, NULL, NULL);
2621 ret = CryptHashPublicKeyInfo(0, 0, 0, 0, NULL, NULL, &len);
2622 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2623 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2624 /* Crashes on some win9x boxes */
2625 if (0)
2627 ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, NULL, NULL, &len);
2628 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2629 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
2631 ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, &info, NULL, &len);
2632 ok(ret ||
2633 broken(!ret), /* win9x */
2634 "CryptHashPublicKeyInfo failed: %08x\n", GetLastError());
2635 if (ret)
2637 ok(len == 16, "Expected hash size 16, got %d\n", len);
2638 if (len == 16)
2640 static const BYTE emptyHash[] = { 0xb8,0x51,0x3a,0x31,0x0e,0x9f,0x40,
2641 0x36,0x9c,0x92,0x45,0x1b,0x9d,0xc8,0xf9,0xf6 };
2642 BYTE buf[16];
2644 ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, &info, buf,
2645 &len);
2646 ok(ret, "CryptHashPublicKeyInfo failed: %08x\n", GetLastError());
2647 ok(!memcmp(buf, emptyHash, len), "Unexpected hash\n");
2652 static const BYTE md5SignedEmptyCertHash[] = { 0xfb,0x0f,0x66,0x82,0x66,0xd9,
2653 0xe5,0xf8,0xd8,0xa2,0x55,0x2b,0xe1,0xa5,0xd9,0x04 };
2655 static void testHashToBeSigned(void)
2657 BOOL ret;
2658 DWORD size;
2659 BYTE hash[16];
2661 /* Crash */
2662 if (0)
2664 ret = CryptHashToBeSigned(0, 0, NULL, 0, NULL, NULL);
2666 SetLastError(0xdeadbeef);
2667 ret = CryptHashToBeSigned(0, 0, NULL, 0, NULL, &size);
2668 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2669 "expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
2670 SetLastError(0xdeadbeef);
2671 ret = CryptHashToBeSigned(0, X509_ASN_ENCODING, NULL, 0, NULL, &size);
2672 ok(!ret &&
2673 (GetLastError() == CRYPT_E_ASN1_EOD ||
2674 GetLastError() == OSS_BAD_ARG), /* win9x */
2675 "expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
2676 /* Can't sign anything: has to be asn.1 encoded, at least */
2677 SetLastError(0xdeadbeef);
2678 ret = CryptHashToBeSigned(0, X509_ASN_ENCODING, int1, sizeof(int1),
2679 NULL, &size);
2680 ok(!ret &&
2681 (GetLastError() == CRYPT_E_ASN1_BADTAG ||
2682 GetLastError() == OSS_MORE_INPUT), /* win9x */
2683 "expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
2684 /* Can't be empty, either */
2685 SetLastError(0xdeadbeef);
2686 ret = CryptHashToBeSigned(0, X509_ASN_ENCODING, emptyCert,
2687 sizeof(emptyCert), NULL, &size);
2688 ok(!ret &&
2689 (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2690 GetLastError() == OSS_DATA_ERROR), /* win9x */
2691 "expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
2692 /* Signing a cert works */
2693 ret = CryptHashToBeSigned(0, X509_ASN_ENCODING, md5SignedEmptyCert,
2694 sizeof(md5SignedEmptyCert), NULL, &size);
2695 ok(ret ||
2696 broken(!ret), /* win9x */
2697 "CryptHashToBeSigned failed: %08x\n", GetLastError());
2698 if (ret)
2700 ok(size == sizeof(md5SignedEmptyCertHash), "unexpected size %d\n", size);
2703 ret = CryptHashToBeSigned(0, X509_ASN_ENCODING, md5SignedEmptyCert,
2704 sizeof(md5SignedEmptyCert), hash, &size);
2705 ok(!memcmp(hash, md5SignedEmptyCertHash, size), "unexpected value\n");
2708 static void testCompareCert(void)
2710 CERT_INFO info1 = { 0 }, info2 = { 0 };
2711 BOOL ret;
2713 /* Crashes
2714 ret = CertCompareCertificate(X509_ASN_ENCODING, NULL, NULL);
2717 /* Certs with the same issuer and serial number are equal, even if they
2718 * differ in other respects (like subject).
2720 info1.SerialNumber.pbData = serialNum;
2721 info1.SerialNumber.cbData = sizeof(serialNum);
2722 info1.Issuer.pbData = subjectName;
2723 info1.Issuer.cbData = sizeof(subjectName);
2724 info1.Subject.pbData = subjectName2;
2725 info1.Subject.cbData = sizeof(subjectName2);
2726 info2.SerialNumber.pbData = serialNum;
2727 info2.SerialNumber.cbData = sizeof(serialNum);
2728 info2.Issuer.pbData = subjectName;
2729 info2.Issuer.cbData = sizeof(subjectName);
2730 info2.Subject.pbData = subjectName;
2731 info2.Subject.cbData = sizeof(subjectName);
2732 ret = CertCompareCertificate(X509_ASN_ENCODING, &info1, &info2);
2733 ok(ret, "Expected certs to be equal\n");
2735 info2.Issuer.pbData = subjectName2;
2736 info2.Issuer.cbData = sizeof(subjectName2);
2737 ret = CertCompareCertificate(X509_ASN_ENCODING, &info1, &info2);
2738 ok(!ret, "Expected certs not to be equal\n");
2741 static void testVerifySubjectCert(void)
2743 BOOL ret;
2744 DWORD flags;
2745 PCCERT_CONTEXT context1, context2;
2747 /* Crashes
2748 ret = CertVerifySubjectCertificateContext(NULL, NULL, NULL);
2750 flags = 0;
2751 ret = CertVerifySubjectCertificateContext(NULL, NULL, &flags);
2752 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
2753 GetLastError());
2754 flags = CERT_STORE_NO_CRL_FLAG;
2755 ret = CertVerifySubjectCertificateContext(NULL, NULL, &flags);
2756 ok(!ret && GetLastError() == E_INVALIDARG,
2757 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2759 flags = 0;
2760 context1 = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
2761 sizeof(bigCert));
2762 ret = CertVerifySubjectCertificateContext(NULL, context1, &flags);
2763 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
2764 GetLastError());
2765 ret = CertVerifySubjectCertificateContext(context1, NULL, &flags);
2766 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
2767 GetLastError());
2768 ret = CertVerifySubjectCertificateContext(context1, context1, &flags);
2769 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
2770 GetLastError());
2772 context2 = CertCreateCertificateContext(X509_ASN_ENCODING,
2773 bigCertWithDifferentSubject, sizeof(bigCertWithDifferentSubject));
2774 SetLastError(0xdeadbeef);
2775 ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
2776 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
2777 GetLastError());
2778 flags = CERT_STORE_REVOCATION_FLAG;
2779 ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
2780 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
2781 GetLastError());
2782 ok(flags == (CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG),
2783 "Expected CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG, got %08x\n",
2784 flags);
2785 flags = CERT_STORE_SIGNATURE_FLAG;
2786 ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
2787 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
2788 GetLastError());
2789 ok(flags == CERT_STORE_SIGNATURE_FLAG,
2790 "Expected CERT_STORE_SIGNATURE_FLAG, got %08x\n", flags);
2791 CertFreeCertificateContext(context2);
2793 CertFreeCertificateContext(context1);
2796 static void testVerifyRevocation(void)
2798 BOOL ret;
2799 CERT_REVOCATION_STATUS status = { 0 };
2800 PCCERT_CONTEXT cert = CertCreateCertificateContext(X509_ASN_ENCODING,
2801 bigCert, sizeof(bigCert));
2803 /* Crash
2804 ret = CertVerifyRevocation(0, 0, 0, NULL, 0, NULL, NULL);
2806 SetLastError(0xdeadbeef);
2807 ret = CertVerifyRevocation(0, 0, 0, NULL, 0, NULL, &status);
2808 ok(!ret && GetLastError() == E_INVALIDARG,
2809 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2810 status.cbSize = sizeof(status);
2811 ret = CertVerifyRevocation(0, 0, 0, NULL, 0, NULL, &status);
2812 ok(ret, "CertVerifyRevocation failed: %08x\n", GetLastError());
2813 ret = CertVerifyRevocation(0, 2, 0, NULL, 0, NULL, &status);
2814 ok(ret, "CertVerifyRevocation failed: %08x\n", GetLastError());
2815 ret = CertVerifyRevocation(2, 0, 0, NULL, 0, NULL, &status);
2816 ok(ret, "CertVerifyRevocation failed: %08x\n", GetLastError());
2817 SetLastError(0xdeadbeef);
2818 ret = CertVerifyRevocation(0, 0, 1, (void **)&cert, 0, NULL, &status);
2819 ok(!ret && GetLastError() == CRYPT_E_NO_REVOCATION_DLL,
2820 "Expected CRYPT_E_NO_REVOCATION_DLL, got %08x\n", GetLastError());
2821 SetLastError(0xdeadbeef);
2822 ret = CertVerifyRevocation(0, 2, 1, (void **)&cert, 0, NULL, &status);
2823 ok(!ret && GetLastError() == CRYPT_E_NO_REVOCATION_DLL,
2824 "Expected CRYPT_E_NO_REVOCATION_DLL, got %08x\n", GetLastError());
2826 CertFreeCertificateContext(cert);
2829 static BYTE privKey[] = {
2830 0x07, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x52, 0x53, 0x41, 0x32, 0x00,
2831 0x02, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x79, 0x10, 0x1c, 0xd0, 0x6b, 0x10,
2832 0x18, 0x30, 0x94, 0x61, 0xdc, 0x0e, 0xcb, 0x96, 0x4e, 0x21, 0x3f, 0x79, 0xcd,
2833 0xa9, 0x17, 0x62, 0xbc, 0xbb, 0x61, 0x4c, 0xe0, 0x75, 0x38, 0x6c, 0xf3, 0xde,
2834 0x60, 0x86, 0x03, 0x97, 0x65, 0xeb, 0x1e, 0x6b, 0xdb, 0x53, 0x85, 0xad, 0x68,
2835 0x21, 0xf1, 0x5d, 0xe7, 0x1f, 0xe6, 0x53, 0xb4, 0xbb, 0x59, 0x3e, 0x14, 0x27,
2836 0xb1, 0x83, 0xa7, 0x3a, 0x54, 0xe2, 0x8f, 0x65, 0x8e, 0x6a, 0x4a, 0xcf, 0x3b,
2837 0x1f, 0x65, 0xff, 0xfe, 0xf1, 0x31, 0x3a, 0x37, 0x7a, 0x8b, 0xcb, 0xc6, 0xd4,
2838 0x98, 0x50, 0x36, 0x67, 0xe4, 0xa1, 0xe8, 0x7e, 0x8a, 0xc5, 0x23, 0xf2, 0x77,
2839 0xf5, 0x37, 0x61, 0x49, 0x72, 0x59, 0xe8, 0x3d, 0xf7, 0x60, 0xb2, 0x77, 0xca,
2840 0x78, 0x54, 0x6d, 0x65, 0x9e, 0x03, 0x97, 0x1b, 0x61, 0xbd, 0x0c, 0xd8, 0x06,
2841 0x63, 0xe2, 0xc5, 0x48, 0xef, 0xb3, 0xe2, 0x6e, 0x98, 0x7d, 0xbd, 0x4e, 0x72,
2842 0x91, 0xdb, 0x31, 0x57, 0xe3, 0x65, 0x3a, 0x49, 0xca, 0xec, 0xd2, 0x02, 0x4e,
2843 0x22, 0x7e, 0x72, 0x8e, 0xf9, 0x79, 0x84, 0x82, 0xdf, 0x7b, 0x92, 0x2d, 0xaf,
2844 0xc9, 0xe4, 0x33, 0xef, 0x89, 0x5c, 0x66, 0x99, 0xd8, 0x80, 0x81, 0x47, 0x2b,
2845 0xb1, 0x66, 0x02, 0x84, 0x59, 0x7b, 0xc3, 0xbe, 0x98, 0x45, 0x4a, 0x3d, 0xdd,
2846 0xea, 0x2b, 0xdf, 0x4e, 0xb4, 0x24, 0x6b, 0xec, 0xe7, 0xd9, 0x0c, 0x45, 0xb8,
2847 0xbe, 0xca, 0x69, 0x37, 0x92, 0x4c, 0x38, 0x6b, 0x96, 0x6d, 0xcd, 0x86, 0x67,
2848 0x5c, 0xea, 0x54, 0x94, 0xa4, 0xca, 0xa4, 0x02, 0xa5, 0x21, 0x4d, 0xae, 0x40,
2849 0x8f, 0x9d, 0x51, 0x83, 0xf2, 0x3f, 0x33, 0xc1, 0x72, 0xb4, 0x1d, 0x94, 0x6e,
2850 0x7d, 0xe4, 0x27, 0x3f, 0xea, 0xff, 0xe5, 0x9b, 0xa7, 0x5e, 0x55, 0x8e, 0x0d,
2851 0x69, 0x1c, 0x7a, 0xff, 0x81, 0x9d, 0x53, 0x52, 0x97, 0x9a, 0x76, 0x79, 0xda,
2852 0x93, 0x32, 0x16, 0xec, 0x69, 0x51, 0x1a, 0x4e, 0xc3, 0xf1, 0x72, 0x80, 0x78,
2853 0x5e, 0x66, 0x4a, 0x8d, 0x85, 0x2f, 0x3f, 0xb2, 0xa7 };
2855 static const BYTE exportedPublicKeyBlob[] = {
2856 0x06,0x02,0x00,0x00,0x00,0xa4,0x00,0x00,0x52,0x53,0x41,0x31,0x00,0x02,0x00,0x00,
2857 0x01,0x00,0x01,0x00,0x79,0x10,0x1c,0xd0,0x6b,0x10,0x18,0x30,0x94,0x61,0xdc,0x0e,
2858 0xcb,0x96,0x4e,0x21,0x3f,0x79,0xcd,0xa9,0x17,0x62,0xbc,0xbb,0x61,0x4c,0xe0,0x75,
2859 0x38,0x6c,0xf3,0xde,0x60,0x86,0x03,0x97,0x65,0xeb,0x1e,0x6b,0xdb,0x53,0x85,0xad,
2860 0x68,0x21,0xf1,0x5d,0xe7,0x1f,0xe6,0x53,0xb4,0xbb,0x59,0x3e,0x14,0x27,0xb1,0x83,
2861 0xa7,0x3a,0x54,0xe2 };
2863 static const BYTE asnEncodedPublicKey[] = {
2864 0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7,0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,
2865 0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21,0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,
2866 0x65,0x97,0x03,0x86,0x60,0xde,0xf3,0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,
2867 0x17,0xa9,0xcd,0x79,0x3f,0x21,0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,
2868 0x6b,0xd0,0x1c,0x10,0x79,0x02,0x03,0x01,0x00,0x01 };
2870 static void testAcquireCertPrivateKey(void)
2872 BOOL ret;
2873 PCCERT_CONTEXT cert;
2874 HCRYPTPROV csp;
2875 DWORD size, keySpec;
2876 BOOL callerFree;
2877 CRYPT_KEY_PROV_INFO keyProvInfo;
2878 HCRYPTKEY key;
2879 WCHAR ms_def_prov_w[MAX_PATH];
2881 if (!pCryptAcquireCertificatePrivateKey)
2883 win_skip("CryptAcquireCertificatePrivateKey() is not available\n");
2884 return;
2887 lstrcpyW(ms_def_prov_w, MS_DEF_PROV_W);
2889 keyProvInfo.pwszContainerName = cspNameW;
2890 keyProvInfo.pwszProvName = ms_def_prov_w;
2891 keyProvInfo.dwProvType = PROV_RSA_FULL;
2892 keyProvInfo.dwFlags = 0;
2893 keyProvInfo.cProvParam = 0;
2894 keyProvInfo.rgProvParam = NULL;
2895 keyProvInfo.dwKeySpec = AT_SIGNATURE;
2897 pCryptAcquireContextA(NULL, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
2898 CRYPT_DELETEKEYSET);
2900 cert = CertCreateCertificateContext(X509_ASN_ENCODING, selfSignedCert,
2901 sizeof(selfSignedCert));
2903 /* Crash
2904 ret = pCryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, NULL, NULL);
2905 ret = pCryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, NULL,
2906 &callerFree);
2907 ret = pCryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, &keySpec,
2908 NULL);
2909 ret = pCryptAcquireCertificatePrivateKey(NULL, 0, NULL, &csp, NULL, NULL);
2910 ret = pCryptAcquireCertificatePrivateKey(NULL, 0, NULL, &csp, &keySpec,
2911 &callerFree);
2912 ret = pCryptAcquireCertificatePrivateKey(cert, 0, NULL, NULL, NULL, NULL);
2915 /* Missing private key */
2916 ret = pCryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, NULL, NULL);
2917 ok(!ret && GetLastError() == CRYPT_E_NO_KEY_PROPERTY,
2918 "Expected CRYPT_E_NO_KEY_PROPERTY, got %08x\n", GetLastError());
2919 ret = pCryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, &keySpec,
2920 &callerFree);
2921 ok(!ret && GetLastError() == CRYPT_E_NO_KEY_PROPERTY,
2922 "Expected CRYPT_E_NO_KEY_PROPERTY, got %08x\n", GetLastError());
2923 CertSetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, 0,
2924 &keyProvInfo);
2925 ret = pCryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, &keySpec,
2926 &callerFree);
2927 ok(!ret && GetLastError() == CRYPT_E_NO_KEY_PROPERTY,
2928 "Expected CRYPT_E_NO_KEY_PROPERTY, got %08x\n", GetLastError());
2930 pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
2931 CRYPT_NEWKEYSET);
2932 ret = CryptImportKey(csp, privKey, sizeof(privKey), 0, 0, &key);
2933 ok(ret, "CryptImportKey failed: %08x\n", GetLastError());
2934 if (ret)
2936 HCRYPTPROV certCSP;
2937 DWORD size;
2938 CERT_KEY_CONTEXT keyContext;
2940 /* Don't cache provider */
2941 ret = pCryptAcquireCertificatePrivateKey(cert, 0, NULL, &certCSP,
2942 &keySpec, &callerFree);
2943 ok(ret ||
2944 broken(!ret), /* win95 */
2945 "CryptAcquireCertificatePrivateKey failed: %08x\n",
2946 GetLastError());
2947 if (ret)
2949 ok(callerFree, "Expected callerFree to be TRUE\n");
2950 CryptReleaseContext(certCSP, 0);
2953 ret = pCryptAcquireCertificatePrivateKey(cert, 0, NULL, &certCSP,
2954 NULL, NULL);
2955 ok(ret ||
2956 broken(!ret), /* win95 */
2957 "CryptAcquireCertificatePrivateKey failed: %08x\n",
2958 GetLastError());
2959 CryptReleaseContext(certCSP, 0);
2961 /* Use the key prov info's caching (there shouldn't be any) */
2962 ret = pCryptAcquireCertificatePrivateKey(cert,
2963 CRYPT_ACQUIRE_USE_PROV_INFO_FLAG, NULL, &certCSP, &keySpec,
2964 &callerFree);
2965 ok(ret ||
2966 broken(!ret), /* win95 */
2967 "CryptAcquireCertificatePrivateKey failed: %08x\n",
2968 GetLastError());
2969 if (ret)
2971 ok(callerFree, "Expected callerFree to be TRUE\n");
2972 CryptReleaseContext(certCSP, 0);
2975 /* Cache it (and check that it's cached) */
2976 ret = pCryptAcquireCertificatePrivateKey(cert,
2977 CRYPT_ACQUIRE_CACHE_FLAG, NULL, &certCSP, &keySpec, &callerFree);
2978 ok(ret ||
2979 broken(!ret), /* win95 */
2980 "CryptAcquireCertificatePrivateKey failed: %08x\n",
2981 GetLastError());
2982 ok(!callerFree, "Expected callerFree to be FALSE\n");
2983 size = sizeof(keyContext);
2984 ret = CertGetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID,
2985 &keyContext, &size);
2986 ok(ret ||
2987 broken(!ret), /* win95 */
2988 "CertGetCertificateContextProperty failed: %08x\n",
2989 GetLastError());
2991 /* Remove the cached provider */
2992 CryptReleaseContext(keyContext.hCryptProv, 0);
2993 CertSetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID, 0,
2994 NULL);
2995 /* Allow caching via the key prov info */
2996 keyProvInfo.dwFlags = CERT_SET_KEY_CONTEXT_PROP_ID;
2997 CertSetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, 0,
2998 &keyProvInfo);
2999 /* Now use the key prov info's caching */
3000 ret = pCryptAcquireCertificatePrivateKey(cert,
3001 CRYPT_ACQUIRE_USE_PROV_INFO_FLAG, NULL, &certCSP, &keySpec,
3002 &callerFree);
3003 ok(ret ||
3004 broken(!ret), /* win95 */
3005 "CryptAcquireCertificatePrivateKey failed: %08x\n",
3006 GetLastError());
3007 ok(!callerFree, "Expected callerFree to be FALSE\n");
3008 size = sizeof(keyContext);
3009 ret = CertGetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID,
3010 &keyContext, &size);
3011 ok(ret ||
3012 broken(!ret), /* win95 */
3013 "CertGetCertificateContextProperty failed: %08x\n",
3014 GetLastError());
3015 CryptReleaseContext(certCSP, 0);
3017 CryptDestroyKey(key);
3020 /* Some sanity-checking on public key exporting */
3021 ret = CryptImportPublicKeyInfo(csp, X509_ASN_ENCODING,
3022 &cert->pCertInfo->SubjectPublicKeyInfo, &key);
3023 ok(ret, "CryptImportPublicKeyInfo failed: %08x\n", GetLastError());
3024 if (ret)
3026 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &size);
3027 ok(ret, "CryptExportKey failed: %08x\n", GetLastError());
3028 if (ret)
3030 LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, size), encodedKey;
3032 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, buf, &size);
3033 ok(ret, "CryptExportKey failed: %08x\n", GetLastError());
3034 ok(size == sizeof(exportedPublicKeyBlob), "Unexpected size %d\n",
3035 size);
3036 ok(!memcmp(buf, exportedPublicKeyBlob, size), "Unexpected value\n");
3037 ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, RSA_CSP_PUBLICKEYBLOB,
3038 buf, CRYPT_ENCODE_ALLOC_FLAG, NULL, &encodedKey, &size);
3039 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3040 if (ret)
3042 ok(size == sizeof(asnEncodedPublicKey), "Unexpected size %d\n",
3043 size);
3044 ok(!memcmp(encodedKey, asnEncodedPublicKey, size),
3045 "Unexpected value\n");
3046 LocalFree(encodedKey);
3048 HeapFree(GetProcessHeap(), 0, buf);
3050 CryptDestroyKey(key);
3052 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
3053 NULL, 0, NULL, NULL, &size);
3054 ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
3055 if (ret)
3057 PCERT_PUBLIC_KEY_INFO info = HeapAlloc(GetProcessHeap(), 0, size);
3059 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
3060 NULL, 0, NULL, info, &size);
3061 ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
3062 if (ret)
3064 ok(info->PublicKey.cbData == sizeof(asnEncodedPublicKey),
3065 "Unexpected size %d\n", info->PublicKey.cbData);
3066 ok(!memcmp(info->PublicKey.pbData, asnEncodedPublicKey,
3067 info->PublicKey.cbData), "Unexpected value\n");
3069 HeapFree(GetProcessHeap(), 0, info);
3072 CryptReleaseContext(csp, 0);
3073 pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
3074 CRYPT_DELETEKEYSET);
3076 CertFreeCertificateContext(cert);
3079 static void testGetPublicKeyLength(void)
3081 static char oid_rsa_rsa[] = szOID_RSA_RSA;
3082 static char oid_rsa_dh[] = szOID_RSA_DH;
3083 static char bogusOID[] = "1.2.3";
3084 DWORD ret;
3085 CERT_PUBLIC_KEY_INFO info = { { 0 } };
3086 BYTE bogusKey[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
3087 BYTE key[] = { 0x30,0x0f,0x02,0x08,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
3088 0x02,0x03,0x01,0x00,0x01 };
3090 /* Crashes
3091 ret = CertGetPublicKeyLength(0, NULL);
3093 /* With an empty public key info */
3094 SetLastError(0xdeadbeef);
3095 ret = CertGetPublicKeyLength(0, &info);
3096 ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
3097 "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
3098 ret, GetLastError());
3099 SetLastError(0xdeadbeef);
3100 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
3101 ok(ret == 0 &&
3102 (GetLastError() == CRYPT_E_ASN1_EOD ||
3103 GetLastError() == OSS_BAD_ARG), /* win9x */
3104 "Expected length 0 and CRYPT_E_ASN1_EOD, got length %d, %08x\n",
3105 ret, GetLastError());
3106 /* With a nearly-empty public key info */
3107 info.Algorithm.pszObjId = oid_rsa_rsa;
3108 SetLastError(0xdeadbeef);
3109 ret = CertGetPublicKeyLength(0, &info);
3110 ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
3111 "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
3112 ret, GetLastError());
3113 SetLastError(0xdeadbeef);
3114 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
3115 ok(ret == 0 &&
3116 (GetLastError() == CRYPT_E_ASN1_EOD ||
3117 GetLastError() == OSS_BAD_ARG), /* win9x */
3118 "Expected length 0 and CRYPT_E_ASN1_EOD, got length %d, %08x\n",
3119 ret, GetLastError());
3120 /* With a bogus key */
3121 info.PublicKey.cbData = sizeof(bogusKey);
3122 info.PublicKey.pbData = bogusKey;
3123 SetLastError(0xdeadbeef);
3124 ret = CertGetPublicKeyLength(0, &info);
3125 ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
3126 "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
3127 ret, GetLastError());
3128 SetLastError(0xdeadbeef);
3129 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
3130 ok(ret == 0 &&
3131 (GetLastError() == CRYPT_E_ASN1_BADTAG ||
3132 GetLastError() == OSS_PDU_MISMATCH), /* win9x */
3133 "Expected length 0 and CRYPT_E_ASN1_BADTAGTAG, got length %d, %08x\n",
3134 ret, GetLastError());
3135 /* With a believable RSA key but a bogus OID */
3136 info.Algorithm.pszObjId = bogusOID;
3137 info.PublicKey.cbData = sizeof(key);
3138 info.PublicKey.pbData = key;
3139 SetLastError(0xdeadbeef);
3140 ret = CertGetPublicKeyLength(0, &info);
3141 ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
3142 "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
3143 ret, GetLastError());
3144 SetLastError(0xdeadbeef);
3145 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
3146 ok(ret == 56, "Expected length 56, got %d\n", ret);
3147 /* An RSA key with the DH OID */
3148 info.Algorithm.pszObjId = oid_rsa_dh;
3149 SetLastError(0xdeadbeef);
3150 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
3151 ok(ret == 0 &&
3152 (GetLastError() == CRYPT_E_ASN1_BADTAG ||
3153 GetLastError() == E_INVALIDARG), /* win9x */
3154 "Expected length 0 and CRYPT_E_ASN1_BADTAG, got length %d, %08x\n",
3155 ret, GetLastError());
3156 /* With the RSA OID */
3157 info.Algorithm.pszObjId = oid_rsa_rsa;
3158 SetLastError(0xdeadbeef);
3159 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
3160 ok(ret == 56, "Expected length 56, got %d\n", ret);
3161 /* With the RSA OID and a message encoding */
3162 info.Algorithm.pszObjId = oid_rsa_rsa;
3163 SetLastError(0xdeadbeef);
3164 ret = CertGetPublicKeyLength(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, &info);
3165 ok(ret == 56, "Expected length 56, got %d\n", ret);
3168 START_TEST(cert)
3170 init_function_pointers();
3172 testAddCert();
3173 testCertProperties();
3174 testDupCert();
3175 testFindCert();
3176 testGetSubjectCert();
3177 testGetIssuerCert();
3179 testCryptHashCert();
3180 testCertSigs();
3181 testSignAndEncodeCert();
3182 testCreateSelfSignCert();
3183 testKeyUsage();
3184 testGetValidUsages();
3185 testCompareCertName();
3186 testCompareIntegerBlob();
3187 testComparePublicKeyInfo();
3188 testHashPublicKeyInfo();
3189 testHashToBeSigned();
3190 testCompareCert();
3191 testVerifySubjectCert();
3192 testVerifyRevocation();
3193 testAcquireCertPrivateKey();
3194 testGetPublicKeyLength();