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