push 18e7434c914c4b496a7d961dbc3fc7a912612215
[wine/hacks.git] / dlls / crypt32 / tests / cert.c
blobcd0808aa3aed5b8c684cc0dac81c64f7437bc09d
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, "CertAddEncodedCertificateToStore failed: %08x\n",
185 GetLastError());
186 if (context)
187 CertFreeCertificateContext(context);
189 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
190 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
191 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
192 GetLastError());
193 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
194 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, NULL);
195 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
196 GetLastError());
197 /* This has the same name as bigCert, so finding isn't done by name */
198 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
199 certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, &context);
200 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
201 GetLastError());
202 ok(context != NULL, "Expected a context\n");
203 if (context)
205 CRYPT_DATA_BLOB hash = { sizeof(bigCert2Hash), bigCert2Hash };
207 /* Duplicate (AddRef) the context so we can still use it after
208 * deleting it from the store.
210 CertDuplicateCertificateContext(context);
211 CertDeleteCertificateFromStore(context);
212 /* Set the same hash as bigCert2, and try to readd it */
213 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID,
214 0, &hash);
215 ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
216 GetLastError());
217 ret = CertAddCertificateContextToStore(store, context,
218 CERT_STORE_ADD_NEW, NULL);
219 /* The failure is a bit odd (CRYPT_E_ASN1_BADTAG), so just check
220 * that it fails.
222 ok(!ret, "Expected failure\n");
223 CertFreeCertificateContext(context);
225 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert2,
226 sizeof(bigCert2));
227 ok(context != NULL, "Expected a context\n");
228 if (context)
230 /* Try to readd bigCert2 to the store */
231 ret = CertAddCertificateContextToStore(store, context,
232 CERT_STORE_ADD_NEW, NULL);
233 ok(!ret && GetLastError() == CRYPT_E_EXISTS,
234 "Expected CRYPT_E_EXISTS, got %08x\n", GetLastError());
235 CertFreeCertificateContext(context);
238 /* Adding a cert with the same issuer name and serial number (but
239 * different subject) as an existing cert succeeds.
241 context = NULL;
242 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
243 bigCert2WithDifferentSerial, sizeof(bigCert2WithDifferentSerial),
244 CERT_STORE_ADD_NEW, &context);
245 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
246 GetLastError());
247 if (context)
248 CertDeleteCertificateFromStore(context);
250 /* Adding a cert with the same subject name and serial number (but
251 * different issuer) as an existing cert succeeds.
253 context = NULL;
254 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
255 bigCertWithDifferentSubject, sizeof(bigCertWithDifferentSubject),
256 CERT_STORE_ADD_NEW, &context);
257 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
258 GetLastError());
259 if (context)
260 CertDeleteCertificateFromStore(context);
262 /* Adding a cert with the same issuer name and serial number (but
263 * different otherwise) as an existing cert succeeds.
265 context = NULL;
266 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
267 bigCertWithDifferentIssuer, sizeof(bigCertWithDifferentIssuer),
268 CERT_STORE_ADD_NEW, &context);
269 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
270 GetLastError());
271 if (context)
272 CertDeleteCertificateFromStore(context);
274 collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
275 CERT_STORE_CREATE_NEW_FLAG, NULL);
276 ok(collection != NULL, "CertOpenStore failed: %08x\n", GetLastError());
277 if (collection && pCertAddStoreToCollection)
279 /* Add store to the collection, but disable updates */
280 pCertAddStoreToCollection(collection, store, 0, 0);
282 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert2,
283 sizeof(bigCert2));
284 ok(context != NULL, "Expected a context\n");
285 if (context)
287 /* Try to readd bigCert2 to the collection */
288 ret = CertAddCertificateContextToStore(collection, context,
289 CERT_STORE_ADD_NEW, NULL);
290 ok(!ret && GetLastError() == CRYPT_E_EXISTS,
291 "Expected CRYPT_E_EXISTS, got %08x\n", GetLastError());
292 /* Replacing an existing certificate context is allowed, even
293 * though updates to the collection aren't..
295 ret = CertAddCertificateContextToStore(collection, context,
296 CERT_STORE_ADD_REPLACE_EXISTING, NULL);
297 ok(ret, "CertAddCertificateContextToStore failed: %08x\n",
298 GetLastError());
299 /* use the existing certificate and ask for a copy of the context*/
300 copyContext = NULL;
301 ret = CertAddCertificateContextToStore(collection, context,
302 CERT_STORE_ADD_USE_EXISTING, &copyContext);
303 ok(ret, "CertAddCertificateContextToStore failed: %08x\n",
304 GetLastError());
305 ok(copyContext != NULL, "Expected on output a non NULL copyContext\n");
306 if (copyContext)
307 CertFreeCertificateContext(copyContext);
308 /* but adding a new certificate isn't allowed. */
309 ret = CertAddCertificateContextToStore(collection, context,
310 CERT_STORE_ADD_ALWAYS, NULL);
311 ok(!ret && GetLastError() == E_ACCESSDENIED,
312 "Expected E_ACCESSDENIED, got %08x\n", GetLastError());
313 CertFreeCertificateContext(context);
316 CertCloseStore(collection, 0);
319 CertCloseStore(store, 0);
322 static void checkHash(const BYTE *data, DWORD dataLen, ALG_ID algID,
323 PCCERT_CONTEXT context, DWORD propID)
325 BYTE hash[20] = { 0 }, hashProperty[20];
326 BOOL ret;
327 DWORD size;
328 DWORD dwSizeWithNull;
330 memset(hash, 0, sizeof(hash));
331 memset(hashProperty, 0, sizeof(hashProperty));
332 size = sizeof(hash);
333 ret = CryptHashCertificate(0, algID, 0, data, dataLen, hash, &size);
334 ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
335 ret = CertGetCertificateContextProperty(context, propID, NULL,
336 &dwSizeWithNull);
337 ok(ret, "algID %08x, propID %d: CertGetCertificateContextProperty failed: %08x\n",
338 algID, propID, GetLastError());
339 ret = CertGetCertificateContextProperty(context, propID, hashProperty,
340 &size);
341 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
342 GetLastError());
343 ok(!memcmp(hash, hashProperty, size), "Unexpected hash for property %d\n",
344 propID);
345 ok(size == dwSizeWithNull, "Unexpected length of hash for property: received %d instead of %d\n",
346 dwSizeWithNull,size);
349 static CHAR cspNameA[] = "WineCryptTemp";
350 static WCHAR cspNameW[] = { 'W','i','n','e','C','r','y','p','t','T','e','m','p',0 };
351 static const BYTE v1CertWithPubKey[] = {
352 0x30,0x81,0x95,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
353 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
354 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
355 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
356 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
357 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
358 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
359 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
360 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,
361 0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,
362 0x01,0x01 };
363 static const BYTE v1CertWithSubjectKeyId[] = {
364 0x30,0x7b,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
365 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
366 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
367 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
368 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
369 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
370 0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x17,0x30,0x15,0x30,
371 0x13,0x06,0x03,0x55,0x1d,0x0e,0x04,0x0c,0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,
372 0x4c,0x61,0x6e,0x67,0x00 };
373 static const BYTE subjectKeyId[] = {
374 0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
375 static const BYTE selfSignedCert[] = {
376 0x30, 0x82, 0x01, 0x1f, 0x30, 0x81, 0xce, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
377 0x10, 0xeb, 0x0d, 0x57, 0x2a, 0x9c, 0x09, 0xba, 0xa4, 0x4a, 0xb7, 0x25, 0x49,
378 0xd9, 0x3e, 0xb5, 0x73, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d,
379 0x05, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
380 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30,
381 0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x36, 0x32, 0x39, 0x30, 0x35, 0x30, 0x30,
382 0x34, 0x36, 0x5a, 0x17, 0x0d, 0x30, 0x37, 0x30, 0x36, 0x32, 0x39, 0x31, 0x31,
383 0x30, 0x30, 0x34, 0x36, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
384 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e,
385 0x67, 0x00, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
386 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
387 0x00, 0xe2, 0x54, 0x3a, 0xa7, 0x83, 0xb1, 0x27, 0x14, 0x3e, 0x59, 0xbb, 0xb4,
388 0x53, 0xe6, 0x1f, 0xe7, 0x5d, 0xf1, 0x21, 0x68, 0xad, 0x85, 0x53, 0xdb, 0x6b,
389 0x1e, 0xeb, 0x65, 0x97, 0x03, 0x86, 0x60, 0xde, 0xf3, 0x6c, 0x38, 0x75, 0xe0,
390 0x4c, 0x61, 0xbb, 0xbc, 0x62, 0x17, 0xa9, 0xcd, 0x79, 0x3f, 0x21, 0x4e, 0x96,
391 0xcb, 0x0e, 0xdc, 0x61, 0x94, 0x30, 0x18, 0x10, 0x6b, 0xd0, 0x1c, 0x10, 0x79,
392 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
393 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x25, 0x90, 0x53, 0x34, 0xd9, 0x56, 0x41,
394 0x5e, 0xdb, 0x7e, 0x01, 0x36, 0xec, 0x27, 0x61, 0x5e, 0xb7, 0x4d, 0x90, 0x66,
395 0xa2, 0xe1, 0x9d, 0x58, 0x76, 0xd4, 0x9c, 0xba, 0x2c, 0x84, 0xc6, 0x83, 0x7a,
396 0x22, 0x0d, 0x03, 0x69, 0x32, 0x1a, 0x6d, 0xcb, 0x0c, 0x15, 0xb3, 0x6b, 0xc7,
397 0x0a, 0x8c, 0xb4, 0x5c, 0x34, 0x78, 0xe0, 0x3c, 0x9c, 0xe9, 0xf3, 0x30, 0x9f,
398 0xa8, 0x76, 0x57, 0x92, 0x36 };
399 static const BYTE selfSignedSignatureHash[] = { 0x07,0x5a,0x3e,0xfd,0x0d,0xf6,
400 0x88,0xeb,0x00,0x64,0xbd,0xc9,0xd6,0xea,0x0a,0x7c,0xcc,0x24,0xdb,0x5d };
402 static void testCertProperties(void)
404 PCCERT_CONTEXT context = CertCreateCertificateContext(X509_ASN_ENCODING,
405 bigCert, sizeof(bigCert));
406 DWORD propID, numProps, access, size;
407 BOOL ret;
408 BYTE hash[20] = { 0 }, hashProperty[20];
409 CRYPT_DATA_BLOB blob;
410 CERT_KEY_CONTEXT keyContext;
412 ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
413 GetLastError());
414 if (!context)
415 return;
417 /* This crashes
418 propID = CertEnumCertificateContextProperties(NULL, 0);
421 propID = 0;
422 numProps = 0;
423 do {
424 propID = CertEnumCertificateContextProperties(context, propID);
425 if (propID)
426 numProps++;
427 } while (propID != 0);
428 ok(numProps == 0, "Expected 0 properties, got %d\n", numProps);
430 /* Tests with a NULL cert context. Prop ID 0 fails.. */
431 ret = CertSetCertificateContextProperty(NULL, 0, 0, NULL);
432 ok(!ret && GetLastError() == E_INVALIDARG,
433 "Expected E_INVALIDARG, got %08x\n", GetLastError());
434 /* while this just crashes.
435 ret = CertSetCertificateContextProperty(NULL,
436 CERT_KEY_PROV_HANDLE_PROP_ID, 0, NULL);
439 ret = CertSetCertificateContextProperty(context, 0, 0, NULL);
440 ok(!ret && GetLastError() == E_INVALIDARG,
441 "Expected E_INVALIDARG, got %08x\n", GetLastError());
442 /* Can't set the cert property directly, this crashes.
443 ret = CertSetCertificateContextProperty(context,
444 CERT_CERT_PROP_ID, 0, bigCert2);
447 /* These all crash.
448 ret = CertGetCertificateContextProperty(context,
449 CERT_ACCESS_STATE_PROP_ID, 0, NULL);
450 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
451 NULL, NULL);
452 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
453 hashProperty, NULL);
455 /* A missing prop */
456 size = 0;
457 ret = CertGetCertificateContextProperty(context,
458 CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
459 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
460 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
461 /* And, an implicit property */
462 size = sizeof(access);
463 ret = CertGetCertificateContextProperty(context,
464 CERT_ACCESS_STATE_PROP_ID, &access, &size);
465 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
466 GetLastError());
467 ok(!(access & CERT_ACCESS_STATE_WRITE_PERSIST_FLAG),
468 "Didn't expect a persisted cert\n");
469 /* Trying to set this "read only" property crashes.
470 access |= CERT_ACCESS_STATE_WRITE_PERSIST_FLAG;
471 ret = CertSetCertificateContextProperty(context,
472 CERT_ACCESS_STATE_PROP_ID, 0, &access);
475 /* Can I set the hash to an invalid hash? */
476 blob.pbData = hash;
477 blob.cbData = sizeof(hash);
478 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID, 0,
479 &blob);
480 ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
481 GetLastError());
482 size = sizeof(hashProperty);
483 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
484 hashProperty, &size);
485 ok(!memcmp(hashProperty, hash, sizeof(hash)), "Unexpected hash\n");
486 /* Delete the (bogus) hash, and get the real one */
487 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID, 0,
488 NULL);
489 ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
490 GetLastError());
491 checkHash(bigCert, sizeof(bigCert), CALG_SHA1, context,
492 CERT_HASH_PROP_ID);
494 /* Now that the hash property is set, we should get one property when
495 * enumerating.
497 propID = 0;
498 numProps = 0;
499 do {
500 propID = CertEnumCertificateContextProperties(context, propID);
501 if (propID)
502 numProps++;
503 } while (propID != 0);
504 ok(numProps == 1, "Expected 1 properties, got %d\n", numProps);
506 /* Check a few other implicit properties */
507 checkHash(bigCert, sizeof(bigCert), CALG_MD5, context,
508 CERT_MD5_HASH_PROP_ID);
510 /* Getting the signature hash fails with this bogus certificate */
511 size = 0;
512 ret = CertGetCertificateContextProperty(context,
513 CERT_SIGNATURE_HASH_PROP_ID, NULL, &size);
514 ok(!ret &&
515 (GetLastError() == CRYPT_E_ASN1_BADTAG ||
516 GetLastError() == CRYPT_E_NOT_FOUND),
517 "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
519 /* Test key contexts and handles and such */
520 size = 0;
521 ret = CertGetCertificateContextProperty(context, CERT_KEY_CONTEXT_PROP_ID,
522 NULL, &size);
523 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
524 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
525 size = sizeof(CERT_KEY_CONTEXT);
526 ret = CertGetCertificateContextProperty(context, CERT_KEY_CONTEXT_PROP_ID,
527 NULL, &size);
528 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
529 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
530 ret = CertGetCertificateContextProperty(context, CERT_KEY_CONTEXT_PROP_ID,
531 &keyContext, &size);
532 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
533 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
534 /* Key context with an invalid size */
535 keyContext.cbSize = 0;
536 ret = CertSetCertificateContextProperty(context, CERT_KEY_CONTEXT_PROP_ID,
537 0, &keyContext);
538 ok(!ret && GetLastError() == E_INVALIDARG,
539 "Expected E_INVALIDARG, got %08x\n", GetLastError());
540 size = sizeof(keyContext);
541 ret = CertGetCertificateContextProperty(context, CERT_KEY_CONTEXT_PROP_ID,
542 &keyContext, &size);
543 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
544 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
545 keyContext.cbSize = sizeof(keyContext);
546 keyContext.hCryptProv = 0;
547 keyContext.dwKeySpec = AT_SIGNATURE;
548 ret = CertSetCertificateContextProperty(context, CERT_KEY_CONTEXT_PROP_ID,
549 0, &keyContext);
550 ok(ret, "CertSetCertificateContextProperty failed: %08x\n", GetLastError());
551 /* Now that that's set, the key prov handle property is also gettable.
553 size = sizeof(DWORD);
554 ret = CertGetCertificateContextProperty(context,
555 CERT_KEY_PROV_HANDLE_PROP_ID, &keyContext.hCryptProv, &size);
556 ok(ret, "Expected to get the CERT_KEY_PROV_HANDLE_PROP_ID, got %08x\n",
557 GetLastError());
558 /* Remove the key prov handle property.. */
559 ret = CertSetCertificateContextProperty(context,
560 CERT_KEY_PROV_HANDLE_PROP_ID, 0, NULL);
561 ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
562 GetLastError());
563 /* and the key context's CSP is set to NULL. */
564 size = sizeof(keyContext);
565 ret = CertGetCertificateContextProperty(context,
566 CERT_KEY_CONTEXT_PROP_ID, &keyContext, &size);
567 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
568 GetLastError());
569 ok(keyContext.hCryptProv == 0, "Expected no hCryptProv\n");
571 /* According to MSDN the subject key id can be stored as a property,
572 * as a subject key extension, or as the SHA1 hash of the public key,
573 * but this cert has none of them:
575 ret = CertGetCertificateContextProperty(context,
576 CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size);
577 ok(!ret && GetLastError() == ERROR_INVALID_DATA,
578 "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
579 CertFreeCertificateContext(context);
580 /* This cert does have a public key, but its subject key identifier still
581 * isn't available: */
582 context = CertCreateCertificateContext(X509_ASN_ENCODING,
583 v1CertWithPubKey, sizeof(v1CertWithPubKey));
584 ret = CertGetCertificateContextProperty(context,
585 CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size);
586 ok(!ret && GetLastError() == ERROR_INVALID_DATA,
587 "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
588 CertFreeCertificateContext(context);
589 /* This cert with a subject key extension can have its key identifier
590 * property retrieved:
592 context = CertCreateCertificateContext(X509_ASN_ENCODING,
593 v1CertWithSubjectKeyId, sizeof(v1CertWithSubjectKeyId));
594 ret = CertGetCertificateContextProperty(context,
595 CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size);
596 ok(ret, "CertGetCertificateContextProperty failed: %08x\n", GetLastError());
597 if (ret)
599 LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, size);
601 if (buf)
603 ret = CertGetCertificateContextProperty(context,
604 CERT_KEY_IDENTIFIER_PROP_ID, buf, &size);
605 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
606 GetLastError());
607 ok(!memcmp(buf, subjectKeyId, size), "Unexpected subject key id\n");
608 HeapFree(GetProcessHeap(), 0, buf);
611 CertFreeCertificateContext(context);
613 context = CertCreateCertificateContext(X509_ASN_ENCODING,
614 selfSignedCert, sizeof(selfSignedCert));
615 /* Getting the signature hash of a valid (self-signed) cert succeeds */
616 size = 0;
617 ret = CertGetCertificateContextProperty(context,
618 CERT_SIGNATURE_HASH_PROP_ID, NULL, &size);
619 ok(ret, "CertGetCertificateContextProperty failed: %08x\n", GetLastError());
620 ok(size == sizeof(selfSignedSignatureHash), "unexpected size %d\n", size);
621 ret = CertGetCertificateContextProperty(context,
622 CERT_SIGNATURE_HASH_PROP_ID, hashProperty, &size);
623 if (ret)
624 ok(!memcmp(hashProperty, selfSignedSignatureHash, size),
625 "unexpected value\n");
626 CertFreeCertificateContext(context);
629 static void testDupCert(void)
631 HCERTSTORE store;
632 PCCERT_CONTEXT context, dupContext;
633 BOOL ret;
635 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
636 CERT_STORE_CREATE_NEW_FLAG, NULL);
637 ok(store != NULL, "CertOpenStore failed: %d\n", GetLastError());
638 if (!store)
639 return;
641 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
642 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
643 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
644 GetLastError());
645 ok(context != NULL, "Expected a valid cert context\n");
646 if (context)
648 ok(context->cbCertEncoded == sizeof(bigCert),
649 "Wrong cert size %d\n", context->cbCertEncoded);
650 ok(!memcmp(context->pbCertEncoded, bigCert, sizeof(bigCert)),
651 "Unexpected encoded cert in context\n");
652 ok(context->hCertStore == store, "Unexpected store\n");
654 dupContext = CertDuplicateCertificateContext(context);
655 ok(dupContext != NULL, "Expected valid duplicate\n");
656 /* Not only is it a duplicate, it's identical: the address is the
657 * same.
659 ok(dupContext == context, "Expected identical context addresses\n");
660 CertFreeCertificateContext(dupContext);
661 CertFreeCertificateContext(context);
663 CertCloseStore(store, 0);
666 static BYTE subjectName3[] = { 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
667 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x52, 0x6f, 0x62, 0x20, 0x20, 0x4c, 0x61,
668 0x6e, 0x67, 0x00 };
669 static const BYTE iTunesCert0[] = {
670 0x30,0x82,0x03,0xc4,0x30,0x82,0x03,0x2d,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,
671 0x47,0xbf,0x19,0x95,0xdf,0x8d,0x52,0x46,0x43,0xf7,0xdb,0x6d,0x48,0x0d,0x31,
672 0xa4,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,
673 0x00,0x30,0x81,0x8b,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,
674 0x5a,0x41,0x31,0x15,0x30,0x13,0x06,0x03,0x55,0x04,0x08,0x13,0x0c,0x57,0x65,
675 0x73,0x74,0x65,0x72,0x6e,0x20,0x43,0x61,0x70,0x65,0x31,0x14,0x30,0x12,0x06,
676 0x03,0x55,0x04,0x07,0x13,0x0b,0x44,0x75,0x72,0x62,0x61,0x6e,0x76,0x69,0x6c,
677 0x6c,0x65,0x31,0x0f,0x30,0x0d,0x06,0x03,0x55,0x04,0x0a,0x13,0x06,0x54,0x68,
678 0x61,0x77,0x74,0x65,0x31,0x1d,0x30,0x1b,0x06,0x03,0x55,0x04,0x0b,0x13,0x14,
679 0x54,0x68,0x61,0x77,0x74,0x65,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,
680 0x61,0x74,0x69,0x6f,0x6e,0x31,0x1f,0x30,0x1d,0x06,0x03,0x55,0x04,0x03,0x13,
681 0x16,0x54,0x68,0x61,0x77,0x74,0x65,0x20,0x54,0x69,0x6d,0x65,0x73,0x74,0x61,
682 0x6d,0x70,0x69,0x6e,0x67,0x20,0x43,0x41,0x30,0x1e,0x17,0x0d,0x30,0x33,0x31,
683 0x32,0x30,0x34,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,0x31,0x33,0x31,
684 0x32,0x30,0x33,0x32,0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x53,0x31,0x0b,0x30,
685 0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x17,0x30,0x15,0x06,
686 0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x2c,
687 0x20,0x49,0x6e,0x63,0x2e,0x31,0x2b,0x30,0x29,0x06,0x03,0x55,0x04,0x03,0x13,
688 0x22,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x54,0x69,0x6d,0x65,0x20,
689 0x53,0x74,0x61,0x6d,0x70,0x69,0x6e,0x67,0x20,0x53,0x65,0x72,0x76,0x69,0x63,
690 0x65,0x73,0x20,0x43,0x41,0x30,0x82,0x01,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,
691 0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0f,0x00,0x30,
692 0x82,0x01,0x0a,0x02,0x82,0x01,0x01,0x00,0xa9,0xca,0xb2,0xa4,0xcc,0xcd,0x20,
693 0xaf,0x0a,0x7d,0x89,0xac,0x87,0x75,0xf0,0xb4,0x4e,0xf1,0xdf,0xc1,0x0f,0xbf,
694 0x67,0x61,0xbd,0xa3,0x64,0x1c,0xda,0xbb,0xf9,0xca,0x33,0xab,0x84,0x30,0x89,
695 0x58,0x7e,0x8c,0xdb,0x6b,0xdd,0x36,0x9e,0x0f,0xbf,0xd1,0xec,0x78,0xf2,0x77,
696 0xa6,0x7e,0x6f,0x3c,0xbf,0x93,0xaf,0x0d,0xba,0x68,0xf4,0x6c,0x94,0xca,0xbd,
697 0x52,0x2d,0xab,0x48,0x3d,0xf5,0xb6,0xd5,0x5d,0x5f,0x1b,0x02,0x9f,0xfa,0x2f,
698 0x6b,0x1e,0xa4,0xf7,0xa3,0x9a,0xa6,0x1a,0xc8,0x02,0xe1,0x7f,0x4c,0x52,0xe3,
699 0x0e,0x60,0xec,0x40,0x1c,0x7e,0xb9,0x0d,0xde,0x3f,0xc7,0xb4,0xdf,0x87,0xbd,
700 0x5f,0x7a,0x6a,0x31,0x2e,0x03,0x99,0x81,0x13,0xa8,0x47,0x20,0xce,0x31,0x73,
701 0x0d,0x57,0x2d,0xcd,0x78,0x34,0x33,0x95,0x12,0x99,0x12,0xb9,0xde,0x68,0x2f,
702 0xaa,0xe6,0xe3,0xc2,0x8a,0x8c,0x2a,0xc3,0x8b,0x21,0x87,0x66,0xbd,0x83,0x58,
703 0x57,0x6f,0x75,0xbf,0x3c,0xaa,0x26,0x87,0x5d,0xca,0x10,0x15,0x3c,0x9f,0x84,
704 0xea,0x54,0xc1,0x0a,0x6e,0xc4,0xfe,0xc5,0x4a,0xdd,0xb9,0x07,0x11,0x97,0x22,
705 0x7c,0xdb,0x3e,0x27,0xd1,0x1e,0x78,0xec,0x9f,0x31,0xc9,0xf1,0xe6,0x22,0x19,
706 0xdb,0xc4,0xb3,0x47,0x43,0x9a,0x1a,0x5f,0xa0,0x1e,0x90,0xe4,0x5e,0xf5,0xee,
707 0x7c,0xf1,0x7d,0xab,0x62,0x01,0x8f,0xf5,0x4d,0x0b,0xde,0xd0,0x22,0x56,0xa8,
708 0x95,0xcd,0xae,0x88,0x76,0xae,0xee,0xba,0x0d,0xf3,0xe4,0x4d,0xd9,0xa0,0xfb,
709 0x68,0xa0,0xae,0x14,0x3b,0xb3,0x87,0xc1,0xbb,0x02,0x03,0x01,0x00,0x01,0xa3,
710 0x81,0xdb,0x30,0x81,0xd8,0x30,0x34,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,
711 0x01,0x01,0x04,0x28,0x30,0x26,0x30,0x24,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,
712 0x07,0x30,0x01,0x86,0x18,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6f,0x63,0x73,
713 0x70,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x30,
714 0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,
715 0xff,0x02,0x01,0x00,0x30,0x41,0x06,0x03,0x55,0x1d,0x1f,0x04,0x3a,0x30,0x38,
716 0x30,0x36,0xa0,0x34,0xa0,0x32,0x86,0x30,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
717 0x63,0x72,0x6c,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,
718 0x6d,0x2f,0x54,0x68,0x61,0x77,0x74,0x65,0x54,0x69,0x6d,0x65,0x73,0x74,0x61,
719 0x6d,0x70,0x69,0x6e,0x67,0x43,0x41,0x2e,0x63,0x72,0x6c,0x30,0x13,0x06,0x03,
720 0x55,0x1d,0x25,0x04,0x0c,0x30,0x0a,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,
721 0x03,0x08,0x30,0x0e,0x06,0x03,0x55,0x1d,0x0f,0x01,0x01,0xff,0x04,0x04,0x03,
722 0x02,0x01,0x06,0x30,0x24,0x06,0x03,0x55,0x1d,0x11,0x04,0x1d,0x30,0x1b,0xa4,
723 0x19,0x30,0x17,0x31,0x15,0x30,0x13,0x06,0x03,0x55,0x04,0x03,0x13,0x0c,0x54,
724 0x53,0x41,0x32,0x30,0x34,0x38,0x2d,0x31,0x2d,0x35,0x33,0x30,0x0d,0x06,0x09,
725 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x03,0x81,0x81,0x00,
726 0x4a,0x6b,0xf9,0xea,0x58,0xc2,0x44,0x1c,0x31,0x89,0x79,0x99,0x2b,0x96,0xbf,
727 0x82,0xac,0x01,0xd6,0x1c,0x4c,0xcd,0xb0,0x8a,0x58,0x6e,0xdf,0x08,0x29,0xa3,
728 0x5e,0xc8,0xca,0x93,0x13,0xe7,0x04,0x52,0x0d,0xef,0x47,0x27,0x2f,0x00,0x38,
729 0xb0,0xe4,0xc9,0x93,0x4e,0x9a,0xd4,0x22,0x62,0x15,0xf7,0x3f,0x37,0x21,0x4f,
730 0x70,0x31,0x80,0xf1,0x8b,0x38,0x87,0xb3,0xe8,0xe8,0x97,0x00,0xfe,0xcf,0x55,
731 0x96,0x4e,0x24,0xd2,0xa9,0x27,0x4e,0x7a,0xae,0xb7,0x61,0x41,0xf3,0x2a,0xce,
732 0xe7,0xc9,0xd9,0x5e,0xdd,0xbb,0x2b,0x85,0x3e,0xb5,0x9d,0xb5,0xd9,0xe1,0x57,
733 0xff,0xbe,0xb4,0xc5,0x7e,0xf5,0xcf,0x0c,0x9e,0xf0,0x97,0xfe,0x2b,0xd3,0x3b,
734 0x52,0x1b,0x1b,0x38,0x27,0xf7,0x3f,0x4a };
735 static const BYTE iTunesCert1[] = {
736 0x30,0x82,0x03,0xff,0x30,0x82,0x02,0xe7,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,
737 0x0d,0xe9,0x2b,0xf0,0xd4,0xd8,0x29,0x88,0x18,0x32,0x05,0x09,0x5e,0x9a,0x76,
738 0x88,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,
739 0x00,0x30,0x53,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,
740 0x53,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,
741 0x69,0x53,0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x2b,0x30,0x29,
742 0x06,0x03,0x55,0x04,0x03,0x13,0x22,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,
743 0x20,0x54,0x69,0x6d,0x65,0x20,0x53,0x74,0x61,0x6d,0x70,0x69,0x6e,0x67,0x20,
744 0x53,0x65,0x72,0x76,0x69,0x63,0x65,0x73,0x20,0x43,0x41,0x30,0x1e,0x17,0x0d,
745 0x30,0x33,0x31,0x32,0x30,0x34,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,
746 0x30,0x38,0x31,0x32,0x30,0x33,0x32,0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x57,
747 0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x17,
748 0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,0x69,
749 0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x2f,0x30,0x2d,0x06,0x03,0x55,
750 0x04,0x03,0x13,0x26,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x54,0x69,
751 0x6d,0x65,0x20,0x53,0x74,0x61,0x6d,0x70,0x69,0x6e,0x67,0x20,0x53,0x65,0x72,
752 0x76,0x69,0x63,0x65,0x73,0x20,0x53,0x69,0x67,0x6e,0x65,0x72,0x30,0x82,0x01,
753 0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,
754 0x00,0x03,0x82,0x01,0x0f,0x00,0x30,0x82,0x01,0x0a,0x02,0x82,0x01,0x01,0x00,
755 0xb2,0x50,0x28,0x48,0xdd,0xd3,0x68,0x7a,0x84,0x18,0x44,0x66,0x75,0x5d,0x7e,
756 0xc4,0xb8,0x9f,0x63,0x26,0xff,0x3d,0x43,0x9c,0x7c,0x11,0x38,0x10,0x25,0x55,
757 0x73,0xd9,0x75,0x27,0x69,0xfd,0x4e,0xb9,0x20,0x5c,0xd3,0x0a,0xf9,0xa0,0x1b,
758 0x2a,0xed,0x55,0x56,0x21,0x61,0xd8,0x1e,0xdb,0xe4,0xbc,0x33,0x6b,0xc7,0xef,
759 0xdd,0xa3,0x37,0x65,0x8e,0x1b,0x93,0x0c,0xb6,0x53,0x1e,0x5c,0x7c,0x66,0x35,
760 0x5f,0x05,0x8a,0x45,0xfe,0x76,0x4e,0xdf,0x53,0x80,0xa2,0x81,0x20,0x9d,0xae,
761 0x88,0x5c,0xa2,0x08,0xf7,0xe5,0x30,0xf9,0xee,0x22,0x37,0x4c,0x42,0x0a,0xce,
762 0xdf,0xc6,0x1f,0xc4,0xd6,0x55,0xe9,0x81,0x3f,0xb5,0x52,0xa3,0x2c,0xaa,0x01,
763 0x7a,0xf2,0xa2,0xaa,0x8d,0x35,0xfe,0x9f,0xe6,0x5d,0x6a,0x05,0x9f,0x3d,0x6b,
764 0xe3,0xbf,0x96,0xc0,0xfe,0xcc,0x60,0xf9,0x40,0xe7,0x07,0xa0,0x44,0xeb,0x81,
765 0x51,0x6e,0xa5,0x2a,0xf2,0xb6,0x8a,0x10,0x28,0xed,0x8f,0xdc,0x06,0xa0,0x86,
766 0x50,0x9a,0x7b,0x4a,0x08,0x0d,0x30,0x1d,0xca,0x10,0x9e,0x6b,0xf7,0xe9,0x58,
767 0xae,0x04,0xa9,0x40,0x99,0xb2,0x28,0xe8,0x8f,0x16,0xac,0x3c,0xe3,0x53,0x6f,
768 0x4b,0xd3,0x35,0x9d,0xb5,0x6f,0x64,0x1d,0xb3,0x96,0x2c,0xbb,0x3d,0xe7,0x79,
769 0xeb,0x6d,0x7a,0xf9,0x16,0xe6,0x26,0xad,0xaf,0xef,0x99,0x53,0xb7,0x40,0x2c,
770 0x95,0xb8,0x79,0xaa,0xfe,0xd4,0x52,0xab,0x29,0x74,0x7e,0x42,0xec,0x39,0x1e,
771 0xa2,0x6a,0x16,0xe6,0x59,0xbb,0x24,0x68,0xd8,0x00,0x80,0x43,0x10,0x87,0x80,
772 0x6b,0x02,0x03,0x01,0x00,0x01,0xa3,0x81,0xca,0x30,0x81,0xc7,0x30,0x34,0x06,
773 0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x28,0x30,0x26,0x30,0x24,
774 0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x18,0x68,0x74,0x74,
775 0x70,0x3a,0x2f,0x2f,0x6f,0x63,0x73,0x70,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,
776 0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x30,0x0c,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
777 0xff,0x04,0x02,0x30,0x00,0x30,0x33,0x06,0x03,0x55,0x1d,0x1f,0x04,0x2c,0x30,
778 0x2a,0x30,0x28,0xa0,0x26,0xa0,0x24,0x86,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,
779 0x2f,0x63,0x72,0x6c,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,
780 0x6f,0x6d,0x2f,0x74,0x73,0x73,0x2d,0x63,0x61,0x2e,0x63,0x72,0x6c,0x30,0x16,
781 0x06,0x03,0x55,0x1d,0x25,0x01,0x01,0xff,0x04,0x0c,0x30,0x0a,0x06,0x08,0x2b,
782 0x06,0x01,0x05,0x05,0x07,0x03,0x08,0x30,0x0e,0x06,0x03,0x55,0x1d,0x0f,0x01,
783 0x01,0xff,0x04,0x04,0x03,0x02,0x06,0xc0,0x30,0x24,0x06,0x03,0x55,0x1d,0x11,
784 0x04,0x1d,0x30,0x1b,0xa4,0x19,0x30,0x17,0x31,0x15,0x30,0x13,0x06,0x03,0x55,
785 0x04,0x03,0x13,0x0c,0x54,0x53,0x41,0x32,0x30,0x34,0x38,0x2d,0x31,0x2d,0x35,
786 0x34,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,
787 0x00,0x03,0x82,0x01,0x01,0x00,0x87,0x78,0x70,0xda,0x4e,0x52,0x01,0x20,0x5b,
788 0xe0,0x79,0xc9,0x82,0x30,0xc4,0xfd,0xb9,0x19,0x96,0xbd,0x91,0x00,0xc3,0xbd,
789 0xcd,0xcd,0xc6,0xf4,0x0e,0xd8,0xff,0xf9,0x4d,0xc0,0x33,0x62,0x30,0x11,0xc5,
790 0xf5,0x74,0x1b,0xd4,0x92,0xde,0x5f,0x9c,0x20,0x13,0xb1,0x7c,0x45,0xbe,0x50,
791 0xcd,0x83,0xe7,0x80,0x17,0x83,0xa7,0x27,0x93,0x67,0x13,0x46,0xfb,0xca,0xb8,
792 0x98,0x41,0x03,0xcc,0x9b,0x51,0x5b,0x05,0x8b,0x7f,0xa8,0x6f,0xf3,0x1b,0x50,
793 0x1b,0x24,0x2e,0xf2,0x69,0x8d,0x6c,0x22,0xf7,0xbb,0xca,0x16,0x95,0xed,0x0c,
794 0x74,0xc0,0x68,0x77,0xd9,0xeb,0x99,0x62,0x87,0xc1,0x73,0x90,0xf8,0x89,0x74,
795 0x7a,0x23,0xab,0xa3,0x98,0x7b,0x97,0xb1,0xf7,0x8f,0x29,0x71,0x4d,0x2e,0x75,
796 0x1b,0x48,0x41,0xda,0xf0,0xb5,0x0d,0x20,0x54,0xd6,0x77,0xa0,0x97,0x82,0x63,
797 0x69,0xfd,0x09,0xcf,0x8a,0xf0,0x75,0xbb,0x09,0x9b,0xd9,0xf9,0x11,0x55,0x26,
798 0x9a,0x61,0x32,0xbe,0x7a,0x02,0xb0,0x7b,0x86,0xbe,0xa2,0xc3,0x8b,0x22,0x2c,
799 0x78,0xd1,0x35,0x76,0xbc,0x92,0x73,0x5c,0xf9,0xb9,0xe6,0x4c,0x15,0x0a,0x23,
800 0xcc,0xe4,0xd2,0xd4,0x34,0x2e,0x49,0x40,0x15,0x3c,0x0f,0x60,0x7a,0x24,0xc6,
801 0xa5,0x66,0xef,0x96,0xcf,0x70,0xeb,0x3e,0xe7,0xf4,0x0d,0x7e,0xdc,0xd1,0x7c,
802 0xa3,0x76,0x71,0x69,0xc1,0x9c,0x4f,0x47,0x30,0x35,0x21,0xb1,0xa2,0xaf,0x1a,
803 0x62,0x3c,0x2b,0xd9,0x8e,0xaa,0x2a,0x07,0x7b,0xd8,0x18,0xb3,0x5c,0x7b,0xe2,
804 0x9d,0xa5,0x6f,0xfe,0x3c,0x89,0xad };
805 static const BYTE iTunesCert2[] = {
806 0x30,0x82,0x04,0xbf,0x30,0x82,0x04,0x28,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,
807 0x41,0x91,0xa1,0x5a,0x39,0x78,0xdf,0xcf,0x49,0x65,0x66,0x38,0x1d,0x4c,0x75,
808 0xc2,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,
809 0x00,0x30,0x5f,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,
810 0x53,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,
811 0x69,0x53,0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x37,0x30,0x35,
812 0x06,0x03,0x55,0x04,0x0b,0x13,0x2e,0x43,0x6c,0x61,0x73,0x73,0x20,0x33,0x20,
813 0x50,0x75,0x62,0x6c,0x69,0x63,0x20,0x50,0x72,0x69,0x6d,0x61,0x72,0x79,0x20,
814 0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x41,
815 0x75,0x74,0x68,0x6f,0x72,0x69,0x74,0x79,0x30,0x1e,0x17,0x0d,0x30,0x34,0x30,
816 0x37,0x31,0x36,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,0x31,0x34,0x30,
817 0x37,0x31,0x35,0x32,0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x81,0xb4,0x31,0x0b,
818 0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x17,0x30,0x15,
819 0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,
820 0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x1f,0x30,0x1d,0x06,0x03,0x55,0x04,0x0b,
821 0x13,0x16,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x54,0x72,0x75,0x73,
822 0x74,0x20,0x4e,0x65,0x74,0x77,0x6f,0x72,0x6b,0x31,0x3b,0x30,0x39,0x06,0x03,
823 0x55,0x04,0x0b,0x13,0x32,0x54,0x65,0x72,0x6d,0x73,0x20,0x6f,0x66,0x20,0x75,
824 0x73,0x65,0x20,0x61,0x74,0x20,0x68,0x74,0x74,0x70,0x73,0x3a,0x2f,0x2f,0x77,
825 0x77,0x77,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,
826 0x2f,0x72,0x70,0x61,0x20,0x28,0x63,0x29,0x30,0x34,0x31,0x2e,0x30,0x2c,0x06,
827 0x03,0x55,0x04,0x03,0x13,0x25,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,
828 0x43,0x6c,0x61,0x73,0x73,0x20,0x33,0x20,0x43,0x6f,0x64,0x65,0x20,0x53,0x69,
829 0x67,0x6e,0x69,0x6e,0x67,0x20,0x32,0x30,0x30,0x34,0x20,0x43,0x41,0x30,0x82,
830 0x01,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,
831 0x05,0x00,0x03,0x82,0x01,0x0f,0x00,0x30,0x82,0x01,0x0a,0x02,0x82,0x01,0x01,
832 0x00,0xbe,0xbc,0xee,0xbc,0x7e,0xef,0x83,0xeb,0xe0,0x37,0x4f,0xfb,0x03,0x10,
833 0x38,0xbe,0x08,0xd2,0x8c,0x7d,0x9d,0xfa,0x92,0x7f,0x19,0x0c,0xc2,0x6b,0xee,
834 0x42,0x52,0x8c,0xde,0xd3,0x1c,0x48,0x13,0x25,0xea,0xc1,0x63,0x7a,0xf9,0x51,
835 0x65,0xee,0xd3,0xaa,0x3b,0xf5,0xf0,0x94,0x9c,0x2b,0xfb,0xf2,0x66,0xd4,0x24,
836 0xda,0xf7,0xf5,0x9f,0x6e,0x19,0x39,0x36,0xbc,0xd0,0xa3,0x76,0x08,0x1e,0x22,
837 0x27,0x24,0x6c,0x38,0x91,0x27,0xe2,0x84,0x49,0xae,0x1b,0x8a,0xa1,0xfd,0x25,
838 0x82,0x2c,0x10,0x30,0xe8,0x71,0xab,0x28,0xe8,0x77,0x4a,0x51,0xf1,0xec,0xcd,
839 0xf8,0xf0,0x54,0xd4,0x6f,0xc0,0xe3,0x6d,0x0a,0x8f,0xd9,0xd8,0x64,0x8d,0x63,
840 0xb2,0x2d,0x4e,0x27,0xf6,0x85,0x0e,0xfe,0x6d,0xe3,0x29,0x99,0xe2,0x85,0x47,
841 0x7c,0x2d,0x86,0x7f,0xe8,0x57,0x8f,0xad,0x67,0xc2,0x33,0x32,0x91,0x13,0x20,
842 0xfc,0xa9,0x23,0x14,0x9a,0x6d,0xc2,0x84,0x4b,0x76,0x68,0x04,0xd5,0x71,0x2c,
843 0x5d,0x21,0xfa,0x88,0x0d,0x26,0xfd,0x1f,0x2d,0x91,0x2b,0xe7,0x01,0x55,0x4d,
844 0xf2,0x6d,0x35,0x28,0x82,0xdf,0xd9,0x6b,0x5c,0xb6,0xd6,0xd9,0xaa,0x81,0xfd,
845 0x5f,0xcd,0x83,0xba,0x63,0x9d,0xd0,0x22,0xfc,0xa9,0x3b,0x42,0x69,0xb2,0x8e,
846 0x3a,0xb5,0xbc,0xb4,0x9e,0x0f,0x5e,0xc4,0xea,0x2c,0x82,0x8b,0x28,0xfd,0x53,
847 0x08,0x96,0xdd,0xb5,0x01,0x20,0xd1,0xf9,0xa5,0x18,0xe7,0xc0,0xee,0x51,0x70,
848 0x37,0xe1,0xb6,0x05,0x48,0x52,0x48,0x6f,0x38,0xea,0xc3,0xe8,0x6c,0x7b,0x44,
849 0x84,0xbb,0x02,0x03,0x01,0x00,0x01,0xa3,0x82,0x01,0xa0,0x30,0x82,0x01,0x9c,
850 0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,
851 0x01,0xff,0x02,0x01,0x00,0x30,0x44,0x06,0x03,0x55,0x1d,0x20,0x04,0x3d,0x30,
852 0x3b,0x30,0x39,0x06,0x0b,0x60,0x86,0x48,0x01,0x86,0xf8,0x45,0x01,0x07,0x17,
853 0x03,0x30,0x2a,0x30,0x28,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x02,0x01,
854 0x16,0x1c,0x68,0x74,0x74,0x70,0x73,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x76,
855 0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x2f,0x72,0x70,0x61,
856 0x30,0x31,0x06,0x03,0x55,0x1d,0x1f,0x04,0x2a,0x30,0x28,0x30,0x26,0xa0,0x24,
857 0xa0,0x22,0x86,0x20,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x63,0x72,0x6c,0x2e,
858 0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x2f,0x70,0x63,
859 0x61,0x33,0x2e,0x63,0x72,0x6c,0x30,0x1d,0x06,0x03,0x55,0x1d,0x25,0x04,0x16,
860 0x30,0x14,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x03,0x02,0x06,0x08,0x2b,
861 0x06,0x01,0x05,0x05,0x07,0x03,0x03,0x30,0x0e,0x06,0x03,0x55,0x1d,0x0f,0x01,
862 0x01,0xff,0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x11,0x06,0x09,0x60,0x86,0x48,
863 0x01,0x86,0xf8,0x42,0x01,0x01,0x04,0x04,0x03,0x02,0x00,0x01,0x30,0x29,0x06,
864 0x03,0x55,0x1d,0x11,0x04,0x22,0x30,0x20,0xa4,0x1e,0x30,0x1c,0x31,0x1a,0x30,
865 0x18,0x06,0x03,0x55,0x04,0x03,0x13,0x11,0x43,0x6c,0x61,0x73,0x73,0x33,0x43,
866 0x41,0x32,0x30,0x34,0x38,0x2d,0x31,0x2d,0x34,0x33,0x30,0x1d,0x06,0x03,0x55,
867 0x1d,0x0e,0x04,0x16,0x04,0x14,0x08,0xf5,0x51,0xe8,0xfb,0xfe,0x3d,0x3d,0x64,
868 0x36,0x7c,0x68,0xcf,0x5b,0x78,0xa8,0xdf,0xb9,0xc5,0x37,0x30,0x81,0x80,0x06,
869 0x03,0x55,0x1d,0x23,0x04,0x79,0x30,0x77,0xa1,0x63,0xa4,0x61,0x30,0x5f,0x31,
870 0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x17,0x30,
871 0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,0x69,0x67,
872 0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x37,0x30,0x35,0x06,0x03,0x55,0x04,
873 0x0b,0x13,0x2e,0x43,0x6c,0x61,0x73,0x73,0x20,0x33,0x20,0x50,0x75,0x62,0x6c,
874 0x69,0x63,0x20,0x50,0x72,0x69,0x6d,0x61,0x72,0x79,0x20,0x43,0x65,0x72,0x74,
875 0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x41,0x75,0x74,0x68,0x6f,
876 0x72,0x69,0x74,0x79,0x82,0x10,0x70,0xba,0xe4,0x1d,0x10,0xd9,0x29,0x34,0xb6,
877 0x38,0xca,0x7b,0x03,0xcc,0xba,0xbf,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,
878 0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x03,0x81,0x81,0x00,0xae,0x3a,0x17,0xb8,
879 0x4a,0x7b,0x55,0xfa,0x64,0x55,0xec,0x40,0xa4,0xed,0x49,0x41,0x90,0x99,0x9c,
880 0x89,0xbc,0xaf,0x2e,0x1d,0xca,0x78,0x23,0xf9,0x1c,0x19,0x0f,0x7f,0xeb,0x68,
881 0xbc,0x32,0xd9,0x88,0x38,0xde,0xdc,0x3f,0xd3,0x89,0xb4,0x3f,0xb1,0x82,0x96,
882 0xf1,0xa4,0x5a,0xba,0xed,0x2e,0x26,0xd3,0xde,0x7c,0x01,0x6e,0x00,0x0a,0x00,
883 0xa4,0x06,0x92,0x11,0x48,0x09,0x40,0xf9,0x1c,0x18,0x79,0x67,0x23,0x24,0xe0,
884 0xbb,0xd5,0xe1,0x50,0xae,0x1b,0xf5,0x0e,0xdd,0xe0,0x2e,0x81,0xcd,0x80,0xa3,
885 0x6c,0x52,0x4f,0x91,0x75,0x55,0x8a,0xba,0x22,0xf2,0xd2,0xea,0x41,0x75,0x88,
886 0x2f,0x63,0x55,0x7d,0x1e,0x54,0x5a,0x95,0x59,0xca,0xd9,0x34,0x81,0xc0,0x5f,
887 0x5e,0xf6,0x7a,0xb5 };
888 static const BYTE iTunesCert3[] = {
889 0x30,0x82,0x04,0xf1,0x30,0x82,0x03,0xd9,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,
890 0x0f,0x1a,0xa0,0xe0,0x9b,0x9b,0x61,0xa6,0xb6,0xfe,0x40,0xd2,0xdf,0x6a,0xf6,
891 0x8d,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,
892 0x00,0x30,0x81,0xb4,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,
893 0x55,0x53,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,
894 0x72,0x69,0x53,0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x1f,0x30,
895 0x1d,0x06,0x03,0x55,0x04,0x0b,0x13,0x16,0x56,0x65,0x72,0x69,0x53,0x69,0x67,
896 0x6e,0x20,0x54,0x72,0x75,0x73,0x74,0x20,0x4e,0x65,0x74,0x77,0x6f,0x72,0x6b,
897 0x31,0x3b,0x30,0x39,0x06,0x03,0x55,0x04,0x0b,0x13,0x32,0x54,0x65,0x72,0x6d,
898 0x73,0x20,0x6f,0x66,0x20,0x75,0x73,0x65,0x20,0x61,0x74,0x20,0x68,0x74,0x74,
899 0x70,0x73,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,
900 0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x2f,0x72,0x70,0x61,0x20,0x28,0x63,0x29,0x30,
901 0x34,0x31,0x2e,0x30,0x2c,0x06,0x03,0x55,0x04,0x03,0x13,0x25,0x56,0x65,0x72,
902 0x69,0x53,0x69,0x67,0x6e,0x20,0x43,0x6c,0x61,0x73,0x73,0x20,0x33,0x20,0x43,
903 0x6f,0x64,0x65,0x20,0x53,0x69,0x67,0x6e,0x69,0x6e,0x67,0x20,0x32,0x30,0x30,
904 0x34,0x20,0x43,0x41,0x30,0x1e,0x17,0x0d,0x30,0x36,0x30,0x31,0x31,0x37,0x30,
905 0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,0x30,0x38,0x30,0x31,0x32,0x32,0x32,
906 0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x81,0xb4,0x31,0x0b,0x30,0x09,0x06,0x03,
907 0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,
908 0x08,0x13,0x0a,0x43,0x61,0x6c,0x69,0x66,0x6f,0x72,0x6e,0x69,0x61,0x31,0x12,
909 0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x13,0x09,0x43,0x75,0x70,0x65,0x72,0x74,
910 0x69,0x6e,0x6f,0x31,0x1d,0x30,0x1b,0x06,0x03,0x55,0x04,0x0a,0x14,0x14,0x41,
911 0x70,0x70,0x6c,0x65,0x20,0x43,0x6f,0x6d,0x70,0x75,0x74,0x65,0x72,0x2c,0x20,
912 0x49,0x6e,0x63,0x2e,0x31,0x3e,0x30,0x3c,0x06,0x03,0x55,0x04,0x0b,0x13,0x35,
913 0x44,0x69,0x67,0x69,0x74,0x61,0x6c,0x20,0x49,0x44,0x20,0x43,0x6c,0x61,0x73,
914 0x73,0x20,0x33,0x20,0x2d,0x20,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,
915 0x20,0x53,0x6f,0x66,0x74,0x77,0x61,0x72,0x65,0x20,0x56,0x61,0x6c,0x69,0x64,
916 0x61,0x74,0x69,0x6f,0x6e,0x20,0x76,0x32,0x31,0x1d,0x30,0x1b,0x06,0x03,0x55,
917 0x04,0x03,0x14,0x14,0x41,0x70,0x70,0x6c,0x65,0x20,0x43,0x6f,0x6d,0x70,0x75,
918 0x74,0x65,0x72,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x30,0x81,0x9f,0x30,0x0d,0x06,
919 0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x81,0x8d,
920 0x00,0x30,0x81,0x89,0x02,0x81,0x81,0x00,0xd3,0xab,0x3b,0x7f,0xec,0x48,0x84,
921 0xce,0xa8,0x1a,0x12,0xf3,0x3c,0x87,0xcb,0x24,0x58,0x96,0x02,0x87,0x66,0x49,
922 0xeb,0x89,0xee,0x79,0x44,0x70,0x8d,0xe7,0xd4,0x1f,0x30,0x92,0xc0,0x9c,0x35,
923 0x78,0xc0,0xaf,0x1c,0xb6,0x28,0xd3,0xe0,0xe0,0x9d,0xd3,0x49,0x76,0x73,0x57,
924 0x19,0x4d,0x8d,0x70,0x85,0x64,0x4d,0x1d,0xc6,0x02,0x3e,0xe5,0x2c,0x66,0x07,
925 0xd2,0x27,0x4b,0xd6,0xc8,0x3c,0x93,0xb6,0x15,0x0c,0xde,0x5b,0xd7,0x93,0xdd,
926 0xbe,0x85,0x62,0x34,0x17,0x8a,0x05,0x60,0xf0,0x8a,0x1c,0x5a,0x40,0x21,0x8d,
927 0x51,0x6c,0xb0,0x62,0xd8,0xb5,0xd4,0xf9,0xb1,0xd0,0x58,0x7a,0x7a,0x82,0x55,
928 0xb3,0xf9,0x53,0x71,0xde,0xd2,0xc9,0x37,0x8c,0xf6,0x5a,0x1f,0x2d,0xcd,0x7c,
929 0x67,0x02,0x03,0x01,0x00,0x01,0xa3,0x82,0x01,0x7f,0x30,0x82,0x01,0x7b,0x30,
930 0x09,0x06,0x03,0x55,0x1d,0x13,0x04,0x02,0x30,0x00,0x30,0x0e,0x06,0x03,0x55,
931 0x1d,0x0f,0x01,0x01,0xff,0x04,0x04,0x03,0x02,0x07,0x80,0x30,0x40,0x06,0x03,
932 0x55,0x1d,0x1f,0x04,0x39,0x30,0x37,0x30,0x35,0xa0,0x33,0xa0,0x31,0x86,0x2f,
933 0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x43,0x53,0x43,0x33,0x2d,0x32,0x30,0x30,
934 0x34,0x2d,0x63,0x72,0x6c,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,
935 0x63,0x6f,0x6d,0x2f,0x43,0x53,0x43,0x33,0x2d,0x32,0x30,0x30,0x34,0x2e,0x63,
936 0x72,0x6c,0x30,0x44,0x06,0x03,0x55,0x1d,0x20,0x04,0x3d,0x30,0x3b,0x30,0x39,
937 0x06,0x0b,0x60,0x86,0x48,0x01,0x86,0xf8,0x45,0x01,0x07,0x17,0x03,0x30,0x2a,
938 0x30,0x28,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x1c,0x68,
939 0x74,0x74,0x70,0x73,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x76,0x65,0x72,0x69,
940 0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x2f,0x72,0x70,0x61,0x30,0x13,0x06,
941 0x03,0x55,0x1d,0x25,0x04,0x0c,0x30,0x0a,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,
942 0x07,0x03,0x03,0x30,0x75,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x01,0x01,
943 0x04,0x69,0x30,0x67,0x30,0x24,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,
944 0x01,0x86,0x18,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6f,0x63,0x73,0x70,0x2e,
945 0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x30,0x3f,0x06,
946 0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x33,0x68,0x74,0x74,0x70,
947 0x3a,0x2f,0x2f,0x43,0x53,0x43,0x33,0x2d,0x32,0x30,0x30,0x34,0x2d,0x61,0x69,
948 0x61,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x2f,
949 0x43,0x53,0x43,0x33,0x2d,0x32,0x30,0x30,0x34,0x2d,0x61,0x69,0x61,0x2e,0x63,
950 0x65,0x72,0x30,0x1f,0x06,0x03,0x55,0x1d,0x23,0x04,0x18,0x30,0x16,0x80,0x14,
951 0x08,0xf5,0x51,0xe8,0xfb,0xfe,0x3d,0x3d,0x64,0x36,0x7c,0x68,0xcf,0x5b,0x78,
952 0xa8,0xdf,0xb9,0xc5,0x37,0x30,0x11,0x06,0x09,0x60,0x86,0x48,0x01,0x86,0xf8,
953 0x42,0x01,0x01,0x04,0x04,0x03,0x02,0x04,0x10,0x30,0x16,0x06,0x0a,0x2b,0x06,
954 0x01,0x04,0x01,0x82,0x37,0x02,0x01,0x1b,0x04,0x08,0x30,0x06,0x01,0x01,0x00,
955 0x01,0x01,0xff,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,
956 0x05,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x6a,0xa6,0x06,0xd0,0x33,0x18,0x64,
957 0xe2,0x69,0x82,0xee,0x6e,0x36,0x9e,0x9d,0x9a,0x0e,0x18,0xa8,0xac,0x9d,0x10,
958 0xed,0x01,0x3c,0xb9,0x61,0x04,0x62,0xf3,0x85,0x8f,0xcc,0x4f,0x2c,0x66,0x35,
959 0x54,0x25,0x45,0x8d,0x95,0x1c,0xd2,0x33,0xbe,0x2e,0xdd,0x7f,0x74,0xaf,0x03,
960 0x7b,0x86,0x63,0xb0,0xc9,0xe6,0xbd,0xc7,0x8e,0xde,0x03,0x18,0x98,0x82,0xc3,
961 0xbb,0xf8,0x15,0x99,0x1a,0xa9,0xdd,0xb9,0x5d,0xb9,0xbd,0x53,0x95,0x25,0x76,
962 0xfb,0x5c,0x53,0x90,0xea,0x01,0x0a,0xa0,0xb1,0xbf,0x09,0x1b,0x97,0x8f,0x40,
963 0xfa,0x85,0x12,0x74,0x01,0xdb,0xf6,0xdb,0x09,0xd6,0x5f,0x4f,0xd7,0x17,0xb4,
964 0xbf,0x9e,0x2f,0x86,0x52,0x5d,0x70,0x24,0x52,0x32,0x1e,0xa5,0x1d,0x39,0x8b,
965 0x66,0xf6,0xba,0x9b,0x69,0x8e,0x12,0x60,0xdb,0xb6,0xcf,0xe6,0x0d,0xd6,0x1c,
966 0x8f,0xd4,0x5b,0x4b,0x00,0xde,0x21,0x93,0xfb,0x6e,0xc7,0x3d,0xb4,0x66,0x0d,
967 0x29,0x0c,0x4e,0xe9,0x3f,0x94,0xd6,0xd6,0xdc,0xec,0xf8,0x53,0x3b,0x62,0xd5,
968 0x97,0x50,0x53,0x84,0x17,0xfe,0xe2,0xed,0x4c,0x23,0x0a,0x49,0xce,0x5b,0xe9,
969 0x70,0x31,0xc1,0x04,0x02,0x02,0x6c,0xb8,0x52,0xcd,0xc7,0x4e,0x70,0xb4,0x13,
970 0xd7,0xe0,0x92,0xba,0x44,0x1a,0x10,0x4c,0x6e,0x45,0xc6,0x86,0x04,0xc6,0x64,
971 0xd3,0x9c,0x6e,0xc1,0x9c,0xac,0x74,0x3d,0x77,0x06,0x5e,0x28,0x28,0x5c,0xf5,
972 0xe0,0x9c,0x19,0xd8,0xba,0x74,0x81,0x2d,0x67,0x77,0x93,0x8d,0xbf,0xd2,0x52,
973 0x00,0xe6,0xa5,0x38,0x4e,0x2e,0x73,0x66,0x7a };
974 static BYTE iTunesIssuer[] = {
975 0x30,0x81,0xb4,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,
976 0x13,0x02,0x55,0x53,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,
977 0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x2c,
978 0x20,0x49,0x6e,0x63,0x2e,0x31,0x1f,0x30,0x1d,0x06,0x03,0x55,
979 0x04,0x0b,0x13,0x16,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,
980 0x20,0x54,0x72,0x75,0x73,0x74,0x20,0x4e,0x65,0x74,0x77,0x6f,
981 0x72,0x6b,0x31,0x3b,0x30,0x39,0x06,0x03,0x55,0x04,0x0b,0x13,
982 0x32,0x54,0x65,0x72,0x6d,0x73,0x20,0x6f,0x66,0x20,0x75,0x73,
983 0x65,0x20,0x61,0x74,0x20,0x68,0x74,0x74,0x70,0x73,0x3a,0x2f,
984 0x2f,0x77,0x77,0x77,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,
985 0x6e,0x2e,0x63,0x6f,0x6d,0x2f,0x72,0x70,0x61,0x20,0x28,0x63,
986 0x29,0x30,0x34,0x31,0x2e,0x30,0x2c,0x06,0x03,0x55,0x04,0x03,
987 0x13,0x25,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x43,
988 0x6c,0x61,0x73,0x73,0x20,0x33,0x20,0x43,0x6f,0x64,0x65,0x20,
989 0x53,0x69,0x67,0x6e,0x69,0x6e,0x67,0x20,0x32,0x30,0x30,0x34,
990 0x20,0x43,0x41 };
991 static BYTE iTunesSerialNum[] = {
992 0x8d,0xf6,0x6a,0xdf,0xd2,0x40,0xfe,0xb6,0xa6,0x61,0x9b,0x9b,
993 0xe0,0xa0,0x1a,0x0f };
995 static void testFindCert(void)
997 HCERTSTORE store;
998 PCCERT_CONTEXT context = NULL, subject;
999 BOOL ret;
1000 CERT_INFO certInfo = { 0 };
1001 CRYPT_HASH_BLOB blob;
1002 BYTE otherSerialNumber[] = { 2 };
1004 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1005 CERT_STORE_CREATE_NEW_FLAG, NULL);
1006 ok(store != NULL, "CertOpenStore failed: %d\n", GetLastError());
1007 if (!store)
1008 return;
1010 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1011 bigCert, sizeof(bigCert), CERT_STORE_ADD_NEW, NULL);
1012 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1013 GetLastError());
1014 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1015 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, NULL);
1016 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1017 GetLastError());
1018 /* This has the same name as bigCert */
1019 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1020 certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, NULL);
1021 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1022 GetLastError());
1024 /* Crashes
1025 context = CertFindCertificateInStore(NULL, 0, 0, 0, NULL, NULL);
1028 /* Check first cert's there, by issuer */
1029 certInfo.Subject.pbData = subjectName;
1030 certInfo.Subject.cbData = sizeof(subjectName);
1031 certInfo.SerialNumber.pbData = serialNum;
1032 certInfo.SerialNumber.cbData = sizeof(serialNum);
1033 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1034 CERT_FIND_ISSUER_NAME, &certInfo.Subject, NULL);
1035 ok(context != NULL, "CertFindCertificateInStore failed: %08x\n",
1036 GetLastError());
1037 if (context)
1039 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1040 CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
1041 ok(context != NULL, "Expected more than one cert\n");
1042 if (context)
1044 context = CertFindCertificateInStore(store, X509_ASN_ENCODING,
1045 0, CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
1046 ok(context == NULL, "Expected precisely two certs\n");
1050 /* Check second cert's there as well, by subject name */
1051 certInfo.Subject.pbData = subjectName2;
1052 certInfo.Subject.cbData = sizeof(subjectName2);
1053 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1054 CERT_FIND_SUBJECT_NAME, &certInfo.Subject, NULL);
1055 ok(context != NULL, "CertFindCertificateInStore failed: %08x\n",
1056 GetLastError());
1057 if (context)
1059 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1060 CERT_FIND_SUBJECT_NAME, &certInfo.Subject, context);
1061 ok(context == NULL, "Expected one cert only\n");
1064 /* Strange but true: searching for the subject cert requires you to set
1065 * the issuer, not the subject
1067 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1068 CERT_FIND_SUBJECT_CERT, &certInfo.Subject, NULL);
1069 ok(context == NULL, "Expected no certificate\n");
1070 certInfo.Subject.pbData = NULL;
1071 certInfo.Subject.cbData = 0;
1072 certInfo.Issuer.pbData = subjectName2;
1073 certInfo.Issuer.cbData = sizeof(subjectName2);
1074 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1075 CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
1076 ok(context != NULL, "CertFindCertificateInStore failed: %08x\n",
1077 GetLastError());
1078 if (context)
1080 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1081 CERT_FIND_SUBJECT_CERT, &certInfo.Subject, context);
1082 ok(context == NULL, "Expected one cert only\n");
1084 /* A non-matching serial number will not match. */
1085 certInfo.SerialNumber.pbData = otherSerialNumber;
1086 certInfo.SerialNumber.cbData = sizeof(otherSerialNumber);
1087 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1088 CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
1089 ok(context == NULL, "Expected no match\n");
1090 /* No serial number will not match */
1091 certInfo.SerialNumber.cbData = 0;
1092 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1093 CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
1094 ok(context == NULL, "Expected no match\n");
1095 /* A serial number still won't match if the name doesn't */
1096 certInfo.SerialNumber.pbData = serialNum;
1097 certInfo.SerialNumber.cbData = sizeof(serialNum);
1098 certInfo.Issuer.pbData = subjectName3;
1099 certInfo.Issuer.cbData = sizeof(subjectName3);
1100 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1101 CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
1102 ok(context == NULL, "Expected no match\n");
1104 /* The nice thing about hashes, they're unique */
1105 blob.pbData = bigCertHash;
1106 blob.cbData = sizeof(bigCertHash);
1107 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1108 CERT_FIND_SHA1_HASH, &blob, NULL);
1109 ok(context != NULL, "CertFindCertificateInStore failed: %08x\n",
1110 GetLastError());
1111 if (context)
1113 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1114 CERT_FIND_SHA1_HASH, &certInfo.Subject, context);
1115 ok(context == NULL, "Expected one cert only\n");
1118 CertCloseStore(store, 0);
1120 /* Another subject cert search, using iTunes's certs */
1121 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1122 CERT_STORE_CREATE_NEW_FLAG, NULL);
1123 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1124 iTunesCert0, sizeof(iTunesCert0), CERT_STORE_ADD_NEW, NULL);
1125 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1126 GetLastError());
1127 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1128 iTunesCert1, sizeof(iTunesCert1), CERT_STORE_ADD_NEW, NULL);
1129 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1130 GetLastError());
1131 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1132 iTunesCert2, sizeof(iTunesCert2), CERT_STORE_ADD_NEW, NULL);
1133 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1134 GetLastError());
1135 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1136 iTunesCert3, sizeof(iTunesCert3), CERT_STORE_ADD_NEW, &subject);
1137 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1138 GetLastError());
1140 /* The certInfo's issuer does not match any subject, but the serial
1141 * number does match a cert whose issuer matches certInfo's issuer.
1142 * This yields a match.
1144 certInfo.SerialNumber.cbData = sizeof(iTunesSerialNum);
1145 certInfo.SerialNumber.pbData = iTunesSerialNum;
1146 certInfo.Issuer.cbData = sizeof(iTunesIssuer);
1147 certInfo.Issuer.pbData = iTunesIssuer;
1148 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1149 CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
1150 ok(context != NULL, "Expected a match\n");
1151 if (context)
1153 ret = CertCompareCertificateName(context->dwCertEncodingType,
1154 &certInfo.Issuer, &context->pCertInfo->Subject);
1155 ok(!ret, "Expected subject name not to match\n");
1156 ret = CertCompareCertificateName(context->dwCertEncodingType,
1157 &certInfo.Issuer, &context->pCertInfo->Issuer);
1158 ok(ret, "Expected issuer name to match\n");
1159 ret = CertCompareIntegerBlob(&certInfo.SerialNumber,
1160 &context->pCertInfo->SerialNumber);
1161 ok(ret, "Expected serial number to match\n");
1162 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1163 CERT_FIND_SUBJECT_CERT, &certInfo, context);
1164 ok(context == NULL, "Expected one cert only\n");
1167 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1168 CERT_FIND_ISSUER_OF, subject, NULL);
1169 ok(context != NULL, "Expected an issuer\n");
1170 if (context)
1172 PCCERT_CONTEXT none = CertFindCertificateInStore(store,
1173 X509_ASN_ENCODING, 0, CERT_FIND_ISSUER_OF, context, NULL);
1175 ok(!none, "Expected no parent of issuer\n");
1176 CertFreeCertificateContext(context);
1178 CertFreeCertificateContext(subject);
1179 CertCloseStore(store, 0);
1182 static void testGetSubjectCert(void)
1184 HCERTSTORE store;
1185 PCCERT_CONTEXT context1, context2;
1186 CERT_INFO info = { 0 };
1187 BOOL ret;
1189 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1190 CERT_STORE_CREATE_NEW_FLAG, NULL);
1191 ok(store != NULL, "CertOpenStore failed: %d\n", GetLastError());
1192 if (!store)
1193 return;
1195 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1196 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
1197 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1198 GetLastError());
1199 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1200 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, &context1);
1201 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1202 GetLastError());
1203 ok(context1 != NULL, "Expected a context\n");
1204 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1205 certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, NULL);
1206 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1207 GetLastError());
1209 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
1210 NULL);
1211 ok(!context2 && GetLastError() == E_INVALIDARG,
1212 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1213 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
1214 &info);
1215 ok(!context2 && GetLastError() == CRYPT_E_NOT_FOUND,
1216 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1217 info.SerialNumber.cbData = sizeof(serialNum);
1218 info.SerialNumber.pbData = serialNum;
1219 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
1220 &info);
1221 ok(!context2 && GetLastError() == CRYPT_E_NOT_FOUND,
1222 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1223 info.Issuer.cbData = sizeof(subjectName2);
1224 info.Issuer.pbData = subjectName2;
1225 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
1226 &info);
1227 ok(context2 != NULL,
1228 "CertGetSubjectCertificateFromStore failed: %08x\n", GetLastError());
1229 /* Not only should this find a context, but it should be the same
1230 * (same address) as context1.
1232 ok(context1 == context2, "Expected identical context addresses\n");
1233 CertFreeCertificateContext(context2);
1235 CertFreeCertificateContext(context1);
1236 CertCloseStore(store, 0);
1239 /* This expires in 1970 or so */
1240 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
1241 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
1242 0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
1243 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
1244 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
1245 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
1246 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
1247 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
1248 0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
1249 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
1250 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
1251 0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
1252 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
1253 0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
1254 0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
1255 0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
1256 0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
1257 0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
1258 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
1259 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
1260 0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
1261 0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
1262 0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
1263 0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
1264 0x49, 0xe5, 0xf9, 0x65, 0xf3 };
1266 /* This expires in 2036 or so */
1267 static const BYTE childOfExpired[] = { 0x30, 0x81, 0xcc, 0x30, 0x78, 0xa0,
1268 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
1269 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d,
1270 0x30, 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63,
1271 0x40, 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e,
1272 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x35, 0x30, 0x35,
1273 0x31, 0x37, 0x31, 0x32, 0x34, 0x39, 0x5a, 0x17, 0x0d, 0x33, 0x36, 0x30, 0x35,
1274 0x30, 0x35, 0x31, 0x37, 0x31, 0x32, 0x34, 0x39, 0x5a, 0x30, 0x15, 0x31, 0x13,
1275 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e,
1276 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03,
1277 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
1278 0x01, 0x05, 0x05, 0x00, 0x03, 0x41, 0x00, 0x20, 0x3b, 0xdb, 0x4d, 0x67, 0x50,
1279 0xec, 0x73, 0x9d, 0xf9, 0x85, 0x5d, 0x18, 0xe9, 0xb4, 0x98, 0xe3, 0x31, 0xb7,
1280 0x03, 0x0b, 0xc0, 0x39, 0x93, 0x56, 0x81, 0x0a, 0xfc, 0x78, 0xa8, 0x29, 0x42,
1281 0x5f, 0x69, 0xfb, 0xbc, 0x5b, 0xf2, 0xa6, 0x2a, 0xbe, 0x91, 0x2c, 0xfc, 0x89,
1282 0x69, 0x15, 0x18, 0x58, 0xe5, 0x02, 0x75, 0xf7, 0x2a, 0xb6, 0xa9, 0xfb, 0x47,
1283 0x6a, 0x6e, 0x0a, 0x9b, 0xe9, 0xdc };
1284 /* chain10_0 -+
1285 * +-> chain7_1
1286 * chain10_1 -+
1287 * A chain with two issuers, only one of whose dates is valid.
1289 static const BYTE chain10_0[] = {
1290 0x30,0x82,0x01,0x9b,0x30,0x82,0x01,0x08,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,
1291 0x4a,0x30,0x3a,0x42,0xa2,0x5a,0xb3,0x93,0x4d,0x94,0x06,0xad,0x6d,0x1c,0x34,
1292 0xe6,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x30,0x10,0x31,
1293 0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x03,0x13,0x05,0x43,0x65,0x72,0x74,0x31,
1294 0x30,0x1e,0x17,0x0d,0x30,0x36,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
1295 0x30,0x5a,0x17,0x0d,0x30,0x36,0x31,0x32,0x33,0x31,0x32,0x33,0x35,0x39,0x35,
1296 0x39,0x5a,0x30,0x10,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x03,0x13,0x05,
1297 0x43,0x65,0x72,0x74,0x31,0x30,0x81,0x9f,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
1298 0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x81,0x8d,0x00,0x30,0x81,0x89,
1299 0x02,0x81,0x81,0x00,0xad,0x7e,0xca,0xf3,0xe5,0x99,0xc2,0x2a,0xca,0x50,0x82,
1300 0x7c,0x2d,0xa4,0x81,0xcd,0x0d,0x0d,0x86,0xd7,0xd8,0xb2,0xde,0xc5,0xc3,0x34,
1301 0x9e,0x07,0x78,0x08,0x11,0x12,0x2d,0x21,0x0a,0x09,0x07,0x14,0x03,0x7a,0xe7,
1302 0x3b,0x58,0xf1,0xde,0x3e,0x01,0x25,0x93,0xab,0x8f,0xce,0x1f,0xc1,0x33,0x91,
1303 0xfe,0x59,0xb9,0x3b,0x9e,0x95,0x12,0x89,0x8e,0xc3,0x4b,0x98,0x1b,0x99,0xc5,
1304 0x07,0xe2,0xdf,0x15,0x4c,0x39,0x76,0x06,0xad,0xdb,0x16,0x06,0x49,0xba,0xcd,
1305 0x0f,0x07,0xd6,0xea,0x27,0xa6,0xfe,0x3d,0x88,0xe5,0x97,0x45,0x72,0xb6,0x1c,
1306 0xc0,0x1c,0xb1,0xa2,0x89,0xe8,0x37,0x9e,0xf6,0x2a,0xcf,0xd5,0x1f,0x2f,0x35,
1307 0x5e,0x8f,0x3a,0x9c,0x61,0xb1,0xf1,0x6c,0xff,0x8c,0xb2,0x2f,0x02,0x03,0x01,
1308 0x00,0x01,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x03,0x81,
1309 0x81,0x00,0x85,0x6e,0x35,0x2f,0x2c,0x51,0x4f,0xd6,0x2a,0xe4,0x9e,0xd0,0x4b,
1310 0xe6,0x90,0xfd,0xf7,0x20,0xad,0x76,0x3f,0x93,0xea,0x7f,0x0d,0x1f,0xb3,0x8e,
1311 0xfd,0xe0,0xe1,0xd6,0xd7,0x9c,0x7d,0x46,0x6b,0x15,0x5c,0xe6,0xc9,0x62,0x3b,
1312 0x70,0x4a,0x4b,0xb2,0x82,0xe3,0x55,0x0c,0xc4,0x90,0x44,0x06,0x6c,0x86,0x1c,
1313 0x6d,0x47,0x12,0xda,0x33,0x95,0x5d,0x98,0x43,0xcb,0x7c,0xfa,0x2b,0xee,0xc4,
1314 0x2d,0xc8,0x95,0x33,0x89,0x08,0x3f,0x9f,0x87,0xea,0x20,0x04,0xaf,0x58,0x4b,
1315 0x9d,0xc0,0x7c,0x0a,0x1b,0x05,0x31,0x3b,0xbb,0x13,0x58,0x2e,0x3f,0x61,0x6b,
1316 0x10,0xb4,0xeb,0xb9,0x1a,0x30,0xfd,0xea,0xca,0x29,0x99,0x5f,0x42,0x2b,0x00,
1317 0xb0,0x08,0xc3,0xf0,0xb6,0xd6,0x6b,0xf9,0x35,0x95 };
1318 static const BYTE chain10_1[] = {
1319 0x30,0x82,0x01,0x9b,0x30,0x82,0x01,0x08,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,
1320 0xbf,0x99,0x4f,0x14,0x03,0x77,0x44,0xb8,0x49,0x02,0x70,0xa1,0xb8,0x9c,0xa7,
1321 0x24,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x30,0x10,0x31,
1322 0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x03,0x13,0x05,0x43,0x65,0x72,0x74,0x31,
1323 0x30,0x1e,0x17,0x0d,0x30,0x37,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
1324 0x30,0x5a,0x17,0x0d,0x30,0x37,0x31,0x32,0x33,0x31,0x32,0x33,0x35,0x39,0x35,
1325 0x39,0x5a,0x30,0x10,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x03,0x13,0x05,
1326 0x43,0x65,0x72,0x74,0x31,0x30,0x81,0x9f,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
1327 0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x81,0x8d,0x00,0x30,0x81,0x89,
1328 0x02,0x81,0x81,0x00,0xad,0x7e,0xca,0xf3,0xe5,0x99,0xc2,0x2a,0xca,0x50,0x82,
1329 0x7c,0x2d,0xa4,0x81,0xcd,0x0d,0x0d,0x86,0xd7,0xd8,0xb2,0xde,0xc5,0xc3,0x34,
1330 0x9e,0x07,0x78,0x08,0x11,0x12,0x2d,0x21,0x0a,0x09,0x07,0x14,0x03,0x7a,0xe7,
1331 0x3b,0x58,0xf1,0xde,0x3e,0x01,0x25,0x93,0xab,0x8f,0xce,0x1f,0xc1,0x33,0x91,
1332 0xfe,0x59,0xb9,0x3b,0x9e,0x95,0x12,0x89,0x8e,0xc3,0x4b,0x98,0x1b,0x99,0xc5,
1333 0x07,0xe2,0xdf,0x15,0x4c,0x39,0x76,0x06,0xad,0xdb,0x16,0x06,0x49,0xba,0xcd,
1334 0x0f,0x07,0xd6,0xea,0x27,0xa6,0xfe,0x3d,0x88,0xe5,0x97,0x45,0x72,0xb6,0x1c,
1335 0xc0,0x1c,0xb1,0xa2,0x89,0xe8,0x37,0x9e,0xf6,0x2a,0xcf,0xd5,0x1f,0x2f,0x35,
1336 0x5e,0x8f,0x3a,0x9c,0x61,0xb1,0xf1,0x6c,0xff,0x8c,0xb2,0x2f,0x02,0x03,0x01,
1337 0x00,0x01,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x03,0x81,
1338 0x81,0x00,0xa8,0xec,0x8c,0x34,0xe7,0x2c,0xdf,0x75,0x87,0xc4,0xf7,0xda,0x71,
1339 0x72,0x29,0xb2,0x48,0xa8,0x2a,0xec,0x7b,0x7d,0x19,0xb9,0x5f,0x1d,0xd9,0x91,
1340 0x2b,0xc4,0x28,0x7e,0xd6,0xb5,0x91,0x69,0xa5,0x8a,0x1a,0x1f,0x97,0x98,0x46,
1341 0x9d,0xdf,0x12,0xf6,0x45,0x62,0xad,0x60,0xb6,0xba,0xb0,0xfd,0xf5,0x9f,0xc6,
1342 0x98,0x05,0x4f,0x4d,0x48,0xdc,0xee,0x69,0xbe,0xb8,0xc4,0xc4,0xd7,0x1b,0xb1,
1343 0x1f,0x64,0xd6,0x45,0xa7,0xdb,0xb3,0x87,0x63,0x0f,0x54,0xe1,0x3a,0x6b,0x57,
1344 0x36,0xd7,0x68,0x65,0xcf,0xda,0x57,0x8d,0xcd,0x84,0x75,0x47,0x26,0x2c,0xef,
1345 0x1e,0x8f,0xc7,0x3b,0xee,0x5d,0x03,0xa6,0xdf,0x3a,0x20,0xb2,0xcc,0xc9,0x09,
1346 0x2c,0xfe,0x2b,0x79,0xb0,0xca,0x2c,0x9a,0x81,0x6b };
1347 static const BYTE chain7_1[] = {
1348 0x30,0x82,0x01,0x93,0x30,0x81,0xfd,0xa0,0x03,0x02,0x01,0x02,0x02,0x01,0x01,
1349 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,
1350 0x30,0x10,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x03,0x13,0x05,0x43,0x65,
1351 0x72,0x74,0x31,0x30,0x1e,0x17,0x0d,0x30,0x37,0x30,0x31,0x30,0x31,0x30,0x30,
1352 0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,0x30,0x37,0x31,0x32,0x33,0x31,0x32,0x33,
1353 0x35,0x39,0x35,0x39,0x5a,0x30,0x10,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,
1354 0x03,0x13,0x05,0x43,0x65,0x72,0x74,0x32,0x30,0x81,0x9f,0x30,0x0d,0x06,0x09,
1355 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x81,0x8d,0x00,
1356 0x30,0x81,0x89,0x02,0x81,0x81,0x00,0xb8,0x52,0xda,0xc5,0x4b,0x3f,0xe5,0x33,
1357 0x0e,0x67,0x5f,0x48,0x21,0xdc,0x7e,0xef,0x37,0x33,0xba,0xff,0xb4,0xc6,0xdc,
1358 0xb6,0x17,0x8e,0x20,0x55,0x07,0x12,0xd2,0x7b,0x3c,0xce,0x30,0xc5,0xa7,0x48,
1359 0x9f,0x6e,0xfe,0xb8,0xbe,0xdb,0x9f,0x9b,0x17,0x60,0x16,0xde,0xc6,0x8b,0x47,
1360 0xd1,0x57,0x71,0x3c,0x93,0xfc,0xbd,0xec,0x44,0x32,0x3b,0xb9,0xcf,0x6b,0x05,
1361 0x72,0xa7,0x87,0x8e,0x7e,0xd4,0x9a,0x87,0x1c,0x2f,0xb7,0x82,0x40,0xfc,0x6a,
1362 0x80,0x83,0x68,0x28,0xce,0x84,0xf4,0x0b,0x2e,0x44,0xcb,0x53,0xac,0x85,0x85,
1363 0xb5,0x46,0x36,0x98,0x3c,0x10,0x02,0xaa,0x02,0xbc,0x8b,0xa2,0x23,0xb2,0xd3,
1364 0x51,0x9a,0x22,0x4a,0xe3,0xaa,0x4e,0x7c,0xda,0x38,0xcf,0x49,0x98,0x72,0xa3,
1365 0x02,0x03,0x01,0x00,0x01,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
1366 0x01,0x01,0x05,0x05,0x00,0x03,0x81,0x81,0x00,0x9f,0x69,0xfd,0x26,0xd5,0x4b,
1367 0xe0,0xab,0x12,0x21,0xb9,0xfc,0xf7,0xe0,0x0c,0x09,0x94,0xad,0x27,0xd7,0x9d,
1368 0xa3,0xcc,0x46,0x2a,0x25,0x9a,0x24,0xa7,0x31,0x58,0x78,0xf5,0xfc,0x30,0xe1,
1369 0x6d,0xfd,0x59,0xab,0xbe,0x69,0xa0,0xea,0xe3,0x7d,0x7a,0x7b,0xe5,0x85,0xeb,
1370 0x86,0x6a,0x84,0x3c,0x96,0x01,0x1a,0x70,0xa7,0xb8,0xcb,0xf2,0x11,0xe7,0x52,
1371 0x9c,0x58,0x2d,0xac,0x63,0xce,0x72,0x4b,0xad,0x62,0xa8,0x1d,0x75,0x96,0xe2,
1372 0x27,0xf5,0x6f,0xba,0x91,0xf8,0xf1,0xb0,0xbf,0x90,0x24,0x6d,0xba,0x5d,0xd7,
1373 0x39,0x63,0x3b,0x7c,0x04,0x5d,0x89,0x9d,0x1c,0xf2,0xf7,0xcc,0xdf,0x6e,0x8a,
1374 0x43,0xa9,0xdd,0x86,0x05,0xa2,0xf3,0x22,0x2d,0x1e,0x70,0xa1,0x59,0xd7,0xa5,
1375 0x94,0x7d };
1377 static void testGetIssuerCert(void)
1379 BOOL ret;
1380 PCCERT_CONTEXT parent, child, cert1, cert2;
1381 DWORD flags = 0xffffffff;
1382 HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1383 CERT_STORE_CREATE_NEW_FLAG, NULL);
1385 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1387 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1388 expiredCert, sizeof(expiredCert), CERT_STORE_ADD_ALWAYS, NULL);
1389 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1390 GetLastError());
1392 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1393 childOfExpired, sizeof(childOfExpired), CERT_STORE_ADD_ALWAYS, &child);
1394 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1395 GetLastError());
1397 /* These crash:
1398 parent = CertGetIssuerCertificateFromStore(NULL, NULL, NULL, NULL);
1399 parent = CertGetIssuerCertificateFromStore(store, NULL, NULL, NULL);
1401 parent = CertGetIssuerCertificateFromStore(NULL, NULL, NULL, &flags);
1402 ok(!parent && GetLastError() == E_INVALIDARG,
1403 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1404 parent = CertGetIssuerCertificateFromStore(store, NULL, NULL, &flags);
1405 ok(!parent && GetLastError() == E_INVALIDARG,
1406 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1407 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1408 ok(!parent && GetLastError() == E_INVALIDARG,
1409 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1410 /* Confusing: the caller cannot set either of the
1411 * CERT_STORE_NO_*_FLAGs, as these are not checks,
1412 * they're results:
1414 flags = CERT_STORE_NO_CRL_FLAG | CERT_STORE_NO_ISSUER_FLAG;
1415 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1416 ok(!parent && GetLastError() == E_INVALIDARG,
1417 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1418 /* Perform no checks */
1419 flags = 0;
1420 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1421 ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08x\n",
1422 GetLastError());
1423 if (parent)
1424 CertFreeCertificateContext(parent);
1425 /* Check revocation and signature only */
1426 flags = CERT_STORE_REVOCATION_FLAG | CERT_STORE_SIGNATURE_FLAG;
1427 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1428 ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08x\n",
1429 GetLastError());
1430 /* Confusing: CERT_STORE_REVOCATION_FLAG succeeds when there is no CRL by
1431 * setting CERT_STORE_NO_CRL_FLAG.
1433 ok(flags == (CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG),
1434 "Expected CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG, got %08x\n",
1435 flags);
1436 if (parent)
1437 CertFreeCertificateContext(parent);
1438 /* Checking time validity is not productive, because while most Windows
1439 * versions return 0 (time valid) because the child is not expired,
1440 * Windows 2003 SP1 returns that it is expired. Thus the range of
1441 * possibilities is covered, and a test verifies nothing.
1444 CertFreeCertificateContext(child);
1445 CertCloseStore(store, 0);
1447 flags = 0;
1448 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1449 CERT_STORE_CREATE_NEW_FLAG, NULL);
1450 /* With only the child certificate, no issuer will be found */
1451 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1452 chain7_1, sizeof(chain7_1), CERT_STORE_ADD_ALWAYS, &child);
1453 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1454 ok(parent == NULL, "Expected no issuer\n");
1455 /* Adding an issuer allows one (and only one) issuer to be found */
1456 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1457 chain10_1, sizeof(chain10_1), CERT_STORE_ADD_ALWAYS, &cert1);
1458 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1459 ok(parent == cert1, "Expected cert1 to be the issuer\n");
1460 parent = CertGetIssuerCertificateFromStore(store, child, parent, &flags);
1461 ok(parent == NULL, "Expected only one issuer\n");
1462 /* Adding a second issuer allows two issuers to be found - and the second
1463 * issuer is found before the first, implying certs are added to the head
1464 * of a list.
1466 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1467 chain10_0, sizeof(chain10_0), CERT_STORE_ADD_ALWAYS, &cert2);
1468 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1469 ok(parent == cert2, "Expected cert2 to be the first issuer\n");
1470 parent = CertGetIssuerCertificateFromStore(store, child, parent, &flags);
1471 ok(parent == cert1, "Expected cert1 to be the second issuer\n");
1472 parent = CertGetIssuerCertificateFromStore(store, child, parent, &flags);
1473 ok(parent == NULL, "Expected no more than two issuers\n");
1474 CertFreeCertificateContext(child);
1475 CertFreeCertificateContext(cert1);
1476 CertFreeCertificateContext(cert2);
1477 CertCloseStore(store, 0);
1479 /* Repeat the test, reversing the order in which issuers are added,
1480 * to show it's order-dependent.
1482 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1483 CERT_STORE_CREATE_NEW_FLAG, NULL);
1484 /* With only the child certificate, no issuer will be found */
1485 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1486 chain7_1, sizeof(chain7_1), CERT_STORE_ADD_ALWAYS, &child);
1487 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1488 ok(parent == NULL, "Expected no issuer\n");
1489 /* Adding an issuer allows one (and only one) issuer to be found */
1490 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1491 chain10_0, sizeof(chain10_0), CERT_STORE_ADD_ALWAYS, &cert1);
1492 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1493 ok(parent == cert1, "Expected cert1 to be the issuer\n");
1494 parent = CertGetIssuerCertificateFromStore(store, child, parent, &flags);
1495 ok(parent == NULL, "Expected only one issuer\n");
1496 /* Adding a second issuer allows two issuers to be found - and the second
1497 * issuer is found before the first, implying certs are added to the head
1498 * of a list.
1500 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1501 chain10_1, sizeof(chain10_1), CERT_STORE_ADD_ALWAYS, &cert2);
1502 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1503 ok(parent == cert2, "Expected cert2 to be the first issuer\n");
1504 parent = CertGetIssuerCertificateFromStore(store, child, parent, &flags);
1505 ok(parent == cert1, "Expected cert1 to be the second issuer\n");
1506 parent = CertGetIssuerCertificateFromStore(store, child, parent, &flags);
1507 ok(parent == NULL, "Expected no more than two issuers\n");
1508 CertFreeCertificateContext(child);
1509 CertFreeCertificateContext(cert1);
1510 CertFreeCertificateContext(cert2);
1511 CertCloseStore(store, 0);
1514 static void testCryptHashCert(void)
1516 static const BYTE emptyHash[] = { 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b,
1517 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07,
1518 0x09 };
1519 static const BYTE knownHash[] = { 0xae, 0x9d, 0xbf, 0x6d, 0xf5, 0x46, 0xee,
1520 0x8b, 0xc5, 0x7a, 0x13, 0xba, 0xc2, 0xb1, 0x04, 0xf2, 0xbf, 0x52, 0xa8,
1521 0xa2 };
1522 static const BYTE toHash[] = "abcdefghijklmnopqrstuvwxyz0123456789.,;!?:";
1523 BOOL ret;
1524 BYTE hash[20];
1525 DWORD hashLen = sizeof(hash);
1527 /* NULL buffer and nonzero length crashes
1528 ret = CryptHashCertificate(0, 0, 0, NULL, size, hash, &hashLen);
1529 empty hash length also crashes
1530 ret = CryptHashCertificate(0, 0, 0, buf, size, hash, NULL);
1532 /* Test empty hash */
1533 ret = CryptHashCertificate(0, 0, 0, toHash, sizeof(toHash), NULL,
1534 &hashLen);
1535 ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
1536 ok(hashLen == sizeof(hash), "Got unexpected size of hash %d\n", hashLen);
1537 /* Test with empty buffer */
1538 ret = CryptHashCertificate(0, 0, 0, NULL, 0, hash, &hashLen);
1539 ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
1540 ok(!memcmp(hash, emptyHash, sizeof(emptyHash)),
1541 "Unexpected hash of nothing\n");
1542 /* Test a known value */
1543 ret = CryptHashCertificate(0, 0, 0, toHash, sizeof(toHash), hash,
1544 &hashLen);
1545 ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
1546 ok(!memcmp(hash, knownHash, sizeof(knownHash)), "Unexpected hash\n");
1549 static void verifySig(HCRYPTPROV csp, const BYTE *toSign, size_t toSignLen,
1550 const BYTE *sig, unsigned int sigLen)
1552 HCRYPTHASH hash;
1553 BOOL ret = CryptCreateHash(csp, CALG_SHA1, 0, 0, &hash);
1555 ok(ret, "CryptCreateHash failed: %08x\n", GetLastError());
1556 if (ret)
1558 BYTE mySig[64];
1559 DWORD mySigSize = sizeof(mySig);
1561 ret = CryptHashData(hash, toSign, toSignLen, 0);
1562 ok(ret, "CryptHashData failed: %08x\n", GetLastError());
1563 /* use the A variant so the test can run on Win9x */
1564 ret = CryptSignHashA(hash, AT_SIGNATURE, NULL, 0, mySig, &mySigSize);
1565 ok(ret, "CryptSignHash failed: %08x\n", GetLastError());
1566 if (ret)
1568 ok(mySigSize == sigLen, "Expected sig length %d, got %d\n",
1569 sigLen, mySigSize);
1570 ok(!memcmp(mySig, sig, sigLen), "Unexpected signature\n");
1572 CryptDestroyHash(hash);
1576 /* Tests signing the certificate described by toBeSigned with the CSP passed in,
1577 * using the algorithm with OID sigOID. The CSP is assumed to be empty, and a
1578 * keyset named AT_SIGNATURE will be added to it. The signing key will be
1579 * stored in *key, and the signature will be stored in sig. sigLen should be
1580 * at least 64 bytes.
1582 static void testSignCert(HCRYPTPROV csp, const CRYPT_DATA_BLOB *toBeSigned,
1583 LPCSTR sigOID, HCRYPTKEY *key, BYTE *sig, DWORD *sigLen)
1585 BOOL ret;
1586 DWORD size = 0;
1587 CRYPT_ALGORITHM_IDENTIFIER algoID = { NULL, { 0, NULL } };
1589 /* These all crash
1590 ret = CryptSignCertificate(0, 0, 0, NULL, 0, NULL, NULL, NULL, NULL);
1591 ret = CryptSignCertificate(0, 0, 0, NULL, 0, NULL, NULL, NULL, &size);
1592 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
1593 NULL, NULL, NULL, &size);
1595 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
1596 &algoID, NULL, NULL, &size);
1597 ok(!ret && GetLastError() == NTE_BAD_ALGID,
1598 "Expected NTE_BAD_ALGID, got %08x\n", GetLastError());
1599 algoID.pszObjId = (LPSTR)sigOID;
1600 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
1601 &algoID, NULL, NULL, &size);
1602 ok(!ret && (GetLastError() == ERROR_INVALID_PARAMETER || NTE_BAD_ALGID),
1603 "Expected ERROR_INVALID_PARAMETER or NTE_BAD_ALGID, got %08x\n",
1604 GetLastError());
1605 ret = CryptSignCertificate(0, AT_SIGNATURE, 0, toBeSigned->pbData,
1606 toBeSigned->cbData, &algoID, NULL, NULL, &size);
1607 ok(!ret && (GetLastError() == ERROR_INVALID_PARAMETER || NTE_BAD_ALGID),
1608 "Expected ERROR_INVALID_PARAMETER or NTE_BAD_ALGID, got %08x\n",
1609 GetLastError());
1611 /* No keys exist in the new CSP yet.. */
1612 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
1613 toBeSigned->cbData, &algoID, NULL, NULL, &size);
1614 ok(!ret && (GetLastError() == NTE_BAD_KEYSET || GetLastError() ==
1615 NTE_NO_KEY), "Expected NTE_BAD_KEYSET or NTE_NO_KEY, got %08x\n",
1616 GetLastError());
1617 ret = CryptGenKey(csp, AT_SIGNATURE, 0, key);
1618 ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
1619 if (ret)
1621 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
1622 toBeSigned->cbData, &algoID, NULL, NULL, &size);
1623 ok(ret, "CryptSignCertificate failed: %08x\n", GetLastError());
1624 ok(size <= *sigLen, "Expected size <= %d, got %d\n", *sigLen, size);
1625 if (ret)
1627 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
1628 toBeSigned->cbData, &algoID, NULL, sig, &size);
1629 ok(ret, "CryptSignCertificate failed: %08x\n", GetLastError());
1630 if (ret)
1632 *sigLen = size;
1633 verifySig(csp, toBeSigned->pbData, toBeSigned->cbData, sig,
1634 size);
1640 static void testVerifyCertSig(HCRYPTPROV csp, const CRYPT_DATA_BLOB *toBeSigned,
1641 LPCSTR sigOID, const BYTE *sig, DWORD sigLen)
1643 CERT_SIGNED_CONTENT_INFO info;
1644 LPBYTE cert = NULL;
1645 DWORD size = 0;
1646 BOOL ret;
1648 if (!pCryptVerifyCertificateSignatureEx)
1650 skip("no CryptVerifyCertificateSignatureEx support\n");
1651 return;
1653 if (!pCryptEncodeObjectEx)
1655 skip("no CryptEncodeObjectEx support\n");
1656 return;
1658 ret = pCryptVerifyCertificateSignatureEx(0, 0, 0, NULL, 0, NULL, 0, NULL);
1659 ok(!ret && GetLastError() == E_INVALIDARG,
1660 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1661 ret = pCryptVerifyCertificateSignatureEx(csp, 0, 0, NULL, 0, NULL, 0, NULL);
1662 ok(!ret && GetLastError() == E_INVALIDARG,
1663 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1664 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING, 0, NULL, 0,
1665 NULL, 0, NULL);
1666 ok(!ret && GetLastError() == E_INVALIDARG,
1667 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1668 /* This crashes
1669 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1670 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, NULL, 0, NULL, 0, NULL);
1672 info.ToBeSigned.cbData = toBeSigned->cbData;
1673 info.ToBeSigned.pbData = toBeSigned->pbData;
1674 info.SignatureAlgorithm.pszObjId = (LPSTR)sigOID;
1675 info.SignatureAlgorithm.Parameters.cbData = 0;
1676 info.Signature.cbData = sigLen;
1677 info.Signature.pbData = (BYTE *)sig;
1678 info.Signature.cUnusedBits = 0;
1679 ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, X509_CERT, &info,
1680 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&cert, &size);
1681 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1682 if (cert)
1684 CRYPT_DATA_BLOB certBlob = { 0, NULL };
1685 PCERT_PUBLIC_KEY_INFO pubKeyInfo = NULL;
1687 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1688 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
1689 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
1690 "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
1691 certBlob.cbData = 1;
1692 certBlob.pbData = (void *)0xdeadbeef;
1693 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1694 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
1695 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1696 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1697 certBlob.cbData = size;
1698 certBlob.pbData = cert;
1699 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1700 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
1701 ok(!ret && GetLastError() == E_INVALIDARG,
1702 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1703 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1704 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
1705 CRYPT_VERIFY_CERT_SIGN_ISSUER_NULL, NULL, 0, NULL);
1706 ok(!ret && GetLastError() == E_INVALIDARG,
1707 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1708 /* This crashes
1709 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1710 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
1711 CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY, NULL, 0, NULL);
1713 CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
1714 (LPSTR)sigOID, 0, NULL, NULL, &size);
1715 pubKeyInfo = HeapAlloc(GetProcessHeap(), 0, size);
1716 if (pubKeyInfo)
1718 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
1719 X509_ASN_ENCODING, (LPSTR)sigOID, 0, NULL, pubKeyInfo, &size);
1720 ok(ret, "CryptExportKey failed: %08x\n", GetLastError());
1721 if (ret)
1723 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1724 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
1725 CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY, pubKeyInfo, 0, NULL);
1726 ok(ret, "CryptVerifyCertificateSignatureEx failed: %08x\n",
1727 GetLastError());
1729 HeapFree(GetProcessHeap(), 0, pubKeyInfo);
1731 LocalFree(cert);
1735 static BYTE emptyCert[] = { 0x30, 0x00 };
1737 static void testCertSigs(void)
1739 HCRYPTPROV csp;
1740 CRYPT_DATA_BLOB toBeSigned = { sizeof(emptyCert), emptyCert };
1741 BOOL ret;
1742 HCRYPTKEY key;
1743 BYTE sig[64];
1744 DWORD sigSize = sizeof(sig);
1746 /* Just in case a previous run failed, delete this thing */
1747 pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
1748 CRYPT_DELETEKEYSET);
1749 ret = pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
1750 CRYPT_NEWKEYSET);
1751 ok(ret, "CryptAcquireContext failed: %08x\n", GetLastError());
1753 testSignCert(csp, &toBeSigned, szOID_RSA_SHA1RSA, &key, sig, &sigSize);
1754 testVerifyCertSig(csp, &toBeSigned, szOID_RSA_SHA1RSA, sig, sigSize);
1756 CryptDestroyKey(key);
1757 CryptReleaseContext(csp, 0);
1758 ret = pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
1759 CRYPT_DELETEKEYSET);
1762 static const BYTE md5SignedEmptyCert[] = {
1763 0x30,0x56,0x30,0x33,0x02,0x00,0x30,0x02,0x06,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,
1764 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,
1765 0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x07,
1766 0x30,0x02,0x06,0x00,0x03,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,
1767 0x0d,0x02,0x05,0x05,0x00,0x03,0x11,0x00,0xfb,0x0f,0x66,0x82,0x66,0xd9,0xe5,0xf8,
1768 0xd8,0xa2,0x55,0x2b,0xe1,0xa5,0xd9,0x04 };
1769 static const BYTE md5SignedEmptyCertNoNull[] = {
1770 0x30,0x54,0x30,0x33,0x02,0x00,0x30,0x02,0x06,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,
1771 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,
1772 0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x07,
1773 0x30,0x02,0x06,0x00,0x03,0x01,0x00,0x30,0x0a,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,
1774 0x0d,0x02,0x05,0x03,0x11,0x00,0x04,0xd9,0xa5,0xe1,0x2b,0x55,0xa2,0xd8,0xf8,0xe5,
1775 0xd9,0x66,0x82,0x66,0x0f,0xfb };
1777 static void testSignAndEncodeCert(void)
1779 static char oid_rsa_md5rsa[] = szOID_RSA_MD5RSA;
1780 static char oid_rsa_md5[] = szOID_RSA_MD5;
1781 BOOL ret;
1782 DWORD size;
1783 CRYPT_ALGORITHM_IDENTIFIER algID = { 0 };
1784 CERT_INFO info = { 0 };
1786 /* Crash
1787 ret = CryptSignAndEncodeCertificate(0, 0, 0, NULL, NULL, NULL, NULL, NULL,
1788 NULL);
1789 ret = CryptSignAndEncodeCertificate(0, 0, 0, NULL, NULL, NULL, NULL, NULL,
1790 &size);
1792 ret = CryptSignAndEncodeCertificate(0, 0, 0, NULL, NULL, &algID, NULL, NULL,
1793 &size);
1794 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1795 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1796 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING, NULL, NULL,
1797 &algID, NULL, NULL, &size);
1798 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1799 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1800 ret = CryptSignAndEncodeCertificate(0, 0, 0, X509_CERT_TO_BE_SIGNED, NULL,
1801 &algID, NULL, NULL, &size);
1802 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1803 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1804 /* Crashes on some win9x boxes */
1805 if (0)
1807 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1808 X509_CERT_TO_BE_SIGNED, NULL, &algID, NULL, NULL, &size);
1809 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1810 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1812 /* Crashes
1813 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1814 X509_CERT_TO_BE_SIGNED, &info, NULL, NULL, NULL, &size);
1816 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1817 X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, NULL, &size);
1818 ok(!ret && GetLastError() == NTE_BAD_ALGID,
1819 "Expected NTE_BAD_ALGID, got %08x\n", GetLastError());
1820 algID.pszObjId = oid_rsa_md5rsa;
1821 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1822 X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, NULL, &size);
1823 ok(!ret && (GetLastError() == ERROR_INVALID_PARAMETER || NTE_BAD_ALGID),
1824 "Expected ERROR_INVALID_PARAMETER or NTE_BAD_ALGID, got %08x\n",
1825 GetLastError());
1826 algID.pszObjId = oid_rsa_md5;
1827 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1828 X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, NULL, &size);
1829 /* oid_rsa_md5 not present in some win2k */
1830 if (ret)
1832 LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, size);
1834 if (buf)
1836 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1837 X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, buf, &size);
1838 ok(ret, "CryptSignAndEncodeCertificate failed: %08x\n",
1839 GetLastError());
1840 /* Tricky: because the NULL parameters may either be omitted or
1841 * included as an asn.1-encoded NULL (0x05,0x00), two different
1842 * values are allowed.
1844 ok(size == sizeof(md5SignedEmptyCert) ||
1845 size == sizeof(md5SignedEmptyCertNoNull), "Unexpected size %d\n",
1846 size);
1847 if (size == sizeof(md5SignedEmptyCert))
1848 ok(!memcmp(buf, md5SignedEmptyCert, size),
1849 "Unexpected value\n");
1850 else if (size == sizeof(md5SignedEmptyCertNoNull))
1851 ok(!memcmp(buf, md5SignedEmptyCertNoNull, size),
1852 "Unexpected value\n");
1853 HeapFree(GetProcessHeap(), 0, buf);
1858 static void testCreateSelfSignCert(void)
1860 PCCERT_CONTEXT context;
1861 CERT_NAME_BLOB name = { sizeof(subjectName), subjectName };
1862 HCRYPTPROV csp;
1863 BOOL ret;
1864 HCRYPTKEY key;
1865 CRYPT_KEY_PROV_INFO info;
1867 if (!pCertCreateSelfSignCertificate)
1869 skip("CertCreateSelfSignCertificate() is not available\n");
1870 return;
1873 /* This crashes:
1874 context = pCertCreateSelfSignCertificate(0, NULL, 0, NULL, NULL, NULL, NULL,
1875 NULL);
1876 * Calling this with no first parameter creates a new key container, which
1877 * lasts beyond the test, so I don't test that. Nb: the generated key
1878 * name is a GUID.
1879 context = pCertCreateSelfSignCertificate(0, &name, 0, NULL, NULL, NULL, NULL,
1880 NULL);
1883 /* Acquire a CSP */
1884 pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
1885 CRYPT_DELETEKEYSET);
1886 ret = pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
1887 CRYPT_NEWKEYSET);
1888 ok(ret, "CryptAcquireContext failed: %08x\n", GetLastError());
1890 context = pCertCreateSelfSignCertificate(csp, &name, 0, NULL, NULL, NULL,
1891 NULL, NULL);
1892 ok(!context && GetLastError() == NTE_NO_KEY,
1893 "Expected NTE_NO_KEY, got %08x\n", GetLastError());
1894 ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
1895 ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
1896 if (ret)
1898 context = pCertCreateSelfSignCertificate(csp, &name, 0, NULL, NULL, NULL,
1899 NULL, NULL);
1900 ok(context != NULL, "CertCreateSelfSignCertificate failed: %08x\n",
1901 GetLastError());
1902 if (context)
1904 DWORD size = 0;
1905 PCRYPT_KEY_PROV_INFO info;
1907 /* The context must have a key provider info property */
1908 ret = CertGetCertificateContextProperty(context,
1909 CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
1910 ok(ret && size, "Expected non-zero key provider info\n");
1911 if (size)
1913 info = HeapAlloc(GetProcessHeap(), 0, size);
1914 if (info)
1916 ret = CertGetCertificateContextProperty(context,
1917 CERT_KEY_PROV_INFO_PROP_ID, info, &size);
1918 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
1919 GetLastError());
1920 if (ret)
1922 /* Sanity-check the key provider */
1923 ok(!lstrcmpW(info->pwszContainerName, cspNameW),
1924 "Unexpected key container\n");
1925 ok(!lstrcmpW(info->pwszProvName, MS_DEF_PROV_W),
1926 "Unexpected provider\n");
1927 ok(info->dwKeySpec == AT_SIGNATURE,
1928 "Expected AT_SIGNATURE, got %d\n", info->dwKeySpec);
1930 HeapFree(GetProcessHeap(), 0, info);
1934 CertFreeCertificateContext(context);
1937 CryptDestroyKey(key);
1940 CryptReleaseContext(csp, 0);
1941 ret = pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
1942 CRYPT_DELETEKEYSET);
1944 /* do the same test with AT_KEYEXCHANGE and key info*/
1945 memset(&info,0,sizeof(info));
1946 info.dwProvType = PROV_RSA_FULL;
1947 info.dwKeySpec = AT_KEYEXCHANGE;
1948 info.pwszProvName = (LPWSTR) MS_DEF_PROV_W;
1949 info.pwszContainerName = cspNameW;
1950 context = pCertCreateSelfSignCertificate(0, &name, 0, &info, NULL, NULL,
1951 NULL, NULL);
1952 ok(context != NULL, "CertCreateSelfSignCertificate failed: %08x\n",
1953 GetLastError());
1954 if (context)
1956 DWORD size = 0;
1957 PCRYPT_KEY_PROV_INFO info;
1959 /* The context must have a key provider info property */
1960 ret = CertGetCertificateContextProperty(context,
1961 CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
1962 ok(ret && size, "Expected non-zero key provider info\n");
1963 if (size)
1965 info = HeapAlloc(GetProcessHeap(), 0, size);
1966 if (info)
1968 ret = CertGetCertificateContextProperty(context,
1969 CERT_KEY_PROV_INFO_PROP_ID, info, &size);
1970 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
1971 GetLastError());
1972 if (ret)
1974 /* Sanity-check the key provider */
1975 ok(!lstrcmpW(info->pwszContainerName, cspNameW),
1976 "Unexpected key container\n");
1977 ok(!lstrcmpW(info->pwszProvName, MS_DEF_PROV_W),
1978 "Unexpected provider\n");
1979 ok(info->dwKeySpec == AT_KEYEXCHANGE,
1980 "Expected AT_KEYEXCHANGE, got %d\n", info->dwKeySpec);
1982 HeapFree(GetProcessHeap(), 0, info);
1986 CertFreeCertificateContext(context);
1989 pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
1990 CRYPT_DELETEKEYSET);
1993 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
1994 szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
1996 static void testKeyUsage(void)
1998 BOOL ret;
1999 PCCERT_CONTEXT context;
2000 DWORD size;
2002 /* Test base cases */
2003 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, NULL);
2004 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2005 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
2006 size = 1;
2007 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, &size);
2008 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2009 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
2010 size = 0;
2011 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, &size);
2012 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2013 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
2014 /* These crash
2015 ret = CertSetEnhancedKeyUsage(NULL, NULL);
2016 usage.cUsageIdentifier = 0;
2017 ret = CertSetEnhancedKeyUsage(NULL, &usage);
2019 /* Test with a cert with no enhanced key usage extension */
2020 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
2021 sizeof(bigCert));
2022 ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
2023 GetLastError());
2024 if (context)
2026 static const char oid[] = "1.2.3.4";
2027 BYTE buf[sizeof(CERT_ENHKEY_USAGE) + 2 * (sizeof(LPSTR) + sizeof(oid))];
2028 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
2030 ret = CertGetEnhancedKeyUsage(context, 0, NULL, NULL);
2031 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2032 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
2033 size = 1;
2034 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &size);
2035 if (ret)
2037 /* Windows 2000, ME, or later: even though it succeeded, we expect
2038 * CRYPT_E_NOT_FOUND, which indicates there is no enhanced key
2039 * usage set for this cert (which implies it's valid for all uses.)
2041 ok(GetLastError() == CRYPT_E_NOT_FOUND,
2042 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
2043 ok(size == sizeof(CERT_ENHKEY_USAGE), "Wrong size %d\n", size);
2044 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2045 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2046 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %d\n",
2047 pUsage->cUsageIdentifier);
2049 else
2051 /* Windows NT, 95, or 98: it fails, and the last error is
2052 * CRYPT_E_NOT_FOUND.
2054 ok(GetLastError() == CRYPT_E_NOT_FOUND,
2055 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
2057 /* I can add a usage identifier when no key usage has been set */
2058 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
2059 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
2060 GetLastError());
2061 size = sizeof(buf);
2062 ret = CertGetEnhancedKeyUsage(context,
2063 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
2064 ok(ret && GetLastError() == 0,
2065 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2066 ok(pUsage->cUsageIdentifier == 1, "Expected 1 usage, got %d\n",
2067 pUsage->cUsageIdentifier);
2068 if (pUsage->cUsageIdentifier)
2069 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
2070 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
2071 /* Now set an empty key usage */
2072 pUsage->cUsageIdentifier = 0;
2073 ret = CertSetEnhancedKeyUsage(context, pUsage);
2074 ok(ret, "CertSetEnhancedKeyUsage failed: %08x\n", GetLastError());
2075 /* Shouldn't find it in the cert */
2076 size = sizeof(buf);
2077 ret = CertGetEnhancedKeyUsage(context,
2078 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
2079 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
2080 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
2081 /* Should find it as an extended property */
2082 ret = CertGetEnhancedKeyUsage(context,
2083 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
2084 ok(ret && GetLastError() == 0,
2085 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2086 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %d\n",
2087 pUsage->cUsageIdentifier);
2088 /* Should find it as either */
2089 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2090 ok(ret && GetLastError() == 0,
2091 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2092 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %d\n",
2093 pUsage->cUsageIdentifier);
2094 /* Add a usage identifier */
2095 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
2096 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
2097 GetLastError());
2098 size = sizeof(buf);
2099 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2100 ok(ret && GetLastError() == 0,
2101 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2102 ok(pUsage->cUsageIdentifier == 1, "Expected 1 identifier, got %d\n",
2103 pUsage->cUsageIdentifier);
2104 if (pUsage->cUsageIdentifier)
2105 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
2106 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
2107 /* Re-adding the same usage identifier succeeds, though it only adds
2108 * a duplicate usage identifier on versions prior to Vista
2110 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
2111 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
2112 GetLastError());
2113 size = sizeof(buf);
2114 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2115 ok(ret && GetLastError() == 0,
2116 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2117 ok(pUsage->cUsageIdentifier == 1 || pUsage->cUsageIdentifier == 2,
2118 "Expected 1 or 2 identifiers, got %d\n", pUsage->cUsageIdentifier);
2119 if (pUsage->cUsageIdentifier)
2120 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
2121 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
2122 if (pUsage->cUsageIdentifier >= 2)
2123 ok(!strcmp(pUsage->rgpszUsageIdentifier[1], oid),
2124 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[1]);
2125 /* Now set a NULL extended property--this deletes the property. */
2126 ret = CertSetEnhancedKeyUsage(context, NULL);
2127 ok(ret, "CertSetEnhancedKeyUsage failed: %08x\n", GetLastError());
2128 SetLastError(0xbaadcafe);
2129 size = sizeof(buf);
2130 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2131 ok(GetLastError() == CRYPT_E_NOT_FOUND,
2132 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
2134 CertFreeCertificateContext(context);
2136 /* Now test with a cert with an enhanced key usage extension */
2137 context = CertCreateCertificateContext(X509_ASN_ENCODING, certWithUsage,
2138 sizeof(certWithUsage));
2139 ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
2140 GetLastError());
2141 if (context)
2143 LPBYTE buf = NULL;
2144 DWORD bufSize = 0, i;
2146 /* The size may depend on what flags are used to query it, so I
2147 * realloc the buffer for each test.
2149 ret = CertGetEnhancedKeyUsage(context,
2150 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, NULL, &bufSize);
2151 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2152 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
2153 if (buf)
2155 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
2157 /* Should find it in the cert */
2158 size = bufSize;
2159 ret = CertGetEnhancedKeyUsage(context,
2160 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
2161 ok(ret && GetLastError() == 0,
2162 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2163 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
2164 pUsage->cUsageIdentifier);
2165 for (i = 0; i < pUsage->cUsageIdentifier; i++)
2166 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
2167 "Expected %s, got %s\n", keyUsages[i],
2168 pUsage->rgpszUsageIdentifier[i]);
2169 HeapFree(GetProcessHeap(), 0, buf);
2171 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
2172 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2173 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
2174 if (buf)
2176 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
2178 /* Should find it as either */
2179 size = bufSize;
2180 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2181 /* In Windows, GetLastError returns CRYPT_E_NOT_FOUND not found
2182 * here, even though the return is successful and the usage id
2183 * count is positive. I don't enforce that here.
2185 ok(ret,
2186 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2187 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
2188 pUsage->cUsageIdentifier);
2189 for (i = 0; i < pUsage->cUsageIdentifier; i++)
2190 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
2191 "Expected %s, got %s\n", keyUsages[i],
2192 pUsage->rgpszUsageIdentifier[i]);
2193 HeapFree(GetProcessHeap(), 0, buf);
2195 /* Shouldn't find it as an extended property */
2196 ret = CertGetEnhancedKeyUsage(context,
2197 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, NULL, &size);
2198 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
2199 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
2200 /* Adding a usage identifier overrides the cert's usage!? */
2201 ret = CertAddEnhancedKeyUsageIdentifier(context, szOID_RSA_RSA);
2202 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
2203 GetLastError());
2204 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
2205 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2206 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
2207 if (buf)
2209 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
2211 /* Should find it as either */
2212 size = bufSize;
2213 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2214 ok(ret,
2215 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2216 ok(pUsage->cUsageIdentifier == 1, "Expected 1 usage, got %d\n",
2217 pUsage->cUsageIdentifier);
2218 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], szOID_RSA_RSA),
2219 "Expected %s, got %s\n", szOID_RSA_RSA,
2220 pUsage->rgpszUsageIdentifier[0]);
2221 HeapFree(GetProcessHeap(), 0, buf);
2223 /* But querying the cert directly returns its usage */
2224 ret = CertGetEnhancedKeyUsage(context,
2225 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, NULL, &bufSize);
2226 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2227 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
2228 if (buf)
2230 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
2232 size = bufSize;
2233 ret = CertGetEnhancedKeyUsage(context,
2234 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
2235 ok(ret,
2236 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2237 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
2238 pUsage->cUsageIdentifier);
2239 for (i = 0; i < pUsage->cUsageIdentifier; i++)
2240 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
2241 "Expected %s, got %s\n", keyUsages[i],
2242 pUsage->rgpszUsageIdentifier[i]);
2243 HeapFree(GetProcessHeap(), 0, buf);
2245 /* And removing the only usage identifier in the extended property
2246 * results in the cert's key usage being found.
2248 ret = CertRemoveEnhancedKeyUsageIdentifier(context, szOID_RSA_RSA);
2249 ok(ret, "CertRemoveEnhancedKeyUsage failed: %08x\n", GetLastError());
2250 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
2251 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2252 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
2253 if (buf)
2255 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
2257 /* Should find it as either */
2258 size = bufSize;
2259 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2260 ok(ret,
2261 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2262 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
2263 pUsage->cUsageIdentifier);
2264 for (i = 0; i < pUsage->cUsageIdentifier; i++)
2265 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
2266 "Expected %s, got %s\n", keyUsages[i],
2267 pUsage->rgpszUsageIdentifier[i]);
2268 HeapFree(GetProcessHeap(), 0, buf);
2271 CertFreeCertificateContext(context);
2275 static const BYTE cert2WithUsage[] = {
2276 0x30,0x81,0x89,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2277 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2278 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2279 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2280 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2281 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2282 0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x25,0x30,0x23,
2283 0x30,0x21,0x06,0x03,0x55,0x1d,0x25,0x01,0x01,0xff,0x04,0x17,0x30,0x15,0x06,
2284 0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x03,0x02,0x06,0x09,0x2a,0x86,0x48,0x86,
2285 0xf7,0x0d,0x01,0x01,0x01 };
2287 static void testGetValidUsages(void)
2289 static const LPCSTR expectedOIDs[] = {
2290 "1.3.6.1.5.5.7.3.3",
2291 "1.3.6.1.5.5.7.3.2",
2292 "1.2.840.113549.1.1.1",
2294 static const LPCSTR expectedOIDs2[] = {
2295 "1.3.6.1.5.5.7.3.2",
2296 "1.2.840.113549.1.1.1",
2298 BOOL ret;
2299 int numOIDs;
2300 DWORD size;
2301 LPSTR *oids = NULL;
2302 PCCERT_CONTEXT contexts[3];
2304 if (!pCertGetValidUsages)
2306 skip("CertGetValidUsages() is not available\n");
2307 return;
2310 /* Crash
2311 ret = pCertGetValidUsages(0, NULL, NULL, NULL, NULL);
2312 ret = pCertGetValidUsages(0, NULL, NULL, NULL, &size);
2314 contexts[0] = NULL;
2315 numOIDs = size = 0xdeadbeef;
2316 SetLastError(0xdeadbeef);
2317 ret = pCertGetValidUsages(1, &contexts[0], &numOIDs, NULL, &size);
2318 ok(ret, "CertGetValidUsages failed: %d\n", GetLastError());
2319 ok(numOIDs == -1, "Expected -1, got %d\n", numOIDs);
2320 ok(size == 0, "Expected size 0, got %d\n", size);
2321 contexts[0] = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
2322 sizeof(bigCert));
2323 contexts[1] = CertCreateCertificateContext(X509_ASN_ENCODING, certWithUsage,
2324 sizeof(certWithUsage));
2325 contexts[2] = CertCreateCertificateContext(X509_ASN_ENCODING,
2326 cert2WithUsage, sizeof(cert2WithUsage));
2327 numOIDs = size = 0xdeadbeef;
2328 ret = pCertGetValidUsages(0, NULL, &numOIDs, NULL, &size);
2329 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2330 ok(numOIDs == -1, "Expected -1, got %d\n", numOIDs);
2331 ok(size == 0, "Expected size 0, got %d\n", size);
2332 numOIDs = size = 0xdeadbeef;
2333 ret = pCertGetValidUsages(1, contexts, &numOIDs, NULL, &size);
2334 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2335 ok(numOIDs == -1, "Expected -1, got %d\n", numOIDs);
2336 ok(size == 0, "Expected size 0, got %d\n", size);
2337 ret = pCertGetValidUsages(1, &contexts[1], &numOIDs, NULL, &size);
2338 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2339 ok(numOIDs == 3, "Expected 3, got %d\n", numOIDs);
2340 ok(size, "Expected non-zero size\n");
2341 oids = HeapAlloc(GetProcessHeap(), 0, size);
2342 if (oids)
2344 int i;
2345 DWORD smallSize = 1;
2347 SetLastError(0xdeadbeef);
2348 ret = pCertGetValidUsages(1, &contexts[1], &numOIDs, oids, &smallSize);
2349 ok(!ret && GetLastError() == ERROR_MORE_DATA,
2350 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
2351 ret = pCertGetValidUsages(1, &contexts[1], &numOIDs, oids, &size);
2352 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2353 for (i = 0; i < numOIDs; i++)
2354 ok(!lstrcmpA(oids[i], expectedOIDs[i]), "unexpected OID %s\n",
2355 oids[i]);
2356 HeapFree(GetProcessHeap(), 0, oids);
2358 numOIDs = size = 0xdeadbeef;
2359 /* Oddly enough, this crashes when the number of contexts is not 1:
2360 ret = pCertGetValidUsages(2, contexts, &numOIDs, NULL, &size);
2361 * but setting size to 0 allows it to succeed:
2363 size = 0;
2364 ret = pCertGetValidUsages(2, contexts, &numOIDs, NULL, &size);
2365 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2366 ok(numOIDs == 3, "Expected 3, got %d\n", numOIDs);
2367 ok(size, "Expected non-zero size\n");
2368 oids = HeapAlloc(GetProcessHeap(), 0, size);
2369 if (oids)
2371 int i;
2373 ret = pCertGetValidUsages(1, &contexts[1], &numOIDs, oids, &size);
2374 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2375 for (i = 0; i < numOIDs; i++)
2376 ok(!lstrcmpA(oids[i], expectedOIDs[i]), "unexpected OID %s\n",
2377 oids[i]);
2378 HeapFree(GetProcessHeap(), 0, oids);
2380 numOIDs = 0xdeadbeef;
2381 size = 0;
2382 ret = pCertGetValidUsages(1, &contexts[2], &numOIDs, NULL, &size);
2383 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2384 ok(numOIDs == 2, "Expected 2, got %d\n", numOIDs);
2385 ok(size, "Expected non-zero size\n");
2386 oids = HeapAlloc(GetProcessHeap(), 0, size);
2387 if (oids)
2389 int i;
2391 ret = pCertGetValidUsages(1, &contexts[2], &numOIDs, oids, &size);
2392 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2393 for (i = 0; i < numOIDs; i++)
2394 ok(!lstrcmpA(oids[i], expectedOIDs2[i]), "unexpected OID %s\n",
2395 oids[i]);
2396 HeapFree(GetProcessHeap(), 0, oids);
2398 numOIDs = 0xdeadbeef;
2399 size = 0;
2400 ret = pCertGetValidUsages(3, contexts, &numOIDs, NULL, &size);
2401 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2402 ok(numOIDs == 2, "Expected 2, got %d\n", numOIDs);
2403 ok(size, "Expected non-zero size\n");
2404 oids = HeapAlloc(GetProcessHeap(), 0, size);
2405 if (oids)
2407 int i;
2409 ret = pCertGetValidUsages(3, contexts, &numOIDs, oids, &size);
2410 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2411 for (i = 0; i < numOIDs; i++)
2412 ok(!lstrcmpA(oids[i], expectedOIDs2[i]), "unexpected OID %s\n",
2413 oids[i]);
2414 HeapFree(GetProcessHeap(), 0, oids);
2416 CertFreeCertificateContext(contexts[0]);
2417 CertFreeCertificateContext(contexts[1]);
2418 CertFreeCertificateContext(contexts[2]);
2421 static void testCompareCertName(void)
2423 static BYTE bogus[] = { 1, 2, 3, 4 };
2424 static BYTE bogusPrime[] = { 0, 1, 2, 3, 4 };
2425 static BYTE emptyPrime[] = { 0x30, 0x00, 0x01 };
2426 BOOL ret;
2427 CERT_NAME_BLOB blob1, blob2;
2429 /* crashes
2430 ret = CertCompareCertificateName(0, NULL, NULL);
2432 /* An empty name checks against itself.. */
2433 blob1.pbData = emptyCert;
2434 blob1.cbData = sizeof(emptyCert);
2435 ret = CertCompareCertificateName(0, &blob1, &blob1);
2436 ok(ret, "CertCompareCertificateName failed: %08x\n", GetLastError());
2437 /* It doesn't have to be a valid encoded name.. */
2438 blob1.pbData = bogus;
2439 blob1.cbData = sizeof(bogus);
2440 ret = CertCompareCertificateName(0, &blob1, &blob1);
2441 ok(ret, "CertCompareCertificateName failed: %08x\n", GetLastError());
2442 /* Leading zeroes matter.. */
2443 blob2.pbData = bogusPrime;
2444 blob2.cbData = sizeof(bogusPrime);
2445 ret = CertCompareCertificateName(0, &blob1, &blob2);
2446 ok(!ret, "Expected failure\n");
2447 /* As do trailing extra bytes. */
2448 blob2.pbData = emptyPrime;
2449 blob2.cbData = sizeof(emptyPrime);
2450 ret = CertCompareCertificateName(0, &blob1, &blob2);
2451 ok(!ret, "Expected failure\n");
2454 static BYTE int1[] = { 0x88, 0xff, 0xff, 0xff };
2455 static BYTE int2[] = { 0x88, 0xff };
2456 static BYTE int3[] = { 0x23, 0xff };
2457 static BYTE int4[] = { 0x7f, 0x00 };
2458 static BYTE int5[] = { 0x7f };
2459 static BYTE int6[] = { 0x80, 0x00, 0x00, 0x00 };
2460 static BYTE int7[] = { 0x80, 0x00 };
2462 static struct IntBlobTest
2464 CRYPT_INTEGER_BLOB blob1;
2465 CRYPT_INTEGER_BLOB blob2;
2466 BOOL areEqual;
2467 } intBlobs[] = {
2468 { { sizeof(int1), int1 }, { sizeof(int2), int2 }, TRUE },
2469 { { sizeof(int3), int3 }, { sizeof(int3), int3 }, TRUE },
2470 { { sizeof(int4), int4 }, { sizeof(int5), int5 }, TRUE },
2471 { { sizeof(int6), int6 }, { sizeof(int7), int7 }, TRUE },
2472 { { sizeof(int1), int1 }, { sizeof(int7), int7 }, FALSE },
2475 static void testCompareIntegerBlob(void)
2477 DWORD i;
2478 BOOL ret;
2480 for (i = 0; i < sizeof(intBlobs) / sizeof(intBlobs[0]); i++)
2482 ret = CertCompareIntegerBlob(&intBlobs[i].blob1, &intBlobs[i].blob2);
2483 ok(ret == intBlobs[i].areEqual,
2484 "%d: expected blobs %s compare\n", i, intBlobs[i].areEqual ?
2485 "to" : "not to");
2489 static void testComparePublicKeyInfo(void)
2491 BOOL ret;
2492 CERT_PUBLIC_KEY_INFO info1 = { { 0 } }, info2 = { { 0 } };
2493 static CHAR oid_rsa_rsa[] = szOID_RSA_RSA;
2494 static CHAR oid_rsa_sha1rsa[] = szOID_RSA_SHA1RSA;
2495 static CHAR oid_x957_dsa[] = szOID_X957_DSA;
2496 static BYTE bits1[] = { 1, 0 };
2497 static BYTE bits2[] = { 0 };
2498 static BYTE bits3[] = { 1 };
2499 static BYTE bits4[] = { 0x30,8, 2,1,0x81, 2,3,1,0,1 };
2500 static BYTE bits5[] = { 0x30,9, 2,2,0,0x81, 2,3,1,0,1 };
2501 static BYTE bits6[] = { 0x30,9, 2,2,0,0x82, 2,3,1,0,1 };
2503 /* crashes
2504 ret = CertComparePublicKeyInfo(0, NULL, NULL);
2506 /* Empty public keys compare */
2507 ret = CertComparePublicKeyInfo(0, &info1, &info2);
2508 ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
2509 /* Different OIDs appear to compare */
2510 info1.Algorithm.pszObjId = oid_rsa_rsa;
2511 info2.Algorithm.pszObjId = oid_rsa_sha1rsa;
2512 ret = CertComparePublicKeyInfo(0, &info1, &info2);
2513 ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
2514 info2.Algorithm.pszObjId = oid_x957_dsa;
2515 ret = CertComparePublicKeyInfo(0, &info1, &info2);
2516 ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
2517 info1.PublicKey.cbData = sizeof(bits1);
2518 info1.PublicKey.pbData = bits1;
2519 info1.PublicKey.cUnusedBits = 0;
2520 info2.PublicKey.cbData = sizeof(bits1);
2521 info2.PublicKey.pbData = bits1;
2522 info2.PublicKey.cUnusedBits = 0;
2523 ret = CertComparePublicKeyInfo(0, &info1, &info2);
2524 ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
2525 info2.Algorithm.pszObjId = oid_rsa_rsa;
2526 info1.PublicKey.cbData = sizeof(bits4);
2527 info1.PublicKey.pbData = bits4;
2528 info1.PublicKey.cUnusedBits = 0;
2529 info2.PublicKey.cbData = sizeof(bits5);
2530 info2.PublicKey.pbData = bits5;
2531 info2.PublicKey.cUnusedBits = 0;
2532 ret = CertComparePublicKeyInfo(0, &info1, &info2);
2533 ok(!ret, "CertComparePublicKeyInfo: as raw binary: keys should be unequal\n");
2534 ret = CertComparePublicKeyInfo(X509_ASN_ENCODING, &info1, &info2);
2535 ok(ret, "CertComparePublicKeyInfo: as ASN.1 encoded: keys should be equal\n");
2536 info1.PublicKey.cUnusedBits = 1;
2537 info2.PublicKey.cUnusedBits = 5;
2538 ret = CertComparePublicKeyInfo(X509_ASN_ENCODING, &info1, &info2);
2539 ok(ret, "CertComparePublicKeyInfo: ASN.1 encoding should ignore cUnusedBits\n");
2540 info1.PublicKey.cUnusedBits = 0;
2541 info2.PublicKey.cUnusedBits = 0;
2542 info1.PublicKey.cbData--; /* kill one byte, make ASN.1 encoded data invalid */
2543 ret = CertComparePublicKeyInfo(X509_ASN_ENCODING, &info1, &info2);
2544 ok(!ret, "CertComparePublicKeyInfo: comparing bad ASN.1 encoded key should fail\n");
2545 /* Even though they compare in their used bits, these do not compare */
2546 info1.PublicKey.cbData = sizeof(bits2);
2547 info1.PublicKey.pbData = bits2;
2548 info1.PublicKey.cUnusedBits = 0;
2549 info2.PublicKey.cbData = sizeof(bits3);
2550 info2.PublicKey.pbData = bits3;
2551 info2.PublicKey.cUnusedBits = 1;
2552 ret = CertComparePublicKeyInfo(0, &info1, &info2);
2553 /* Simple (non-comparing) case */
2554 ok(!ret, "Expected keys not to compare\n");
2555 info2.PublicKey.cbData = sizeof(bits1);
2556 info2.PublicKey.pbData = bits1;
2557 info2.PublicKey.cUnusedBits = 0;
2558 ret = CertComparePublicKeyInfo(0, &info1, &info2);
2559 ok(!ret, "Expected keys not to compare\n");
2560 /* ASN.1 encoded non-comparing case */
2561 info1.PublicKey.cbData = sizeof(bits5);
2562 info1.PublicKey.pbData = bits5;
2563 info1.PublicKey.cUnusedBits = 0;
2564 info2.PublicKey.cbData = sizeof(bits6);
2565 info2.PublicKey.pbData = bits6;
2566 info2.PublicKey.cUnusedBits = 0;
2567 ret = CertComparePublicKeyInfo(X509_ASN_ENCODING, &info1, &info2);
2568 ok(!ret, "CertComparePublicKeyInfo: different keys should be unequal\n");
2571 static void testHashPublicKeyInfo(void)
2573 BOOL ret;
2574 CERT_PUBLIC_KEY_INFO info = { { 0 } };
2575 DWORD len;
2577 /* Crash
2578 ret = CryptHashPublicKeyInfo(0, 0, 0, 0, NULL, NULL, NULL);
2579 ret = CryptHashPublicKeyInfo(0, 0, 0, 0, &info, NULL, NULL);
2581 ret = CryptHashPublicKeyInfo(0, 0, 0, 0, NULL, NULL, &len);
2582 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2583 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2584 /* Crashes on some win9x boxes */
2585 if (0)
2587 ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, NULL, NULL, &len);
2588 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2589 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
2591 ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, &info, NULL, &len);
2592 ok(ret, "CryptHashPublicKeyInfo failed: %08x\n", GetLastError());
2593 ok(len == 16, "Expected hash size 16, got %d\n", len);
2594 if (len == 16)
2596 static const BYTE emptyHash[] = { 0xb8,0x51,0x3a,0x31,0x0e,0x9f,0x40,
2597 0x36,0x9c,0x92,0x45,0x1b,0x9d,0xc8,0xf9,0xf6 };
2598 BYTE buf[16];
2600 ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, &info, buf,
2601 &len);
2602 ok(ret, "CryptHashPublicKeyInfo failed: %08x\n", GetLastError());
2603 ok(!memcmp(buf, emptyHash, len), "Unexpected hash\n");
2607 static const BYTE md5SignedEmptyCertHash[] = { 0xfb,0x0f,0x66,0x82,0x66,0xd9,
2608 0xe5,0xf8,0xd8,0xa2,0x55,0x2b,0xe1,0xa5,0xd9,0x04 };
2610 static void testHashToBeSigned(void)
2612 BOOL ret;
2613 DWORD size;
2614 BYTE hash[16];
2616 /* Crash */
2617 if (0)
2619 ret = CryptHashToBeSigned(0, 0, NULL, 0, NULL, NULL);
2621 SetLastError(0xdeadbeef);
2622 ret = CryptHashToBeSigned(0, 0, NULL, 0, NULL, &size);
2623 todo_wine
2624 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2625 "expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
2626 SetLastError(0xdeadbeef);
2627 ret = CryptHashToBeSigned(0, X509_ASN_ENCODING, NULL, 0, NULL, &size);
2628 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
2629 "expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
2630 /* Can't sign anything: has to be asn.1 encoded, at least */
2631 SetLastError(0xdeadbeef);
2632 ret = CryptHashToBeSigned(0, X509_ASN_ENCODING, int1, sizeof(int1),
2633 NULL, &size);
2634 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
2635 "expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
2636 /* Can't be empty, either */
2637 SetLastError(0xdeadbeef);
2638 ret = CryptHashToBeSigned(0, X509_ASN_ENCODING, emptyCert,
2639 sizeof(emptyCert), NULL, &size);
2640 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
2641 "expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
2642 /* Signing a cert works */
2643 ret = CryptHashToBeSigned(0, X509_ASN_ENCODING, md5SignedEmptyCert,
2644 sizeof(md5SignedEmptyCert), NULL, &size);
2645 ok(ret, "CryptHashToBeSigned failed: %08x\n", GetLastError());
2646 ok(size == sizeof(md5SignedEmptyCertHash), "unexpected size %d\n", size);
2647 ret = CryptHashToBeSigned(0, X509_ASN_ENCODING, md5SignedEmptyCert,
2648 sizeof(md5SignedEmptyCert), hash, &size);
2649 ok(!memcmp(hash, md5SignedEmptyCertHash, size), "unexpected value\n");
2652 static void testCompareCert(void)
2654 CERT_INFO info1 = { 0 }, info2 = { 0 };
2655 BOOL ret;
2657 /* Crashes
2658 ret = CertCompareCertificate(X509_ASN_ENCODING, NULL, NULL);
2661 /* Certs with the same issuer and serial number are equal, even if they
2662 * differ in other respects (like subject).
2664 info1.SerialNumber.pbData = serialNum;
2665 info1.SerialNumber.cbData = sizeof(serialNum);
2666 info1.Issuer.pbData = subjectName;
2667 info1.Issuer.cbData = sizeof(subjectName);
2668 info1.Subject.pbData = subjectName2;
2669 info1.Subject.cbData = sizeof(subjectName2);
2670 info2.SerialNumber.pbData = serialNum;
2671 info2.SerialNumber.cbData = sizeof(serialNum);
2672 info2.Issuer.pbData = subjectName;
2673 info2.Issuer.cbData = sizeof(subjectName);
2674 info2.Subject.pbData = subjectName;
2675 info2.Subject.cbData = sizeof(subjectName);
2676 ret = CertCompareCertificate(X509_ASN_ENCODING, &info1, &info2);
2677 ok(ret, "Expected certs to be equal\n");
2679 info2.Issuer.pbData = subjectName2;
2680 info2.Issuer.cbData = sizeof(subjectName2);
2681 ret = CertCompareCertificate(X509_ASN_ENCODING, &info1, &info2);
2682 ok(!ret, "Expected certs not to be equal\n");
2685 static void testVerifySubjectCert(void)
2687 BOOL ret;
2688 DWORD flags;
2689 PCCERT_CONTEXT context1, context2;
2691 /* Crashes
2692 ret = CertVerifySubjectCertificateContext(NULL, NULL, NULL);
2694 flags = 0;
2695 ret = CertVerifySubjectCertificateContext(NULL, NULL, &flags);
2696 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
2697 GetLastError());
2698 flags = CERT_STORE_NO_CRL_FLAG;
2699 ret = CertVerifySubjectCertificateContext(NULL, NULL, &flags);
2700 ok(!ret && GetLastError() == E_INVALIDARG,
2701 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2703 flags = 0;
2704 context1 = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
2705 sizeof(bigCert));
2706 ret = CertVerifySubjectCertificateContext(NULL, context1, &flags);
2707 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
2708 GetLastError());
2709 ret = CertVerifySubjectCertificateContext(context1, NULL, &flags);
2710 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
2711 GetLastError());
2712 ret = CertVerifySubjectCertificateContext(context1, context1, &flags);
2713 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
2714 GetLastError());
2716 context2 = CertCreateCertificateContext(X509_ASN_ENCODING,
2717 bigCertWithDifferentSubject, sizeof(bigCertWithDifferentSubject));
2718 SetLastError(0xdeadbeef);
2719 ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
2720 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
2721 GetLastError());
2722 flags = CERT_STORE_REVOCATION_FLAG;
2723 ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
2724 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
2725 GetLastError());
2726 ok(flags == (CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG),
2727 "Expected CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG, got %08x\n",
2728 flags);
2729 flags = CERT_STORE_SIGNATURE_FLAG;
2730 ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
2731 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
2732 GetLastError());
2733 ok(flags == CERT_STORE_SIGNATURE_FLAG,
2734 "Expected CERT_STORE_SIGNATURE_FLAG, got %08x\n", flags);
2735 CertFreeCertificateContext(context2);
2737 CertFreeCertificateContext(context1);
2740 static void testVerifyRevocation(void)
2742 BOOL ret;
2743 CERT_REVOCATION_STATUS status = { 0 };
2744 PCCERT_CONTEXT cert = CertCreateCertificateContext(X509_ASN_ENCODING,
2745 bigCert, sizeof(bigCert));
2747 /* Crash
2748 ret = CertVerifyRevocation(0, 0, 0, NULL, 0, NULL, NULL);
2750 SetLastError(0xdeadbeef);
2751 ret = CertVerifyRevocation(0, 0, 0, NULL, 0, NULL, &status);
2752 ok(!ret && GetLastError() == E_INVALIDARG,
2753 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2754 status.cbSize = sizeof(status);
2755 ret = CertVerifyRevocation(0, 0, 0, NULL, 0, NULL, &status);
2756 ok(ret, "CertVerifyRevocation failed: %08x\n", GetLastError());
2757 ret = CertVerifyRevocation(0, 2, 0, NULL, 0, NULL, &status);
2758 ok(ret, "CertVerifyRevocation failed: %08x\n", GetLastError());
2759 ret = CertVerifyRevocation(2, 0, 0, NULL, 0, NULL, &status);
2760 ok(ret, "CertVerifyRevocation failed: %08x\n", GetLastError());
2761 SetLastError(0xdeadbeef);
2762 ret = CertVerifyRevocation(0, 0, 1, (void **)&cert, 0, NULL, &status);
2763 ok(!ret && GetLastError() == CRYPT_E_NO_REVOCATION_DLL,
2764 "Expected CRYPT_E_NO_REVOCATION_DLL, got %08x\n", GetLastError());
2765 SetLastError(0xdeadbeef);
2766 ret = CertVerifyRevocation(0, 2, 1, (void **)&cert, 0, NULL, &status);
2767 ok(!ret && GetLastError() == CRYPT_E_NO_REVOCATION_DLL,
2768 "Expected CRYPT_E_NO_REVOCATION_DLL, got %08x\n", GetLastError());
2770 CertFreeCertificateContext(cert);
2773 static BYTE privKey[] = {
2774 0x07, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x52, 0x53, 0x41, 0x32, 0x00,
2775 0x02, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x79, 0x10, 0x1c, 0xd0, 0x6b, 0x10,
2776 0x18, 0x30, 0x94, 0x61, 0xdc, 0x0e, 0xcb, 0x96, 0x4e, 0x21, 0x3f, 0x79, 0xcd,
2777 0xa9, 0x17, 0x62, 0xbc, 0xbb, 0x61, 0x4c, 0xe0, 0x75, 0x38, 0x6c, 0xf3, 0xde,
2778 0x60, 0x86, 0x03, 0x97, 0x65, 0xeb, 0x1e, 0x6b, 0xdb, 0x53, 0x85, 0xad, 0x68,
2779 0x21, 0xf1, 0x5d, 0xe7, 0x1f, 0xe6, 0x53, 0xb4, 0xbb, 0x59, 0x3e, 0x14, 0x27,
2780 0xb1, 0x83, 0xa7, 0x3a, 0x54, 0xe2, 0x8f, 0x65, 0x8e, 0x6a, 0x4a, 0xcf, 0x3b,
2781 0x1f, 0x65, 0xff, 0xfe, 0xf1, 0x31, 0x3a, 0x37, 0x7a, 0x8b, 0xcb, 0xc6, 0xd4,
2782 0x98, 0x50, 0x36, 0x67, 0xe4, 0xa1, 0xe8, 0x7e, 0x8a, 0xc5, 0x23, 0xf2, 0x77,
2783 0xf5, 0x37, 0x61, 0x49, 0x72, 0x59, 0xe8, 0x3d, 0xf7, 0x60, 0xb2, 0x77, 0xca,
2784 0x78, 0x54, 0x6d, 0x65, 0x9e, 0x03, 0x97, 0x1b, 0x61, 0xbd, 0x0c, 0xd8, 0x06,
2785 0x63, 0xe2, 0xc5, 0x48, 0xef, 0xb3, 0xe2, 0x6e, 0x98, 0x7d, 0xbd, 0x4e, 0x72,
2786 0x91, 0xdb, 0x31, 0x57, 0xe3, 0x65, 0x3a, 0x49, 0xca, 0xec, 0xd2, 0x02, 0x4e,
2787 0x22, 0x7e, 0x72, 0x8e, 0xf9, 0x79, 0x84, 0x82, 0xdf, 0x7b, 0x92, 0x2d, 0xaf,
2788 0xc9, 0xe4, 0x33, 0xef, 0x89, 0x5c, 0x66, 0x99, 0xd8, 0x80, 0x81, 0x47, 0x2b,
2789 0xb1, 0x66, 0x02, 0x84, 0x59, 0x7b, 0xc3, 0xbe, 0x98, 0x45, 0x4a, 0x3d, 0xdd,
2790 0xea, 0x2b, 0xdf, 0x4e, 0xb4, 0x24, 0x6b, 0xec, 0xe7, 0xd9, 0x0c, 0x45, 0xb8,
2791 0xbe, 0xca, 0x69, 0x37, 0x92, 0x4c, 0x38, 0x6b, 0x96, 0x6d, 0xcd, 0x86, 0x67,
2792 0x5c, 0xea, 0x54, 0x94, 0xa4, 0xca, 0xa4, 0x02, 0xa5, 0x21, 0x4d, 0xae, 0x40,
2793 0x8f, 0x9d, 0x51, 0x83, 0xf2, 0x3f, 0x33, 0xc1, 0x72, 0xb4, 0x1d, 0x94, 0x6e,
2794 0x7d, 0xe4, 0x27, 0x3f, 0xea, 0xff, 0xe5, 0x9b, 0xa7, 0x5e, 0x55, 0x8e, 0x0d,
2795 0x69, 0x1c, 0x7a, 0xff, 0x81, 0x9d, 0x53, 0x52, 0x97, 0x9a, 0x76, 0x79, 0xda,
2796 0x93, 0x32, 0x16, 0xec, 0x69, 0x51, 0x1a, 0x4e, 0xc3, 0xf1, 0x72, 0x80, 0x78,
2797 0x5e, 0x66, 0x4a, 0x8d, 0x85, 0x2f, 0x3f, 0xb2, 0xa7 };
2799 static const BYTE exportedPublicKeyBlob[] = {
2800 0x06,0x02,0x00,0x00,0x00,0xa4,0x00,0x00,0x52,0x53,0x41,0x31,0x00,0x02,0x00,0x00,
2801 0x01,0x00,0x01,0x00,0x79,0x10,0x1c,0xd0,0x6b,0x10,0x18,0x30,0x94,0x61,0xdc,0x0e,
2802 0xcb,0x96,0x4e,0x21,0x3f,0x79,0xcd,0xa9,0x17,0x62,0xbc,0xbb,0x61,0x4c,0xe0,0x75,
2803 0x38,0x6c,0xf3,0xde,0x60,0x86,0x03,0x97,0x65,0xeb,0x1e,0x6b,0xdb,0x53,0x85,0xad,
2804 0x68,0x21,0xf1,0x5d,0xe7,0x1f,0xe6,0x53,0xb4,0xbb,0x59,0x3e,0x14,0x27,0xb1,0x83,
2805 0xa7,0x3a,0x54,0xe2 };
2807 static const BYTE asnEncodedPublicKey[] = {
2808 0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7,0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,
2809 0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21,0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,
2810 0x65,0x97,0x03,0x86,0x60,0xde,0xf3,0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,
2811 0x17,0xa9,0xcd,0x79,0x3f,0x21,0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,
2812 0x6b,0xd0,0x1c,0x10,0x79,0x02,0x03,0x01,0x00,0x01 };
2814 static void testAcquireCertPrivateKey(void)
2816 BOOL ret;
2817 PCCERT_CONTEXT cert;
2818 HCRYPTPROV csp;
2819 DWORD size, keySpec;
2820 BOOL callerFree;
2821 CRYPT_KEY_PROV_INFO keyProvInfo;
2822 HCRYPTKEY key;
2823 WCHAR ms_def_prov_w[MAX_PATH];
2825 if (!pCryptAcquireCertificatePrivateKey)
2827 skip("CryptAcquireCertificatePrivateKey() is not available\n");
2828 return;
2831 lstrcpyW(ms_def_prov_w, MS_DEF_PROV_W);
2833 keyProvInfo.pwszContainerName = cspNameW;
2834 keyProvInfo.pwszProvName = ms_def_prov_w;
2835 keyProvInfo.dwProvType = PROV_RSA_FULL;
2836 keyProvInfo.dwFlags = 0;
2837 keyProvInfo.cProvParam = 0;
2838 keyProvInfo.rgProvParam = NULL;
2839 keyProvInfo.dwKeySpec = AT_SIGNATURE;
2841 pCryptAcquireContextA(NULL, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
2842 CRYPT_DELETEKEYSET);
2844 cert = CertCreateCertificateContext(X509_ASN_ENCODING, selfSignedCert,
2845 sizeof(selfSignedCert));
2847 /* Crash
2848 ret = pCryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, NULL, NULL);
2849 ret = pCryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, NULL,
2850 &callerFree);
2851 ret = pCryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, &keySpec,
2852 NULL);
2853 ret = pCryptAcquireCertificatePrivateKey(NULL, 0, NULL, &csp, NULL, NULL);
2854 ret = pCryptAcquireCertificatePrivateKey(NULL, 0, NULL, &csp, &keySpec,
2855 &callerFree);
2856 ret = pCryptAcquireCertificatePrivateKey(cert, 0, NULL, NULL, NULL, NULL);
2859 /* Missing private key */
2860 ret = pCryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, NULL, NULL);
2861 ok(!ret && GetLastError() == CRYPT_E_NO_KEY_PROPERTY,
2862 "Expected CRYPT_E_NO_KEY_PROPERTY, got %08x\n", GetLastError());
2863 ret = pCryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, &keySpec,
2864 &callerFree);
2865 ok(!ret && GetLastError() == CRYPT_E_NO_KEY_PROPERTY,
2866 "Expected CRYPT_E_NO_KEY_PROPERTY, got %08x\n", GetLastError());
2867 CertSetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, 0,
2868 &keyProvInfo);
2869 ret = pCryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, &keySpec,
2870 &callerFree);
2871 ok(!ret && GetLastError() == CRYPT_E_NO_KEY_PROPERTY,
2872 "Expected CRYPT_E_NO_KEY_PROPERTY, got %08x\n", GetLastError());
2874 pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
2875 CRYPT_NEWKEYSET);
2876 ret = CryptImportKey(csp, privKey, sizeof(privKey), 0, 0, &key);
2877 ok(ret, "CryptImportKey failed: %08x\n", GetLastError());
2878 if (ret)
2880 HCRYPTPROV certCSP;
2881 DWORD size;
2882 CERT_KEY_CONTEXT keyContext;
2884 /* Don't cache provider */
2885 ret = pCryptAcquireCertificatePrivateKey(cert, 0, NULL, &certCSP,
2886 &keySpec, &callerFree);
2887 ok(ret, "CryptAcquireCertificatePrivateKey failed: %08x\n",
2888 GetLastError());
2889 ok(callerFree, "Expected callerFree to be TRUE\n");
2890 CryptReleaseContext(certCSP, 0);
2891 ret = pCryptAcquireCertificatePrivateKey(cert, 0, NULL, &certCSP,
2892 NULL, NULL);
2893 ok(ret, "CryptAcquireCertificatePrivateKey failed: %08x\n",
2894 GetLastError());
2895 CryptReleaseContext(certCSP, 0);
2897 /* Use the key prov info's caching (there shouldn't be any) */
2898 ret = pCryptAcquireCertificatePrivateKey(cert,
2899 CRYPT_ACQUIRE_USE_PROV_INFO_FLAG, NULL, &certCSP, &keySpec,
2900 &callerFree);
2901 ok(ret, "CryptAcquireCertificatePrivateKey failed: %08x\n",
2902 GetLastError());
2903 ok(callerFree, "Expected callerFree to be TRUE\n");
2904 CryptReleaseContext(certCSP, 0);
2906 /* Cache it (and check that it's cached) */
2907 ret = pCryptAcquireCertificatePrivateKey(cert,
2908 CRYPT_ACQUIRE_CACHE_FLAG, NULL, &certCSP, &keySpec, &callerFree);
2909 ok(ret, "CryptAcquireCertificatePrivateKey failed: %08x\n",
2910 GetLastError());
2911 ok(!callerFree, "Expected callerFree to be FALSE\n");
2912 size = sizeof(keyContext);
2913 ret = CertGetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID,
2914 &keyContext, &size);
2915 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
2916 GetLastError());
2918 /* Remove the cached provider */
2919 CryptReleaseContext(keyContext.hCryptProv, 0);
2920 CertSetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID, 0,
2921 NULL);
2922 /* Allow caching via the key prov info */
2923 keyProvInfo.dwFlags = CERT_SET_KEY_CONTEXT_PROP_ID;
2924 CertSetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, 0,
2925 &keyProvInfo);
2926 /* Now use the key prov info's caching */
2927 ret = pCryptAcquireCertificatePrivateKey(cert,
2928 CRYPT_ACQUIRE_USE_PROV_INFO_FLAG, NULL, &certCSP, &keySpec,
2929 &callerFree);
2930 ok(ret, "CryptAcquireCertificatePrivateKey failed: %08x\n",
2931 GetLastError());
2932 ok(!callerFree, "Expected callerFree to be FALSE\n");
2933 size = sizeof(keyContext);
2934 ret = CertGetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID,
2935 &keyContext, &size);
2936 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
2937 GetLastError());
2938 CryptReleaseContext(certCSP, 0);
2940 CryptDestroyKey(key);
2943 /* Some sanity-checking on public key exporting */
2944 ret = CryptImportPublicKeyInfo(csp, X509_ASN_ENCODING,
2945 &cert->pCertInfo->SubjectPublicKeyInfo, &key);
2946 ok(ret, "CryptImportPublicKeyInfo failed: %08x\n", GetLastError());
2947 if (ret)
2949 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &size);
2950 ok(ret, "CryptExportKey failed: %08x\n", GetLastError());
2951 if (ret)
2953 LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, size), encodedKey;
2955 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, buf, &size);
2956 ok(ret, "CryptExportKey failed: %08x\n", GetLastError());
2957 ok(size == sizeof(exportedPublicKeyBlob), "Unexpected size %d\n",
2958 size);
2959 ok(!memcmp(buf, exportedPublicKeyBlob, size), "Unexpected value\n");
2960 ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, RSA_CSP_PUBLICKEYBLOB,
2961 buf, CRYPT_ENCODE_ALLOC_FLAG, NULL, &encodedKey, &size);
2962 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2963 if (ret)
2965 ok(size == sizeof(asnEncodedPublicKey), "Unexpected size %d\n",
2966 size);
2967 ok(!memcmp(encodedKey, asnEncodedPublicKey, size),
2968 "Unexpected value\n");
2969 LocalFree(encodedKey);
2971 HeapFree(GetProcessHeap(), 0, buf);
2973 CryptDestroyKey(key);
2975 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
2976 NULL, 0, NULL, NULL, &size);
2977 ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
2978 if (ret)
2980 PCERT_PUBLIC_KEY_INFO info = HeapAlloc(GetProcessHeap(), 0, size);
2982 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
2983 NULL, 0, NULL, info, &size);
2984 ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
2985 if (ret)
2987 ok(info->PublicKey.cbData == sizeof(asnEncodedPublicKey),
2988 "Unexpected size %d\n", info->PublicKey.cbData);
2989 ok(!memcmp(info->PublicKey.pbData, asnEncodedPublicKey,
2990 info->PublicKey.cbData), "Unexpected value\n");
2992 HeapFree(GetProcessHeap(), 0, info);
2995 CryptReleaseContext(csp, 0);
2996 pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
2997 CRYPT_DELETEKEYSET);
2999 CertFreeCertificateContext(cert);
3002 static void testGetPublicKeyLength(void)
3004 static char oid_rsa_rsa[] = szOID_RSA_RSA;
3005 static char oid_rsa_dh[] = szOID_RSA_DH;
3006 static char bogusOID[] = "1.2.3";
3007 DWORD ret;
3008 CERT_PUBLIC_KEY_INFO info = { { 0 } };
3009 BYTE bogusKey[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
3010 BYTE key[] = { 0x30,0x0f,0x02,0x08,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
3011 0x02,0x03,0x01,0x00,0x01 };
3013 /* Crashes
3014 ret = CertGetPublicKeyLength(0, NULL);
3016 /* With an empty public key info */
3017 SetLastError(0xdeadbeef);
3018 ret = CertGetPublicKeyLength(0, &info);
3019 ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
3020 "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
3021 ret, GetLastError());
3022 SetLastError(0xdeadbeef);
3023 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
3024 ok(ret == 0 && GetLastError() == CRYPT_E_ASN1_EOD,
3025 "Expected length 0 and CRYPT_E_ASN1_EOD, got length %d, %08x\n",
3026 ret, GetLastError());
3027 /* With a nearly-empty public key info */
3028 info.Algorithm.pszObjId = oid_rsa_rsa;
3029 SetLastError(0xdeadbeef);
3030 ret = CertGetPublicKeyLength(0, &info);
3031 ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
3032 "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
3033 ret, GetLastError());
3034 SetLastError(0xdeadbeef);
3035 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
3036 ok(ret == 0 && GetLastError() == CRYPT_E_ASN1_EOD,
3037 "Expected length 0 and CRYPT_E_ASN1_EOD, got length %d, %08x\n",
3038 ret, GetLastError());
3039 /* With a bogus key */
3040 info.PublicKey.cbData = sizeof(bogusKey);
3041 info.PublicKey.pbData = bogusKey;
3042 SetLastError(0xdeadbeef);
3043 ret = CertGetPublicKeyLength(0, &info);
3044 ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
3045 "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
3046 ret, GetLastError());
3047 SetLastError(0xdeadbeef);
3048 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
3049 ok(ret == 0 && GetLastError() == CRYPT_E_ASN1_BADTAG,
3050 "Expected length 0 and CRYPT_E_ASN1_BADTAGTAG, got length %d, %08x\n",
3051 ret, GetLastError());
3052 /* With a believable RSA key but a bogus OID */
3053 info.Algorithm.pszObjId = bogusOID;
3054 info.PublicKey.cbData = sizeof(key);
3055 info.PublicKey.pbData = key;
3056 SetLastError(0xdeadbeef);
3057 ret = CertGetPublicKeyLength(0, &info);
3058 ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
3059 "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
3060 ret, GetLastError());
3061 SetLastError(0xdeadbeef);
3062 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
3063 ok(ret == 56, "Expected length 56, got %d\n", ret);
3064 /* An RSA key with the DH OID */
3065 info.Algorithm.pszObjId = oid_rsa_dh;
3066 SetLastError(0xdeadbeef);
3067 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
3068 ok(ret == 0 && GetLastError() == CRYPT_E_ASN1_BADTAG,
3069 "Expected length 0 and CRYPT_E_ASN1_BADTAG, got length %d, %08x\n",
3070 ret, GetLastError());
3071 /* With the RSA OID */
3072 info.Algorithm.pszObjId = oid_rsa_rsa;
3073 SetLastError(0xdeadbeef);
3074 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
3075 ok(ret == 56, "Expected length 56, got %d\n", ret);
3076 /* With the RSA OID and a message encoding */
3077 info.Algorithm.pszObjId = oid_rsa_rsa;
3078 SetLastError(0xdeadbeef);
3079 ret = CertGetPublicKeyLength(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, &info);
3080 ok(ret == 56, "Expected length 56, got %d\n", ret);
3083 START_TEST(cert)
3085 init_function_pointers();
3087 testAddCert();
3088 testCertProperties();
3089 testDupCert();
3090 testFindCert();
3091 testGetSubjectCert();
3092 testGetIssuerCert();
3094 testCryptHashCert();
3095 testCertSigs();
3096 testSignAndEncodeCert();
3097 testCreateSelfSignCert();
3098 testKeyUsage();
3099 testGetValidUsages();
3100 testCompareCertName();
3101 testCompareIntegerBlob();
3102 testComparePublicKeyInfo();
3103 testHashPublicKeyInfo();
3104 testHashToBeSigned();
3105 testCompareCert();
3106 testVerifySubjectCert();
3107 testVerifyRevocation();
3108 testAcquireCertPrivateKey();
3109 testGetPublicKeyLength();