push 30c3afdf8e27eb453070f5cf144ec76e9777c0a8
[wine/hacks.git] / dlls / crypt32 / tests / cert.c
blob2027c4aa2b11dfcff5f91c08f68d62a9b7f2e406
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 GetLastError() == OSS_DATA_ERROR), /* win9x */
518 "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
520 /* Test key contexts and handles and such */
521 size = 0;
522 ret = CertGetCertificateContextProperty(context, CERT_KEY_CONTEXT_PROP_ID,
523 NULL, &size);
524 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
525 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
526 size = sizeof(CERT_KEY_CONTEXT);
527 ret = CertGetCertificateContextProperty(context, CERT_KEY_CONTEXT_PROP_ID,
528 NULL, &size);
529 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
530 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
531 ret = CertGetCertificateContextProperty(context, CERT_KEY_CONTEXT_PROP_ID,
532 &keyContext, &size);
533 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
534 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
535 /* Key context with an invalid size */
536 keyContext.cbSize = 0;
537 ret = CertSetCertificateContextProperty(context, CERT_KEY_CONTEXT_PROP_ID,
538 0, &keyContext);
539 ok(!ret && GetLastError() == E_INVALIDARG,
540 "Expected E_INVALIDARG, got %08x\n", GetLastError());
541 size = sizeof(keyContext);
542 ret = CertGetCertificateContextProperty(context, CERT_KEY_CONTEXT_PROP_ID,
543 &keyContext, &size);
544 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
545 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
546 keyContext.cbSize = sizeof(keyContext);
547 keyContext.hCryptProv = 0;
548 keyContext.dwKeySpec = AT_SIGNATURE;
549 ret = CertSetCertificateContextProperty(context, CERT_KEY_CONTEXT_PROP_ID,
550 0, &keyContext);
551 ok(ret, "CertSetCertificateContextProperty failed: %08x\n", GetLastError());
552 /* Now that that's set, the key prov handle property is also gettable.
554 size = sizeof(DWORD);
555 ret = CertGetCertificateContextProperty(context,
556 CERT_KEY_PROV_HANDLE_PROP_ID, &keyContext.hCryptProv, &size);
557 ok(ret, "Expected to get the CERT_KEY_PROV_HANDLE_PROP_ID, got %08x\n",
558 GetLastError());
559 /* Remove the key prov handle property.. */
560 ret = CertSetCertificateContextProperty(context,
561 CERT_KEY_PROV_HANDLE_PROP_ID, 0, NULL);
562 ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
563 GetLastError());
564 /* and the key context's CSP is set to NULL. */
565 size = sizeof(keyContext);
566 ret = CertGetCertificateContextProperty(context,
567 CERT_KEY_CONTEXT_PROP_ID, &keyContext, &size);
568 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
569 GetLastError());
570 ok(keyContext.hCryptProv == 0, "Expected no hCryptProv\n");
572 /* According to MSDN the subject key id can be stored as a property,
573 * as a subject key extension, or as the SHA1 hash of the public key,
574 * but this cert has none of them:
576 ret = CertGetCertificateContextProperty(context,
577 CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size);
578 ok(!ret && GetLastError() == ERROR_INVALID_DATA,
579 "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
580 CertFreeCertificateContext(context);
581 /* This cert does have a public key, but its subject key identifier still
582 * isn't available: */
583 context = CertCreateCertificateContext(X509_ASN_ENCODING,
584 v1CertWithPubKey, sizeof(v1CertWithPubKey));
585 ret = CertGetCertificateContextProperty(context,
586 CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size);
587 ok(!ret && GetLastError() == ERROR_INVALID_DATA,
588 "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
589 CertFreeCertificateContext(context);
590 /* This cert with a subject key extension can have its key identifier
591 * property retrieved:
593 context = CertCreateCertificateContext(X509_ASN_ENCODING,
594 v1CertWithSubjectKeyId, sizeof(v1CertWithSubjectKeyId));
595 ret = CertGetCertificateContextProperty(context,
596 CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size);
597 ok(ret, "CertGetCertificateContextProperty failed: %08x\n", GetLastError());
598 if (ret)
600 LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, size);
602 if (buf)
604 ret = CertGetCertificateContextProperty(context,
605 CERT_KEY_IDENTIFIER_PROP_ID, buf, &size);
606 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
607 GetLastError());
608 ok(!memcmp(buf, subjectKeyId, size), "Unexpected subject key id\n");
609 HeapFree(GetProcessHeap(), 0, buf);
612 CertFreeCertificateContext(context);
614 context = CertCreateCertificateContext(X509_ASN_ENCODING,
615 selfSignedCert, sizeof(selfSignedCert));
616 /* Getting the signature hash of a valid (self-signed) cert succeeds */
617 size = 0;
618 ret = CertGetCertificateContextProperty(context,
619 CERT_SIGNATURE_HASH_PROP_ID, NULL, &size);
620 ok(ret, "CertGetCertificateContextProperty failed: %08x\n", GetLastError());
621 ok(size == sizeof(selfSignedSignatureHash), "unexpected size %d\n", size);
622 ret = CertGetCertificateContextProperty(context,
623 CERT_SIGNATURE_HASH_PROP_ID, hashProperty, &size);
624 if (ret)
625 ok(!memcmp(hashProperty, selfSignedSignatureHash, size),
626 "unexpected value\n");
627 CertFreeCertificateContext(context);
630 static void testDupCert(void)
632 HCERTSTORE store;
633 PCCERT_CONTEXT context, dupContext;
634 BOOL ret;
636 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
637 CERT_STORE_CREATE_NEW_FLAG, NULL);
638 ok(store != NULL, "CertOpenStore failed: %d\n", GetLastError());
639 if (!store)
640 return;
642 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
643 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
644 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
645 GetLastError());
646 ok(context != NULL, "Expected a valid cert context\n");
647 if (context)
649 ok(context->cbCertEncoded == sizeof(bigCert),
650 "Wrong cert size %d\n", context->cbCertEncoded);
651 ok(!memcmp(context->pbCertEncoded, bigCert, sizeof(bigCert)),
652 "Unexpected encoded cert in context\n");
653 ok(context->hCertStore == store, "Unexpected store\n");
655 dupContext = CertDuplicateCertificateContext(context);
656 ok(dupContext != NULL, "Expected valid duplicate\n");
657 /* Not only is it a duplicate, it's identical: the address is the
658 * same.
660 ok(dupContext == context, "Expected identical context addresses\n");
661 CertFreeCertificateContext(dupContext);
662 CertFreeCertificateContext(context);
664 CertCloseStore(store, 0);
667 static BYTE subjectName3[] = { 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
668 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x52, 0x6f, 0x62, 0x20, 0x20, 0x4c, 0x61,
669 0x6e, 0x67, 0x00 };
670 static const BYTE iTunesCert0[] = {
671 0x30,0x82,0x03,0xc4,0x30,0x82,0x03,0x2d,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,
672 0x47,0xbf,0x19,0x95,0xdf,0x8d,0x52,0x46,0x43,0xf7,0xdb,0x6d,0x48,0x0d,0x31,
673 0xa4,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,
674 0x00,0x30,0x81,0x8b,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,
675 0x5a,0x41,0x31,0x15,0x30,0x13,0x06,0x03,0x55,0x04,0x08,0x13,0x0c,0x57,0x65,
676 0x73,0x74,0x65,0x72,0x6e,0x20,0x43,0x61,0x70,0x65,0x31,0x14,0x30,0x12,0x06,
677 0x03,0x55,0x04,0x07,0x13,0x0b,0x44,0x75,0x72,0x62,0x61,0x6e,0x76,0x69,0x6c,
678 0x6c,0x65,0x31,0x0f,0x30,0x0d,0x06,0x03,0x55,0x04,0x0a,0x13,0x06,0x54,0x68,
679 0x61,0x77,0x74,0x65,0x31,0x1d,0x30,0x1b,0x06,0x03,0x55,0x04,0x0b,0x13,0x14,
680 0x54,0x68,0x61,0x77,0x74,0x65,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,
681 0x61,0x74,0x69,0x6f,0x6e,0x31,0x1f,0x30,0x1d,0x06,0x03,0x55,0x04,0x03,0x13,
682 0x16,0x54,0x68,0x61,0x77,0x74,0x65,0x20,0x54,0x69,0x6d,0x65,0x73,0x74,0x61,
683 0x6d,0x70,0x69,0x6e,0x67,0x20,0x43,0x41,0x30,0x1e,0x17,0x0d,0x30,0x33,0x31,
684 0x32,0x30,0x34,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,0x31,0x33,0x31,
685 0x32,0x30,0x33,0x32,0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x53,0x31,0x0b,0x30,
686 0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x17,0x30,0x15,0x06,
687 0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x2c,
688 0x20,0x49,0x6e,0x63,0x2e,0x31,0x2b,0x30,0x29,0x06,0x03,0x55,0x04,0x03,0x13,
689 0x22,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x54,0x69,0x6d,0x65,0x20,
690 0x53,0x74,0x61,0x6d,0x70,0x69,0x6e,0x67,0x20,0x53,0x65,0x72,0x76,0x69,0x63,
691 0x65,0x73,0x20,0x43,0x41,0x30,0x82,0x01,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,
692 0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0f,0x00,0x30,
693 0x82,0x01,0x0a,0x02,0x82,0x01,0x01,0x00,0xa9,0xca,0xb2,0xa4,0xcc,0xcd,0x20,
694 0xaf,0x0a,0x7d,0x89,0xac,0x87,0x75,0xf0,0xb4,0x4e,0xf1,0xdf,0xc1,0x0f,0xbf,
695 0x67,0x61,0xbd,0xa3,0x64,0x1c,0xda,0xbb,0xf9,0xca,0x33,0xab,0x84,0x30,0x89,
696 0x58,0x7e,0x8c,0xdb,0x6b,0xdd,0x36,0x9e,0x0f,0xbf,0xd1,0xec,0x78,0xf2,0x77,
697 0xa6,0x7e,0x6f,0x3c,0xbf,0x93,0xaf,0x0d,0xba,0x68,0xf4,0x6c,0x94,0xca,0xbd,
698 0x52,0x2d,0xab,0x48,0x3d,0xf5,0xb6,0xd5,0x5d,0x5f,0x1b,0x02,0x9f,0xfa,0x2f,
699 0x6b,0x1e,0xa4,0xf7,0xa3,0x9a,0xa6,0x1a,0xc8,0x02,0xe1,0x7f,0x4c,0x52,0xe3,
700 0x0e,0x60,0xec,0x40,0x1c,0x7e,0xb9,0x0d,0xde,0x3f,0xc7,0xb4,0xdf,0x87,0xbd,
701 0x5f,0x7a,0x6a,0x31,0x2e,0x03,0x99,0x81,0x13,0xa8,0x47,0x20,0xce,0x31,0x73,
702 0x0d,0x57,0x2d,0xcd,0x78,0x34,0x33,0x95,0x12,0x99,0x12,0xb9,0xde,0x68,0x2f,
703 0xaa,0xe6,0xe3,0xc2,0x8a,0x8c,0x2a,0xc3,0x8b,0x21,0x87,0x66,0xbd,0x83,0x58,
704 0x57,0x6f,0x75,0xbf,0x3c,0xaa,0x26,0x87,0x5d,0xca,0x10,0x15,0x3c,0x9f,0x84,
705 0xea,0x54,0xc1,0x0a,0x6e,0xc4,0xfe,0xc5,0x4a,0xdd,0xb9,0x07,0x11,0x97,0x22,
706 0x7c,0xdb,0x3e,0x27,0xd1,0x1e,0x78,0xec,0x9f,0x31,0xc9,0xf1,0xe6,0x22,0x19,
707 0xdb,0xc4,0xb3,0x47,0x43,0x9a,0x1a,0x5f,0xa0,0x1e,0x90,0xe4,0x5e,0xf5,0xee,
708 0x7c,0xf1,0x7d,0xab,0x62,0x01,0x8f,0xf5,0x4d,0x0b,0xde,0xd0,0x22,0x56,0xa8,
709 0x95,0xcd,0xae,0x88,0x76,0xae,0xee,0xba,0x0d,0xf3,0xe4,0x4d,0xd9,0xa0,0xfb,
710 0x68,0xa0,0xae,0x14,0x3b,0xb3,0x87,0xc1,0xbb,0x02,0x03,0x01,0x00,0x01,0xa3,
711 0x81,0xdb,0x30,0x81,0xd8,0x30,0x34,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,
712 0x01,0x01,0x04,0x28,0x30,0x26,0x30,0x24,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,
713 0x07,0x30,0x01,0x86,0x18,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6f,0x63,0x73,
714 0x70,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x30,
715 0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,
716 0xff,0x02,0x01,0x00,0x30,0x41,0x06,0x03,0x55,0x1d,0x1f,0x04,0x3a,0x30,0x38,
717 0x30,0x36,0xa0,0x34,0xa0,0x32,0x86,0x30,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
718 0x63,0x72,0x6c,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,
719 0x6d,0x2f,0x54,0x68,0x61,0x77,0x74,0x65,0x54,0x69,0x6d,0x65,0x73,0x74,0x61,
720 0x6d,0x70,0x69,0x6e,0x67,0x43,0x41,0x2e,0x63,0x72,0x6c,0x30,0x13,0x06,0x03,
721 0x55,0x1d,0x25,0x04,0x0c,0x30,0x0a,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,
722 0x03,0x08,0x30,0x0e,0x06,0x03,0x55,0x1d,0x0f,0x01,0x01,0xff,0x04,0x04,0x03,
723 0x02,0x01,0x06,0x30,0x24,0x06,0x03,0x55,0x1d,0x11,0x04,0x1d,0x30,0x1b,0xa4,
724 0x19,0x30,0x17,0x31,0x15,0x30,0x13,0x06,0x03,0x55,0x04,0x03,0x13,0x0c,0x54,
725 0x53,0x41,0x32,0x30,0x34,0x38,0x2d,0x31,0x2d,0x35,0x33,0x30,0x0d,0x06,0x09,
726 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x03,0x81,0x81,0x00,
727 0x4a,0x6b,0xf9,0xea,0x58,0xc2,0x44,0x1c,0x31,0x89,0x79,0x99,0x2b,0x96,0xbf,
728 0x82,0xac,0x01,0xd6,0x1c,0x4c,0xcd,0xb0,0x8a,0x58,0x6e,0xdf,0x08,0x29,0xa3,
729 0x5e,0xc8,0xca,0x93,0x13,0xe7,0x04,0x52,0x0d,0xef,0x47,0x27,0x2f,0x00,0x38,
730 0xb0,0xe4,0xc9,0x93,0x4e,0x9a,0xd4,0x22,0x62,0x15,0xf7,0x3f,0x37,0x21,0x4f,
731 0x70,0x31,0x80,0xf1,0x8b,0x38,0x87,0xb3,0xe8,0xe8,0x97,0x00,0xfe,0xcf,0x55,
732 0x96,0x4e,0x24,0xd2,0xa9,0x27,0x4e,0x7a,0xae,0xb7,0x61,0x41,0xf3,0x2a,0xce,
733 0xe7,0xc9,0xd9,0x5e,0xdd,0xbb,0x2b,0x85,0x3e,0xb5,0x9d,0xb5,0xd9,0xe1,0x57,
734 0xff,0xbe,0xb4,0xc5,0x7e,0xf5,0xcf,0x0c,0x9e,0xf0,0x97,0xfe,0x2b,0xd3,0x3b,
735 0x52,0x1b,0x1b,0x38,0x27,0xf7,0x3f,0x4a };
736 static const BYTE iTunesCert1[] = {
737 0x30,0x82,0x03,0xff,0x30,0x82,0x02,0xe7,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,
738 0x0d,0xe9,0x2b,0xf0,0xd4,0xd8,0x29,0x88,0x18,0x32,0x05,0x09,0x5e,0x9a,0x76,
739 0x88,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,
740 0x00,0x30,0x53,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,
741 0x53,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,
742 0x69,0x53,0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x2b,0x30,0x29,
743 0x06,0x03,0x55,0x04,0x03,0x13,0x22,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,
744 0x20,0x54,0x69,0x6d,0x65,0x20,0x53,0x74,0x61,0x6d,0x70,0x69,0x6e,0x67,0x20,
745 0x53,0x65,0x72,0x76,0x69,0x63,0x65,0x73,0x20,0x43,0x41,0x30,0x1e,0x17,0x0d,
746 0x30,0x33,0x31,0x32,0x30,0x34,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,
747 0x30,0x38,0x31,0x32,0x30,0x33,0x32,0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x57,
748 0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x17,
749 0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,0x69,
750 0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x2f,0x30,0x2d,0x06,0x03,0x55,
751 0x04,0x03,0x13,0x26,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x54,0x69,
752 0x6d,0x65,0x20,0x53,0x74,0x61,0x6d,0x70,0x69,0x6e,0x67,0x20,0x53,0x65,0x72,
753 0x76,0x69,0x63,0x65,0x73,0x20,0x53,0x69,0x67,0x6e,0x65,0x72,0x30,0x82,0x01,
754 0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,
755 0x00,0x03,0x82,0x01,0x0f,0x00,0x30,0x82,0x01,0x0a,0x02,0x82,0x01,0x01,0x00,
756 0xb2,0x50,0x28,0x48,0xdd,0xd3,0x68,0x7a,0x84,0x18,0x44,0x66,0x75,0x5d,0x7e,
757 0xc4,0xb8,0x9f,0x63,0x26,0xff,0x3d,0x43,0x9c,0x7c,0x11,0x38,0x10,0x25,0x55,
758 0x73,0xd9,0x75,0x27,0x69,0xfd,0x4e,0xb9,0x20,0x5c,0xd3,0x0a,0xf9,0xa0,0x1b,
759 0x2a,0xed,0x55,0x56,0x21,0x61,0xd8,0x1e,0xdb,0xe4,0xbc,0x33,0x6b,0xc7,0xef,
760 0xdd,0xa3,0x37,0x65,0x8e,0x1b,0x93,0x0c,0xb6,0x53,0x1e,0x5c,0x7c,0x66,0x35,
761 0x5f,0x05,0x8a,0x45,0xfe,0x76,0x4e,0xdf,0x53,0x80,0xa2,0x81,0x20,0x9d,0xae,
762 0x88,0x5c,0xa2,0x08,0xf7,0xe5,0x30,0xf9,0xee,0x22,0x37,0x4c,0x42,0x0a,0xce,
763 0xdf,0xc6,0x1f,0xc4,0xd6,0x55,0xe9,0x81,0x3f,0xb5,0x52,0xa3,0x2c,0xaa,0x01,
764 0x7a,0xf2,0xa2,0xaa,0x8d,0x35,0xfe,0x9f,0xe6,0x5d,0x6a,0x05,0x9f,0x3d,0x6b,
765 0xe3,0xbf,0x96,0xc0,0xfe,0xcc,0x60,0xf9,0x40,0xe7,0x07,0xa0,0x44,0xeb,0x81,
766 0x51,0x6e,0xa5,0x2a,0xf2,0xb6,0x8a,0x10,0x28,0xed,0x8f,0xdc,0x06,0xa0,0x86,
767 0x50,0x9a,0x7b,0x4a,0x08,0x0d,0x30,0x1d,0xca,0x10,0x9e,0x6b,0xf7,0xe9,0x58,
768 0xae,0x04,0xa9,0x40,0x99,0xb2,0x28,0xe8,0x8f,0x16,0xac,0x3c,0xe3,0x53,0x6f,
769 0x4b,0xd3,0x35,0x9d,0xb5,0x6f,0x64,0x1d,0xb3,0x96,0x2c,0xbb,0x3d,0xe7,0x79,
770 0xeb,0x6d,0x7a,0xf9,0x16,0xe6,0x26,0xad,0xaf,0xef,0x99,0x53,0xb7,0x40,0x2c,
771 0x95,0xb8,0x79,0xaa,0xfe,0xd4,0x52,0xab,0x29,0x74,0x7e,0x42,0xec,0x39,0x1e,
772 0xa2,0x6a,0x16,0xe6,0x59,0xbb,0x24,0x68,0xd8,0x00,0x80,0x43,0x10,0x87,0x80,
773 0x6b,0x02,0x03,0x01,0x00,0x01,0xa3,0x81,0xca,0x30,0x81,0xc7,0x30,0x34,0x06,
774 0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x28,0x30,0x26,0x30,0x24,
775 0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x18,0x68,0x74,0x74,
776 0x70,0x3a,0x2f,0x2f,0x6f,0x63,0x73,0x70,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,
777 0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x30,0x0c,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
778 0xff,0x04,0x02,0x30,0x00,0x30,0x33,0x06,0x03,0x55,0x1d,0x1f,0x04,0x2c,0x30,
779 0x2a,0x30,0x28,0xa0,0x26,0xa0,0x24,0x86,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,
780 0x2f,0x63,0x72,0x6c,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,
781 0x6f,0x6d,0x2f,0x74,0x73,0x73,0x2d,0x63,0x61,0x2e,0x63,0x72,0x6c,0x30,0x16,
782 0x06,0x03,0x55,0x1d,0x25,0x01,0x01,0xff,0x04,0x0c,0x30,0x0a,0x06,0x08,0x2b,
783 0x06,0x01,0x05,0x05,0x07,0x03,0x08,0x30,0x0e,0x06,0x03,0x55,0x1d,0x0f,0x01,
784 0x01,0xff,0x04,0x04,0x03,0x02,0x06,0xc0,0x30,0x24,0x06,0x03,0x55,0x1d,0x11,
785 0x04,0x1d,0x30,0x1b,0xa4,0x19,0x30,0x17,0x31,0x15,0x30,0x13,0x06,0x03,0x55,
786 0x04,0x03,0x13,0x0c,0x54,0x53,0x41,0x32,0x30,0x34,0x38,0x2d,0x31,0x2d,0x35,
787 0x34,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,
788 0x00,0x03,0x82,0x01,0x01,0x00,0x87,0x78,0x70,0xda,0x4e,0x52,0x01,0x20,0x5b,
789 0xe0,0x79,0xc9,0x82,0x30,0xc4,0xfd,0xb9,0x19,0x96,0xbd,0x91,0x00,0xc3,0xbd,
790 0xcd,0xcd,0xc6,0xf4,0x0e,0xd8,0xff,0xf9,0x4d,0xc0,0x33,0x62,0x30,0x11,0xc5,
791 0xf5,0x74,0x1b,0xd4,0x92,0xde,0x5f,0x9c,0x20,0x13,0xb1,0x7c,0x45,0xbe,0x50,
792 0xcd,0x83,0xe7,0x80,0x17,0x83,0xa7,0x27,0x93,0x67,0x13,0x46,0xfb,0xca,0xb8,
793 0x98,0x41,0x03,0xcc,0x9b,0x51,0x5b,0x05,0x8b,0x7f,0xa8,0x6f,0xf3,0x1b,0x50,
794 0x1b,0x24,0x2e,0xf2,0x69,0x8d,0x6c,0x22,0xf7,0xbb,0xca,0x16,0x95,0xed,0x0c,
795 0x74,0xc0,0x68,0x77,0xd9,0xeb,0x99,0x62,0x87,0xc1,0x73,0x90,0xf8,0x89,0x74,
796 0x7a,0x23,0xab,0xa3,0x98,0x7b,0x97,0xb1,0xf7,0x8f,0x29,0x71,0x4d,0x2e,0x75,
797 0x1b,0x48,0x41,0xda,0xf0,0xb5,0x0d,0x20,0x54,0xd6,0x77,0xa0,0x97,0x82,0x63,
798 0x69,0xfd,0x09,0xcf,0x8a,0xf0,0x75,0xbb,0x09,0x9b,0xd9,0xf9,0x11,0x55,0x26,
799 0x9a,0x61,0x32,0xbe,0x7a,0x02,0xb0,0x7b,0x86,0xbe,0xa2,0xc3,0x8b,0x22,0x2c,
800 0x78,0xd1,0x35,0x76,0xbc,0x92,0x73,0x5c,0xf9,0xb9,0xe6,0x4c,0x15,0x0a,0x23,
801 0xcc,0xe4,0xd2,0xd4,0x34,0x2e,0x49,0x40,0x15,0x3c,0x0f,0x60,0x7a,0x24,0xc6,
802 0xa5,0x66,0xef,0x96,0xcf,0x70,0xeb,0x3e,0xe7,0xf4,0x0d,0x7e,0xdc,0xd1,0x7c,
803 0xa3,0x76,0x71,0x69,0xc1,0x9c,0x4f,0x47,0x30,0x35,0x21,0xb1,0xa2,0xaf,0x1a,
804 0x62,0x3c,0x2b,0xd9,0x8e,0xaa,0x2a,0x07,0x7b,0xd8,0x18,0xb3,0x5c,0x7b,0xe2,
805 0x9d,0xa5,0x6f,0xfe,0x3c,0x89,0xad };
806 static const BYTE iTunesCert2[] = {
807 0x30,0x82,0x04,0xbf,0x30,0x82,0x04,0x28,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,
808 0x41,0x91,0xa1,0x5a,0x39,0x78,0xdf,0xcf,0x49,0x65,0x66,0x38,0x1d,0x4c,0x75,
809 0xc2,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,
810 0x00,0x30,0x5f,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,
811 0x53,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,
812 0x69,0x53,0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x37,0x30,0x35,
813 0x06,0x03,0x55,0x04,0x0b,0x13,0x2e,0x43,0x6c,0x61,0x73,0x73,0x20,0x33,0x20,
814 0x50,0x75,0x62,0x6c,0x69,0x63,0x20,0x50,0x72,0x69,0x6d,0x61,0x72,0x79,0x20,
815 0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x41,
816 0x75,0x74,0x68,0x6f,0x72,0x69,0x74,0x79,0x30,0x1e,0x17,0x0d,0x30,0x34,0x30,
817 0x37,0x31,0x36,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,0x31,0x34,0x30,
818 0x37,0x31,0x35,0x32,0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x81,0xb4,0x31,0x0b,
819 0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x17,0x30,0x15,
820 0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,
821 0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x1f,0x30,0x1d,0x06,0x03,0x55,0x04,0x0b,
822 0x13,0x16,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x54,0x72,0x75,0x73,
823 0x74,0x20,0x4e,0x65,0x74,0x77,0x6f,0x72,0x6b,0x31,0x3b,0x30,0x39,0x06,0x03,
824 0x55,0x04,0x0b,0x13,0x32,0x54,0x65,0x72,0x6d,0x73,0x20,0x6f,0x66,0x20,0x75,
825 0x73,0x65,0x20,0x61,0x74,0x20,0x68,0x74,0x74,0x70,0x73,0x3a,0x2f,0x2f,0x77,
826 0x77,0x77,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,
827 0x2f,0x72,0x70,0x61,0x20,0x28,0x63,0x29,0x30,0x34,0x31,0x2e,0x30,0x2c,0x06,
828 0x03,0x55,0x04,0x03,0x13,0x25,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,
829 0x43,0x6c,0x61,0x73,0x73,0x20,0x33,0x20,0x43,0x6f,0x64,0x65,0x20,0x53,0x69,
830 0x67,0x6e,0x69,0x6e,0x67,0x20,0x32,0x30,0x30,0x34,0x20,0x43,0x41,0x30,0x82,
831 0x01,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,
832 0x05,0x00,0x03,0x82,0x01,0x0f,0x00,0x30,0x82,0x01,0x0a,0x02,0x82,0x01,0x01,
833 0x00,0xbe,0xbc,0xee,0xbc,0x7e,0xef,0x83,0xeb,0xe0,0x37,0x4f,0xfb,0x03,0x10,
834 0x38,0xbe,0x08,0xd2,0x8c,0x7d,0x9d,0xfa,0x92,0x7f,0x19,0x0c,0xc2,0x6b,0xee,
835 0x42,0x52,0x8c,0xde,0xd3,0x1c,0x48,0x13,0x25,0xea,0xc1,0x63,0x7a,0xf9,0x51,
836 0x65,0xee,0xd3,0xaa,0x3b,0xf5,0xf0,0x94,0x9c,0x2b,0xfb,0xf2,0x66,0xd4,0x24,
837 0xda,0xf7,0xf5,0x9f,0x6e,0x19,0x39,0x36,0xbc,0xd0,0xa3,0x76,0x08,0x1e,0x22,
838 0x27,0x24,0x6c,0x38,0x91,0x27,0xe2,0x84,0x49,0xae,0x1b,0x8a,0xa1,0xfd,0x25,
839 0x82,0x2c,0x10,0x30,0xe8,0x71,0xab,0x28,0xe8,0x77,0x4a,0x51,0xf1,0xec,0xcd,
840 0xf8,0xf0,0x54,0xd4,0x6f,0xc0,0xe3,0x6d,0x0a,0x8f,0xd9,0xd8,0x64,0x8d,0x63,
841 0xb2,0x2d,0x4e,0x27,0xf6,0x85,0x0e,0xfe,0x6d,0xe3,0x29,0x99,0xe2,0x85,0x47,
842 0x7c,0x2d,0x86,0x7f,0xe8,0x57,0x8f,0xad,0x67,0xc2,0x33,0x32,0x91,0x13,0x20,
843 0xfc,0xa9,0x23,0x14,0x9a,0x6d,0xc2,0x84,0x4b,0x76,0x68,0x04,0xd5,0x71,0x2c,
844 0x5d,0x21,0xfa,0x88,0x0d,0x26,0xfd,0x1f,0x2d,0x91,0x2b,0xe7,0x01,0x55,0x4d,
845 0xf2,0x6d,0x35,0x28,0x82,0xdf,0xd9,0x6b,0x5c,0xb6,0xd6,0xd9,0xaa,0x81,0xfd,
846 0x5f,0xcd,0x83,0xba,0x63,0x9d,0xd0,0x22,0xfc,0xa9,0x3b,0x42,0x69,0xb2,0x8e,
847 0x3a,0xb5,0xbc,0xb4,0x9e,0x0f,0x5e,0xc4,0xea,0x2c,0x82,0x8b,0x28,0xfd,0x53,
848 0x08,0x96,0xdd,0xb5,0x01,0x20,0xd1,0xf9,0xa5,0x18,0xe7,0xc0,0xee,0x51,0x70,
849 0x37,0xe1,0xb6,0x05,0x48,0x52,0x48,0x6f,0x38,0xea,0xc3,0xe8,0x6c,0x7b,0x44,
850 0x84,0xbb,0x02,0x03,0x01,0x00,0x01,0xa3,0x82,0x01,0xa0,0x30,0x82,0x01,0x9c,
851 0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,
852 0x01,0xff,0x02,0x01,0x00,0x30,0x44,0x06,0x03,0x55,0x1d,0x20,0x04,0x3d,0x30,
853 0x3b,0x30,0x39,0x06,0x0b,0x60,0x86,0x48,0x01,0x86,0xf8,0x45,0x01,0x07,0x17,
854 0x03,0x30,0x2a,0x30,0x28,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x02,0x01,
855 0x16,0x1c,0x68,0x74,0x74,0x70,0x73,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x76,
856 0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x2f,0x72,0x70,0x61,
857 0x30,0x31,0x06,0x03,0x55,0x1d,0x1f,0x04,0x2a,0x30,0x28,0x30,0x26,0xa0,0x24,
858 0xa0,0x22,0x86,0x20,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x63,0x72,0x6c,0x2e,
859 0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x2f,0x70,0x63,
860 0x61,0x33,0x2e,0x63,0x72,0x6c,0x30,0x1d,0x06,0x03,0x55,0x1d,0x25,0x04,0x16,
861 0x30,0x14,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x03,0x02,0x06,0x08,0x2b,
862 0x06,0x01,0x05,0x05,0x07,0x03,0x03,0x30,0x0e,0x06,0x03,0x55,0x1d,0x0f,0x01,
863 0x01,0xff,0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x11,0x06,0x09,0x60,0x86,0x48,
864 0x01,0x86,0xf8,0x42,0x01,0x01,0x04,0x04,0x03,0x02,0x00,0x01,0x30,0x29,0x06,
865 0x03,0x55,0x1d,0x11,0x04,0x22,0x30,0x20,0xa4,0x1e,0x30,0x1c,0x31,0x1a,0x30,
866 0x18,0x06,0x03,0x55,0x04,0x03,0x13,0x11,0x43,0x6c,0x61,0x73,0x73,0x33,0x43,
867 0x41,0x32,0x30,0x34,0x38,0x2d,0x31,0x2d,0x34,0x33,0x30,0x1d,0x06,0x03,0x55,
868 0x1d,0x0e,0x04,0x16,0x04,0x14,0x08,0xf5,0x51,0xe8,0xfb,0xfe,0x3d,0x3d,0x64,
869 0x36,0x7c,0x68,0xcf,0x5b,0x78,0xa8,0xdf,0xb9,0xc5,0x37,0x30,0x81,0x80,0x06,
870 0x03,0x55,0x1d,0x23,0x04,0x79,0x30,0x77,0xa1,0x63,0xa4,0x61,0x30,0x5f,0x31,
871 0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x17,0x30,
872 0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,0x69,0x67,
873 0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x37,0x30,0x35,0x06,0x03,0x55,0x04,
874 0x0b,0x13,0x2e,0x43,0x6c,0x61,0x73,0x73,0x20,0x33,0x20,0x50,0x75,0x62,0x6c,
875 0x69,0x63,0x20,0x50,0x72,0x69,0x6d,0x61,0x72,0x79,0x20,0x43,0x65,0x72,0x74,
876 0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x41,0x75,0x74,0x68,0x6f,
877 0x72,0x69,0x74,0x79,0x82,0x10,0x70,0xba,0xe4,0x1d,0x10,0xd9,0x29,0x34,0xb6,
878 0x38,0xca,0x7b,0x03,0xcc,0xba,0xbf,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,
879 0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x03,0x81,0x81,0x00,0xae,0x3a,0x17,0xb8,
880 0x4a,0x7b,0x55,0xfa,0x64,0x55,0xec,0x40,0xa4,0xed,0x49,0x41,0x90,0x99,0x9c,
881 0x89,0xbc,0xaf,0x2e,0x1d,0xca,0x78,0x23,0xf9,0x1c,0x19,0x0f,0x7f,0xeb,0x68,
882 0xbc,0x32,0xd9,0x88,0x38,0xde,0xdc,0x3f,0xd3,0x89,0xb4,0x3f,0xb1,0x82,0x96,
883 0xf1,0xa4,0x5a,0xba,0xed,0x2e,0x26,0xd3,0xde,0x7c,0x01,0x6e,0x00,0x0a,0x00,
884 0xa4,0x06,0x92,0x11,0x48,0x09,0x40,0xf9,0x1c,0x18,0x79,0x67,0x23,0x24,0xe0,
885 0xbb,0xd5,0xe1,0x50,0xae,0x1b,0xf5,0x0e,0xdd,0xe0,0x2e,0x81,0xcd,0x80,0xa3,
886 0x6c,0x52,0x4f,0x91,0x75,0x55,0x8a,0xba,0x22,0xf2,0xd2,0xea,0x41,0x75,0x88,
887 0x2f,0x63,0x55,0x7d,0x1e,0x54,0x5a,0x95,0x59,0xca,0xd9,0x34,0x81,0xc0,0x5f,
888 0x5e,0xf6,0x7a,0xb5 };
889 static const BYTE iTunesCert3[] = {
890 0x30,0x82,0x04,0xf1,0x30,0x82,0x03,0xd9,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,
891 0x0f,0x1a,0xa0,0xe0,0x9b,0x9b,0x61,0xa6,0xb6,0xfe,0x40,0xd2,0xdf,0x6a,0xf6,
892 0x8d,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,
893 0x00,0x30,0x81,0xb4,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,
894 0x55,0x53,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,
895 0x72,0x69,0x53,0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x1f,0x30,
896 0x1d,0x06,0x03,0x55,0x04,0x0b,0x13,0x16,0x56,0x65,0x72,0x69,0x53,0x69,0x67,
897 0x6e,0x20,0x54,0x72,0x75,0x73,0x74,0x20,0x4e,0x65,0x74,0x77,0x6f,0x72,0x6b,
898 0x31,0x3b,0x30,0x39,0x06,0x03,0x55,0x04,0x0b,0x13,0x32,0x54,0x65,0x72,0x6d,
899 0x73,0x20,0x6f,0x66,0x20,0x75,0x73,0x65,0x20,0x61,0x74,0x20,0x68,0x74,0x74,
900 0x70,0x73,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,
901 0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x2f,0x72,0x70,0x61,0x20,0x28,0x63,0x29,0x30,
902 0x34,0x31,0x2e,0x30,0x2c,0x06,0x03,0x55,0x04,0x03,0x13,0x25,0x56,0x65,0x72,
903 0x69,0x53,0x69,0x67,0x6e,0x20,0x43,0x6c,0x61,0x73,0x73,0x20,0x33,0x20,0x43,
904 0x6f,0x64,0x65,0x20,0x53,0x69,0x67,0x6e,0x69,0x6e,0x67,0x20,0x32,0x30,0x30,
905 0x34,0x20,0x43,0x41,0x30,0x1e,0x17,0x0d,0x30,0x36,0x30,0x31,0x31,0x37,0x30,
906 0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,0x30,0x38,0x30,0x31,0x32,0x32,0x32,
907 0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x81,0xb4,0x31,0x0b,0x30,0x09,0x06,0x03,
908 0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,
909 0x08,0x13,0x0a,0x43,0x61,0x6c,0x69,0x66,0x6f,0x72,0x6e,0x69,0x61,0x31,0x12,
910 0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x13,0x09,0x43,0x75,0x70,0x65,0x72,0x74,
911 0x69,0x6e,0x6f,0x31,0x1d,0x30,0x1b,0x06,0x03,0x55,0x04,0x0a,0x14,0x14,0x41,
912 0x70,0x70,0x6c,0x65,0x20,0x43,0x6f,0x6d,0x70,0x75,0x74,0x65,0x72,0x2c,0x20,
913 0x49,0x6e,0x63,0x2e,0x31,0x3e,0x30,0x3c,0x06,0x03,0x55,0x04,0x0b,0x13,0x35,
914 0x44,0x69,0x67,0x69,0x74,0x61,0x6c,0x20,0x49,0x44,0x20,0x43,0x6c,0x61,0x73,
915 0x73,0x20,0x33,0x20,0x2d,0x20,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,
916 0x20,0x53,0x6f,0x66,0x74,0x77,0x61,0x72,0x65,0x20,0x56,0x61,0x6c,0x69,0x64,
917 0x61,0x74,0x69,0x6f,0x6e,0x20,0x76,0x32,0x31,0x1d,0x30,0x1b,0x06,0x03,0x55,
918 0x04,0x03,0x14,0x14,0x41,0x70,0x70,0x6c,0x65,0x20,0x43,0x6f,0x6d,0x70,0x75,
919 0x74,0x65,0x72,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x30,0x81,0x9f,0x30,0x0d,0x06,
920 0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x81,0x8d,
921 0x00,0x30,0x81,0x89,0x02,0x81,0x81,0x00,0xd3,0xab,0x3b,0x7f,0xec,0x48,0x84,
922 0xce,0xa8,0x1a,0x12,0xf3,0x3c,0x87,0xcb,0x24,0x58,0x96,0x02,0x87,0x66,0x49,
923 0xeb,0x89,0xee,0x79,0x44,0x70,0x8d,0xe7,0xd4,0x1f,0x30,0x92,0xc0,0x9c,0x35,
924 0x78,0xc0,0xaf,0x1c,0xb6,0x28,0xd3,0xe0,0xe0,0x9d,0xd3,0x49,0x76,0x73,0x57,
925 0x19,0x4d,0x8d,0x70,0x85,0x64,0x4d,0x1d,0xc6,0x02,0x3e,0xe5,0x2c,0x66,0x07,
926 0xd2,0x27,0x4b,0xd6,0xc8,0x3c,0x93,0xb6,0x15,0x0c,0xde,0x5b,0xd7,0x93,0xdd,
927 0xbe,0x85,0x62,0x34,0x17,0x8a,0x05,0x60,0xf0,0x8a,0x1c,0x5a,0x40,0x21,0x8d,
928 0x51,0x6c,0xb0,0x62,0xd8,0xb5,0xd4,0xf9,0xb1,0xd0,0x58,0x7a,0x7a,0x82,0x55,
929 0xb3,0xf9,0x53,0x71,0xde,0xd2,0xc9,0x37,0x8c,0xf6,0x5a,0x1f,0x2d,0xcd,0x7c,
930 0x67,0x02,0x03,0x01,0x00,0x01,0xa3,0x82,0x01,0x7f,0x30,0x82,0x01,0x7b,0x30,
931 0x09,0x06,0x03,0x55,0x1d,0x13,0x04,0x02,0x30,0x00,0x30,0x0e,0x06,0x03,0x55,
932 0x1d,0x0f,0x01,0x01,0xff,0x04,0x04,0x03,0x02,0x07,0x80,0x30,0x40,0x06,0x03,
933 0x55,0x1d,0x1f,0x04,0x39,0x30,0x37,0x30,0x35,0xa0,0x33,0xa0,0x31,0x86,0x2f,
934 0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x43,0x53,0x43,0x33,0x2d,0x32,0x30,0x30,
935 0x34,0x2d,0x63,0x72,0x6c,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,
936 0x63,0x6f,0x6d,0x2f,0x43,0x53,0x43,0x33,0x2d,0x32,0x30,0x30,0x34,0x2e,0x63,
937 0x72,0x6c,0x30,0x44,0x06,0x03,0x55,0x1d,0x20,0x04,0x3d,0x30,0x3b,0x30,0x39,
938 0x06,0x0b,0x60,0x86,0x48,0x01,0x86,0xf8,0x45,0x01,0x07,0x17,0x03,0x30,0x2a,
939 0x30,0x28,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x1c,0x68,
940 0x74,0x74,0x70,0x73,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x76,0x65,0x72,0x69,
941 0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x2f,0x72,0x70,0x61,0x30,0x13,0x06,
942 0x03,0x55,0x1d,0x25,0x04,0x0c,0x30,0x0a,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,
943 0x07,0x03,0x03,0x30,0x75,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x01,0x01,
944 0x04,0x69,0x30,0x67,0x30,0x24,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,
945 0x01,0x86,0x18,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6f,0x63,0x73,0x70,0x2e,
946 0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x30,0x3f,0x06,
947 0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x33,0x68,0x74,0x74,0x70,
948 0x3a,0x2f,0x2f,0x43,0x53,0x43,0x33,0x2d,0x32,0x30,0x30,0x34,0x2d,0x61,0x69,
949 0x61,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x2f,
950 0x43,0x53,0x43,0x33,0x2d,0x32,0x30,0x30,0x34,0x2d,0x61,0x69,0x61,0x2e,0x63,
951 0x65,0x72,0x30,0x1f,0x06,0x03,0x55,0x1d,0x23,0x04,0x18,0x30,0x16,0x80,0x14,
952 0x08,0xf5,0x51,0xe8,0xfb,0xfe,0x3d,0x3d,0x64,0x36,0x7c,0x68,0xcf,0x5b,0x78,
953 0xa8,0xdf,0xb9,0xc5,0x37,0x30,0x11,0x06,0x09,0x60,0x86,0x48,0x01,0x86,0xf8,
954 0x42,0x01,0x01,0x04,0x04,0x03,0x02,0x04,0x10,0x30,0x16,0x06,0x0a,0x2b,0x06,
955 0x01,0x04,0x01,0x82,0x37,0x02,0x01,0x1b,0x04,0x08,0x30,0x06,0x01,0x01,0x00,
956 0x01,0x01,0xff,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,
957 0x05,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x6a,0xa6,0x06,0xd0,0x33,0x18,0x64,
958 0xe2,0x69,0x82,0xee,0x6e,0x36,0x9e,0x9d,0x9a,0x0e,0x18,0xa8,0xac,0x9d,0x10,
959 0xed,0x01,0x3c,0xb9,0x61,0x04,0x62,0xf3,0x85,0x8f,0xcc,0x4f,0x2c,0x66,0x35,
960 0x54,0x25,0x45,0x8d,0x95,0x1c,0xd2,0x33,0xbe,0x2e,0xdd,0x7f,0x74,0xaf,0x03,
961 0x7b,0x86,0x63,0xb0,0xc9,0xe6,0xbd,0xc7,0x8e,0xde,0x03,0x18,0x98,0x82,0xc3,
962 0xbb,0xf8,0x15,0x99,0x1a,0xa9,0xdd,0xb9,0x5d,0xb9,0xbd,0x53,0x95,0x25,0x76,
963 0xfb,0x5c,0x53,0x90,0xea,0x01,0x0a,0xa0,0xb1,0xbf,0x09,0x1b,0x97,0x8f,0x40,
964 0xfa,0x85,0x12,0x74,0x01,0xdb,0xf6,0xdb,0x09,0xd6,0x5f,0x4f,0xd7,0x17,0xb4,
965 0xbf,0x9e,0x2f,0x86,0x52,0x5d,0x70,0x24,0x52,0x32,0x1e,0xa5,0x1d,0x39,0x8b,
966 0x66,0xf6,0xba,0x9b,0x69,0x8e,0x12,0x60,0xdb,0xb6,0xcf,0xe6,0x0d,0xd6,0x1c,
967 0x8f,0xd4,0x5b,0x4b,0x00,0xde,0x21,0x93,0xfb,0x6e,0xc7,0x3d,0xb4,0x66,0x0d,
968 0x29,0x0c,0x4e,0xe9,0x3f,0x94,0xd6,0xd6,0xdc,0xec,0xf8,0x53,0x3b,0x62,0xd5,
969 0x97,0x50,0x53,0x84,0x17,0xfe,0xe2,0xed,0x4c,0x23,0x0a,0x49,0xce,0x5b,0xe9,
970 0x70,0x31,0xc1,0x04,0x02,0x02,0x6c,0xb8,0x52,0xcd,0xc7,0x4e,0x70,0xb4,0x13,
971 0xd7,0xe0,0x92,0xba,0x44,0x1a,0x10,0x4c,0x6e,0x45,0xc6,0x86,0x04,0xc6,0x64,
972 0xd3,0x9c,0x6e,0xc1,0x9c,0xac,0x74,0x3d,0x77,0x06,0x5e,0x28,0x28,0x5c,0xf5,
973 0xe0,0x9c,0x19,0xd8,0xba,0x74,0x81,0x2d,0x67,0x77,0x93,0x8d,0xbf,0xd2,0x52,
974 0x00,0xe6,0xa5,0x38,0x4e,0x2e,0x73,0x66,0x7a };
975 static BYTE iTunesIssuer[] = {
976 0x30,0x81,0xb4,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,
977 0x13,0x02,0x55,0x53,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,
978 0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x2c,
979 0x20,0x49,0x6e,0x63,0x2e,0x31,0x1f,0x30,0x1d,0x06,0x03,0x55,
980 0x04,0x0b,0x13,0x16,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,
981 0x20,0x54,0x72,0x75,0x73,0x74,0x20,0x4e,0x65,0x74,0x77,0x6f,
982 0x72,0x6b,0x31,0x3b,0x30,0x39,0x06,0x03,0x55,0x04,0x0b,0x13,
983 0x32,0x54,0x65,0x72,0x6d,0x73,0x20,0x6f,0x66,0x20,0x75,0x73,
984 0x65,0x20,0x61,0x74,0x20,0x68,0x74,0x74,0x70,0x73,0x3a,0x2f,
985 0x2f,0x77,0x77,0x77,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,
986 0x6e,0x2e,0x63,0x6f,0x6d,0x2f,0x72,0x70,0x61,0x20,0x28,0x63,
987 0x29,0x30,0x34,0x31,0x2e,0x30,0x2c,0x06,0x03,0x55,0x04,0x03,
988 0x13,0x25,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x43,
989 0x6c,0x61,0x73,0x73,0x20,0x33,0x20,0x43,0x6f,0x64,0x65,0x20,
990 0x53,0x69,0x67,0x6e,0x69,0x6e,0x67,0x20,0x32,0x30,0x30,0x34,
991 0x20,0x43,0x41 };
992 static BYTE iTunesSerialNum[] = {
993 0x8d,0xf6,0x6a,0xdf,0xd2,0x40,0xfe,0xb6,0xa6,0x61,0x9b,0x9b,
994 0xe0,0xa0,0x1a,0x0f };
996 static void testFindCert(void)
998 HCERTSTORE store;
999 PCCERT_CONTEXT context = NULL, subject;
1000 BOOL ret;
1001 CERT_INFO certInfo = { 0 };
1002 CRYPT_HASH_BLOB blob;
1003 BYTE otherSerialNumber[] = { 2 };
1005 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1006 CERT_STORE_CREATE_NEW_FLAG, NULL);
1007 ok(store != NULL, "CertOpenStore failed: %d\n", GetLastError());
1008 if (!store)
1009 return;
1011 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1012 bigCert, sizeof(bigCert), CERT_STORE_ADD_NEW, NULL);
1013 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1014 GetLastError());
1015 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1016 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, NULL);
1017 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1018 GetLastError());
1019 /* This has the same name as bigCert */
1020 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1021 certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, NULL);
1022 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1023 GetLastError());
1025 /* Crashes
1026 context = CertFindCertificateInStore(NULL, 0, 0, 0, NULL, NULL);
1029 /* Check first cert's there, by issuer */
1030 certInfo.Subject.pbData = subjectName;
1031 certInfo.Subject.cbData = sizeof(subjectName);
1032 certInfo.SerialNumber.pbData = serialNum;
1033 certInfo.SerialNumber.cbData = sizeof(serialNum);
1034 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1035 CERT_FIND_ISSUER_NAME, &certInfo.Subject, NULL);
1036 ok(context != NULL, "CertFindCertificateInStore failed: %08x\n",
1037 GetLastError());
1038 if (context)
1040 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1041 CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
1042 ok(context != NULL, "Expected more than one cert\n");
1043 if (context)
1045 context = CertFindCertificateInStore(store, X509_ASN_ENCODING,
1046 0, CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
1047 ok(context == NULL, "Expected precisely two certs\n");
1051 /* Check second cert's there as well, by subject name */
1052 certInfo.Subject.pbData = subjectName2;
1053 certInfo.Subject.cbData = sizeof(subjectName2);
1054 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1055 CERT_FIND_SUBJECT_NAME, &certInfo.Subject, NULL);
1056 ok(context != NULL, "CertFindCertificateInStore failed: %08x\n",
1057 GetLastError());
1058 if (context)
1060 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1061 CERT_FIND_SUBJECT_NAME, &certInfo.Subject, context);
1062 ok(context == NULL, "Expected one cert only\n");
1065 /* Strange but true: searching for the subject cert requires you to set
1066 * the issuer, not the subject
1068 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1069 CERT_FIND_SUBJECT_CERT, &certInfo.Subject, NULL);
1070 ok(context == NULL, "Expected no certificate\n");
1071 certInfo.Subject.pbData = NULL;
1072 certInfo.Subject.cbData = 0;
1073 certInfo.Issuer.pbData = subjectName2;
1074 certInfo.Issuer.cbData = sizeof(subjectName2);
1075 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1076 CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
1077 ok(context != NULL, "CertFindCertificateInStore failed: %08x\n",
1078 GetLastError());
1079 if (context)
1081 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1082 CERT_FIND_SUBJECT_CERT, &certInfo.Subject, context);
1083 ok(context == NULL, "Expected one cert only\n");
1085 /* A non-matching serial number will not match. */
1086 certInfo.SerialNumber.pbData = otherSerialNumber;
1087 certInfo.SerialNumber.cbData = sizeof(otherSerialNumber);
1088 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1089 CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
1090 ok(context == NULL, "Expected no match\n");
1091 /* No serial number will not match */
1092 certInfo.SerialNumber.cbData = 0;
1093 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1094 CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
1095 ok(context == NULL, "Expected no match\n");
1096 /* A serial number still won't match if the name doesn't */
1097 certInfo.SerialNumber.pbData = serialNum;
1098 certInfo.SerialNumber.cbData = sizeof(serialNum);
1099 certInfo.Issuer.pbData = subjectName3;
1100 certInfo.Issuer.cbData = sizeof(subjectName3);
1101 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1102 CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
1103 ok(context == NULL, "Expected no match\n");
1105 /* The nice thing about hashes, they're unique */
1106 blob.pbData = bigCertHash;
1107 blob.cbData = sizeof(bigCertHash);
1108 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1109 CERT_FIND_SHA1_HASH, &blob, NULL);
1110 ok(context != NULL, "CertFindCertificateInStore failed: %08x\n",
1111 GetLastError());
1112 if (context)
1114 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1115 CERT_FIND_SHA1_HASH, &certInfo.Subject, context);
1116 ok(context == NULL, "Expected one cert only\n");
1119 CertCloseStore(store, 0);
1121 /* Another subject cert search, using iTunes's certs */
1122 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1123 CERT_STORE_CREATE_NEW_FLAG, NULL);
1124 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1125 iTunesCert0, sizeof(iTunesCert0), CERT_STORE_ADD_NEW, NULL);
1126 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1127 GetLastError());
1128 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1129 iTunesCert1, sizeof(iTunesCert1), CERT_STORE_ADD_NEW, NULL);
1130 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1131 GetLastError());
1132 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1133 iTunesCert2, sizeof(iTunesCert2), CERT_STORE_ADD_NEW, NULL);
1134 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1135 GetLastError());
1136 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1137 iTunesCert3, sizeof(iTunesCert3), CERT_STORE_ADD_NEW, &subject);
1138 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1139 GetLastError());
1141 /* The certInfo's issuer does not match any subject, but the serial
1142 * number does match a cert whose issuer matches certInfo's issuer.
1143 * This yields a match.
1145 certInfo.SerialNumber.cbData = sizeof(iTunesSerialNum);
1146 certInfo.SerialNumber.pbData = iTunesSerialNum;
1147 certInfo.Issuer.cbData = sizeof(iTunesIssuer);
1148 certInfo.Issuer.pbData = iTunesIssuer;
1149 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1150 CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
1151 ok(context != NULL, "Expected a match\n");
1152 if (context)
1154 ret = CertCompareCertificateName(context->dwCertEncodingType,
1155 &certInfo.Issuer, &context->pCertInfo->Subject);
1156 ok(!ret, "Expected subject name not to match\n");
1157 ret = CertCompareCertificateName(context->dwCertEncodingType,
1158 &certInfo.Issuer, &context->pCertInfo->Issuer);
1159 ok(ret, "Expected issuer name to match\n");
1160 ret = CertCompareIntegerBlob(&certInfo.SerialNumber,
1161 &context->pCertInfo->SerialNumber);
1162 ok(ret, "Expected serial number to match\n");
1163 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1164 CERT_FIND_SUBJECT_CERT, &certInfo, context);
1165 ok(context == NULL, "Expected one cert only\n");
1168 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1169 CERT_FIND_ISSUER_OF, subject, NULL);
1170 ok(context != NULL, "Expected an issuer\n");
1171 if (context)
1173 PCCERT_CONTEXT none = CertFindCertificateInStore(store,
1174 X509_ASN_ENCODING, 0, CERT_FIND_ISSUER_OF, context, NULL);
1176 ok(!none, "Expected no parent of issuer\n");
1177 CertFreeCertificateContext(context);
1179 CertFreeCertificateContext(subject);
1180 CertCloseStore(store, 0);
1183 static void testGetSubjectCert(void)
1185 HCERTSTORE store;
1186 PCCERT_CONTEXT context1, context2;
1187 CERT_INFO info = { 0 };
1188 BOOL ret;
1190 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1191 CERT_STORE_CREATE_NEW_FLAG, NULL);
1192 ok(store != NULL, "CertOpenStore failed: %d\n", GetLastError());
1193 if (!store)
1194 return;
1196 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1197 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
1198 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1199 GetLastError());
1200 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1201 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, &context1);
1202 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1203 GetLastError());
1204 ok(context1 != NULL, "Expected a context\n");
1205 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1206 certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, NULL);
1207 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1208 GetLastError());
1210 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
1211 NULL);
1212 ok(!context2 && GetLastError() == E_INVALIDARG,
1213 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1214 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
1215 &info);
1216 ok(!context2 && GetLastError() == CRYPT_E_NOT_FOUND,
1217 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1218 info.SerialNumber.cbData = sizeof(serialNum);
1219 info.SerialNumber.pbData = serialNum;
1220 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
1221 &info);
1222 ok(!context2 && GetLastError() == CRYPT_E_NOT_FOUND,
1223 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1224 info.Issuer.cbData = sizeof(subjectName2);
1225 info.Issuer.pbData = subjectName2;
1226 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
1227 &info);
1228 ok(context2 != NULL,
1229 "CertGetSubjectCertificateFromStore failed: %08x\n", GetLastError());
1230 /* Not only should this find a context, but it should be the same
1231 * (same address) as context1.
1233 ok(context1 == context2, "Expected identical context addresses\n");
1234 CertFreeCertificateContext(context2);
1236 CertFreeCertificateContext(context1);
1237 CertCloseStore(store, 0);
1240 /* This expires in 1970 or so */
1241 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
1242 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
1243 0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
1244 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
1245 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
1246 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
1247 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
1248 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
1249 0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
1250 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
1251 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
1252 0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
1253 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
1254 0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
1255 0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
1256 0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
1257 0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
1258 0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
1259 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
1260 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
1261 0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
1262 0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
1263 0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
1264 0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
1265 0x49, 0xe5, 0xf9, 0x65, 0xf3 };
1267 /* This expires in 2036 or so */
1268 static const BYTE childOfExpired[] = { 0x30, 0x81, 0xcc, 0x30, 0x78, 0xa0,
1269 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
1270 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d,
1271 0x30, 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63,
1272 0x40, 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e,
1273 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x35, 0x30, 0x35,
1274 0x31, 0x37, 0x31, 0x32, 0x34, 0x39, 0x5a, 0x17, 0x0d, 0x33, 0x36, 0x30, 0x35,
1275 0x30, 0x35, 0x31, 0x37, 0x31, 0x32, 0x34, 0x39, 0x5a, 0x30, 0x15, 0x31, 0x13,
1276 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e,
1277 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03,
1278 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
1279 0x01, 0x05, 0x05, 0x00, 0x03, 0x41, 0x00, 0x20, 0x3b, 0xdb, 0x4d, 0x67, 0x50,
1280 0xec, 0x73, 0x9d, 0xf9, 0x85, 0x5d, 0x18, 0xe9, 0xb4, 0x98, 0xe3, 0x31, 0xb7,
1281 0x03, 0x0b, 0xc0, 0x39, 0x93, 0x56, 0x81, 0x0a, 0xfc, 0x78, 0xa8, 0x29, 0x42,
1282 0x5f, 0x69, 0xfb, 0xbc, 0x5b, 0xf2, 0xa6, 0x2a, 0xbe, 0x91, 0x2c, 0xfc, 0x89,
1283 0x69, 0x15, 0x18, 0x58, 0xe5, 0x02, 0x75, 0xf7, 0x2a, 0xb6, 0xa9, 0xfb, 0x47,
1284 0x6a, 0x6e, 0x0a, 0x9b, 0xe9, 0xdc };
1285 /* chain10_0 -+
1286 * +-> chain7_1
1287 * chain10_1 -+
1288 * A chain with two issuers, only one of whose dates is valid.
1290 static const BYTE chain10_0[] = {
1291 0x30,0x82,0x01,0x9b,0x30,0x82,0x01,0x08,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,
1292 0x4a,0x30,0x3a,0x42,0xa2,0x5a,0xb3,0x93,0x4d,0x94,0x06,0xad,0x6d,0x1c,0x34,
1293 0xe6,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x30,0x10,0x31,
1294 0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x03,0x13,0x05,0x43,0x65,0x72,0x74,0x31,
1295 0x30,0x1e,0x17,0x0d,0x30,0x36,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
1296 0x30,0x5a,0x17,0x0d,0x30,0x36,0x31,0x32,0x33,0x31,0x32,0x33,0x35,0x39,0x35,
1297 0x39,0x5a,0x30,0x10,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x03,0x13,0x05,
1298 0x43,0x65,0x72,0x74,0x31,0x30,0x81,0x9f,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
1299 0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x81,0x8d,0x00,0x30,0x81,0x89,
1300 0x02,0x81,0x81,0x00,0xad,0x7e,0xca,0xf3,0xe5,0x99,0xc2,0x2a,0xca,0x50,0x82,
1301 0x7c,0x2d,0xa4,0x81,0xcd,0x0d,0x0d,0x86,0xd7,0xd8,0xb2,0xde,0xc5,0xc3,0x34,
1302 0x9e,0x07,0x78,0x08,0x11,0x12,0x2d,0x21,0x0a,0x09,0x07,0x14,0x03,0x7a,0xe7,
1303 0x3b,0x58,0xf1,0xde,0x3e,0x01,0x25,0x93,0xab,0x8f,0xce,0x1f,0xc1,0x33,0x91,
1304 0xfe,0x59,0xb9,0x3b,0x9e,0x95,0x12,0x89,0x8e,0xc3,0x4b,0x98,0x1b,0x99,0xc5,
1305 0x07,0xe2,0xdf,0x15,0x4c,0x39,0x76,0x06,0xad,0xdb,0x16,0x06,0x49,0xba,0xcd,
1306 0x0f,0x07,0xd6,0xea,0x27,0xa6,0xfe,0x3d,0x88,0xe5,0x97,0x45,0x72,0xb6,0x1c,
1307 0xc0,0x1c,0xb1,0xa2,0x89,0xe8,0x37,0x9e,0xf6,0x2a,0xcf,0xd5,0x1f,0x2f,0x35,
1308 0x5e,0x8f,0x3a,0x9c,0x61,0xb1,0xf1,0x6c,0xff,0x8c,0xb2,0x2f,0x02,0x03,0x01,
1309 0x00,0x01,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x03,0x81,
1310 0x81,0x00,0x85,0x6e,0x35,0x2f,0x2c,0x51,0x4f,0xd6,0x2a,0xe4,0x9e,0xd0,0x4b,
1311 0xe6,0x90,0xfd,0xf7,0x20,0xad,0x76,0x3f,0x93,0xea,0x7f,0x0d,0x1f,0xb3,0x8e,
1312 0xfd,0xe0,0xe1,0xd6,0xd7,0x9c,0x7d,0x46,0x6b,0x15,0x5c,0xe6,0xc9,0x62,0x3b,
1313 0x70,0x4a,0x4b,0xb2,0x82,0xe3,0x55,0x0c,0xc4,0x90,0x44,0x06,0x6c,0x86,0x1c,
1314 0x6d,0x47,0x12,0xda,0x33,0x95,0x5d,0x98,0x43,0xcb,0x7c,0xfa,0x2b,0xee,0xc4,
1315 0x2d,0xc8,0x95,0x33,0x89,0x08,0x3f,0x9f,0x87,0xea,0x20,0x04,0xaf,0x58,0x4b,
1316 0x9d,0xc0,0x7c,0x0a,0x1b,0x05,0x31,0x3b,0xbb,0x13,0x58,0x2e,0x3f,0x61,0x6b,
1317 0x10,0xb4,0xeb,0xb9,0x1a,0x30,0xfd,0xea,0xca,0x29,0x99,0x5f,0x42,0x2b,0x00,
1318 0xb0,0x08,0xc3,0xf0,0xb6,0xd6,0x6b,0xf9,0x35,0x95 };
1319 static const BYTE chain10_1[] = {
1320 0x30,0x82,0x01,0x9b,0x30,0x82,0x01,0x08,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,
1321 0xbf,0x99,0x4f,0x14,0x03,0x77,0x44,0xb8,0x49,0x02,0x70,0xa1,0xb8,0x9c,0xa7,
1322 0x24,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x30,0x10,0x31,
1323 0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x03,0x13,0x05,0x43,0x65,0x72,0x74,0x31,
1324 0x30,0x1e,0x17,0x0d,0x30,0x37,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
1325 0x30,0x5a,0x17,0x0d,0x30,0x37,0x31,0x32,0x33,0x31,0x32,0x33,0x35,0x39,0x35,
1326 0x39,0x5a,0x30,0x10,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x03,0x13,0x05,
1327 0x43,0x65,0x72,0x74,0x31,0x30,0x81,0x9f,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
1328 0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x81,0x8d,0x00,0x30,0x81,0x89,
1329 0x02,0x81,0x81,0x00,0xad,0x7e,0xca,0xf3,0xe5,0x99,0xc2,0x2a,0xca,0x50,0x82,
1330 0x7c,0x2d,0xa4,0x81,0xcd,0x0d,0x0d,0x86,0xd7,0xd8,0xb2,0xde,0xc5,0xc3,0x34,
1331 0x9e,0x07,0x78,0x08,0x11,0x12,0x2d,0x21,0x0a,0x09,0x07,0x14,0x03,0x7a,0xe7,
1332 0x3b,0x58,0xf1,0xde,0x3e,0x01,0x25,0x93,0xab,0x8f,0xce,0x1f,0xc1,0x33,0x91,
1333 0xfe,0x59,0xb9,0x3b,0x9e,0x95,0x12,0x89,0x8e,0xc3,0x4b,0x98,0x1b,0x99,0xc5,
1334 0x07,0xe2,0xdf,0x15,0x4c,0x39,0x76,0x06,0xad,0xdb,0x16,0x06,0x49,0xba,0xcd,
1335 0x0f,0x07,0xd6,0xea,0x27,0xa6,0xfe,0x3d,0x88,0xe5,0x97,0x45,0x72,0xb6,0x1c,
1336 0xc0,0x1c,0xb1,0xa2,0x89,0xe8,0x37,0x9e,0xf6,0x2a,0xcf,0xd5,0x1f,0x2f,0x35,
1337 0x5e,0x8f,0x3a,0x9c,0x61,0xb1,0xf1,0x6c,0xff,0x8c,0xb2,0x2f,0x02,0x03,0x01,
1338 0x00,0x01,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x03,0x81,
1339 0x81,0x00,0xa8,0xec,0x8c,0x34,0xe7,0x2c,0xdf,0x75,0x87,0xc4,0xf7,0xda,0x71,
1340 0x72,0x29,0xb2,0x48,0xa8,0x2a,0xec,0x7b,0x7d,0x19,0xb9,0x5f,0x1d,0xd9,0x91,
1341 0x2b,0xc4,0x28,0x7e,0xd6,0xb5,0x91,0x69,0xa5,0x8a,0x1a,0x1f,0x97,0x98,0x46,
1342 0x9d,0xdf,0x12,0xf6,0x45,0x62,0xad,0x60,0xb6,0xba,0xb0,0xfd,0xf5,0x9f,0xc6,
1343 0x98,0x05,0x4f,0x4d,0x48,0xdc,0xee,0x69,0xbe,0xb8,0xc4,0xc4,0xd7,0x1b,0xb1,
1344 0x1f,0x64,0xd6,0x45,0xa7,0xdb,0xb3,0x87,0x63,0x0f,0x54,0xe1,0x3a,0x6b,0x57,
1345 0x36,0xd7,0x68,0x65,0xcf,0xda,0x57,0x8d,0xcd,0x84,0x75,0x47,0x26,0x2c,0xef,
1346 0x1e,0x8f,0xc7,0x3b,0xee,0x5d,0x03,0xa6,0xdf,0x3a,0x20,0xb2,0xcc,0xc9,0x09,
1347 0x2c,0xfe,0x2b,0x79,0xb0,0xca,0x2c,0x9a,0x81,0x6b };
1348 static const BYTE chain7_1[] = {
1349 0x30,0x82,0x01,0x93,0x30,0x81,0xfd,0xa0,0x03,0x02,0x01,0x02,0x02,0x01,0x01,
1350 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,
1351 0x30,0x10,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x03,0x13,0x05,0x43,0x65,
1352 0x72,0x74,0x31,0x30,0x1e,0x17,0x0d,0x30,0x37,0x30,0x31,0x30,0x31,0x30,0x30,
1353 0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,0x30,0x37,0x31,0x32,0x33,0x31,0x32,0x33,
1354 0x35,0x39,0x35,0x39,0x5a,0x30,0x10,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,
1355 0x03,0x13,0x05,0x43,0x65,0x72,0x74,0x32,0x30,0x81,0x9f,0x30,0x0d,0x06,0x09,
1356 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x81,0x8d,0x00,
1357 0x30,0x81,0x89,0x02,0x81,0x81,0x00,0xb8,0x52,0xda,0xc5,0x4b,0x3f,0xe5,0x33,
1358 0x0e,0x67,0x5f,0x48,0x21,0xdc,0x7e,0xef,0x37,0x33,0xba,0xff,0xb4,0xc6,0xdc,
1359 0xb6,0x17,0x8e,0x20,0x55,0x07,0x12,0xd2,0x7b,0x3c,0xce,0x30,0xc5,0xa7,0x48,
1360 0x9f,0x6e,0xfe,0xb8,0xbe,0xdb,0x9f,0x9b,0x17,0x60,0x16,0xde,0xc6,0x8b,0x47,
1361 0xd1,0x57,0x71,0x3c,0x93,0xfc,0xbd,0xec,0x44,0x32,0x3b,0xb9,0xcf,0x6b,0x05,
1362 0x72,0xa7,0x87,0x8e,0x7e,0xd4,0x9a,0x87,0x1c,0x2f,0xb7,0x82,0x40,0xfc,0x6a,
1363 0x80,0x83,0x68,0x28,0xce,0x84,0xf4,0x0b,0x2e,0x44,0xcb,0x53,0xac,0x85,0x85,
1364 0xb5,0x46,0x36,0x98,0x3c,0x10,0x02,0xaa,0x02,0xbc,0x8b,0xa2,0x23,0xb2,0xd3,
1365 0x51,0x9a,0x22,0x4a,0xe3,0xaa,0x4e,0x7c,0xda,0x38,0xcf,0x49,0x98,0x72,0xa3,
1366 0x02,0x03,0x01,0x00,0x01,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
1367 0x01,0x01,0x05,0x05,0x00,0x03,0x81,0x81,0x00,0x9f,0x69,0xfd,0x26,0xd5,0x4b,
1368 0xe0,0xab,0x12,0x21,0xb9,0xfc,0xf7,0xe0,0x0c,0x09,0x94,0xad,0x27,0xd7,0x9d,
1369 0xa3,0xcc,0x46,0x2a,0x25,0x9a,0x24,0xa7,0x31,0x58,0x78,0xf5,0xfc,0x30,0xe1,
1370 0x6d,0xfd,0x59,0xab,0xbe,0x69,0xa0,0xea,0xe3,0x7d,0x7a,0x7b,0xe5,0x85,0xeb,
1371 0x86,0x6a,0x84,0x3c,0x96,0x01,0x1a,0x70,0xa7,0xb8,0xcb,0xf2,0x11,0xe7,0x52,
1372 0x9c,0x58,0x2d,0xac,0x63,0xce,0x72,0x4b,0xad,0x62,0xa8,0x1d,0x75,0x96,0xe2,
1373 0x27,0xf5,0x6f,0xba,0x91,0xf8,0xf1,0xb0,0xbf,0x90,0x24,0x6d,0xba,0x5d,0xd7,
1374 0x39,0x63,0x3b,0x7c,0x04,0x5d,0x89,0x9d,0x1c,0xf2,0xf7,0xcc,0xdf,0x6e,0x8a,
1375 0x43,0xa9,0xdd,0x86,0x05,0xa2,0xf3,0x22,0x2d,0x1e,0x70,0xa1,0x59,0xd7,0xa5,
1376 0x94,0x7d };
1378 static void testGetIssuerCert(void)
1380 BOOL ret;
1381 PCCERT_CONTEXT parent, child, cert1, cert2;
1382 DWORD flags = 0xffffffff;
1383 HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1384 CERT_STORE_CREATE_NEW_FLAG, NULL);
1386 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1388 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1389 expiredCert, sizeof(expiredCert), CERT_STORE_ADD_ALWAYS, NULL);
1390 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1391 GetLastError());
1393 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1394 childOfExpired, sizeof(childOfExpired), CERT_STORE_ADD_ALWAYS, &child);
1395 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1396 GetLastError());
1398 /* These crash:
1399 parent = CertGetIssuerCertificateFromStore(NULL, NULL, NULL, NULL);
1400 parent = CertGetIssuerCertificateFromStore(store, NULL, NULL, NULL);
1402 parent = CertGetIssuerCertificateFromStore(NULL, NULL, NULL, &flags);
1403 ok(!parent && GetLastError() == E_INVALIDARG,
1404 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1405 parent = CertGetIssuerCertificateFromStore(store, NULL, NULL, &flags);
1406 ok(!parent && GetLastError() == E_INVALIDARG,
1407 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1408 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1409 ok(!parent && GetLastError() == E_INVALIDARG,
1410 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1411 /* Confusing: the caller cannot set either of the
1412 * CERT_STORE_NO_*_FLAGs, as these are not checks,
1413 * they're results:
1415 flags = CERT_STORE_NO_CRL_FLAG | CERT_STORE_NO_ISSUER_FLAG;
1416 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1417 ok(!parent && GetLastError() == E_INVALIDARG,
1418 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1419 /* Perform no checks */
1420 flags = 0;
1421 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1422 ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08x\n",
1423 GetLastError());
1424 if (parent)
1425 CertFreeCertificateContext(parent);
1426 /* Check revocation and signature only */
1427 flags = CERT_STORE_REVOCATION_FLAG | CERT_STORE_SIGNATURE_FLAG;
1428 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1429 ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08x\n",
1430 GetLastError());
1431 /* Confusing: CERT_STORE_REVOCATION_FLAG succeeds when there is no CRL by
1432 * setting CERT_STORE_NO_CRL_FLAG.
1434 ok(flags == (CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG),
1435 "Expected CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG, got %08x\n",
1436 flags);
1437 if (parent)
1438 CertFreeCertificateContext(parent);
1439 /* Checking time validity is not productive, because while most Windows
1440 * versions return 0 (time valid) because the child is not expired,
1441 * Windows 2003 SP1 returns that it is expired. Thus the range of
1442 * possibilities is covered, and a test verifies nothing.
1445 CertFreeCertificateContext(child);
1446 CertCloseStore(store, 0);
1448 flags = 0;
1449 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1450 CERT_STORE_CREATE_NEW_FLAG, NULL);
1451 /* With only the child certificate, no issuer will be found */
1452 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1453 chain7_1, sizeof(chain7_1), CERT_STORE_ADD_ALWAYS, &child);
1454 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1455 ok(parent == NULL, "Expected no issuer\n");
1456 /* Adding an issuer allows one (and only one) issuer to be found */
1457 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1458 chain10_1, sizeof(chain10_1), CERT_STORE_ADD_ALWAYS, &cert1);
1459 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1460 ok(parent == cert1, "Expected cert1 to be the issuer\n");
1461 parent = CertGetIssuerCertificateFromStore(store, child, parent, &flags);
1462 ok(parent == NULL, "Expected only one issuer\n");
1463 /* Adding a second issuer allows two issuers to be found - and the second
1464 * issuer is found before the first, implying certs are added to the head
1465 * of a list.
1467 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1468 chain10_0, sizeof(chain10_0), CERT_STORE_ADD_ALWAYS, &cert2);
1469 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1470 ok(parent == cert2, "Expected cert2 to be the first issuer\n");
1471 parent = CertGetIssuerCertificateFromStore(store, child, parent, &flags);
1472 ok(parent == cert1, "Expected cert1 to be the second issuer\n");
1473 parent = CertGetIssuerCertificateFromStore(store, child, parent, &flags);
1474 ok(parent == NULL, "Expected no more than two issuers\n");
1475 CertFreeCertificateContext(child);
1476 CertFreeCertificateContext(cert1);
1477 CertFreeCertificateContext(cert2);
1478 CertCloseStore(store, 0);
1480 /* Repeat the test, reversing the order in which issuers are added,
1481 * to show it's order-dependent.
1483 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1484 CERT_STORE_CREATE_NEW_FLAG, NULL);
1485 /* With only the child certificate, no issuer will be found */
1486 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1487 chain7_1, sizeof(chain7_1), CERT_STORE_ADD_ALWAYS, &child);
1488 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1489 ok(parent == NULL, "Expected no issuer\n");
1490 /* Adding an issuer allows one (and only one) issuer to be found */
1491 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1492 chain10_0, sizeof(chain10_0), CERT_STORE_ADD_ALWAYS, &cert1);
1493 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1494 ok(parent == cert1, "Expected cert1 to be the issuer\n");
1495 parent = CertGetIssuerCertificateFromStore(store, child, parent, &flags);
1496 ok(parent == NULL, "Expected only one issuer\n");
1497 /* Adding a second issuer allows two issuers to be found - and the second
1498 * issuer is found before the first, implying certs are added to the head
1499 * of a list.
1501 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1502 chain10_1, sizeof(chain10_1), CERT_STORE_ADD_ALWAYS, &cert2);
1503 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1504 ok(parent == cert2, "Expected cert2 to be the first issuer\n");
1505 parent = CertGetIssuerCertificateFromStore(store, child, parent, &flags);
1506 ok(parent == cert1, "Expected cert1 to be the second issuer\n");
1507 parent = CertGetIssuerCertificateFromStore(store, child, parent, &flags);
1508 ok(parent == NULL, "Expected no more than two issuers\n");
1509 CertFreeCertificateContext(child);
1510 CertFreeCertificateContext(cert1);
1511 CertFreeCertificateContext(cert2);
1512 CertCloseStore(store, 0);
1515 static void testCryptHashCert(void)
1517 static const BYTE emptyHash[] = { 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b,
1518 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07,
1519 0x09 };
1520 static const BYTE knownHash[] = { 0xae, 0x9d, 0xbf, 0x6d, 0xf5, 0x46, 0xee,
1521 0x8b, 0xc5, 0x7a, 0x13, 0xba, 0xc2, 0xb1, 0x04, 0xf2, 0xbf, 0x52, 0xa8,
1522 0xa2 };
1523 static const BYTE toHash[] = "abcdefghijklmnopqrstuvwxyz0123456789.,;!?:";
1524 BOOL ret;
1525 BYTE hash[20];
1526 DWORD hashLen = sizeof(hash);
1528 /* NULL buffer and nonzero length crashes
1529 ret = CryptHashCertificate(0, 0, 0, NULL, size, hash, &hashLen);
1530 empty hash length also crashes
1531 ret = CryptHashCertificate(0, 0, 0, buf, size, hash, NULL);
1533 /* Test empty hash */
1534 ret = CryptHashCertificate(0, 0, 0, toHash, sizeof(toHash), NULL,
1535 &hashLen);
1536 ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
1537 ok(hashLen == sizeof(hash), "Got unexpected size of hash %d\n", hashLen);
1538 /* Test with empty buffer */
1539 ret = CryptHashCertificate(0, 0, 0, NULL, 0, hash, &hashLen);
1540 ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
1541 ok(!memcmp(hash, emptyHash, sizeof(emptyHash)),
1542 "Unexpected hash of nothing\n");
1543 /* Test a known value */
1544 ret = CryptHashCertificate(0, 0, 0, toHash, sizeof(toHash), hash,
1545 &hashLen);
1546 ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
1547 ok(!memcmp(hash, knownHash, sizeof(knownHash)), "Unexpected hash\n");
1550 static void verifySig(HCRYPTPROV csp, const BYTE *toSign, size_t toSignLen,
1551 const BYTE *sig, unsigned int sigLen)
1553 HCRYPTHASH hash;
1554 BOOL ret = CryptCreateHash(csp, CALG_SHA1, 0, 0, &hash);
1556 ok(ret, "CryptCreateHash failed: %08x\n", GetLastError());
1557 if (ret)
1559 BYTE mySig[64];
1560 DWORD mySigSize = sizeof(mySig);
1562 ret = CryptHashData(hash, toSign, toSignLen, 0);
1563 ok(ret, "CryptHashData failed: %08x\n", GetLastError());
1564 /* use the A variant so the test can run on Win9x */
1565 ret = CryptSignHashA(hash, AT_SIGNATURE, NULL, 0, mySig, &mySigSize);
1566 ok(ret, "CryptSignHash failed: %08x\n", GetLastError());
1567 if (ret)
1569 ok(mySigSize == sigLen, "Expected sig length %d, got %d\n",
1570 sigLen, mySigSize);
1571 ok(!memcmp(mySig, sig, sigLen), "Unexpected signature\n");
1573 CryptDestroyHash(hash);
1577 /* Tests signing the certificate described by toBeSigned with the CSP passed in,
1578 * using the algorithm with OID sigOID. The CSP is assumed to be empty, and a
1579 * keyset named AT_SIGNATURE will be added to it. The signing key will be
1580 * stored in *key, and the signature will be stored in sig. sigLen should be
1581 * at least 64 bytes.
1583 static void testSignCert(HCRYPTPROV csp, const CRYPT_DATA_BLOB *toBeSigned,
1584 LPCSTR sigOID, HCRYPTKEY *key, BYTE *sig, DWORD *sigLen)
1586 BOOL ret;
1587 DWORD size = 0;
1588 CRYPT_ALGORITHM_IDENTIFIER algoID = { NULL, { 0, NULL } };
1590 /* These all crash
1591 ret = CryptSignCertificate(0, 0, 0, NULL, 0, NULL, NULL, NULL, NULL);
1592 ret = CryptSignCertificate(0, 0, 0, NULL, 0, NULL, NULL, NULL, &size);
1593 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
1594 NULL, NULL, NULL, &size);
1596 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
1597 &algoID, NULL, NULL, &size);
1598 ok(!ret && GetLastError() == NTE_BAD_ALGID,
1599 "Expected NTE_BAD_ALGID, got %08x\n", GetLastError());
1600 algoID.pszObjId = (LPSTR)sigOID;
1601 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
1602 &algoID, NULL, NULL, &size);
1603 ok(!ret && (GetLastError() == ERROR_INVALID_PARAMETER || NTE_BAD_ALGID),
1604 "Expected ERROR_INVALID_PARAMETER or NTE_BAD_ALGID, got %08x\n",
1605 GetLastError());
1606 ret = CryptSignCertificate(0, AT_SIGNATURE, 0, toBeSigned->pbData,
1607 toBeSigned->cbData, &algoID, NULL, NULL, &size);
1608 ok(!ret && (GetLastError() == ERROR_INVALID_PARAMETER || NTE_BAD_ALGID),
1609 "Expected ERROR_INVALID_PARAMETER or NTE_BAD_ALGID, got %08x\n",
1610 GetLastError());
1612 /* No keys exist in the new CSP yet.. */
1613 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
1614 toBeSigned->cbData, &algoID, NULL, NULL, &size);
1615 ok(!ret && (GetLastError() == NTE_BAD_KEYSET || GetLastError() ==
1616 NTE_NO_KEY), "Expected NTE_BAD_KEYSET or NTE_NO_KEY, got %08x\n",
1617 GetLastError());
1618 ret = CryptGenKey(csp, AT_SIGNATURE, 0, key);
1619 ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
1620 if (ret)
1622 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
1623 toBeSigned->cbData, &algoID, NULL, NULL, &size);
1624 ok(ret, "CryptSignCertificate failed: %08x\n", GetLastError());
1625 ok(size <= *sigLen, "Expected size <= %d, got %d\n", *sigLen, size);
1626 if (ret)
1628 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
1629 toBeSigned->cbData, &algoID, NULL, sig, &size);
1630 ok(ret, "CryptSignCertificate failed: %08x\n", GetLastError());
1631 if (ret)
1633 *sigLen = size;
1634 verifySig(csp, toBeSigned->pbData, toBeSigned->cbData, sig,
1635 size);
1641 static void testVerifyCertSig(HCRYPTPROV csp, const CRYPT_DATA_BLOB *toBeSigned,
1642 LPCSTR sigOID, const BYTE *sig, DWORD sigLen)
1644 CERT_SIGNED_CONTENT_INFO info;
1645 LPBYTE cert = NULL;
1646 DWORD size = 0;
1647 BOOL ret;
1649 if (!pCryptVerifyCertificateSignatureEx)
1651 skip("no CryptVerifyCertificateSignatureEx support\n");
1652 return;
1654 if (!pCryptEncodeObjectEx)
1656 skip("no CryptEncodeObjectEx support\n");
1657 return;
1659 ret = pCryptVerifyCertificateSignatureEx(0, 0, 0, NULL, 0, NULL, 0, NULL);
1660 ok(!ret && GetLastError() == E_INVALIDARG,
1661 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1662 ret = pCryptVerifyCertificateSignatureEx(csp, 0, 0, NULL, 0, NULL, 0, NULL);
1663 ok(!ret && GetLastError() == E_INVALIDARG,
1664 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1665 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING, 0, NULL, 0,
1666 NULL, 0, NULL);
1667 ok(!ret && GetLastError() == E_INVALIDARG,
1668 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1669 /* This crashes
1670 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1671 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, NULL, 0, NULL, 0, NULL);
1673 info.ToBeSigned.cbData = toBeSigned->cbData;
1674 info.ToBeSigned.pbData = toBeSigned->pbData;
1675 info.SignatureAlgorithm.pszObjId = (LPSTR)sigOID;
1676 info.SignatureAlgorithm.Parameters.cbData = 0;
1677 info.Signature.cbData = sigLen;
1678 info.Signature.pbData = (BYTE *)sig;
1679 info.Signature.cUnusedBits = 0;
1680 ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, X509_CERT, &info,
1681 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&cert, &size);
1682 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1683 if (cert)
1685 CRYPT_DATA_BLOB certBlob = { 0, NULL };
1686 PCERT_PUBLIC_KEY_INFO pubKeyInfo = NULL;
1688 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1689 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
1690 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
1691 "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
1692 certBlob.cbData = 1;
1693 certBlob.pbData = (void *)0xdeadbeef;
1694 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1695 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
1696 ok(!ret && (GetLastError() == STATUS_ACCESS_VIOLATION ||
1697 GetLastError() == CRYPT_E_ASN1_EOD /* Win9x */),
1698 "Expected STATUS_ACCESS_VIOLATION or CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
1700 certBlob.cbData = size;
1701 certBlob.pbData = cert;
1702 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1703 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
1704 ok(!ret && GetLastError() == E_INVALIDARG,
1705 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1706 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1707 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
1708 CRYPT_VERIFY_CERT_SIGN_ISSUER_NULL, NULL, 0, NULL);
1709 ok(!ret && GetLastError() == E_INVALIDARG,
1710 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1711 /* This crashes
1712 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1713 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
1714 CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY, NULL, 0, NULL);
1716 CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
1717 (LPSTR)sigOID, 0, NULL, NULL, &size);
1718 pubKeyInfo = HeapAlloc(GetProcessHeap(), 0, size);
1719 if (pubKeyInfo)
1721 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
1722 X509_ASN_ENCODING, (LPSTR)sigOID, 0, NULL, pubKeyInfo, &size);
1723 ok(ret, "CryptExportKey failed: %08x\n", GetLastError());
1724 if (ret)
1726 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1727 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
1728 CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY, pubKeyInfo, 0, NULL);
1729 ok(ret, "CryptVerifyCertificateSignatureEx failed: %08x\n",
1730 GetLastError());
1732 HeapFree(GetProcessHeap(), 0, pubKeyInfo);
1734 LocalFree(cert);
1738 static BYTE emptyCert[] = { 0x30, 0x00 };
1740 static void testCertSigs(void)
1742 HCRYPTPROV csp;
1743 CRYPT_DATA_BLOB toBeSigned = { sizeof(emptyCert), emptyCert };
1744 BOOL ret;
1745 HCRYPTKEY key;
1746 BYTE sig[64];
1747 DWORD sigSize = sizeof(sig);
1749 /* Just in case a previous run failed, delete this thing */
1750 pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
1751 CRYPT_DELETEKEYSET);
1752 ret = pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
1753 CRYPT_NEWKEYSET);
1754 ok(ret, "CryptAcquireContext failed: %08x\n", GetLastError());
1756 testSignCert(csp, &toBeSigned, szOID_RSA_SHA1RSA, &key, sig, &sigSize);
1757 testVerifyCertSig(csp, &toBeSigned, szOID_RSA_SHA1RSA, sig, sigSize);
1759 CryptDestroyKey(key);
1760 CryptReleaseContext(csp, 0);
1761 ret = pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
1762 CRYPT_DELETEKEYSET);
1765 static const BYTE md5SignedEmptyCert[] = {
1766 0x30,0x56,0x30,0x33,0x02,0x00,0x30,0x02,0x06,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,
1767 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,
1768 0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x07,
1769 0x30,0x02,0x06,0x00,0x03,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,
1770 0x0d,0x02,0x05,0x05,0x00,0x03,0x11,0x00,0xfb,0x0f,0x66,0x82,0x66,0xd9,0xe5,0xf8,
1771 0xd8,0xa2,0x55,0x2b,0xe1,0xa5,0xd9,0x04 };
1772 static const BYTE md5SignedEmptyCertNoNull[] = {
1773 0x30,0x54,0x30,0x33,0x02,0x00,0x30,0x02,0x06,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,
1774 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,
1775 0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x07,
1776 0x30,0x02,0x06,0x00,0x03,0x01,0x00,0x30,0x0a,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,
1777 0x0d,0x02,0x05,0x03,0x11,0x00,0x04,0xd9,0xa5,0xe1,0x2b,0x55,0xa2,0xd8,0xf8,0xe5,
1778 0xd9,0x66,0x82,0x66,0x0f,0xfb };
1780 static void testSignAndEncodeCert(void)
1782 static char oid_rsa_md5rsa[] = szOID_RSA_MD5RSA;
1783 static char oid_rsa_md5[] = szOID_RSA_MD5;
1784 BOOL ret;
1785 DWORD size;
1786 CRYPT_ALGORITHM_IDENTIFIER algID = { 0 };
1787 CERT_INFO info = { 0 };
1789 /* Crash
1790 ret = CryptSignAndEncodeCertificate(0, 0, 0, NULL, NULL, NULL, NULL, NULL,
1791 NULL);
1792 ret = CryptSignAndEncodeCertificate(0, 0, 0, NULL, NULL, NULL, NULL, NULL,
1793 &size);
1795 ret = CryptSignAndEncodeCertificate(0, 0, 0, NULL, NULL, &algID, NULL, NULL,
1796 &size);
1797 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1798 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1799 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING, NULL, NULL,
1800 &algID, NULL, NULL, &size);
1801 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1802 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1803 ret = CryptSignAndEncodeCertificate(0, 0, 0, X509_CERT_TO_BE_SIGNED, NULL,
1804 &algID, NULL, NULL, &size);
1805 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1806 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1807 /* Crashes on some win9x boxes */
1808 if (0)
1810 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1811 X509_CERT_TO_BE_SIGNED, NULL, &algID, NULL, NULL, &size);
1812 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1813 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1815 /* Crashes
1816 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1817 X509_CERT_TO_BE_SIGNED, &info, NULL, NULL, NULL, &size);
1819 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1820 X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, NULL, &size);
1821 ok(!ret &&
1822 (GetLastError() == NTE_BAD_ALGID ||
1823 GetLastError() == OSS_BAD_PTR), /* win9x */
1824 "Expected NTE_BAD_ALGID, got %08x\n", GetLastError());
1825 algID.pszObjId = oid_rsa_md5rsa;
1826 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1827 X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, NULL, &size);
1828 ok(!ret && (GetLastError() == ERROR_INVALID_PARAMETER || NTE_BAD_ALGID),
1829 "Expected ERROR_INVALID_PARAMETER or NTE_BAD_ALGID, got %08x\n",
1830 GetLastError());
1831 algID.pszObjId = oid_rsa_md5;
1832 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1833 X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, NULL, &size);
1834 /* oid_rsa_md5 not present in some win2k */
1835 if (ret)
1837 LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, size);
1839 if (buf)
1841 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1842 X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, buf, &size);
1843 ok(ret, "CryptSignAndEncodeCertificate failed: %08x\n",
1844 GetLastError());
1845 /* Tricky: because the NULL parameters may either be omitted or
1846 * included as an asn.1-encoded NULL (0x05,0x00), two different
1847 * values are allowed.
1849 ok(size == sizeof(md5SignedEmptyCert) ||
1850 size == sizeof(md5SignedEmptyCertNoNull), "Unexpected size %d\n",
1851 size);
1852 if (size == sizeof(md5SignedEmptyCert))
1853 ok(!memcmp(buf, md5SignedEmptyCert, size),
1854 "Unexpected value\n");
1855 else if (size == sizeof(md5SignedEmptyCertNoNull))
1856 ok(!memcmp(buf, md5SignedEmptyCertNoNull, size),
1857 "Unexpected value\n");
1858 HeapFree(GetProcessHeap(), 0, buf);
1863 static void testCreateSelfSignCert(void)
1865 PCCERT_CONTEXT context;
1866 CERT_NAME_BLOB name = { sizeof(subjectName), subjectName };
1867 HCRYPTPROV csp;
1868 BOOL ret;
1869 HCRYPTKEY key;
1870 CRYPT_KEY_PROV_INFO info;
1872 if (!pCertCreateSelfSignCertificate)
1874 skip("CertCreateSelfSignCertificate() is not available\n");
1875 return;
1878 /* This crashes:
1879 context = pCertCreateSelfSignCertificate(0, NULL, 0, NULL, NULL, NULL, NULL,
1880 NULL);
1881 * Calling this with no first parameter creates a new key container, which
1882 * lasts beyond the test, so I don't test that. Nb: the generated key
1883 * name is a GUID.
1884 context = pCertCreateSelfSignCertificate(0, &name, 0, NULL, NULL, NULL, NULL,
1885 NULL);
1888 /* Acquire a CSP */
1889 pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
1890 CRYPT_DELETEKEYSET);
1891 ret = pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
1892 CRYPT_NEWKEYSET);
1893 ok(ret, "CryptAcquireContext failed: %08x\n", GetLastError());
1895 context = pCertCreateSelfSignCertificate(csp, &name, 0, NULL, NULL, NULL,
1896 NULL, NULL);
1897 ok(!context && GetLastError() == NTE_NO_KEY,
1898 "Expected NTE_NO_KEY, got %08x\n", GetLastError());
1899 ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
1900 ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
1901 if (ret)
1903 context = pCertCreateSelfSignCertificate(csp, &name, 0, NULL, NULL, NULL,
1904 NULL, NULL);
1905 ok(context != NULL, "CertCreateSelfSignCertificate failed: %08x\n",
1906 GetLastError());
1907 if (context)
1909 DWORD size = 0;
1910 PCRYPT_KEY_PROV_INFO info;
1912 /* The context must have a key provider info property */
1913 ret = CertGetCertificateContextProperty(context,
1914 CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
1915 ok(ret && size, "Expected non-zero key provider info\n");
1916 if (size)
1918 info = HeapAlloc(GetProcessHeap(), 0, size);
1919 if (info)
1921 ret = CertGetCertificateContextProperty(context,
1922 CERT_KEY_PROV_INFO_PROP_ID, info, &size);
1923 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
1924 GetLastError());
1925 if (ret)
1927 /* Sanity-check the key provider */
1928 ok(!lstrcmpW(info->pwszContainerName, cspNameW),
1929 "Unexpected key container\n");
1930 ok(!lstrcmpW(info->pwszProvName, MS_DEF_PROV_W),
1931 "Unexpected provider\n");
1932 ok(info->dwKeySpec == AT_SIGNATURE,
1933 "Expected AT_SIGNATURE, got %d\n", info->dwKeySpec);
1935 HeapFree(GetProcessHeap(), 0, info);
1939 CertFreeCertificateContext(context);
1942 CryptDestroyKey(key);
1945 CryptReleaseContext(csp, 0);
1946 ret = pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
1947 CRYPT_DELETEKEYSET);
1949 /* do the same test with AT_KEYEXCHANGE and key info*/
1950 memset(&info,0,sizeof(info));
1951 info.dwProvType = PROV_RSA_FULL;
1952 info.dwKeySpec = AT_KEYEXCHANGE;
1953 info.pwszProvName = (LPWSTR) MS_DEF_PROV_W;
1954 info.pwszContainerName = cspNameW;
1955 context = pCertCreateSelfSignCertificate(0, &name, 0, &info, NULL, NULL,
1956 NULL, NULL);
1957 ok(context != NULL, "CertCreateSelfSignCertificate failed: %08x\n",
1958 GetLastError());
1959 if (context)
1961 DWORD size = 0;
1962 PCRYPT_KEY_PROV_INFO info;
1964 /* The context must have a key provider info property */
1965 ret = CertGetCertificateContextProperty(context,
1966 CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
1967 ok(ret && size, "Expected non-zero key provider info\n");
1968 if (size)
1970 info = HeapAlloc(GetProcessHeap(), 0, size);
1971 if (info)
1973 ret = CertGetCertificateContextProperty(context,
1974 CERT_KEY_PROV_INFO_PROP_ID, info, &size);
1975 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
1976 GetLastError());
1977 if (ret)
1979 /* Sanity-check the key provider */
1980 ok(!lstrcmpW(info->pwszContainerName, cspNameW),
1981 "Unexpected key container\n");
1982 ok(!lstrcmpW(info->pwszProvName, MS_DEF_PROV_W),
1983 "Unexpected provider\n");
1984 ok(info->dwKeySpec == AT_KEYEXCHANGE,
1985 "Expected AT_KEYEXCHANGE, got %d\n", info->dwKeySpec);
1987 HeapFree(GetProcessHeap(), 0, info);
1991 CertFreeCertificateContext(context);
1994 pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
1995 CRYPT_DELETEKEYSET);
1998 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
1999 szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
2001 static void testKeyUsage(void)
2003 BOOL ret;
2004 PCCERT_CONTEXT context;
2005 DWORD size;
2007 /* Test base cases */
2008 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, NULL);
2009 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2010 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
2011 size = 1;
2012 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, &size);
2013 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2014 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
2015 size = 0;
2016 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, &size);
2017 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2018 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
2019 /* These crash
2020 ret = CertSetEnhancedKeyUsage(NULL, NULL);
2021 usage.cUsageIdentifier = 0;
2022 ret = CertSetEnhancedKeyUsage(NULL, &usage);
2024 /* Test with a cert with no enhanced key usage extension */
2025 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
2026 sizeof(bigCert));
2027 ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
2028 GetLastError());
2029 if (context)
2031 static const char oid[] = "1.2.3.4";
2032 BYTE buf[sizeof(CERT_ENHKEY_USAGE) + 2 * (sizeof(LPSTR) + sizeof(oid))];
2033 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
2035 ret = CertGetEnhancedKeyUsage(context, 0, NULL, NULL);
2036 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2037 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
2038 size = 1;
2039 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &size);
2040 if (ret)
2042 /* Windows 2000, ME, or later: even though it succeeded, we expect
2043 * CRYPT_E_NOT_FOUND, which indicates there is no enhanced key
2044 * usage set for this cert (which implies it's valid for all uses.)
2046 ok(GetLastError() == CRYPT_E_NOT_FOUND,
2047 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
2048 ok(size == sizeof(CERT_ENHKEY_USAGE), "Wrong size %d\n", size);
2049 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2050 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2051 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %d\n",
2052 pUsage->cUsageIdentifier);
2054 else
2056 /* Windows NT, 95, or 98: it fails, and the last error is
2057 * CRYPT_E_NOT_FOUND.
2059 ok(GetLastError() == CRYPT_E_NOT_FOUND,
2060 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
2062 /* I can add a usage identifier when no key usage has been set */
2063 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
2064 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
2065 GetLastError());
2066 size = sizeof(buf);
2067 ret = CertGetEnhancedKeyUsage(context,
2068 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
2069 ok(ret && GetLastError() == 0,
2070 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2071 ok(pUsage->cUsageIdentifier == 1, "Expected 1 usage, got %d\n",
2072 pUsage->cUsageIdentifier);
2073 if (pUsage->cUsageIdentifier)
2074 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
2075 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
2076 /* Now set an empty key usage */
2077 pUsage->cUsageIdentifier = 0;
2078 ret = CertSetEnhancedKeyUsage(context, pUsage);
2079 ok(ret, "CertSetEnhancedKeyUsage failed: %08x\n", GetLastError());
2080 /* Shouldn't find it in the cert */
2081 size = sizeof(buf);
2082 ret = CertGetEnhancedKeyUsage(context,
2083 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
2084 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
2085 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
2086 /* Should find it as an extended property */
2087 ret = CertGetEnhancedKeyUsage(context,
2088 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
2089 ok(ret && GetLastError() == 0,
2090 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2091 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %d\n",
2092 pUsage->cUsageIdentifier);
2093 /* Should find it as either */
2094 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2095 ok(ret && GetLastError() == 0,
2096 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2097 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %d\n",
2098 pUsage->cUsageIdentifier);
2099 /* Add a usage identifier */
2100 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
2101 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
2102 GetLastError());
2103 size = sizeof(buf);
2104 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2105 ok(ret && GetLastError() == 0,
2106 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2107 ok(pUsage->cUsageIdentifier == 1, "Expected 1 identifier, got %d\n",
2108 pUsage->cUsageIdentifier);
2109 if (pUsage->cUsageIdentifier)
2110 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
2111 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
2112 /* Re-adding the same usage identifier succeeds, though it only adds
2113 * a duplicate usage identifier on versions prior to Vista
2115 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
2116 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
2117 GetLastError());
2118 size = sizeof(buf);
2119 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2120 ok(ret && GetLastError() == 0,
2121 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2122 ok(pUsage->cUsageIdentifier == 1 || pUsage->cUsageIdentifier == 2,
2123 "Expected 1 or 2 identifiers, got %d\n", pUsage->cUsageIdentifier);
2124 if (pUsage->cUsageIdentifier)
2125 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
2126 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
2127 if (pUsage->cUsageIdentifier >= 2)
2128 ok(!strcmp(pUsage->rgpszUsageIdentifier[1], oid),
2129 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[1]);
2130 /* Now set a NULL extended property--this deletes the property. */
2131 ret = CertSetEnhancedKeyUsage(context, NULL);
2132 ok(ret, "CertSetEnhancedKeyUsage failed: %08x\n", GetLastError());
2133 SetLastError(0xbaadcafe);
2134 size = sizeof(buf);
2135 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2136 ok(GetLastError() == CRYPT_E_NOT_FOUND,
2137 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
2139 CertFreeCertificateContext(context);
2141 /* Now test with a cert with an enhanced key usage extension */
2142 context = CertCreateCertificateContext(X509_ASN_ENCODING, certWithUsage,
2143 sizeof(certWithUsage));
2144 ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
2145 GetLastError());
2146 if (context)
2148 LPBYTE buf = NULL;
2149 DWORD bufSize = 0, i;
2151 /* The size may depend on what flags are used to query it, so I
2152 * realloc the buffer for each test.
2154 ret = CertGetEnhancedKeyUsage(context,
2155 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, NULL, &bufSize);
2156 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2157 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
2158 if (buf)
2160 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
2162 /* Should find it in the cert */
2163 size = bufSize;
2164 ret = CertGetEnhancedKeyUsage(context,
2165 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
2166 ok(ret && GetLastError() == 0,
2167 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2168 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
2169 pUsage->cUsageIdentifier);
2170 for (i = 0; i < pUsage->cUsageIdentifier; i++)
2171 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
2172 "Expected %s, got %s\n", keyUsages[i],
2173 pUsage->rgpszUsageIdentifier[i]);
2174 HeapFree(GetProcessHeap(), 0, buf);
2176 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
2177 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2178 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
2179 if (buf)
2181 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
2183 /* Should find it as either */
2184 size = bufSize;
2185 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2186 /* In Windows, GetLastError returns CRYPT_E_NOT_FOUND not found
2187 * here, even though the return is successful and the usage id
2188 * count is positive. I don't enforce that here.
2190 ok(ret,
2191 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2192 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
2193 pUsage->cUsageIdentifier);
2194 for (i = 0; i < pUsage->cUsageIdentifier; i++)
2195 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
2196 "Expected %s, got %s\n", keyUsages[i],
2197 pUsage->rgpszUsageIdentifier[i]);
2198 HeapFree(GetProcessHeap(), 0, buf);
2200 /* Shouldn't find it as an extended property */
2201 ret = CertGetEnhancedKeyUsage(context,
2202 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, NULL, &size);
2203 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
2204 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
2205 /* Adding a usage identifier overrides the cert's usage!? */
2206 ret = CertAddEnhancedKeyUsageIdentifier(context, szOID_RSA_RSA);
2207 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
2208 GetLastError());
2209 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
2210 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2211 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
2212 if (buf)
2214 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
2216 /* Should find it as either */
2217 size = bufSize;
2218 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2219 ok(ret,
2220 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2221 ok(pUsage->cUsageIdentifier == 1, "Expected 1 usage, got %d\n",
2222 pUsage->cUsageIdentifier);
2223 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], szOID_RSA_RSA),
2224 "Expected %s, got %s\n", szOID_RSA_RSA,
2225 pUsage->rgpszUsageIdentifier[0]);
2226 HeapFree(GetProcessHeap(), 0, buf);
2228 /* But querying the cert directly returns its usage */
2229 ret = CertGetEnhancedKeyUsage(context,
2230 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, NULL, &bufSize);
2231 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2232 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
2233 if (buf)
2235 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
2237 size = bufSize;
2238 ret = CertGetEnhancedKeyUsage(context,
2239 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
2240 ok(ret,
2241 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2242 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
2243 pUsage->cUsageIdentifier);
2244 for (i = 0; i < pUsage->cUsageIdentifier; i++)
2245 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
2246 "Expected %s, got %s\n", keyUsages[i],
2247 pUsage->rgpszUsageIdentifier[i]);
2248 HeapFree(GetProcessHeap(), 0, buf);
2250 /* And removing the only usage identifier in the extended property
2251 * results in the cert's key usage being found.
2253 ret = CertRemoveEnhancedKeyUsageIdentifier(context, szOID_RSA_RSA);
2254 ok(ret, "CertRemoveEnhancedKeyUsage failed: %08x\n", GetLastError());
2255 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
2256 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2257 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
2258 if (buf)
2260 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
2262 /* Should find it as either */
2263 size = bufSize;
2264 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2265 ok(ret,
2266 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2267 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
2268 pUsage->cUsageIdentifier);
2269 for (i = 0; i < pUsage->cUsageIdentifier; i++)
2270 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
2271 "Expected %s, got %s\n", keyUsages[i],
2272 pUsage->rgpszUsageIdentifier[i]);
2273 HeapFree(GetProcessHeap(), 0, buf);
2276 CertFreeCertificateContext(context);
2280 static const BYTE cert2WithUsage[] = {
2281 0x30,0x81,0x89,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2282 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2283 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2284 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2285 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2286 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2287 0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x25,0x30,0x23,
2288 0x30,0x21,0x06,0x03,0x55,0x1d,0x25,0x01,0x01,0xff,0x04,0x17,0x30,0x15,0x06,
2289 0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x03,0x02,0x06,0x09,0x2a,0x86,0x48,0x86,
2290 0xf7,0x0d,0x01,0x01,0x01 };
2292 static void testGetValidUsages(void)
2294 static const LPCSTR expectedOIDs[] = {
2295 "1.3.6.1.5.5.7.3.3",
2296 "1.3.6.1.5.5.7.3.2",
2297 "1.2.840.113549.1.1.1",
2299 static const LPCSTR expectedOIDs2[] = {
2300 "1.3.6.1.5.5.7.3.2",
2301 "1.2.840.113549.1.1.1",
2303 BOOL ret;
2304 int numOIDs;
2305 DWORD size;
2306 LPSTR *oids = NULL;
2307 PCCERT_CONTEXT contexts[3];
2309 if (!pCertGetValidUsages)
2311 skip("CertGetValidUsages() is not available\n");
2312 return;
2315 /* Crash
2316 ret = pCertGetValidUsages(0, NULL, NULL, NULL, NULL);
2317 ret = pCertGetValidUsages(0, NULL, NULL, NULL, &size);
2319 contexts[0] = NULL;
2320 numOIDs = size = 0xdeadbeef;
2321 SetLastError(0xdeadbeef);
2322 ret = pCertGetValidUsages(1, &contexts[0], &numOIDs, NULL, &size);
2323 ok(ret, "CertGetValidUsages failed: %d\n", GetLastError());
2324 ok(numOIDs == -1, "Expected -1, got %d\n", numOIDs);
2325 ok(size == 0, "Expected size 0, got %d\n", size);
2326 contexts[0] = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
2327 sizeof(bigCert));
2328 contexts[1] = CertCreateCertificateContext(X509_ASN_ENCODING, certWithUsage,
2329 sizeof(certWithUsage));
2330 contexts[2] = CertCreateCertificateContext(X509_ASN_ENCODING,
2331 cert2WithUsage, sizeof(cert2WithUsage));
2332 numOIDs = size = 0xdeadbeef;
2333 ret = pCertGetValidUsages(0, NULL, &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 numOIDs = size = 0xdeadbeef;
2338 ret = pCertGetValidUsages(1, contexts, &numOIDs, NULL, &size);
2339 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2340 ok(numOIDs == -1, "Expected -1, got %d\n", numOIDs);
2341 ok(size == 0, "Expected size 0, got %d\n", size);
2342 ret = pCertGetValidUsages(1, &contexts[1], &numOIDs, NULL, &size);
2343 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2344 ok(numOIDs == 3, "Expected 3, got %d\n", numOIDs);
2345 ok(size, "Expected non-zero size\n");
2346 oids = HeapAlloc(GetProcessHeap(), 0, size);
2347 if (oids)
2349 int i;
2350 DWORD smallSize = 1;
2352 SetLastError(0xdeadbeef);
2353 ret = pCertGetValidUsages(1, &contexts[1], &numOIDs, oids, &smallSize);
2354 ok(!ret && GetLastError() == ERROR_MORE_DATA,
2355 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
2356 ret = pCertGetValidUsages(1, &contexts[1], &numOIDs, oids, &size);
2357 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2358 for (i = 0; i < numOIDs; i++)
2359 ok(!lstrcmpA(oids[i], expectedOIDs[i]), "unexpected OID %s\n",
2360 oids[i]);
2361 HeapFree(GetProcessHeap(), 0, oids);
2363 numOIDs = size = 0xdeadbeef;
2364 /* Oddly enough, this crashes when the number of contexts is not 1:
2365 ret = pCertGetValidUsages(2, contexts, &numOIDs, NULL, &size);
2366 * but setting size to 0 allows it to succeed:
2368 size = 0;
2369 ret = pCertGetValidUsages(2, contexts, &numOIDs, NULL, &size);
2370 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2371 ok(numOIDs == 3, "Expected 3, got %d\n", numOIDs);
2372 ok(size, "Expected non-zero size\n");
2373 oids = HeapAlloc(GetProcessHeap(), 0, size);
2374 if (oids)
2376 int i;
2378 ret = pCertGetValidUsages(1, &contexts[1], &numOIDs, oids, &size);
2379 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2380 for (i = 0; i < numOIDs; i++)
2381 ok(!lstrcmpA(oids[i], expectedOIDs[i]), "unexpected OID %s\n",
2382 oids[i]);
2383 HeapFree(GetProcessHeap(), 0, oids);
2385 numOIDs = 0xdeadbeef;
2386 size = 0;
2387 ret = pCertGetValidUsages(1, &contexts[2], &numOIDs, NULL, &size);
2388 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2389 ok(numOIDs == 2, "Expected 2, got %d\n", numOIDs);
2390 ok(size, "Expected non-zero size\n");
2391 oids = HeapAlloc(GetProcessHeap(), 0, size);
2392 if (oids)
2394 int i;
2396 ret = pCertGetValidUsages(1, &contexts[2], &numOIDs, oids, &size);
2397 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2398 for (i = 0; i < numOIDs; i++)
2399 ok(!lstrcmpA(oids[i], expectedOIDs2[i]), "unexpected OID %s\n",
2400 oids[i]);
2401 HeapFree(GetProcessHeap(), 0, oids);
2403 numOIDs = 0xdeadbeef;
2404 size = 0;
2405 ret = pCertGetValidUsages(3, contexts, &numOIDs, NULL, &size);
2406 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2407 ok(numOIDs == 2, "Expected 2, got %d\n", numOIDs);
2408 ok(size, "Expected non-zero size\n");
2409 oids = HeapAlloc(GetProcessHeap(), 0, size);
2410 if (oids)
2412 int i;
2414 ret = pCertGetValidUsages(3, contexts, &numOIDs, oids, &size);
2415 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2416 for (i = 0; i < numOIDs; i++)
2417 ok(!lstrcmpA(oids[i], expectedOIDs2[i]), "unexpected OID %s\n",
2418 oids[i]);
2419 HeapFree(GetProcessHeap(), 0, oids);
2421 CertFreeCertificateContext(contexts[0]);
2422 CertFreeCertificateContext(contexts[1]);
2423 CertFreeCertificateContext(contexts[2]);
2426 static void testCompareCertName(void)
2428 static BYTE bogus[] = { 1, 2, 3, 4 };
2429 static BYTE bogusPrime[] = { 0, 1, 2, 3, 4 };
2430 static BYTE emptyPrime[] = { 0x30, 0x00, 0x01 };
2431 BOOL ret;
2432 CERT_NAME_BLOB blob1, blob2;
2434 /* crashes
2435 ret = CertCompareCertificateName(0, NULL, NULL);
2437 /* An empty name checks against itself.. */
2438 blob1.pbData = emptyCert;
2439 blob1.cbData = sizeof(emptyCert);
2440 ret = CertCompareCertificateName(0, &blob1, &blob1);
2441 ok(ret, "CertCompareCertificateName failed: %08x\n", GetLastError());
2442 /* It doesn't have to be a valid encoded name.. */
2443 blob1.pbData = bogus;
2444 blob1.cbData = sizeof(bogus);
2445 ret = CertCompareCertificateName(0, &blob1, &blob1);
2446 ok(ret, "CertCompareCertificateName failed: %08x\n", GetLastError());
2447 /* Leading zeroes matter.. */
2448 blob2.pbData = bogusPrime;
2449 blob2.cbData = sizeof(bogusPrime);
2450 ret = CertCompareCertificateName(0, &blob1, &blob2);
2451 ok(!ret, "Expected failure\n");
2452 /* As do trailing extra bytes. */
2453 blob2.pbData = emptyPrime;
2454 blob2.cbData = sizeof(emptyPrime);
2455 ret = CertCompareCertificateName(0, &blob1, &blob2);
2456 ok(!ret, "Expected failure\n");
2459 static BYTE int1[] = { 0x88, 0xff, 0xff, 0xff };
2460 static BYTE int2[] = { 0x88, 0xff };
2461 static BYTE int3[] = { 0x23, 0xff };
2462 static BYTE int4[] = { 0x7f, 0x00 };
2463 static BYTE int5[] = { 0x7f };
2464 static BYTE int6[] = { 0x80, 0x00, 0x00, 0x00 };
2465 static BYTE int7[] = { 0x80, 0x00 };
2467 static struct IntBlobTest
2469 CRYPT_INTEGER_BLOB blob1;
2470 CRYPT_INTEGER_BLOB blob2;
2471 BOOL areEqual;
2472 } intBlobs[] = {
2473 { { sizeof(int1), int1 }, { sizeof(int2), int2 }, TRUE },
2474 { { sizeof(int3), int3 }, { sizeof(int3), int3 }, TRUE },
2475 { { sizeof(int4), int4 }, { sizeof(int5), int5 }, TRUE },
2476 { { sizeof(int6), int6 }, { sizeof(int7), int7 }, TRUE },
2477 { { sizeof(int1), int1 }, { sizeof(int7), int7 }, FALSE },
2480 static void testCompareIntegerBlob(void)
2482 DWORD i;
2483 BOOL ret;
2485 for (i = 0; i < sizeof(intBlobs) / sizeof(intBlobs[0]); i++)
2487 ret = CertCompareIntegerBlob(&intBlobs[i].blob1, &intBlobs[i].blob2);
2488 ok(ret == intBlobs[i].areEqual,
2489 "%d: expected blobs %s compare\n", i, intBlobs[i].areEqual ?
2490 "to" : "not to");
2494 static void testComparePublicKeyInfo(void)
2496 BOOL ret;
2497 CERT_PUBLIC_KEY_INFO info1 = { { 0 } }, info2 = { { 0 } };
2498 static CHAR oid_rsa_rsa[] = szOID_RSA_RSA;
2499 static CHAR oid_rsa_sha1rsa[] = szOID_RSA_SHA1RSA;
2500 static CHAR oid_x957_dsa[] = szOID_X957_DSA;
2501 static BYTE bits1[] = { 1, 0 };
2502 static BYTE bits2[] = { 0 };
2503 static BYTE bits3[] = { 1 };
2504 static BYTE bits4[] = { 0x30,8, 2,1,0x81, 2,3,1,0,1 };
2505 static BYTE bits5[] = { 0x30,9, 2,2,0,0x81, 2,3,1,0,1 };
2506 static BYTE bits6[] = { 0x30,9, 2,2,0,0x82, 2,3,1,0,1 };
2508 /* crashes
2509 ret = CertComparePublicKeyInfo(0, NULL, NULL);
2511 /* Empty public keys compare */
2512 ret = CertComparePublicKeyInfo(0, &info1, &info2);
2513 ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
2514 /* Different OIDs appear to compare */
2515 info1.Algorithm.pszObjId = oid_rsa_rsa;
2516 info2.Algorithm.pszObjId = oid_rsa_sha1rsa;
2517 ret = CertComparePublicKeyInfo(0, &info1, &info2);
2518 ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
2519 info2.Algorithm.pszObjId = oid_x957_dsa;
2520 ret = CertComparePublicKeyInfo(0, &info1, &info2);
2521 ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
2522 info1.PublicKey.cbData = sizeof(bits1);
2523 info1.PublicKey.pbData = bits1;
2524 info1.PublicKey.cUnusedBits = 0;
2525 info2.PublicKey.cbData = sizeof(bits1);
2526 info2.PublicKey.pbData = bits1;
2527 info2.PublicKey.cUnusedBits = 0;
2528 ret = CertComparePublicKeyInfo(0, &info1, &info2);
2529 ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
2530 info2.Algorithm.pszObjId = oid_rsa_rsa;
2531 info1.PublicKey.cbData = sizeof(bits4);
2532 info1.PublicKey.pbData = bits4;
2533 info1.PublicKey.cUnusedBits = 0;
2534 info2.PublicKey.cbData = sizeof(bits5);
2535 info2.PublicKey.pbData = bits5;
2536 info2.PublicKey.cUnusedBits = 0;
2537 ret = CertComparePublicKeyInfo(0, &info1, &info2);
2538 ok(!ret, "CertComparePublicKeyInfo: as raw binary: keys should be unequal\n");
2539 ret = CertComparePublicKeyInfo(X509_ASN_ENCODING, &info1, &info2);
2540 ok(ret ||
2541 broken(!ret), /* win9x */
2542 "CertComparePublicKeyInfo: as ASN.1 encoded: keys should be equal\n");
2543 info1.PublicKey.cUnusedBits = 1;
2544 info2.PublicKey.cUnusedBits = 5;
2545 ret = CertComparePublicKeyInfo(X509_ASN_ENCODING, &info1, &info2);
2546 ok(ret ||
2547 broken(!ret), /* win9x */
2548 "CertComparePublicKeyInfo: ASN.1 encoding should ignore cUnusedBits\n");
2549 info1.PublicKey.cUnusedBits = 0;
2550 info2.PublicKey.cUnusedBits = 0;
2551 info1.PublicKey.cbData--; /* kill one byte, make ASN.1 encoded data invalid */
2552 ret = CertComparePublicKeyInfo(X509_ASN_ENCODING, &info1, &info2);
2553 ok(!ret, "CertComparePublicKeyInfo: comparing bad ASN.1 encoded key should fail\n");
2554 /* Even though they compare in their used bits, these do not compare */
2555 info1.PublicKey.cbData = sizeof(bits2);
2556 info1.PublicKey.pbData = bits2;
2557 info1.PublicKey.cUnusedBits = 0;
2558 info2.PublicKey.cbData = sizeof(bits3);
2559 info2.PublicKey.pbData = bits3;
2560 info2.PublicKey.cUnusedBits = 1;
2561 ret = CertComparePublicKeyInfo(0, &info1, &info2);
2562 /* Simple (non-comparing) case */
2563 ok(!ret, "Expected keys not to compare\n");
2564 info2.PublicKey.cbData = sizeof(bits1);
2565 info2.PublicKey.pbData = bits1;
2566 info2.PublicKey.cUnusedBits = 0;
2567 ret = CertComparePublicKeyInfo(0, &info1, &info2);
2568 ok(!ret, "Expected keys not to compare\n");
2569 /* ASN.1 encoded non-comparing case */
2570 info1.PublicKey.cbData = sizeof(bits5);
2571 info1.PublicKey.pbData = bits5;
2572 info1.PublicKey.cUnusedBits = 0;
2573 info2.PublicKey.cbData = sizeof(bits6);
2574 info2.PublicKey.pbData = bits6;
2575 info2.PublicKey.cUnusedBits = 0;
2576 ret = CertComparePublicKeyInfo(X509_ASN_ENCODING, &info1, &info2);
2577 ok(!ret, "CertComparePublicKeyInfo: different keys should be unequal\n");
2580 static void testHashPublicKeyInfo(void)
2582 BOOL ret;
2583 CERT_PUBLIC_KEY_INFO info = { { 0 } };
2584 DWORD len;
2586 /* Crash
2587 ret = CryptHashPublicKeyInfo(0, 0, 0, 0, NULL, NULL, NULL);
2588 ret = CryptHashPublicKeyInfo(0, 0, 0, 0, &info, NULL, NULL);
2590 ret = CryptHashPublicKeyInfo(0, 0, 0, 0, NULL, NULL, &len);
2591 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2592 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2593 /* Crashes on some win9x boxes */
2594 if (0)
2596 ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, NULL, NULL, &len);
2597 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2598 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
2600 ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, &info, NULL, &len);
2601 ok(ret ||
2602 broken(!ret), /* win9x */
2603 "CryptHashPublicKeyInfo failed: %08x\n", GetLastError());
2604 if (ret)
2606 ok(len == 16, "Expected hash size 16, got %d\n", len);
2607 if (len == 16)
2609 static const BYTE emptyHash[] = { 0xb8,0x51,0x3a,0x31,0x0e,0x9f,0x40,
2610 0x36,0x9c,0x92,0x45,0x1b,0x9d,0xc8,0xf9,0xf6 };
2611 BYTE buf[16];
2613 ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, &info, buf,
2614 &len);
2615 ok(ret, "CryptHashPublicKeyInfo failed: %08x\n", GetLastError());
2616 ok(!memcmp(buf, emptyHash, len), "Unexpected hash\n");
2621 static const BYTE md5SignedEmptyCertHash[] = { 0xfb,0x0f,0x66,0x82,0x66,0xd9,
2622 0xe5,0xf8,0xd8,0xa2,0x55,0x2b,0xe1,0xa5,0xd9,0x04 };
2624 static void testHashToBeSigned(void)
2626 BOOL ret;
2627 DWORD size;
2628 BYTE hash[16];
2630 /* Crash */
2631 if (0)
2633 ret = CryptHashToBeSigned(0, 0, NULL, 0, NULL, NULL);
2635 SetLastError(0xdeadbeef);
2636 ret = CryptHashToBeSigned(0, 0, NULL, 0, NULL, &size);
2637 todo_wine
2638 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2639 "expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
2640 SetLastError(0xdeadbeef);
2641 ret = CryptHashToBeSigned(0, X509_ASN_ENCODING, NULL, 0, NULL, &size);
2642 ok(!ret &&
2643 (GetLastError() == CRYPT_E_ASN1_EOD ||
2644 GetLastError() == OSS_BAD_ARG), /* win9x */
2645 "expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
2646 /* Can't sign anything: has to be asn.1 encoded, at least */
2647 SetLastError(0xdeadbeef);
2648 ret = CryptHashToBeSigned(0, X509_ASN_ENCODING, int1, sizeof(int1),
2649 NULL, &size);
2650 ok(!ret &&
2651 (GetLastError() == CRYPT_E_ASN1_BADTAG ||
2652 GetLastError() == OSS_MORE_INPUT), /* win9x */
2653 "expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
2654 /* Can't be empty, either */
2655 SetLastError(0xdeadbeef);
2656 ret = CryptHashToBeSigned(0, X509_ASN_ENCODING, emptyCert,
2657 sizeof(emptyCert), NULL, &size);
2658 ok(!ret &&
2659 (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2660 GetLastError() == OSS_DATA_ERROR), /* win9x */
2661 "expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
2662 /* Signing a cert works */
2663 ret = CryptHashToBeSigned(0, X509_ASN_ENCODING, md5SignedEmptyCert,
2664 sizeof(md5SignedEmptyCert), NULL, &size);
2665 ok(ret ||
2666 broken(!ret), /* win9x */
2667 "CryptHashToBeSigned failed: %08x\n", GetLastError());
2668 if (ret)
2670 ok(size == sizeof(md5SignedEmptyCertHash), "unexpected size %d\n", size);
2673 ret = CryptHashToBeSigned(0, X509_ASN_ENCODING, md5SignedEmptyCert,
2674 sizeof(md5SignedEmptyCert), hash, &size);
2675 ok(!memcmp(hash, md5SignedEmptyCertHash, size), "unexpected value\n");
2678 static void testCompareCert(void)
2680 CERT_INFO info1 = { 0 }, info2 = { 0 };
2681 BOOL ret;
2683 /* Crashes
2684 ret = CertCompareCertificate(X509_ASN_ENCODING, NULL, NULL);
2687 /* Certs with the same issuer and serial number are equal, even if they
2688 * differ in other respects (like subject).
2690 info1.SerialNumber.pbData = serialNum;
2691 info1.SerialNumber.cbData = sizeof(serialNum);
2692 info1.Issuer.pbData = subjectName;
2693 info1.Issuer.cbData = sizeof(subjectName);
2694 info1.Subject.pbData = subjectName2;
2695 info1.Subject.cbData = sizeof(subjectName2);
2696 info2.SerialNumber.pbData = serialNum;
2697 info2.SerialNumber.cbData = sizeof(serialNum);
2698 info2.Issuer.pbData = subjectName;
2699 info2.Issuer.cbData = sizeof(subjectName);
2700 info2.Subject.pbData = subjectName;
2701 info2.Subject.cbData = sizeof(subjectName);
2702 ret = CertCompareCertificate(X509_ASN_ENCODING, &info1, &info2);
2703 ok(ret, "Expected certs to be equal\n");
2705 info2.Issuer.pbData = subjectName2;
2706 info2.Issuer.cbData = sizeof(subjectName2);
2707 ret = CertCompareCertificate(X509_ASN_ENCODING, &info1, &info2);
2708 ok(!ret, "Expected certs not to be equal\n");
2711 static void testVerifySubjectCert(void)
2713 BOOL ret;
2714 DWORD flags;
2715 PCCERT_CONTEXT context1, context2;
2717 /* Crashes
2718 ret = CertVerifySubjectCertificateContext(NULL, NULL, NULL);
2720 flags = 0;
2721 ret = CertVerifySubjectCertificateContext(NULL, NULL, &flags);
2722 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
2723 GetLastError());
2724 flags = CERT_STORE_NO_CRL_FLAG;
2725 ret = CertVerifySubjectCertificateContext(NULL, NULL, &flags);
2726 ok(!ret && GetLastError() == E_INVALIDARG,
2727 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2729 flags = 0;
2730 context1 = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
2731 sizeof(bigCert));
2732 ret = CertVerifySubjectCertificateContext(NULL, context1, &flags);
2733 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
2734 GetLastError());
2735 ret = CertVerifySubjectCertificateContext(context1, NULL, &flags);
2736 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
2737 GetLastError());
2738 ret = CertVerifySubjectCertificateContext(context1, context1, &flags);
2739 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
2740 GetLastError());
2742 context2 = CertCreateCertificateContext(X509_ASN_ENCODING,
2743 bigCertWithDifferentSubject, sizeof(bigCertWithDifferentSubject));
2744 SetLastError(0xdeadbeef);
2745 ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
2746 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
2747 GetLastError());
2748 flags = CERT_STORE_REVOCATION_FLAG;
2749 ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
2750 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
2751 GetLastError());
2752 ok(flags == (CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG),
2753 "Expected CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG, got %08x\n",
2754 flags);
2755 flags = CERT_STORE_SIGNATURE_FLAG;
2756 ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
2757 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
2758 GetLastError());
2759 ok(flags == CERT_STORE_SIGNATURE_FLAG,
2760 "Expected CERT_STORE_SIGNATURE_FLAG, got %08x\n", flags);
2761 CertFreeCertificateContext(context2);
2763 CertFreeCertificateContext(context1);
2766 static void testVerifyRevocation(void)
2768 BOOL ret;
2769 CERT_REVOCATION_STATUS status = { 0 };
2770 PCCERT_CONTEXT cert = CertCreateCertificateContext(X509_ASN_ENCODING,
2771 bigCert, sizeof(bigCert));
2773 /* Crash
2774 ret = CertVerifyRevocation(0, 0, 0, NULL, 0, NULL, NULL);
2776 SetLastError(0xdeadbeef);
2777 ret = CertVerifyRevocation(0, 0, 0, NULL, 0, NULL, &status);
2778 ok(!ret && GetLastError() == E_INVALIDARG,
2779 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2780 status.cbSize = sizeof(status);
2781 ret = CertVerifyRevocation(0, 0, 0, NULL, 0, NULL, &status);
2782 ok(ret, "CertVerifyRevocation failed: %08x\n", GetLastError());
2783 ret = CertVerifyRevocation(0, 2, 0, NULL, 0, NULL, &status);
2784 ok(ret, "CertVerifyRevocation failed: %08x\n", GetLastError());
2785 ret = CertVerifyRevocation(2, 0, 0, NULL, 0, NULL, &status);
2786 ok(ret, "CertVerifyRevocation failed: %08x\n", GetLastError());
2787 SetLastError(0xdeadbeef);
2788 ret = CertVerifyRevocation(0, 0, 1, (void **)&cert, 0, NULL, &status);
2789 ok(!ret && GetLastError() == CRYPT_E_NO_REVOCATION_DLL,
2790 "Expected CRYPT_E_NO_REVOCATION_DLL, got %08x\n", GetLastError());
2791 SetLastError(0xdeadbeef);
2792 ret = CertVerifyRevocation(0, 2, 1, (void **)&cert, 0, NULL, &status);
2793 ok(!ret && GetLastError() == CRYPT_E_NO_REVOCATION_DLL,
2794 "Expected CRYPT_E_NO_REVOCATION_DLL, got %08x\n", GetLastError());
2796 CertFreeCertificateContext(cert);
2799 static BYTE privKey[] = {
2800 0x07, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x52, 0x53, 0x41, 0x32, 0x00,
2801 0x02, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x79, 0x10, 0x1c, 0xd0, 0x6b, 0x10,
2802 0x18, 0x30, 0x94, 0x61, 0xdc, 0x0e, 0xcb, 0x96, 0x4e, 0x21, 0x3f, 0x79, 0xcd,
2803 0xa9, 0x17, 0x62, 0xbc, 0xbb, 0x61, 0x4c, 0xe0, 0x75, 0x38, 0x6c, 0xf3, 0xde,
2804 0x60, 0x86, 0x03, 0x97, 0x65, 0xeb, 0x1e, 0x6b, 0xdb, 0x53, 0x85, 0xad, 0x68,
2805 0x21, 0xf1, 0x5d, 0xe7, 0x1f, 0xe6, 0x53, 0xb4, 0xbb, 0x59, 0x3e, 0x14, 0x27,
2806 0xb1, 0x83, 0xa7, 0x3a, 0x54, 0xe2, 0x8f, 0x65, 0x8e, 0x6a, 0x4a, 0xcf, 0x3b,
2807 0x1f, 0x65, 0xff, 0xfe, 0xf1, 0x31, 0x3a, 0x37, 0x7a, 0x8b, 0xcb, 0xc6, 0xd4,
2808 0x98, 0x50, 0x36, 0x67, 0xe4, 0xa1, 0xe8, 0x7e, 0x8a, 0xc5, 0x23, 0xf2, 0x77,
2809 0xf5, 0x37, 0x61, 0x49, 0x72, 0x59, 0xe8, 0x3d, 0xf7, 0x60, 0xb2, 0x77, 0xca,
2810 0x78, 0x54, 0x6d, 0x65, 0x9e, 0x03, 0x97, 0x1b, 0x61, 0xbd, 0x0c, 0xd8, 0x06,
2811 0x63, 0xe2, 0xc5, 0x48, 0xef, 0xb3, 0xe2, 0x6e, 0x98, 0x7d, 0xbd, 0x4e, 0x72,
2812 0x91, 0xdb, 0x31, 0x57, 0xe3, 0x65, 0x3a, 0x49, 0xca, 0xec, 0xd2, 0x02, 0x4e,
2813 0x22, 0x7e, 0x72, 0x8e, 0xf9, 0x79, 0x84, 0x82, 0xdf, 0x7b, 0x92, 0x2d, 0xaf,
2814 0xc9, 0xe4, 0x33, 0xef, 0x89, 0x5c, 0x66, 0x99, 0xd8, 0x80, 0x81, 0x47, 0x2b,
2815 0xb1, 0x66, 0x02, 0x84, 0x59, 0x7b, 0xc3, 0xbe, 0x98, 0x45, 0x4a, 0x3d, 0xdd,
2816 0xea, 0x2b, 0xdf, 0x4e, 0xb4, 0x24, 0x6b, 0xec, 0xe7, 0xd9, 0x0c, 0x45, 0xb8,
2817 0xbe, 0xca, 0x69, 0x37, 0x92, 0x4c, 0x38, 0x6b, 0x96, 0x6d, 0xcd, 0x86, 0x67,
2818 0x5c, 0xea, 0x54, 0x94, 0xa4, 0xca, 0xa4, 0x02, 0xa5, 0x21, 0x4d, 0xae, 0x40,
2819 0x8f, 0x9d, 0x51, 0x83, 0xf2, 0x3f, 0x33, 0xc1, 0x72, 0xb4, 0x1d, 0x94, 0x6e,
2820 0x7d, 0xe4, 0x27, 0x3f, 0xea, 0xff, 0xe5, 0x9b, 0xa7, 0x5e, 0x55, 0x8e, 0x0d,
2821 0x69, 0x1c, 0x7a, 0xff, 0x81, 0x9d, 0x53, 0x52, 0x97, 0x9a, 0x76, 0x79, 0xda,
2822 0x93, 0x32, 0x16, 0xec, 0x69, 0x51, 0x1a, 0x4e, 0xc3, 0xf1, 0x72, 0x80, 0x78,
2823 0x5e, 0x66, 0x4a, 0x8d, 0x85, 0x2f, 0x3f, 0xb2, 0xa7 };
2825 static const BYTE exportedPublicKeyBlob[] = {
2826 0x06,0x02,0x00,0x00,0x00,0xa4,0x00,0x00,0x52,0x53,0x41,0x31,0x00,0x02,0x00,0x00,
2827 0x01,0x00,0x01,0x00,0x79,0x10,0x1c,0xd0,0x6b,0x10,0x18,0x30,0x94,0x61,0xdc,0x0e,
2828 0xcb,0x96,0x4e,0x21,0x3f,0x79,0xcd,0xa9,0x17,0x62,0xbc,0xbb,0x61,0x4c,0xe0,0x75,
2829 0x38,0x6c,0xf3,0xde,0x60,0x86,0x03,0x97,0x65,0xeb,0x1e,0x6b,0xdb,0x53,0x85,0xad,
2830 0x68,0x21,0xf1,0x5d,0xe7,0x1f,0xe6,0x53,0xb4,0xbb,0x59,0x3e,0x14,0x27,0xb1,0x83,
2831 0xa7,0x3a,0x54,0xe2 };
2833 static const BYTE asnEncodedPublicKey[] = {
2834 0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7,0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,
2835 0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21,0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,
2836 0x65,0x97,0x03,0x86,0x60,0xde,0xf3,0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,
2837 0x17,0xa9,0xcd,0x79,0x3f,0x21,0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,
2838 0x6b,0xd0,0x1c,0x10,0x79,0x02,0x03,0x01,0x00,0x01 };
2840 static void testAcquireCertPrivateKey(void)
2842 BOOL ret;
2843 PCCERT_CONTEXT cert;
2844 HCRYPTPROV csp;
2845 DWORD size, keySpec;
2846 BOOL callerFree;
2847 CRYPT_KEY_PROV_INFO keyProvInfo;
2848 HCRYPTKEY key;
2849 WCHAR ms_def_prov_w[MAX_PATH];
2851 if (!pCryptAcquireCertificatePrivateKey)
2853 skip("CryptAcquireCertificatePrivateKey() is not available\n");
2854 return;
2857 lstrcpyW(ms_def_prov_w, MS_DEF_PROV_W);
2859 keyProvInfo.pwszContainerName = cspNameW;
2860 keyProvInfo.pwszProvName = ms_def_prov_w;
2861 keyProvInfo.dwProvType = PROV_RSA_FULL;
2862 keyProvInfo.dwFlags = 0;
2863 keyProvInfo.cProvParam = 0;
2864 keyProvInfo.rgProvParam = NULL;
2865 keyProvInfo.dwKeySpec = AT_SIGNATURE;
2867 pCryptAcquireContextA(NULL, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
2868 CRYPT_DELETEKEYSET);
2870 cert = CertCreateCertificateContext(X509_ASN_ENCODING, selfSignedCert,
2871 sizeof(selfSignedCert));
2873 /* Crash
2874 ret = pCryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, NULL, NULL);
2875 ret = pCryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, NULL,
2876 &callerFree);
2877 ret = pCryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, &keySpec,
2878 NULL);
2879 ret = pCryptAcquireCertificatePrivateKey(NULL, 0, NULL, &csp, NULL, NULL);
2880 ret = pCryptAcquireCertificatePrivateKey(NULL, 0, NULL, &csp, &keySpec,
2881 &callerFree);
2882 ret = pCryptAcquireCertificatePrivateKey(cert, 0, NULL, NULL, NULL, NULL);
2885 /* Missing private key */
2886 ret = pCryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, NULL, NULL);
2887 ok(!ret && GetLastError() == CRYPT_E_NO_KEY_PROPERTY,
2888 "Expected CRYPT_E_NO_KEY_PROPERTY, got %08x\n", GetLastError());
2889 ret = pCryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, &keySpec,
2890 &callerFree);
2891 ok(!ret && GetLastError() == CRYPT_E_NO_KEY_PROPERTY,
2892 "Expected CRYPT_E_NO_KEY_PROPERTY, got %08x\n", GetLastError());
2893 CertSetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, 0,
2894 &keyProvInfo);
2895 ret = pCryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, &keySpec,
2896 &callerFree);
2897 ok(!ret && GetLastError() == CRYPT_E_NO_KEY_PROPERTY,
2898 "Expected CRYPT_E_NO_KEY_PROPERTY, got %08x\n", GetLastError());
2900 pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
2901 CRYPT_NEWKEYSET);
2902 ret = CryptImportKey(csp, privKey, sizeof(privKey), 0, 0, &key);
2903 ok(ret, "CryptImportKey failed: %08x\n", GetLastError());
2904 if (ret)
2906 HCRYPTPROV certCSP;
2907 DWORD size;
2908 CERT_KEY_CONTEXT keyContext;
2910 /* Don't cache provider */
2911 ret = pCryptAcquireCertificatePrivateKey(cert, 0, NULL, &certCSP,
2912 &keySpec, &callerFree);
2913 ok(ret ||
2914 broken(!ret), /* win95 */
2915 "CryptAcquireCertificatePrivateKey failed: %08x\n",
2916 GetLastError());
2917 if (ret)
2919 ok(callerFree, "Expected callerFree to be TRUE\n");
2920 CryptReleaseContext(certCSP, 0);
2923 ret = pCryptAcquireCertificatePrivateKey(cert, 0, NULL, &certCSP,
2924 NULL, NULL);
2925 ok(ret ||
2926 broken(!ret), /* win95 */
2927 "CryptAcquireCertificatePrivateKey failed: %08x\n",
2928 GetLastError());
2929 CryptReleaseContext(certCSP, 0);
2931 /* Use the key prov info's caching (there shouldn't be any) */
2932 ret = pCryptAcquireCertificatePrivateKey(cert,
2933 CRYPT_ACQUIRE_USE_PROV_INFO_FLAG, NULL, &certCSP, &keySpec,
2934 &callerFree);
2935 ok(ret ||
2936 broken(!ret), /* win95 */
2937 "CryptAcquireCertificatePrivateKey failed: %08x\n",
2938 GetLastError());
2939 if (ret)
2941 ok(callerFree, "Expected callerFree to be TRUE\n");
2942 CryptReleaseContext(certCSP, 0);
2945 /* Cache it (and check that it's cached) */
2946 ret = pCryptAcquireCertificatePrivateKey(cert,
2947 CRYPT_ACQUIRE_CACHE_FLAG, NULL, &certCSP, &keySpec, &callerFree);
2948 ok(ret ||
2949 broken(!ret), /* win95 */
2950 "CryptAcquireCertificatePrivateKey failed: %08x\n",
2951 GetLastError());
2952 ok(!callerFree, "Expected callerFree to be FALSE\n");
2953 size = sizeof(keyContext);
2954 ret = CertGetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID,
2955 &keyContext, &size);
2956 ok(ret ||
2957 broken(!ret), /* win95 */
2958 "CertGetCertificateContextProperty failed: %08x\n",
2959 GetLastError());
2961 /* Remove the cached provider */
2962 CryptReleaseContext(keyContext.hCryptProv, 0);
2963 CertSetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID, 0,
2964 NULL);
2965 /* Allow caching via the key prov info */
2966 keyProvInfo.dwFlags = CERT_SET_KEY_CONTEXT_PROP_ID;
2967 CertSetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, 0,
2968 &keyProvInfo);
2969 /* Now use the key prov info's caching */
2970 ret = pCryptAcquireCertificatePrivateKey(cert,
2971 CRYPT_ACQUIRE_USE_PROV_INFO_FLAG, NULL, &certCSP, &keySpec,
2972 &callerFree);
2973 ok(ret ||
2974 broken(!ret), /* win95 */
2975 "CryptAcquireCertificatePrivateKey failed: %08x\n",
2976 GetLastError());
2977 ok(!callerFree, "Expected callerFree to be FALSE\n");
2978 size = sizeof(keyContext);
2979 ret = CertGetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID,
2980 &keyContext, &size);
2981 ok(ret ||
2982 broken(!ret), /* win95 */
2983 "CertGetCertificateContextProperty failed: %08x\n",
2984 GetLastError());
2985 CryptReleaseContext(certCSP, 0);
2987 CryptDestroyKey(key);
2990 /* Some sanity-checking on public key exporting */
2991 ret = CryptImportPublicKeyInfo(csp, X509_ASN_ENCODING,
2992 &cert->pCertInfo->SubjectPublicKeyInfo, &key);
2993 ok(ret, "CryptImportPublicKeyInfo failed: %08x\n", GetLastError());
2994 if (ret)
2996 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &size);
2997 ok(ret, "CryptExportKey failed: %08x\n", GetLastError());
2998 if (ret)
3000 LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, size), encodedKey;
3002 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, buf, &size);
3003 ok(ret, "CryptExportKey failed: %08x\n", GetLastError());
3004 ok(size == sizeof(exportedPublicKeyBlob), "Unexpected size %d\n",
3005 size);
3006 ok(!memcmp(buf, exportedPublicKeyBlob, size), "Unexpected value\n");
3007 ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, RSA_CSP_PUBLICKEYBLOB,
3008 buf, CRYPT_ENCODE_ALLOC_FLAG, NULL, &encodedKey, &size);
3009 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3010 if (ret)
3012 ok(size == sizeof(asnEncodedPublicKey), "Unexpected size %d\n",
3013 size);
3014 ok(!memcmp(encodedKey, asnEncodedPublicKey, size),
3015 "Unexpected value\n");
3016 LocalFree(encodedKey);
3018 HeapFree(GetProcessHeap(), 0, buf);
3020 CryptDestroyKey(key);
3022 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
3023 NULL, 0, NULL, NULL, &size);
3024 ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
3025 if (ret)
3027 PCERT_PUBLIC_KEY_INFO info = HeapAlloc(GetProcessHeap(), 0, size);
3029 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
3030 NULL, 0, NULL, info, &size);
3031 ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
3032 if (ret)
3034 ok(info->PublicKey.cbData == sizeof(asnEncodedPublicKey),
3035 "Unexpected size %d\n", info->PublicKey.cbData);
3036 ok(!memcmp(info->PublicKey.pbData, asnEncodedPublicKey,
3037 info->PublicKey.cbData), "Unexpected value\n");
3039 HeapFree(GetProcessHeap(), 0, info);
3042 CryptReleaseContext(csp, 0);
3043 pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
3044 CRYPT_DELETEKEYSET);
3046 CertFreeCertificateContext(cert);
3049 static void testGetPublicKeyLength(void)
3051 static char oid_rsa_rsa[] = szOID_RSA_RSA;
3052 static char oid_rsa_dh[] = szOID_RSA_DH;
3053 static char bogusOID[] = "1.2.3";
3054 DWORD ret;
3055 CERT_PUBLIC_KEY_INFO info = { { 0 } };
3056 BYTE bogusKey[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
3057 BYTE key[] = { 0x30,0x0f,0x02,0x08,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
3058 0x02,0x03,0x01,0x00,0x01 };
3060 /* Crashes
3061 ret = CertGetPublicKeyLength(0, NULL);
3063 /* With an empty public key info */
3064 SetLastError(0xdeadbeef);
3065 ret = CertGetPublicKeyLength(0, &info);
3066 ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
3067 "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
3068 ret, GetLastError());
3069 SetLastError(0xdeadbeef);
3070 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
3071 ok(ret == 0 &&
3072 (GetLastError() == CRYPT_E_ASN1_EOD ||
3073 GetLastError() == OSS_BAD_ARG), /* win9x */
3074 "Expected length 0 and CRYPT_E_ASN1_EOD, got length %d, %08x\n",
3075 ret, GetLastError());
3076 /* With a nearly-empty public key info */
3077 info.Algorithm.pszObjId = oid_rsa_rsa;
3078 SetLastError(0xdeadbeef);
3079 ret = CertGetPublicKeyLength(0, &info);
3080 ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
3081 "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
3082 ret, GetLastError());
3083 SetLastError(0xdeadbeef);
3084 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
3085 ok(ret == 0 &&
3086 (GetLastError() == CRYPT_E_ASN1_EOD ||
3087 GetLastError() == OSS_BAD_ARG), /* win9x */
3088 "Expected length 0 and CRYPT_E_ASN1_EOD, got length %d, %08x\n",
3089 ret, GetLastError());
3090 /* With a bogus key */
3091 info.PublicKey.cbData = sizeof(bogusKey);
3092 info.PublicKey.pbData = bogusKey;
3093 SetLastError(0xdeadbeef);
3094 ret = CertGetPublicKeyLength(0, &info);
3095 ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
3096 "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
3097 ret, GetLastError());
3098 SetLastError(0xdeadbeef);
3099 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
3100 ok(ret == 0 &&
3101 (GetLastError() == CRYPT_E_ASN1_BADTAG ||
3102 GetLastError() == OSS_PDU_MISMATCH), /* win9x */
3103 "Expected length 0 and CRYPT_E_ASN1_BADTAGTAG, got length %d, %08x\n",
3104 ret, GetLastError());
3105 /* With a believable RSA key but a bogus OID */
3106 info.Algorithm.pszObjId = bogusOID;
3107 info.PublicKey.cbData = sizeof(key);
3108 info.PublicKey.pbData = key;
3109 SetLastError(0xdeadbeef);
3110 ret = CertGetPublicKeyLength(0, &info);
3111 ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
3112 "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
3113 ret, GetLastError());
3114 SetLastError(0xdeadbeef);
3115 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
3116 ok(ret == 56, "Expected length 56, got %d\n", ret);
3117 /* An RSA key with the DH OID */
3118 info.Algorithm.pszObjId = oid_rsa_dh;
3119 SetLastError(0xdeadbeef);
3120 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
3121 ok(ret == 0 &&
3122 (GetLastError() == CRYPT_E_ASN1_BADTAG ||
3123 GetLastError() == E_INVALIDARG), /* win9x */
3124 "Expected length 0 and CRYPT_E_ASN1_BADTAG, got length %d, %08x\n",
3125 ret, GetLastError());
3126 /* With the RSA OID */
3127 info.Algorithm.pszObjId = oid_rsa_rsa;
3128 SetLastError(0xdeadbeef);
3129 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
3130 ok(ret == 56, "Expected length 56, got %d\n", ret);
3131 /* With the RSA OID and a message encoding */
3132 info.Algorithm.pszObjId = oid_rsa_rsa;
3133 SetLastError(0xdeadbeef);
3134 ret = CertGetPublicKeyLength(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, &info);
3135 ok(ret == 56, "Expected length 56, got %d\n", ret);
3138 START_TEST(cert)
3140 init_function_pointers();
3142 testAddCert();
3143 testCertProperties();
3144 testDupCert();
3145 testFindCert();
3146 testGetSubjectCert();
3147 testGetIssuerCert();
3149 testCryptHashCert();
3150 testCertSigs();
3151 testSignAndEncodeCert();
3152 testCreateSelfSignCert();
3153 testKeyUsage();
3154 testGetValidUsages();
3155 testCompareCertName();
3156 testCompareIntegerBlob();
3157 testComparePublicKeyInfo();
3158 testHashPublicKeyInfo();
3159 testHashToBeSigned();
3160 testCompareCert();
3161 testVerifySubjectCert();
3162 testVerifyRevocation();
3163 testAcquireCertPrivateKey();
3164 testGetPublicKeyLength();