crypt32: Don't fail if HCRYPTPROV and PCRYPT_KEY_PROV_INFO parameters are both non...
[wine/multimedia.git] / dlls / crypt32 / tests / cert.c
blob92a92b5e4a372b4beb76dcf6465729b5a340ece6
1 /*
2 * crypt32 cert functions tests
4 * Copyright 2005-2006 Juan Lang
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <stdio.h>
22 #include <stdarg.h>
24 #include <windef.h>
25 #include <winbase.h>
26 #include <winreg.h>
27 #include <winerror.h>
28 #include <wincrypt.h>
30 #include "wine/test.h"
32 static BOOL (WINAPI *pCertAddStoreToCollection)(HCERTSTORE,HCERTSTORE,DWORD,DWORD);
33 static PCCERT_CONTEXT (WINAPI *pCertCreateSelfSignCertificate)(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE,PCERT_NAME_BLOB,DWORD,PCRYPT_KEY_PROV_INFO,PCRYPT_ALGORITHM_IDENTIFIER,PSYSTEMTIME,PSYSTEMTIME,PCERT_EXTENSIONS);
34 static BOOL (WINAPI *pCertGetValidUsages)(DWORD,PCCERT_CONTEXT*,int*,LPSTR*,DWORD*);
35 static BOOL (WINAPI *pCryptAcquireCertificatePrivateKey)(PCCERT_CONTEXT,DWORD,void*,HCRYPTPROV_OR_NCRYPT_KEY_HANDLE*,DWORD*,BOOL*);
36 static BOOL (WINAPI *pCryptEncodeObjectEx)(DWORD,LPCSTR,const void*,DWORD,PCRYPT_ENCODE_PARA,void*,DWORD*);
37 static BOOL (WINAPI * pCryptVerifyCertificateSignatureEx)
38 (HCRYPTPROV, DWORD, DWORD, void *, DWORD, void *, DWORD, void *);
40 static BOOL (WINAPI * pCryptAcquireContextA)
41 (HCRYPTPROV *, LPCSTR, LPCSTR, DWORD, DWORD);
43 static void init_function_pointers(void)
45 HMODULE hCrypt32 = GetModuleHandleA("crypt32.dll");
46 HMODULE hAdvapi32 = GetModuleHandleA("advapi32.dll");
48 #define GET_PROC(dll, func) \
49 p ## func = (void *)GetProcAddress(dll, #func); \
50 if(!p ## func) \
51 trace("GetProcAddress(%s) failed\n", #func);
53 GET_PROC(hCrypt32, CertAddStoreToCollection)
54 GET_PROC(hCrypt32, CertCreateSelfSignCertificate)
55 GET_PROC(hCrypt32, CertGetValidUsages)
56 GET_PROC(hCrypt32, CryptAcquireCertificatePrivateKey)
57 GET_PROC(hCrypt32, CryptEncodeObjectEx)
58 GET_PROC(hCrypt32, CryptVerifyCertificateSignatureEx)
60 GET_PROC(hAdvapi32, CryptAcquireContextA)
62 #undef GET_PROC
65 static BYTE subjectName[] = { 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
66 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
67 0x6e, 0x67, 0x00 };
68 static BYTE serialNum[] = { 1 };
69 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
70 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
71 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
72 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
73 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
74 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
75 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
76 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
77 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
78 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
79 static BYTE bigCertHash[] = { 0x6e, 0x30, 0x90, 0x71, 0x5f, 0xd9, 0x23,
80 0x56, 0xeb, 0xae, 0x25, 0x40, 0xe6, 0x22, 0xda, 0x19, 0x26, 0x02, 0xa6, 0x08 };
82 static const BYTE bigCertWithDifferentSubject[] = { 0x30, 0x7a, 0x02, 0x01, 0x02,
83 0x30, 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
84 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67,
85 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31,
86 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
87 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15,
88 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c,
89 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06,
90 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55,
91 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02,
92 0x01, 0x01 };
93 static const BYTE bigCertWithDifferentIssuer[] = { 0x30, 0x7a, 0x02, 0x01,
94 0x01, 0x30, 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
95 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e,
96 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
97 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30,
98 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30,
99 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
100 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02,
101 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03,
102 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff,
103 0x02, 0x01, 0x01 };
105 static BYTE subjectName2[] = { 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
106 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61,
107 0x6e, 0x67, 0x00 };
108 static const BYTE bigCert2[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
109 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
110 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
111 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
112 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
113 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
114 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20,
115 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
116 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
117 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
118 static const BYTE bigCert2WithDifferentSerial[] = { 0x30, 0x7a, 0x02, 0x01,
119 0x02, 0x30, 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
120 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e,
121 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
122 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30,
123 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30,
124 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41,
125 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02,
126 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03,
127 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff,
128 0x02, 0x01, 0x01 };
129 static BYTE bigCert2Hash[] = { 0x4a, 0x7f, 0x32, 0x1f, 0xcf, 0x3b, 0xc0,
130 0x87, 0x48, 0x2b, 0xa1, 0x86, 0x54, 0x18, 0xe4, 0x3a, 0x0e, 0x53, 0x7e, 0x2b };
132 static const BYTE certWithUsage[] = { 0x30, 0x81, 0x93, 0x02, 0x01, 0x01, 0x30,
133 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04,
134 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00,
135 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
136 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
137 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31,
138 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61,
139 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00,
140 0x03, 0x01, 0x00, 0xa3, 0x2f, 0x30, 0x2d, 0x30, 0x2b, 0x06, 0x03, 0x55, 0x1d,
141 0x25, 0x01, 0x01, 0xff, 0x04, 0x21, 0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01,
142 0x05, 0x05, 0x07, 0x03, 0x03, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
143 0x03, 0x02, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
145 static void testAddCert(void)
147 HCERTSTORE store;
148 HCERTSTORE collection;
149 PCCERT_CONTEXT context;
150 PCCERT_CONTEXT copyContext;
151 BOOL ret;
153 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
154 CERT_STORE_CREATE_NEW_FLAG, NULL);
155 ok(store != NULL, "CertOpenStore failed: %d\n", GetLastError());
156 if (!store)
157 return;
159 /* Weird--bad add disposition leads to an access violation in Windows.
160 * Both tests crash on some win9x boxes.
162 if (0)
164 ret = CertAddEncodedCertificateToStore(0, X509_ASN_ENCODING, bigCert,
165 sizeof(bigCert), 0, NULL);
166 ok(!ret && (GetLastError() == STATUS_ACCESS_VIOLATION ||
167 GetLastError() == E_INVALIDARG),
168 "Expected STATUS_ACCESS_VIOLATION or E_INVALIDARG, got %08x\n",
169 GetLastError());
170 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
171 bigCert, sizeof(bigCert), 0, NULL);
172 ok(!ret && (GetLastError() == STATUS_ACCESS_VIOLATION ||
173 GetLastError() == E_INVALIDARG),
174 "Expected STATUS_ACCESS_VIOLATION or E_INVALIDARG, got %08x\n",
175 GetLastError());
178 /* Weird--can add a cert to the NULL store (does this have special
179 * meaning?)
181 context = NULL;
182 ret = CertAddEncodedCertificateToStore(0, X509_ASN_ENCODING, bigCert,
183 sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
184 ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* win98 */),
185 "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
186 if (context)
187 CertFreeCertificateContext(context);
188 if (!ret && GetLastError() == OSS_DATA_ERROR)
190 skip("bigCert can't be decoded, skipping tests\n");
191 return;
194 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
195 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
196 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
197 GetLastError());
198 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
199 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, NULL);
200 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
201 GetLastError());
202 /* This has the same name as bigCert, so finding isn't done by name */
203 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
204 certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, &context);
205 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
206 GetLastError());
207 ok(context != NULL, "Expected a context\n");
208 if (context)
210 CRYPT_DATA_BLOB hash = { sizeof(bigCert2Hash), bigCert2Hash };
212 /* Duplicate (AddRef) the context so we can still use it after
213 * deleting it from the store.
215 CertDuplicateCertificateContext(context);
216 CertDeleteCertificateFromStore(context);
217 /* Set the same hash as bigCert2, and try to readd it */
218 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID,
219 0, &hash);
220 ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
221 GetLastError());
222 ret = CertAddCertificateContextToStore(store, context,
223 CERT_STORE_ADD_NEW, NULL);
224 /* The failure is a bit odd (CRYPT_E_ASN1_BADTAG), so just check
225 * that it fails.
227 ok(!ret, "Expected failure\n");
228 CertFreeCertificateContext(context);
230 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert2,
231 sizeof(bigCert2));
232 ok(context != NULL, "Expected a context\n");
233 if (context)
235 /* Try to readd bigCert2 to the store */
236 ret = CertAddCertificateContextToStore(store, context,
237 CERT_STORE_ADD_NEW, NULL);
238 ok(!ret && GetLastError() == CRYPT_E_EXISTS,
239 "Expected CRYPT_E_EXISTS, got %08x\n", GetLastError());
240 CertFreeCertificateContext(context);
243 /* Adding a cert with the same issuer name and serial number (but
244 * different subject) as an existing cert succeeds.
246 context = NULL;
247 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
248 bigCert2WithDifferentSerial, sizeof(bigCert2WithDifferentSerial),
249 CERT_STORE_ADD_NEW, &context);
250 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
251 GetLastError());
252 if (context)
253 CertDeleteCertificateFromStore(context);
255 /* Adding a cert with the same subject name and serial number (but
256 * different issuer) as an existing cert succeeds.
258 context = NULL;
259 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
260 bigCertWithDifferentSubject, sizeof(bigCertWithDifferentSubject),
261 CERT_STORE_ADD_NEW, &context);
262 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
263 GetLastError());
264 if (context)
265 CertDeleteCertificateFromStore(context);
267 /* Adding a cert with the same issuer name and serial number (but
268 * different otherwise) as an existing cert succeeds.
270 context = NULL;
271 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
272 bigCertWithDifferentIssuer, sizeof(bigCertWithDifferentIssuer),
273 CERT_STORE_ADD_NEW, &context);
274 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
275 GetLastError());
276 if (context)
277 CertDeleteCertificateFromStore(context);
279 collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
280 CERT_STORE_CREATE_NEW_FLAG, NULL);
281 ok(collection != NULL, "CertOpenStore failed: %08x\n", GetLastError());
282 if (collection && pCertAddStoreToCollection)
284 /* Add store to the collection, but disable updates */
285 pCertAddStoreToCollection(collection, store, 0, 0);
287 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert2,
288 sizeof(bigCert2));
289 ok(context != NULL, "Expected a context\n");
290 if (context)
292 /* Try to readd bigCert2 to the collection */
293 ret = CertAddCertificateContextToStore(collection, context,
294 CERT_STORE_ADD_NEW, NULL);
295 ok(!ret && GetLastError() == CRYPT_E_EXISTS,
296 "Expected CRYPT_E_EXISTS, got %08x\n", GetLastError());
297 /* Replacing an existing certificate context is allowed, even
298 * though updates to the collection aren't..
300 ret = CertAddCertificateContextToStore(collection, context,
301 CERT_STORE_ADD_REPLACE_EXISTING, NULL);
302 ok(ret, "CertAddCertificateContextToStore failed: %08x\n",
303 GetLastError());
304 /* use the existing certificate and ask for a copy of the context*/
305 copyContext = NULL;
306 ret = CertAddCertificateContextToStore(collection, context,
307 CERT_STORE_ADD_USE_EXISTING, &copyContext);
308 ok(ret, "CertAddCertificateContextToStore failed: %08x\n",
309 GetLastError());
310 ok(copyContext != NULL, "Expected on output a non NULL copyContext\n");
311 if (copyContext)
312 CertFreeCertificateContext(copyContext);
313 /* but adding a new certificate isn't allowed. */
314 ret = CertAddCertificateContextToStore(collection, context,
315 CERT_STORE_ADD_ALWAYS, NULL);
316 ok(!ret && GetLastError() == E_ACCESSDENIED,
317 "Expected E_ACCESSDENIED, got %08x\n", GetLastError());
318 CertFreeCertificateContext(context);
321 CertCloseStore(collection, 0);
324 CertCloseStore(store, 0);
327 static void checkHash(const BYTE *data, DWORD dataLen, ALG_ID algID,
328 PCCERT_CONTEXT context, DWORD propID)
330 BYTE hash[20] = { 0 }, hashProperty[20];
331 BOOL ret;
332 DWORD size;
333 DWORD dwSizeWithNull;
335 memset(hash, 0, sizeof(hash));
336 memset(hashProperty, 0, sizeof(hashProperty));
337 size = sizeof(hash);
338 ret = CryptHashCertificate(0, algID, 0, data, dataLen, hash, &size);
339 ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
340 ret = CertGetCertificateContextProperty(context, propID, NULL,
341 &dwSizeWithNull);
342 ok(ret, "algID %08x, propID %d: CertGetCertificateContextProperty failed: %08x\n",
343 algID, propID, GetLastError());
344 ret = CertGetCertificateContextProperty(context, propID, hashProperty,
345 &size);
346 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
347 GetLastError());
348 ok(!memcmp(hash, hashProperty, size), "Unexpected hash for property %d\n",
349 propID);
350 ok(size == dwSizeWithNull, "Unexpected length of hash for property: received %d instead of %d\n",
351 dwSizeWithNull,size);
354 static CHAR cspNameA[] = "WineCryptTemp";
355 static WCHAR cspNameW[] = { 'W','i','n','e','C','r','y','p','t','T','e','m','p',0 };
356 static const BYTE v1CertWithPubKey[] = {
357 0x30,0x81,0x95,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
358 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
359 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
360 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
361 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
362 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
363 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
364 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
365 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,
366 0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,
367 0x01,0x01 };
368 static const BYTE v1CertWithSubjectKeyId[] = {
369 0x30,0x7b,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
370 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
371 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
372 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
373 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
374 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
375 0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x17,0x30,0x15,0x30,
376 0x13,0x06,0x03,0x55,0x1d,0x0e,0x04,0x0c,0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,
377 0x4c,0x61,0x6e,0x67,0x00 };
378 static const BYTE subjectKeyId[] = {
379 0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
380 static const BYTE selfSignedCert[] = {
381 0x30, 0x82, 0x01, 0x1f, 0x30, 0x81, 0xce, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
382 0x10, 0xeb, 0x0d, 0x57, 0x2a, 0x9c, 0x09, 0xba, 0xa4, 0x4a, 0xb7, 0x25, 0x49,
383 0xd9, 0x3e, 0xb5, 0x73, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d,
384 0x05, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
385 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30,
386 0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x36, 0x32, 0x39, 0x30, 0x35, 0x30, 0x30,
387 0x34, 0x36, 0x5a, 0x17, 0x0d, 0x30, 0x37, 0x30, 0x36, 0x32, 0x39, 0x31, 0x31,
388 0x30, 0x30, 0x34, 0x36, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
389 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e,
390 0x67, 0x00, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
391 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
392 0x00, 0xe2, 0x54, 0x3a, 0xa7, 0x83, 0xb1, 0x27, 0x14, 0x3e, 0x59, 0xbb, 0xb4,
393 0x53, 0xe6, 0x1f, 0xe7, 0x5d, 0xf1, 0x21, 0x68, 0xad, 0x85, 0x53, 0xdb, 0x6b,
394 0x1e, 0xeb, 0x65, 0x97, 0x03, 0x86, 0x60, 0xde, 0xf3, 0x6c, 0x38, 0x75, 0xe0,
395 0x4c, 0x61, 0xbb, 0xbc, 0x62, 0x17, 0xa9, 0xcd, 0x79, 0x3f, 0x21, 0x4e, 0x96,
396 0xcb, 0x0e, 0xdc, 0x61, 0x94, 0x30, 0x18, 0x10, 0x6b, 0xd0, 0x1c, 0x10, 0x79,
397 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
398 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x25, 0x90, 0x53, 0x34, 0xd9, 0x56, 0x41,
399 0x5e, 0xdb, 0x7e, 0x01, 0x36, 0xec, 0x27, 0x61, 0x5e, 0xb7, 0x4d, 0x90, 0x66,
400 0xa2, 0xe1, 0x9d, 0x58, 0x76, 0xd4, 0x9c, 0xba, 0x2c, 0x84, 0xc6, 0x83, 0x7a,
401 0x22, 0x0d, 0x03, 0x69, 0x32, 0x1a, 0x6d, 0xcb, 0x0c, 0x15, 0xb3, 0x6b, 0xc7,
402 0x0a, 0x8c, 0xb4, 0x5c, 0x34, 0x78, 0xe0, 0x3c, 0x9c, 0xe9, 0xf3, 0x30, 0x9f,
403 0xa8, 0x76, 0x57, 0x92, 0x36 };
404 static const BYTE selfSignedSignatureHash[] = { 0x07,0x5a,0x3e,0xfd,0x0d,0xf6,
405 0x88,0xeb,0x00,0x64,0xbd,0xc9,0xd6,0xea,0x0a,0x7c,0xcc,0x24,0xdb,0x5d };
407 static void testCertProperties(void)
409 PCCERT_CONTEXT context = CertCreateCertificateContext(X509_ASN_ENCODING,
410 bigCert, sizeof(bigCert));
411 DWORD propID, numProps, access, size;
412 BOOL ret;
413 BYTE hash[20] = { 0 }, hashProperty[20];
414 CRYPT_DATA_BLOB blob;
415 CERT_KEY_CONTEXT keyContext;
417 ok(context != NULL || broken(GetLastError() == OSS_DATA_ERROR /* win98 */),
418 "CertCreateCertificateContext failed: %08x\n", GetLastError());
419 if (!context)
420 return;
422 /* This crashes
423 propID = CertEnumCertificateContextProperties(NULL, 0);
426 propID = 0;
427 numProps = 0;
428 do {
429 propID = CertEnumCertificateContextProperties(context, propID);
430 if (propID)
431 numProps++;
432 } while (propID != 0);
433 ok(numProps == 0, "Expected 0 properties, got %d\n", numProps);
435 /* Tests with a NULL cert context. Prop ID 0 fails.. */
436 ret = CertSetCertificateContextProperty(NULL, 0, 0, NULL);
437 ok(!ret && GetLastError() == E_INVALIDARG,
438 "Expected E_INVALIDARG, got %08x\n", GetLastError());
439 /* while this just crashes.
440 ret = CertSetCertificateContextProperty(NULL,
441 CERT_KEY_PROV_HANDLE_PROP_ID, 0, NULL);
444 ret = CertSetCertificateContextProperty(context, 0, 0, NULL);
445 ok(!ret && GetLastError() == E_INVALIDARG,
446 "Expected E_INVALIDARG, got %08x\n", GetLastError());
447 /* Can't set the cert property directly, this crashes.
448 ret = CertSetCertificateContextProperty(context,
449 CERT_CERT_PROP_ID, 0, bigCert2);
452 /* These all crash.
453 ret = CertGetCertificateContextProperty(context,
454 CERT_ACCESS_STATE_PROP_ID, 0, NULL);
455 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
456 NULL, NULL);
457 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
458 hashProperty, NULL);
460 /* A missing prop */
461 size = 0;
462 ret = CertGetCertificateContextProperty(context,
463 CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
464 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
465 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
466 /* And, an implicit property */
467 size = sizeof(access);
468 ret = CertGetCertificateContextProperty(context,
469 CERT_ACCESS_STATE_PROP_ID, &access, &size);
470 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
471 GetLastError());
472 ok(!(access & CERT_ACCESS_STATE_WRITE_PERSIST_FLAG),
473 "Didn't expect a persisted cert\n");
474 /* Trying to set this "read only" property crashes.
475 access |= CERT_ACCESS_STATE_WRITE_PERSIST_FLAG;
476 ret = CertSetCertificateContextProperty(context,
477 CERT_ACCESS_STATE_PROP_ID, 0, &access);
480 /* Can I set the hash to an invalid hash? */
481 blob.pbData = hash;
482 blob.cbData = sizeof(hash);
483 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID, 0,
484 &blob);
485 ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
486 GetLastError());
487 size = sizeof(hashProperty);
488 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
489 hashProperty, &size);
490 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
491 GetLastError());
492 ok(!memcmp(hashProperty, hash, sizeof(hash)), "Unexpected hash\n");
493 /* Delete the (bogus) hash, and get the real one */
494 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID, 0,
495 NULL);
496 ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
497 GetLastError());
498 checkHash(bigCert, sizeof(bigCert), CALG_SHA1, context,
499 CERT_HASH_PROP_ID);
501 /* Now that the hash property is set, we should get one property when
502 * enumerating.
504 propID = 0;
505 numProps = 0;
506 do {
507 propID = CertEnumCertificateContextProperties(context, propID);
508 if (propID)
509 numProps++;
510 } while (propID != 0);
511 ok(numProps == 1, "Expected 1 properties, got %d\n", numProps);
513 /* Check a few other implicit properties */
514 checkHash(bigCert, sizeof(bigCert), CALG_MD5, context,
515 CERT_MD5_HASH_PROP_ID);
517 /* Getting the signature hash fails with this bogus certificate */
518 size = 0;
519 ret = CertGetCertificateContextProperty(context,
520 CERT_SIGNATURE_HASH_PROP_ID, NULL, &size);
521 ok(!ret &&
522 (GetLastError() == CRYPT_E_ASN1_BADTAG ||
523 GetLastError() == CRYPT_E_NOT_FOUND ||
524 GetLastError() == OSS_DATA_ERROR), /* win9x */
525 "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
527 /* Test key contexts and handles and such */
528 size = 0;
529 ret = CertGetCertificateContextProperty(context, CERT_KEY_CONTEXT_PROP_ID,
530 NULL, &size);
531 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
532 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
533 size = sizeof(CERT_KEY_CONTEXT);
534 ret = CertGetCertificateContextProperty(context, CERT_KEY_CONTEXT_PROP_ID,
535 NULL, &size);
536 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
537 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
538 ret = CertGetCertificateContextProperty(context, CERT_KEY_CONTEXT_PROP_ID,
539 &keyContext, &size);
540 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
541 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
542 /* Key context with an invalid size */
543 keyContext.cbSize = 0;
544 ret = CertSetCertificateContextProperty(context, CERT_KEY_CONTEXT_PROP_ID,
545 0, &keyContext);
546 ok(!ret && GetLastError() == E_INVALIDARG,
547 "Expected E_INVALIDARG, got %08x\n", GetLastError());
548 size = sizeof(keyContext);
549 ret = CertGetCertificateContextProperty(context, CERT_KEY_CONTEXT_PROP_ID,
550 &keyContext, &size);
551 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
552 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
553 keyContext.cbSize = sizeof(keyContext);
554 keyContext.hCryptProv = 0;
555 keyContext.dwKeySpec = AT_SIGNATURE;
556 ret = CertSetCertificateContextProperty(context, CERT_KEY_CONTEXT_PROP_ID,
557 0, &keyContext);
558 ok(ret, "CertSetCertificateContextProperty failed: %08x\n", GetLastError());
559 /* Now that that's set, the key prov handle property is also gettable.
561 size = sizeof(keyContext.hCryptProv);
562 ret = CertGetCertificateContextProperty(context,
563 CERT_KEY_PROV_HANDLE_PROP_ID, &keyContext.hCryptProv, &size);
564 ok(ret, "Expected to get the CERT_KEY_PROV_HANDLE_PROP_ID, got %08x\n",
565 GetLastError());
566 /* Remove the key prov handle property.. */
567 ret = CertSetCertificateContextProperty(context,
568 CERT_KEY_PROV_HANDLE_PROP_ID, 0, NULL);
569 ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
570 GetLastError());
571 /* and the key context's CSP is set to NULL. */
572 size = sizeof(keyContext);
573 ret = CertGetCertificateContextProperty(context,
574 CERT_KEY_CONTEXT_PROP_ID, &keyContext, &size);
575 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
576 GetLastError());
577 ok(keyContext.hCryptProv == 0, "Expected no hCryptProv\n");
579 /* According to MSDN the subject key id can be stored as a property,
580 * as a subject key extension, or as the SHA1 hash of the public key,
581 * but this cert has none of them:
583 ret = CertGetCertificateContextProperty(context,
584 CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size);
585 ok(!ret && GetLastError() == ERROR_INVALID_DATA,
586 "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
587 CertFreeCertificateContext(context);
588 /* This cert does have a public key, but its subject key identifier still
589 * isn't available: */
590 context = CertCreateCertificateContext(X509_ASN_ENCODING,
591 v1CertWithPubKey, sizeof(v1CertWithPubKey));
592 ret = CertGetCertificateContextProperty(context,
593 CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size);
594 ok(!ret && GetLastError() == ERROR_INVALID_DATA,
595 "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
596 CertFreeCertificateContext(context);
597 /* This cert with a subject key extension can have its key identifier
598 * property retrieved:
600 context = CertCreateCertificateContext(X509_ASN_ENCODING,
601 v1CertWithSubjectKeyId, sizeof(v1CertWithSubjectKeyId));
602 ret = CertGetCertificateContextProperty(context,
603 CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size);
604 ok(ret, "CertGetCertificateContextProperty failed: %08x\n", GetLastError());
605 if (ret)
607 LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, size);
609 if (buf)
611 ret = CertGetCertificateContextProperty(context,
612 CERT_KEY_IDENTIFIER_PROP_ID, buf, &size);
613 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
614 GetLastError());
615 ok(!memcmp(buf, subjectKeyId, size), "Unexpected subject key id\n");
616 HeapFree(GetProcessHeap(), 0, buf);
619 CertFreeCertificateContext(context);
621 context = CertCreateCertificateContext(X509_ASN_ENCODING,
622 selfSignedCert, sizeof(selfSignedCert));
623 /* Getting the signature hash of a valid (self-signed) cert succeeds */
624 size = 0;
625 ret = CertGetCertificateContextProperty(context,
626 CERT_SIGNATURE_HASH_PROP_ID, NULL, &size);
627 ok(ret, "CertGetCertificateContextProperty failed: %08x\n", GetLastError());
628 ok(size == sizeof(selfSignedSignatureHash), "unexpected size %d\n", size);
629 ret = CertGetCertificateContextProperty(context,
630 CERT_SIGNATURE_HASH_PROP_ID, hashProperty, &size);
631 if (ret)
632 ok(!memcmp(hashProperty, selfSignedSignatureHash, size),
633 "unexpected value\n");
634 CertFreeCertificateContext(context);
637 static void testCreateCert(void)
639 PCCERT_CONTEXT cert, enumCert;
640 DWORD count, size;
641 BOOL ret;
643 SetLastError(0xdeadbeef);
644 cert = CertCreateCertificateContext(0, NULL, 0);
645 ok(!cert && GetLastError() == E_INVALIDARG,
646 "expected E_INVALIDARG, got %08x\n", GetLastError());
647 SetLastError(0xdeadbeef);
648 cert = CertCreateCertificateContext(0, selfSignedCert,
649 sizeof(selfSignedCert));
650 ok(!cert && GetLastError() == E_INVALIDARG,
651 "expected E_INVALIDARG, got %08x\n", GetLastError());
652 SetLastError(0xdeadbeef);
653 cert = CertCreateCertificateContext(X509_ASN_ENCODING, NULL, 0);
654 ok(!cert &&
655 (GetLastError() == CRYPT_E_ASN1_EOD ||
656 broken(GetLastError() == OSS_MORE_INPUT /* NT4 */)),
657 "expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
659 cert = CertCreateCertificateContext(X509_ASN_ENCODING,
660 selfSignedCert, sizeof(selfSignedCert));
661 ok(cert != NULL, "creating cert failed: %08x\n", GetLastError());
662 /* Even in-memory certs are expected to have a store associated with them */
663 todo_wine
664 ok(cert->hCertStore != NULL, "expected created cert to have a store\n");
665 /* The cert doesn't have the archived property set (which would imply it
666 * doesn't show up in enumerations.)
668 size = 0;
669 ret = CertGetCertificateContextProperty(cert, CERT_ARCHIVED_PROP_ID,
670 NULL, &size);
671 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
672 "expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
673 /* Strangely, enumerating the certs in the store finds none. */
674 enumCert = NULL;
675 count = 0;
676 while ((enumCert = CertEnumCertificatesInStore(cert->hCertStore, enumCert)))
677 count++;
678 ok(!count, "expected 0, got %d\n", count);
679 CertFreeCertificateContext(cert);
682 static void testDupCert(void)
684 HCERTSTORE store;
685 PCCERT_CONTEXT context, dupContext;
686 BOOL ret;
688 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
689 CERT_STORE_CREATE_NEW_FLAG, NULL);
690 ok(store != NULL, "CertOpenStore failed: %d\n", GetLastError());
691 if (!store)
692 return;
694 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
695 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
696 ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* win98 */),
697 "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
698 if (!ret && GetLastError() == OSS_DATA_ERROR)
700 skip("bigCert can't be decoded, skipping tests\n");
701 return;
703 ok(context != NULL, "Expected a valid cert context\n");
704 if (context)
706 ok(context->cbCertEncoded == sizeof(bigCert),
707 "Wrong cert size %d\n", context->cbCertEncoded);
708 ok(!memcmp(context->pbCertEncoded, bigCert, sizeof(bigCert)),
709 "Unexpected encoded cert in context\n");
710 ok(context->hCertStore == store, "Unexpected store\n");
712 dupContext = CertDuplicateCertificateContext(context);
713 ok(dupContext != NULL, "Expected valid duplicate\n");
714 /* Not only is it a duplicate, it's identical: the address is the
715 * same.
717 ok(dupContext == context, "Expected identical context addresses\n");
718 CertFreeCertificateContext(dupContext);
719 CertFreeCertificateContext(context);
721 CertCloseStore(store, 0);
723 SetLastError(0xdeadbeef);
724 context = CertDuplicateCertificateContext(NULL);
725 ok(context == NULL, "Expected context to be NULL\n");
728 static BYTE subjectName3[] = { 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
729 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x52, 0x6f, 0x62, 0x20, 0x20, 0x4c, 0x61,
730 0x6e, 0x67, 0x00 };
731 static const BYTE iTunesCert0[] = {
732 0x30,0x82,0x03,0xc4,0x30,0x82,0x03,0x2d,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,
733 0x47,0xbf,0x19,0x95,0xdf,0x8d,0x52,0x46,0x43,0xf7,0xdb,0x6d,0x48,0x0d,0x31,
734 0xa4,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,
735 0x00,0x30,0x81,0x8b,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,
736 0x5a,0x41,0x31,0x15,0x30,0x13,0x06,0x03,0x55,0x04,0x08,0x13,0x0c,0x57,0x65,
737 0x73,0x74,0x65,0x72,0x6e,0x20,0x43,0x61,0x70,0x65,0x31,0x14,0x30,0x12,0x06,
738 0x03,0x55,0x04,0x07,0x13,0x0b,0x44,0x75,0x72,0x62,0x61,0x6e,0x76,0x69,0x6c,
739 0x6c,0x65,0x31,0x0f,0x30,0x0d,0x06,0x03,0x55,0x04,0x0a,0x13,0x06,0x54,0x68,
740 0x61,0x77,0x74,0x65,0x31,0x1d,0x30,0x1b,0x06,0x03,0x55,0x04,0x0b,0x13,0x14,
741 0x54,0x68,0x61,0x77,0x74,0x65,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,
742 0x61,0x74,0x69,0x6f,0x6e,0x31,0x1f,0x30,0x1d,0x06,0x03,0x55,0x04,0x03,0x13,
743 0x16,0x54,0x68,0x61,0x77,0x74,0x65,0x20,0x54,0x69,0x6d,0x65,0x73,0x74,0x61,
744 0x6d,0x70,0x69,0x6e,0x67,0x20,0x43,0x41,0x30,0x1e,0x17,0x0d,0x30,0x33,0x31,
745 0x32,0x30,0x34,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,0x31,0x33,0x31,
746 0x32,0x30,0x33,0x32,0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x53,0x31,0x0b,0x30,
747 0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x17,0x30,0x15,0x06,
748 0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x2c,
749 0x20,0x49,0x6e,0x63,0x2e,0x31,0x2b,0x30,0x29,0x06,0x03,0x55,0x04,0x03,0x13,
750 0x22,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x54,0x69,0x6d,0x65,0x20,
751 0x53,0x74,0x61,0x6d,0x70,0x69,0x6e,0x67,0x20,0x53,0x65,0x72,0x76,0x69,0x63,
752 0x65,0x73,0x20,0x43,0x41,0x30,0x82,0x01,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,
753 0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0f,0x00,0x30,
754 0x82,0x01,0x0a,0x02,0x82,0x01,0x01,0x00,0xa9,0xca,0xb2,0xa4,0xcc,0xcd,0x20,
755 0xaf,0x0a,0x7d,0x89,0xac,0x87,0x75,0xf0,0xb4,0x4e,0xf1,0xdf,0xc1,0x0f,0xbf,
756 0x67,0x61,0xbd,0xa3,0x64,0x1c,0xda,0xbb,0xf9,0xca,0x33,0xab,0x84,0x30,0x89,
757 0x58,0x7e,0x8c,0xdb,0x6b,0xdd,0x36,0x9e,0x0f,0xbf,0xd1,0xec,0x78,0xf2,0x77,
758 0xa6,0x7e,0x6f,0x3c,0xbf,0x93,0xaf,0x0d,0xba,0x68,0xf4,0x6c,0x94,0xca,0xbd,
759 0x52,0x2d,0xab,0x48,0x3d,0xf5,0xb6,0xd5,0x5d,0x5f,0x1b,0x02,0x9f,0xfa,0x2f,
760 0x6b,0x1e,0xa4,0xf7,0xa3,0x9a,0xa6,0x1a,0xc8,0x02,0xe1,0x7f,0x4c,0x52,0xe3,
761 0x0e,0x60,0xec,0x40,0x1c,0x7e,0xb9,0x0d,0xde,0x3f,0xc7,0xb4,0xdf,0x87,0xbd,
762 0x5f,0x7a,0x6a,0x31,0x2e,0x03,0x99,0x81,0x13,0xa8,0x47,0x20,0xce,0x31,0x73,
763 0x0d,0x57,0x2d,0xcd,0x78,0x34,0x33,0x95,0x12,0x99,0x12,0xb9,0xde,0x68,0x2f,
764 0xaa,0xe6,0xe3,0xc2,0x8a,0x8c,0x2a,0xc3,0x8b,0x21,0x87,0x66,0xbd,0x83,0x58,
765 0x57,0x6f,0x75,0xbf,0x3c,0xaa,0x26,0x87,0x5d,0xca,0x10,0x15,0x3c,0x9f,0x84,
766 0xea,0x54,0xc1,0x0a,0x6e,0xc4,0xfe,0xc5,0x4a,0xdd,0xb9,0x07,0x11,0x97,0x22,
767 0x7c,0xdb,0x3e,0x27,0xd1,0x1e,0x78,0xec,0x9f,0x31,0xc9,0xf1,0xe6,0x22,0x19,
768 0xdb,0xc4,0xb3,0x47,0x43,0x9a,0x1a,0x5f,0xa0,0x1e,0x90,0xe4,0x5e,0xf5,0xee,
769 0x7c,0xf1,0x7d,0xab,0x62,0x01,0x8f,0xf5,0x4d,0x0b,0xde,0xd0,0x22,0x56,0xa8,
770 0x95,0xcd,0xae,0x88,0x76,0xae,0xee,0xba,0x0d,0xf3,0xe4,0x4d,0xd9,0xa0,0xfb,
771 0x68,0xa0,0xae,0x14,0x3b,0xb3,0x87,0xc1,0xbb,0x02,0x03,0x01,0x00,0x01,0xa3,
772 0x81,0xdb,0x30,0x81,0xd8,0x30,0x34,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,
773 0x01,0x01,0x04,0x28,0x30,0x26,0x30,0x24,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,
774 0x07,0x30,0x01,0x86,0x18,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6f,0x63,0x73,
775 0x70,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x30,
776 0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,
777 0xff,0x02,0x01,0x00,0x30,0x41,0x06,0x03,0x55,0x1d,0x1f,0x04,0x3a,0x30,0x38,
778 0x30,0x36,0xa0,0x34,0xa0,0x32,0x86,0x30,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
779 0x63,0x72,0x6c,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,
780 0x6d,0x2f,0x54,0x68,0x61,0x77,0x74,0x65,0x54,0x69,0x6d,0x65,0x73,0x74,0x61,
781 0x6d,0x70,0x69,0x6e,0x67,0x43,0x41,0x2e,0x63,0x72,0x6c,0x30,0x13,0x06,0x03,
782 0x55,0x1d,0x25,0x04,0x0c,0x30,0x0a,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,
783 0x03,0x08,0x30,0x0e,0x06,0x03,0x55,0x1d,0x0f,0x01,0x01,0xff,0x04,0x04,0x03,
784 0x02,0x01,0x06,0x30,0x24,0x06,0x03,0x55,0x1d,0x11,0x04,0x1d,0x30,0x1b,0xa4,
785 0x19,0x30,0x17,0x31,0x15,0x30,0x13,0x06,0x03,0x55,0x04,0x03,0x13,0x0c,0x54,
786 0x53,0x41,0x32,0x30,0x34,0x38,0x2d,0x31,0x2d,0x35,0x33,0x30,0x0d,0x06,0x09,
787 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x03,0x81,0x81,0x00,
788 0x4a,0x6b,0xf9,0xea,0x58,0xc2,0x44,0x1c,0x31,0x89,0x79,0x99,0x2b,0x96,0xbf,
789 0x82,0xac,0x01,0xd6,0x1c,0x4c,0xcd,0xb0,0x8a,0x58,0x6e,0xdf,0x08,0x29,0xa3,
790 0x5e,0xc8,0xca,0x93,0x13,0xe7,0x04,0x52,0x0d,0xef,0x47,0x27,0x2f,0x00,0x38,
791 0xb0,0xe4,0xc9,0x93,0x4e,0x9a,0xd4,0x22,0x62,0x15,0xf7,0x3f,0x37,0x21,0x4f,
792 0x70,0x31,0x80,0xf1,0x8b,0x38,0x87,0xb3,0xe8,0xe8,0x97,0x00,0xfe,0xcf,0x55,
793 0x96,0x4e,0x24,0xd2,0xa9,0x27,0x4e,0x7a,0xae,0xb7,0x61,0x41,0xf3,0x2a,0xce,
794 0xe7,0xc9,0xd9,0x5e,0xdd,0xbb,0x2b,0x85,0x3e,0xb5,0x9d,0xb5,0xd9,0xe1,0x57,
795 0xff,0xbe,0xb4,0xc5,0x7e,0xf5,0xcf,0x0c,0x9e,0xf0,0x97,0xfe,0x2b,0xd3,0x3b,
796 0x52,0x1b,0x1b,0x38,0x27,0xf7,0x3f,0x4a };
797 static const BYTE iTunesCert1[] = {
798 0x30,0x82,0x03,0xff,0x30,0x82,0x02,0xe7,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,
799 0x0d,0xe9,0x2b,0xf0,0xd4,0xd8,0x29,0x88,0x18,0x32,0x05,0x09,0x5e,0x9a,0x76,
800 0x88,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,
801 0x00,0x30,0x53,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,
802 0x53,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,
803 0x69,0x53,0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x2b,0x30,0x29,
804 0x06,0x03,0x55,0x04,0x03,0x13,0x22,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,
805 0x20,0x54,0x69,0x6d,0x65,0x20,0x53,0x74,0x61,0x6d,0x70,0x69,0x6e,0x67,0x20,
806 0x53,0x65,0x72,0x76,0x69,0x63,0x65,0x73,0x20,0x43,0x41,0x30,0x1e,0x17,0x0d,
807 0x30,0x33,0x31,0x32,0x30,0x34,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,
808 0x30,0x38,0x31,0x32,0x30,0x33,0x32,0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x57,
809 0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x17,
810 0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,0x69,
811 0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x2f,0x30,0x2d,0x06,0x03,0x55,
812 0x04,0x03,0x13,0x26,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x54,0x69,
813 0x6d,0x65,0x20,0x53,0x74,0x61,0x6d,0x70,0x69,0x6e,0x67,0x20,0x53,0x65,0x72,
814 0x76,0x69,0x63,0x65,0x73,0x20,0x53,0x69,0x67,0x6e,0x65,0x72,0x30,0x82,0x01,
815 0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,
816 0x00,0x03,0x82,0x01,0x0f,0x00,0x30,0x82,0x01,0x0a,0x02,0x82,0x01,0x01,0x00,
817 0xb2,0x50,0x28,0x48,0xdd,0xd3,0x68,0x7a,0x84,0x18,0x44,0x66,0x75,0x5d,0x7e,
818 0xc4,0xb8,0x9f,0x63,0x26,0xff,0x3d,0x43,0x9c,0x7c,0x11,0x38,0x10,0x25,0x55,
819 0x73,0xd9,0x75,0x27,0x69,0xfd,0x4e,0xb9,0x20,0x5c,0xd3,0x0a,0xf9,0xa0,0x1b,
820 0x2a,0xed,0x55,0x56,0x21,0x61,0xd8,0x1e,0xdb,0xe4,0xbc,0x33,0x6b,0xc7,0xef,
821 0xdd,0xa3,0x37,0x65,0x8e,0x1b,0x93,0x0c,0xb6,0x53,0x1e,0x5c,0x7c,0x66,0x35,
822 0x5f,0x05,0x8a,0x45,0xfe,0x76,0x4e,0xdf,0x53,0x80,0xa2,0x81,0x20,0x9d,0xae,
823 0x88,0x5c,0xa2,0x08,0xf7,0xe5,0x30,0xf9,0xee,0x22,0x37,0x4c,0x42,0x0a,0xce,
824 0xdf,0xc6,0x1f,0xc4,0xd6,0x55,0xe9,0x81,0x3f,0xb5,0x52,0xa3,0x2c,0xaa,0x01,
825 0x7a,0xf2,0xa2,0xaa,0x8d,0x35,0xfe,0x9f,0xe6,0x5d,0x6a,0x05,0x9f,0x3d,0x6b,
826 0xe3,0xbf,0x96,0xc0,0xfe,0xcc,0x60,0xf9,0x40,0xe7,0x07,0xa0,0x44,0xeb,0x81,
827 0x51,0x6e,0xa5,0x2a,0xf2,0xb6,0x8a,0x10,0x28,0xed,0x8f,0xdc,0x06,0xa0,0x86,
828 0x50,0x9a,0x7b,0x4a,0x08,0x0d,0x30,0x1d,0xca,0x10,0x9e,0x6b,0xf7,0xe9,0x58,
829 0xae,0x04,0xa9,0x40,0x99,0xb2,0x28,0xe8,0x8f,0x16,0xac,0x3c,0xe3,0x53,0x6f,
830 0x4b,0xd3,0x35,0x9d,0xb5,0x6f,0x64,0x1d,0xb3,0x96,0x2c,0xbb,0x3d,0xe7,0x79,
831 0xeb,0x6d,0x7a,0xf9,0x16,0xe6,0x26,0xad,0xaf,0xef,0x99,0x53,0xb7,0x40,0x2c,
832 0x95,0xb8,0x79,0xaa,0xfe,0xd4,0x52,0xab,0x29,0x74,0x7e,0x42,0xec,0x39,0x1e,
833 0xa2,0x6a,0x16,0xe6,0x59,0xbb,0x24,0x68,0xd8,0x00,0x80,0x43,0x10,0x87,0x80,
834 0x6b,0x02,0x03,0x01,0x00,0x01,0xa3,0x81,0xca,0x30,0x81,0xc7,0x30,0x34,0x06,
835 0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x28,0x30,0x26,0x30,0x24,
836 0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x18,0x68,0x74,0x74,
837 0x70,0x3a,0x2f,0x2f,0x6f,0x63,0x73,0x70,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,
838 0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x30,0x0c,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
839 0xff,0x04,0x02,0x30,0x00,0x30,0x33,0x06,0x03,0x55,0x1d,0x1f,0x04,0x2c,0x30,
840 0x2a,0x30,0x28,0xa0,0x26,0xa0,0x24,0x86,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,
841 0x2f,0x63,0x72,0x6c,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,
842 0x6f,0x6d,0x2f,0x74,0x73,0x73,0x2d,0x63,0x61,0x2e,0x63,0x72,0x6c,0x30,0x16,
843 0x06,0x03,0x55,0x1d,0x25,0x01,0x01,0xff,0x04,0x0c,0x30,0x0a,0x06,0x08,0x2b,
844 0x06,0x01,0x05,0x05,0x07,0x03,0x08,0x30,0x0e,0x06,0x03,0x55,0x1d,0x0f,0x01,
845 0x01,0xff,0x04,0x04,0x03,0x02,0x06,0xc0,0x30,0x24,0x06,0x03,0x55,0x1d,0x11,
846 0x04,0x1d,0x30,0x1b,0xa4,0x19,0x30,0x17,0x31,0x15,0x30,0x13,0x06,0x03,0x55,
847 0x04,0x03,0x13,0x0c,0x54,0x53,0x41,0x32,0x30,0x34,0x38,0x2d,0x31,0x2d,0x35,
848 0x34,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,
849 0x00,0x03,0x82,0x01,0x01,0x00,0x87,0x78,0x70,0xda,0x4e,0x52,0x01,0x20,0x5b,
850 0xe0,0x79,0xc9,0x82,0x30,0xc4,0xfd,0xb9,0x19,0x96,0xbd,0x91,0x00,0xc3,0xbd,
851 0xcd,0xcd,0xc6,0xf4,0x0e,0xd8,0xff,0xf9,0x4d,0xc0,0x33,0x62,0x30,0x11,0xc5,
852 0xf5,0x74,0x1b,0xd4,0x92,0xde,0x5f,0x9c,0x20,0x13,0xb1,0x7c,0x45,0xbe,0x50,
853 0xcd,0x83,0xe7,0x80,0x17,0x83,0xa7,0x27,0x93,0x67,0x13,0x46,0xfb,0xca,0xb8,
854 0x98,0x41,0x03,0xcc,0x9b,0x51,0x5b,0x05,0x8b,0x7f,0xa8,0x6f,0xf3,0x1b,0x50,
855 0x1b,0x24,0x2e,0xf2,0x69,0x8d,0x6c,0x22,0xf7,0xbb,0xca,0x16,0x95,0xed,0x0c,
856 0x74,0xc0,0x68,0x77,0xd9,0xeb,0x99,0x62,0x87,0xc1,0x73,0x90,0xf8,0x89,0x74,
857 0x7a,0x23,0xab,0xa3,0x98,0x7b,0x97,0xb1,0xf7,0x8f,0x29,0x71,0x4d,0x2e,0x75,
858 0x1b,0x48,0x41,0xda,0xf0,0xb5,0x0d,0x20,0x54,0xd6,0x77,0xa0,0x97,0x82,0x63,
859 0x69,0xfd,0x09,0xcf,0x8a,0xf0,0x75,0xbb,0x09,0x9b,0xd9,0xf9,0x11,0x55,0x26,
860 0x9a,0x61,0x32,0xbe,0x7a,0x02,0xb0,0x7b,0x86,0xbe,0xa2,0xc3,0x8b,0x22,0x2c,
861 0x78,0xd1,0x35,0x76,0xbc,0x92,0x73,0x5c,0xf9,0xb9,0xe6,0x4c,0x15,0x0a,0x23,
862 0xcc,0xe4,0xd2,0xd4,0x34,0x2e,0x49,0x40,0x15,0x3c,0x0f,0x60,0x7a,0x24,0xc6,
863 0xa5,0x66,0xef,0x96,0xcf,0x70,0xeb,0x3e,0xe7,0xf4,0x0d,0x7e,0xdc,0xd1,0x7c,
864 0xa3,0x76,0x71,0x69,0xc1,0x9c,0x4f,0x47,0x30,0x35,0x21,0xb1,0xa2,0xaf,0x1a,
865 0x62,0x3c,0x2b,0xd9,0x8e,0xaa,0x2a,0x07,0x7b,0xd8,0x18,0xb3,0x5c,0x7b,0xe2,
866 0x9d,0xa5,0x6f,0xfe,0x3c,0x89,0xad };
867 static const BYTE iTunesCert2[] = {
868 0x30,0x82,0x04,0xbf,0x30,0x82,0x04,0x28,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,
869 0x41,0x91,0xa1,0x5a,0x39,0x78,0xdf,0xcf,0x49,0x65,0x66,0x38,0x1d,0x4c,0x75,
870 0xc2,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,
871 0x00,0x30,0x5f,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,
872 0x53,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,
873 0x69,0x53,0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x37,0x30,0x35,
874 0x06,0x03,0x55,0x04,0x0b,0x13,0x2e,0x43,0x6c,0x61,0x73,0x73,0x20,0x33,0x20,
875 0x50,0x75,0x62,0x6c,0x69,0x63,0x20,0x50,0x72,0x69,0x6d,0x61,0x72,0x79,0x20,
876 0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x41,
877 0x75,0x74,0x68,0x6f,0x72,0x69,0x74,0x79,0x30,0x1e,0x17,0x0d,0x30,0x34,0x30,
878 0x37,0x31,0x36,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,0x31,0x34,0x30,
879 0x37,0x31,0x35,0x32,0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x81,0xb4,0x31,0x0b,
880 0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x17,0x30,0x15,
881 0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,
882 0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x1f,0x30,0x1d,0x06,0x03,0x55,0x04,0x0b,
883 0x13,0x16,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x54,0x72,0x75,0x73,
884 0x74,0x20,0x4e,0x65,0x74,0x77,0x6f,0x72,0x6b,0x31,0x3b,0x30,0x39,0x06,0x03,
885 0x55,0x04,0x0b,0x13,0x32,0x54,0x65,0x72,0x6d,0x73,0x20,0x6f,0x66,0x20,0x75,
886 0x73,0x65,0x20,0x61,0x74,0x20,0x68,0x74,0x74,0x70,0x73,0x3a,0x2f,0x2f,0x77,
887 0x77,0x77,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,
888 0x2f,0x72,0x70,0x61,0x20,0x28,0x63,0x29,0x30,0x34,0x31,0x2e,0x30,0x2c,0x06,
889 0x03,0x55,0x04,0x03,0x13,0x25,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,
890 0x43,0x6c,0x61,0x73,0x73,0x20,0x33,0x20,0x43,0x6f,0x64,0x65,0x20,0x53,0x69,
891 0x67,0x6e,0x69,0x6e,0x67,0x20,0x32,0x30,0x30,0x34,0x20,0x43,0x41,0x30,0x82,
892 0x01,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,
893 0x05,0x00,0x03,0x82,0x01,0x0f,0x00,0x30,0x82,0x01,0x0a,0x02,0x82,0x01,0x01,
894 0x00,0xbe,0xbc,0xee,0xbc,0x7e,0xef,0x83,0xeb,0xe0,0x37,0x4f,0xfb,0x03,0x10,
895 0x38,0xbe,0x08,0xd2,0x8c,0x7d,0x9d,0xfa,0x92,0x7f,0x19,0x0c,0xc2,0x6b,0xee,
896 0x42,0x52,0x8c,0xde,0xd3,0x1c,0x48,0x13,0x25,0xea,0xc1,0x63,0x7a,0xf9,0x51,
897 0x65,0xee,0xd3,0xaa,0x3b,0xf5,0xf0,0x94,0x9c,0x2b,0xfb,0xf2,0x66,0xd4,0x24,
898 0xda,0xf7,0xf5,0x9f,0x6e,0x19,0x39,0x36,0xbc,0xd0,0xa3,0x76,0x08,0x1e,0x22,
899 0x27,0x24,0x6c,0x38,0x91,0x27,0xe2,0x84,0x49,0xae,0x1b,0x8a,0xa1,0xfd,0x25,
900 0x82,0x2c,0x10,0x30,0xe8,0x71,0xab,0x28,0xe8,0x77,0x4a,0x51,0xf1,0xec,0xcd,
901 0xf8,0xf0,0x54,0xd4,0x6f,0xc0,0xe3,0x6d,0x0a,0x8f,0xd9,0xd8,0x64,0x8d,0x63,
902 0xb2,0x2d,0x4e,0x27,0xf6,0x85,0x0e,0xfe,0x6d,0xe3,0x29,0x99,0xe2,0x85,0x47,
903 0x7c,0x2d,0x86,0x7f,0xe8,0x57,0x8f,0xad,0x67,0xc2,0x33,0x32,0x91,0x13,0x20,
904 0xfc,0xa9,0x23,0x14,0x9a,0x6d,0xc2,0x84,0x4b,0x76,0x68,0x04,0xd5,0x71,0x2c,
905 0x5d,0x21,0xfa,0x88,0x0d,0x26,0xfd,0x1f,0x2d,0x91,0x2b,0xe7,0x01,0x55,0x4d,
906 0xf2,0x6d,0x35,0x28,0x82,0xdf,0xd9,0x6b,0x5c,0xb6,0xd6,0xd9,0xaa,0x81,0xfd,
907 0x5f,0xcd,0x83,0xba,0x63,0x9d,0xd0,0x22,0xfc,0xa9,0x3b,0x42,0x69,0xb2,0x8e,
908 0x3a,0xb5,0xbc,0xb4,0x9e,0x0f,0x5e,0xc4,0xea,0x2c,0x82,0x8b,0x28,0xfd,0x53,
909 0x08,0x96,0xdd,0xb5,0x01,0x20,0xd1,0xf9,0xa5,0x18,0xe7,0xc0,0xee,0x51,0x70,
910 0x37,0xe1,0xb6,0x05,0x48,0x52,0x48,0x6f,0x38,0xea,0xc3,0xe8,0x6c,0x7b,0x44,
911 0x84,0xbb,0x02,0x03,0x01,0x00,0x01,0xa3,0x82,0x01,0xa0,0x30,0x82,0x01,0x9c,
912 0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,
913 0x01,0xff,0x02,0x01,0x00,0x30,0x44,0x06,0x03,0x55,0x1d,0x20,0x04,0x3d,0x30,
914 0x3b,0x30,0x39,0x06,0x0b,0x60,0x86,0x48,0x01,0x86,0xf8,0x45,0x01,0x07,0x17,
915 0x03,0x30,0x2a,0x30,0x28,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x02,0x01,
916 0x16,0x1c,0x68,0x74,0x74,0x70,0x73,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x76,
917 0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x2f,0x72,0x70,0x61,
918 0x30,0x31,0x06,0x03,0x55,0x1d,0x1f,0x04,0x2a,0x30,0x28,0x30,0x26,0xa0,0x24,
919 0xa0,0x22,0x86,0x20,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x63,0x72,0x6c,0x2e,
920 0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x2f,0x70,0x63,
921 0x61,0x33,0x2e,0x63,0x72,0x6c,0x30,0x1d,0x06,0x03,0x55,0x1d,0x25,0x04,0x16,
922 0x30,0x14,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x03,0x02,0x06,0x08,0x2b,
923 0x06,0x01,0x05,0x05,0x07,0x03,0x03,0x30,0x0e,0x06,0x03,0x55,0x1d,0x0f,0x01,
924 0x01,0xff,0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x11,0x06,0x09,0x60,0x86,0x48,
925 0x01,0x86,0xf8,0x42,0x01,0x01,0x04,0x04,0x03,0x02,0x00,0x01,0x30,0x29,0x06,
926 0x03,0x55,0x1d,0x11,0x04,0x22,0x30,0x20,0xa4,0x1e,0x30,0x1c,0x31,0x1a,0x30,
927 0x18,0x06,0x03,0x55,0x04,0x03,0x13,0x11,0x43,0x6c,0x61,0x73,0x73,0x33,0x43,
928 0x41,0x32,0x30,0x34,0x38,0x2d,0x31,0x2d,0x34,0x33,0x30,0x1d,0x06,0x03,0x55,
929 0x1d,0x0e,0x04,0x16,0x04,0x14,0x08,0xf5,0x51,0xe8,0xfb,0xfe,0x3d,0x3d,0x64,
930 0x36,0x7c,0x68,0xcf,0x5b,0x78,0xa8,0xdf,0xb9,0xc5,0x37,0x30,0x81,0x80,0x06,
931 0x03,0x55,0x1d,0x23,0x04,0x79,0x30,0x77,0xa1,0x63,0xa4,0x61,0x30,0x5f,0x31,
932 0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x17,0x30,
933 0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,0x69,0x67,
934 0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x37,0x30,0x35,0x06,0x03,0x55,0x04,
935 0x0b,0x13,0x2e,0x43,0x6c,0x61,0x73,0x73,0x20,0x33,0x20,0x50,0x75,0x62,0x6c,
936 0x69,0x63,0x20,0x50,0x72,0x69,0x6d,0x61,0x72,0x79,0x20,0x43,0x65,0x72,0x74,
937 0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x41,0x75,0x74,0x68,0x6f,
938 0x72,0x69,0x74,0x79,0x82,0x10,0x70,0xba,0xe4,0x1d,0x10,0xd9,0x29,0x34,0xb6,
939 0x38,0xca,0x7b,0x03,0xcc,0xba,0xbf,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,
940 0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x03,0x81,0x81,0x00,0xae,0x3a,0x17,0xb8,
941 0x4a,0x7b,0x55,0xfa,0x64,0x55,0xec,0x40,0xa4,0xed,0x49,0x41,0x90,0x99,0x9c,
942 0x89,0xbc,0xaf,0x2e,0x1d,0xca,0x78,0x23,0xf9,0x1c,0x19,0x0f,0x7f,0xeb,0x68,
943 0xbc,0x32,0xd9,0x88,0x38,0xde,0xdc,0x3f,0xd3,0x89,0xb4,0x3f,0xb1,0x82,0x96,
944 0xf1,0xa4,0x5a,0xba,0xed,0x2e,0x26,0xd3,0xde,0x7c,0x01,0x6e,0x00,0x0a,0x00,
945 0xa4,0x06,0x92,0x11,0x48,0x09,0x40,0xf9,0x1c,0x18,0x79,0x67,0x23,0x24,0xe0,
946 0xbb,0xd5,0xe1,0x50,0xae,0x1b,0xf5,0x0e,0xdd,0xe0,0x2e,0x81,0xcd,0x80,0xa3,
947 0x6c,0x52,0x4f,0x91,0x75,0x55,0x8a,0xba,0x22,0xf2,0xd2,0xea,0x41,0x75,0x88,
948 0x2f,0x63,0x55,0x7d,0x1e,0x54,0x5a,0x95,0x59,0xca,0xd9,0x34,0x81,0xc0,0x5f,
949 0x5e,0xf6,0x7a,0xb5 };
950 static const BYTE iTunesCert3[] = {
951 0x30,0x82,0x04,0xf1,0x30,0x82,0x03,0xd9,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,
952 0x0f,0x1a,0xa0,0xe0,0x9b,0x9b,0x61,0xa6,0xb6,0xfe,0x40,0xd2,0xdf,0x6a,0xf6,
953 0x8d,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,
954 0x00,0x30,0x81,0xb4,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,
955 0x55,0x53,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,
956 0x72,0x69,0x53,0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x1f,0x30,
957 0x1d,0x06,0x03,0x55,0x04,0x0b,0x13,0x16,0x56,0x65,0x72,0x69,0x53,0x69,0x67,
958 0x6e,0x20,0x54,0x72,0x75,0x73,0x74,0x20,0x4e,0x65,0x74,0x77,0x6f,0x72,0x6b,
959 0x31,0x3b,0x30,0x39,0x06,0x03,0x55,0x04,0x0b,0x13,0x32,0x54,0x65,0x72,0x6d,
960 0x73,0x20,0x6f,0x66,0x20,0x75,0x73,0x65,0x20,0x61,0x74,0x20,0x68,0x74,0x74,
961 0x70,0x73,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,
962 0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x2f,0x72,0x70,0x61,0x20,0x28,0x63,0x29,0x30,
963 0x34,0x31,0x2e,0x30,0x2c,0x06,0x03,0x55,0x04,0x03,0x13,0x25,0x56,0x65,0x72,
964 0x69,0x53,0x69,0x67,0x6e,0x20,0x43,0x6c,0x61,0x73,0x73,0x20,0x33,0x20,0x43,
965 0x6f,0x64,0x65,0x20,0x53,0x69,0x67,0x6e,0x69,0x6e,0x67,0x20,0x32,0x30,0x30,
966 0x34,0x20,0x43,0x41,0x30,0x1e,0x17,0x0d,0x30,0x36,0x30,0x31,0x31,0x37,0x30,
967 0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,0x30,0x38,0x30,0x31,0x32,0x32,0x32,
968 0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x81,0xb4,0x31,0x0b,0x30,0x09,0x06,0x03,
969 0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,
970 0x08,0x13,0x0a,0x43,0x61,0x6c,0x69,0x66,0x6f,0x72,0x6e,0x69,0x61,0x31,0x12,
971 0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x13,0x09,0x43,0x75,0x70,0x65,0x72,0x74,
972 0x69,0x6e,0x6f,0x31,0x1d,0x30,0x1b,0x06,0x03,0x55,0x04,0x0a,0x14,0x14,0x41,
973 0x70,0x70,0x6c,0x65,0x20,0x43,0x6f,0x6d,0x70,0x75,0x74,0x65,0x72,0x2c,0x20,
974 0x49,0x6e,0x63,0x2e,0x31,0x3e,0x30,0x3c,0x06,0x03,0x55,0x04,0x0b,0x13,0x35,
975 0x44,0x69,0x67,0x69,0x74,0x61,0x6c,0x20,0x49,0x44,0x20,0x43,0x6c,0x61,0x73,
976 0x73,0x20,0x33,0x20,0x2d,0x20,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,
977 0x20,0x53,0x6f,0x66,0x74,0x77,0x61,0x72,0x65,0x20,0x56,0x61,0x6c,0x69,0x64,
978 0x61,0x74,0x69,0x6f,0x6e,0x20,0x76,0x32,0x31,0x1d,0x30,0x1b,0x06,0x03,0x55,
979 0x04,0x03,0x14,0x14,0x41,0x70,0x70,0x6c,0x65,0x20,0x43,0x6f,0x6d,0x70,0x75,
980 0x74,0x65,0x72,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x30,0x81,0x9f,0x30,0x0d,0x06,
981 0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x81,0x8d,
982 0x00,0x30,0x81,0x89,0x02,0x81,0x81,0x00,0xd3,0xab,0x3b,0x7f,0xec,0x48,0x84,
983 0xce,0xa8,0x1a,0x12,0xf3,0x3c,0x87,0xcb,0x24,0x58,0x96,0x02,0x87,0x66,0x49,
984 0xeb,0x89,0xee,0x79,0x44,0x70,0x8d,0xe7,0xd4,0x1f,0x30,0x92,0xc0,0x9c,0x35,
985 0x78,0xc0,0xaf,0x1c,0xb6,0x28,0xd3,0xe0,0xe0,0x9d,0xd3,0x49,0x76,0x73,0x57,
986 0x19,0x4d,0x8d,0x70,0x85,0x64,0x4d,0x1d,0xc6,0x02,0x3e,0xe5,0x2c,0x66,0x07,
987 0xd2,0x27,0x4b,0xd6,0xc8,0x3c,0x93,0xb6,0x15,0x0c,0xde,0x5b,0xd7,0x93,0xdd,
988 0xbe,0x85,0x62,0x34,0x17,0x8a,0x05,0x60,0xf0,0x8a,0x1c,0x5a,0x40,0x21,0x8d,
989 0x51,0x6c,0xb0,0x62,0xd8,0xb5,0xd4,0xf9,0xb1,0xd0,0x58,0x7a,0x7a,0x82,0x55,
990 0xb3,0xf9,0x53,0x71,0xde,0xd2,0xc9,0x37,0x8c,0xf6,0x5a,0x1f,0x2d,0xcd,0x7c,
991 0x67,0x02,0x03,0x01,0x00,0x01,0xa3,0x82,0x01,0x7f,0x30,0x82,0x01,0x7b,0x30,
992 0x09,0x06,0x03,0x55,0x1d,0x13,0x04,0x02,0x30,0x00,0x30,0x0e,0x06,0x03,0x55,
993 0x1d,0x0f,0x01,0x01,0xff,0x04,0x04,0x03,0x02,0x07,0x80,0x30,0x40,0x06,0x03,
994 0x55,0x1d,0x1f,0x04,0x39,0x30,0x37,0x30,0x35,0xa0,0x33,0xa0,0x31,0x86,0x2f,
995 0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x43,0x53,0x43,0x33,0x2d,0x32,0x30,0x30,
996 0x34,0x2d,0x63,0x72,0x6c,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,
997 0x63,0x6f,0x6d,0x2f,0x43,0x53,0x43,0x33,0x2d,0x32,0x30,0x30,0x34,0x2e,0x63,
998 0x72,0x6c,0x30,0x44,0x06,0x03,0x55,0x1d,0x20,0x04,0x3d,0x30,0x3b,0x30,0x39,
999 0x06,0x0b,0x60,0x86,0x48,0x01,0x86,0xf8,0x45,0x01,0x07,0x17,0x03,0x30,0x2a,
1000 0x30,0x28,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x1c,0x68,
1001 0x74,0x74,0x70,0x73,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x76,0x65,0x72,0x69,
1002 0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x2f,0x72,0x70,0x61,0x30,0x13,0x06,
1003 0x03,0x55,0x1d,0x25,0x04,0x0c,0x30,0x0a,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,
1004 0x07,0x03,0x03,0x30,0x75,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x01,0x01,
1005 0x04,0x69,0x30,0x67,0x30,0x24,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,
1006 0x01,0x86,0x18,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6f,0x63,0x73,0x70,0x2e,
1007 0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x30,0x3f,0x06,
1008 0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x33,0x68,0x74,0x74,0x70,
1009 0x3a,0x2f,0x2f,0x43,0x53,0x43,0x33,0x2d,0x32,0x30,0x30,0x34,0x2d,0x61,0x69,
1010 0x61,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x2f,
1011 0x43,0x53,0x43,0x33,0x2d,0x32,0x30,0x30,0x34,0x2d,0x61,0x69,0x61,0x2e,0x63,
1012 0x65,0x72,0x30,0x1f,0x06,0x03,0x55,0x1d,0x23,0x04,0x18,0x30,0x16,0x80,0x14,
1013 0x08,0xf5,0x51,0xe8,0xfb,0xfe,0x3d,0x3d,0x64,0x36,0x7c,0x68,0xcf,0x5b,0x78,
1014 0xa8,0xdf,0xb9,0xc5,0x37,0x30,0x11,0x06,0x09,0x60,0x86,0x48,0x01,0x86,0xf8,
1015 0x42,0x01,0x01,0x04,0x04,0x03,0x02,0x04,0x10,0x30,0x16,0x06,0x0a,0x2b,0x06,
1016 0x01,0x04,0x01,0x82,0x37,0x02,0x01,0x1b,0x04,0x08,0x30,0x06,0x01,0x01,0x00,
1017 0x01,0x01,0xff,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,
1018 0x05,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x6a,0xa6,0x06,0xd0,0x33,0x18,0x64,
1019 0xe2,0x69,0x82,0xee,0x6e,0x36,0x9e,0x9d,0x9a,0x0e,0x18,0xa8,0xac,0x9d,0x10,
1020 0xed,0x01,0x3c,0xb9,0x61,0x04,0x62,0xf3,0x85,0x8f,0xcc,0x4f,0x2c,0x66,0x35,
1021 0x54,0x25,0x45,0x8d,0x95,0x1c,0xd2,0x33,0xbe,0x2e,0xdd,0x7f,0x74,0xaf,0x03,
1022 0x7b,0x86,0x63,0xb0,0xc9,0xe6,0xbd,0xc7,0x8e,0xde,0x03,0x18,0x98,0x82,0xc3,
1023 0xbb,0xf8,0x15,0x99,0x1a,0xa9,0xdd,0xb9,0x5d,0xb9,0xbd,0x53,0x95,0x25,0x76,
1024 0xfb,0x5c,0x53,0x90,0xea,0x01,0x0a,0xa0,0xb1,0xbf,0x09,0x1b,0x97,0x8f,0x40,
1025 0xfa,0x85,0x12,0x74,0x01,0xdb,0xf6,0xdb,0x09,0xd6,0x5f,0x4f,0xd7,0x17,0xb4,
1026 0xbf,0x9e,0x2f,0x86,0x52,0x5d,0x70,0x24,0x52,0x32,0x1e,0xa5,0x1d,0x39,0x8b,
1027 0x66,0xf6,0xba,0x9b,0x69,0x8e,0x12,0x60,0xdb,0xb6,0xcf,0xe6,0x0d,0xd6,0x1c,
1028 0x8f,0xd4,0x5b,0x4b,0x00,0xde,0x21,0x93,0xfb,0x6e,0xc7,0x3d,0xb4,0x66,0x0d,
1029 0x29,0x0c,0x4e,0xe9,0x3f,0x94,0xd6,0xd6,0xdc,0xec,0xf8,0x53,0x3b,0x62,0xd5,
1030 0x97,0x50,0x53,0x84,0x17,0xfe,0xe2,0xed,0x4c,0x23,0x0a,0x49,0xce,0x5b,0xe9,
1031 0x70,0x31,0xc1,0x04,0x02,0x02,0x6c,0xb8,0x52,0xcd,0xc7,0x4e,0x70,0xb4,0x13,
1032 0xd7,0xe0,0x92,0xba,0x44,0x1a,0x10,0x4c,0x6e,0x45,0xc6,0x86,0x04,0xc6,0x64,
1033 0xd3,0x9c,0x6e,0xc1,0x9c,0xac,0x74,0x3d,0x77,0x06,0x5e,0x28,0x28,0x5c,0xf5,
1034 0xe0,0x9c,0x19,0xd8,0xba,0x74,0x81,0x2d,0x67,0x77,0x93,0x8d,0xbf,0xd2,0x52,
1035 0x00,0xe6,0xa5,0x38,0x4e,0x2e,0x73,0x66,0x7a };
1036 static BYTE iTunesIssuer[] = {
1037 0x30,0x81,0xb4,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,
1038 0x13,0x02,0x55,0x53,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,
1039 0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x2c,
1040 0x20,0x49,0x6e,0x63,0x2e,0x31,0x1f,0x30,0x1d,0x06,0x03,0x55,
1041 0x04,0x0b,0x13,0x16,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,
1042 0x20,0x54,0x72,0x75,0x73,0x74,0x20,0x4e,0x65,0x74,0x77,0x6f,
1043 0x72,0x6b,0x31,0x3b,0x30,0x39,0x06,0x03,0x55,0x04,0x0b,0x13,
1044 0x32,0x54,0x65,0x72,0x6d,0x73,0x20,0x6f,0x66,0x20,0x75,0x73,
1045 0x65,0x20,0x61,0x74,0x20,0x68,0x74,0x74,0x70,0x73,0x3a,0x2f,
1046 0x2f,0x77,0x77,0x77,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,
1047 0x6e,0x2e,0x63,0x6f,0x6d,0x2f,0x72,0x70,0x61,0x20,0x28,0x63,
1048 0x29,0x30,0x34,0x31,0x2e,0x30,0x2c,0x06,0x03,0x55,0x04,0x03,
1049 0x13,0x25,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x43,
1050 0x6c,0x61,0x73,0x73,0x20,0x33,0x20,0x43,0x6f,0x64,0x65,0x20,
1051 0x53,0x69,0x67,0x6e,0x69,0x6e,0x67,0x20,0x32,0x30,0x30,0x34,
1052 0x20,0x43,0x41 };
1053 static BYTE iTunesSerialNum[] = {
1054 0x8d,0xf6,0x6a,0xdf,0xd2,0x40,0xfe,0xb6,0xa6,0x61,0x9b,0x9b,
1055 0xe0,0xa0,0x1a,0x0f };
1057 static void testFindCert(void)
1059 HCERTSTORE store;
1060 PCCERT_CONTEXT context = NULL, subject;
1061 BOOL ret;
1062 CERT_INFO certInfo = { 0 };
1063 CRYPT_HASH_BLOB blob;
1064 BYTE otherSerialNumber[] = { 2 };
1065 DWORD count;
1066 static const WCHAR juan[] = { 'j','u','a','n',0 };
1067 static const WCHAR lang[] = { 'L','A','N','G',0 };
1068 static const WCHAR malcolm[] = { 'm','a','l','c','o','l','m',0 };
1070 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1071 CERT_STORE_CREATE_NEW_FLAG, NULL);
1072 ok(store != NULL, "CertOpenStore failed: %d\n", GetLastError());
1073 if (!store)
1074 return;
1076 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1077 bigCert, sizeof(bigCert), CERT_STORE_ADD_NEW, NULL);
1078 ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* win98 */),
1079 "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
1080 if (!ret && GetLastError() == OSS_DATA_ERROR)
1082 skip("bigCert can't be decoded, skipping tests\n");
1083 return;
1085 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1086 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, NULL);
1087 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1088 GetLastError());
1089 /* This has the same name as bigCert */
1090 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1091 certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, NULL);
1092 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1093 GetLastError());
1095 /* Crashes
1096 context = CertFindCertificateInStore(NULL, 0, 0, 0, NULL, NULL);
1099 /* Check first cert's there, by issuer */
1100 certInfo.Subject.pbData = subjectName;
1101 certInfo.Subject.cbData = sizeof(subjectName);
1102 certInfo.SerialNumber.pbData = serialNum;
1103 certInfo.SerialNumber.cbData = sizeof(serialNum);
1104 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1105 CERT_FIND_ISSUER_NAME, &certInfo.Subject, NULL);
1106 ok(context != NULL, "CertFindCertificateInStore failed: %08x\n",
1107 GetLastError());
1108 if (context)
1110 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1111 CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
1112 ok(context != NULL, "Expected more than one cert\n");
1113 if (context)
1115 context = CertFindCertificateInStore(store, X509_ASN_ENCODING,
1116 0, CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
1117 ok(context == NULL, "Expected precisely two certs\n");
1121 /* Check second cert's there as well, by subject name */
1122 certInfo.Subject.pbData = subjectName2;
1123 certInfo.Subject.cbData = sizeof(subjectName2);
1124 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1125 CERT_FIND_SUBJECT_NAME, &certInfo.Subject, NULL);
1126 ok(context != NULL, "CertFindCertificateInStore failed: %08x\n",
1127 GetLastError());
1128 if (context)
1130 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1131 CERT_FIND_SUBJECT_NAME, &certInfo.Subject, context);
1132 ok(context == NULL, "Expected one cert only\n");
1135 /* Strange but true: searching for the subject cert requires you to set
1136 * the issuer, not the subject
1138 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1139 CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
1140 ok(context == NULL, "Expected no certificate\n");
1141 certInfo.Subject.pbData = NULL;
1142 certInfo.Subject.cbData = 0;
1143 certInfo.Issuer.pbData = subjectName2;
1144 certInfo.Issuer.cbData = sizeof(subjectName2);
1145 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1146 CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
1147 ok(context != NULL, "CertFindCertificateInStore failed: %08x\n",
1148 GetLastError());
1149 if (context)
1151 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1152 CERT_FIND_SUBJECT_CERT, &certInfo, context);
1153 ok(context == NULL, "Expected one cert only\n");
1155 /* A non-matching serial number will not match. */
1156 certInfo.SerialNumber.pbData = otherSerialNumber;
1157 certInfo.SerialNumber.cbData = sizeof(otherSerialNumber);
1158 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1159 CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
1160 ok(context == NULL, "Expected no match\n");
1161 /* No serial number will not match */
1162 certInfo.SerialNumber.cbData = 0;
1163 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1164 CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
1165 ok(context == NULL, "Expected no match\n");
1166 /* A serial number still won't match if the name doesn't */
1167 certInfo.SerialNumber.pbData = serialNum;
1168 certInfo.SerialNumber.cbData = sizeof(serialNum);
1169 certInfo.Issuer.pbData = subjectName3;
1170 certInfo.Issuer.cbData = sizeof(subjectName3);
1171 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1172 CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
1173 ok(context == NULL, "Expected no match\n");
1175 /* The nice thing about hashes, they're unique */
1176 blob.pbData = bigCertHash;
1177 blob.cbData = sizeof(bigCertHash);
1178 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1179 CERT_FIND_SHA1_HASH, &blob, NULL);
1180 ok(context != NULL, "CertFindCertificateInStore failed: %08x\n",
1181 GetLastError());
1182 if (context)
1184 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1185 CERT_FIND_SHA1_HASH, &certInfo.Subject, context);
1186 ok(context == NULL, "Expected one cert only\n");
1189 /* Searching for NULL string matches any context. */
1190 count = 0;
1191 context = NULL;
1192 do {
1193 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1194 CERT_FIND_ISSUER_STR, NULL, context);
1195 if (context)
1196 count++;
1197 } while (context);
1198 ok(count == 3, "expected 3 contexts\n");
1199 count = 0;
1200 context = NULL;
1201 do {
1202 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1203 CERT_FIND_ISSUER_STR, juan, context);
1204 if (context)
1205 count++;
1206 } while (context);
1207 ok(count == 2, "expected 2 contexts\n");
1208 count = 0;
1209 context = NULL;
1210 do {
1211 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1212 CERT_FIND_ISSUER_STR, lang, context);
1213 if (context)
1214 count++;
1215 } while (context);
1216 ok(count == 3, "expected 3 contexts\n");
1217 SetLastError(0xdeadbeef);
1218 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1219 CERT_FIND_ISSUER_STR, malcolm, NULL);
1220 ok(!context, "expected no certs\n");
1221 ok(GetLastError() == CRYPT_E_NOT_FOUND,
1222 "expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1224 CertCloseStore(store, 0);
1226 /* Another subject cert search, using iTunes's certs */
1227 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1228 CERT_STORE_CREATE_NEW_FLAG, NULL);
1229 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1230 iTunesCert0, sizeof(iTunesCert0), CERT_STORE_ADD_NEW, NULL);
1231 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1232 GetLastError());
1233 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1234 iTunesCert1, sizeof(iTunesCert1), CERT_STORE_ADD_NEW, NULL);
1235 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1236 GetLastError());
1237 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1238 iTunesCert2, sizeof(iTunesCert2), CERT_STORE_ADD_NEW, NULL);
1239 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1240 GetLastError());
1241 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1242 iTunesCert3, sizeof(iTunesCert3), CERT_STORE_ADD_NEW, &subject);
1243 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1244 GetLastError());
1246 /* The certInfo's issuer does not match any subject, but the serial
1247 * number does match a cert whose issuer matches certInfo's issuer.
1248 * This yields a match.
1250 certInfo.SerialNumber.cbData = sizeof(iTunesSerialNum);
1251 certInfo.SerialNumber.pbData = iTunesSerialNum;
1252 certInfo.Issuer.cbData = sizeof(iTunesIssuer);
1253 certInfo.Issuer.pbData = iTunesIssuer;
1254 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1255 CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
1256 ok(context != NULL, "Expected a match\n");
1257 if (context)
1259 ret = CertCompareCertificateName(context->dwCertEncodingType,
1260 &certInfo.Issuer, &context->pCertInfo->Subject);
1261 ok(!ret, "Expected subject name not to match\n");
1262 ret = CertCompareCertificateName(context->dwCertEncodingType,
1263 &certInfo.Issuer, &context->pCertInfo->Issuer);
1264 ok(ret, "Expected issuer name to match\n");
1265 ret = CertCompareIntegerBlob(&certInfo.SerialNumber,
1266 &context->pCertInfo->SerialNumber);
1267 ok(ret, "Expected serial number to match\n");
1268 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1269 CERT_FIND_SUBJECT_CERT, &certInfo, context);
1270 ok(context == NULL, "Expected one cert only\n");
1273 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1274 CERT_FIND_ISSUER_OF, subject, NULL);
1275 ok(context != NULL, "Expected an issuer\n");
1276 if (context)
1278 PCCERT_CONTEXT none = CertFindCertificateInStore(store,
1279 X509_ASN_ENCODING, 0, CERT_FIND_ISSUER_OF, context, NULL);
1281 ok(!none, "Expected no parent of issuer\n");
1282 CertFreeCertificateContext(context);
1284 CertFreeCertificateContext(subject);
1285 CertCloseStore(store, 0);
1288 static void testGetSubjectCert(void)
1290 HCERTSTORE store;
1291 PCCERT_CONTEXT context1, context2;
1292 CERT_INFO info = { 0 };
1293 BOOL ret;
1295 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1296 CERT_STORE_CREATE_NEW_FLAG, NULL);
1297 ok(store != NULL, "CertOpenStore failed: %d\n", GetLastError());
1298 if (!store)
1299 return;
1301 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1302 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
1303 ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* win98 */),
1304 "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
1305 if (!ret && GetLastError() == OSS_DATA_ERROR)
1307 skip("bigCert can't be decoded, skipping tests\n");
1308 return;
1310 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1311 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, &context1);
1312 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1313 GetLastError());
1314 ok(context1 != NULL, "Expected a context\n");
1315 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1316 certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, NULL);
1317 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1318 GetLastError());
1320 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
1321 NULL);
1322 ok(!context2 && GetLastError() == E_INVALIDARG,
1323 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1324 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
1325 &info);
1326 ok(!context2 && GetLastError() == CRYPT_E_NOT_FOUND,
1327 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1328 info.SerialNumber.cbData = sizeof(serialNum);
1329 info.SerialNumber.pbData = serialNum;
1330 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
1331 &info);
1332 ok(!context2 && GetLastError() == CRYPT_E_NOT_FOUND,
1333 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1334 info.Issuer.cbData = sizeof(subjectName2);
1335 info.Issuer.pbData = subjectName2;
1336 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
1337 &info);
1338 ok(context2 != NULL,
1339 "CertGetSubjectCertificateFromStore failed: %08x\n", GetLastError());
1340 /* Not only should this find a context, but it should be the same
1341 * (same address) as context1.
1343 ok(context1 == context2, "Expected identical context addresses\n");
1344 CertFreeCertificateContext(context2);
1346 CertFreeCertificateContext(context1);
1347 CertCloseStore(store, 0);
1350 /* This expires in 1970 or so */
1351 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
1352 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
1353 0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
1354 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
1355 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
1356 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
1357 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
1358 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
1359 0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
1360 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
1361 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
1362 0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
1363 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
1364 0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
1365 0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
1366 0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
1367 0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
1368 0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
1369 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
1370 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
1371 0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
1372 0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
1373 0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
1374 0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
1375 0x49, 0xe5, 0xf9, 0x65, 0xf3 };
1377 /* This expires in 2036 or so */
1378 static const BYTE childOfExpired[] = { 0x30, 0x81, 0xcc, 0x30, 0x78, 0xa0,
1379 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
1380 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d,
1381 0x30, 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63,
1382 0x40, 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e,
1383 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x35, 0x30, 0x35,
1384 0x31, 0x37, 0x31, 0x32, 0x34, 0x39, 0x5a, 0x17, 0x0d, 0x33, 0x36, 0x30, 0x35,
1385 0x30, 0x35, 0x31, 0x37, 0x31, 0x32, 0x34, 0x39, 0x5a, 0x30, 0x15, 0x31, 0x13,
1386 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e,
1387 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03,
1388 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
1389 0x01, 0x05, 0x05, 0x00, 0x03, 0x41, 0x00, 0x20, 0x3b, 0xdb, 0x4d, 0x67, 0x50,
1390 0xec, 0x73, 0x9d, 0xf9, 0x85, 0x5d, 0x18, 0xe9, 0xb4, 0x98, 0xe3, 0x31, 0xb7,
1391 0x03, 0x0b, 0xc0, 0x39, 0x93, 0x56, 0x81, 0x0a, 0xfc, 0x78, 0xa8, 0x29, 0x42,
1392 0x5f, 0x69, 0xfb, 0xbc, 0x5b, 0xf2, 0xa6, 0x2a, 0xbe, 0x91, 0x2c, 0xfc, 0x89,
1393 0x69, 0x15, 0x18, 0x58, 0xe5, 0x02, 0x75, 0xf7, 0x2a, 0xb6, 0xa9, 0xfb, 0x47,
1394 0x6a, 0x6e, 0x0a, 0x9b, 0xe9, 0xdc };
1395 /* chain10_0 -+
1396 * +-> chain7_1
1397 * chain10_1 -+
1398 * A chain with two issuers, only one of whose dates is valid.
1400 static const BYTE chain10_0[] = {
1401 0x30,0x82,0x01,0x9b,0x30,0x82,0x01,0x08,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,
1402 0x4a,0x30,0x3a,0x42,0xa2,0x5a,0xb3,0x93,0x4d,0x94,0x06,0xad,0x6d,0x1c,0x34,
1403 0xe6,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x30,0x10,0x31,
1404 0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x03,0x13,0x05,0x43,0x65,0x72,0x74,0x31,
1405 0x30,0x1e,0x17,0x0d,0x30,0x36,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
1406 0x30,0x5a,0x17,0x0d,0x30,0x36,0x31,0x32,0x33,0x31,0x32,0x33,0x35,0x39,0x35,
1407 0x39,0x5a,0x30,0x10,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x03,0x13,0x05,
1408 0x43,0x65,0x72,0x74,0x31,0x30,0x81,0x9f,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
1409 0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x81,0x8d,0x00,0x30,0x81,0x89,
1410 0x02,0x81,0x81,0x00,0xad,0x7e,0xca,0xf3,0xe5,0x99,0xc2,0x2a,0xca,0x50,0x82,
1411 0x7c,0x2d,0xa4,0x81,0xcd,0x0d,0x0d,0x86,0xd7,0xd8,0xb2,0xde,0xc5,0xc3,0x34,
1412 0x9e,0x07,0x78,0x08,0x11,0x12,0x2d,0x21,0x0a,0x09,0x07,0x14,0x03,0x7a,0xe7,
1413 0x3b,0x58,0xf1,0xde,0x3e,0x01,0x25,0x93,0xab,0x8f,0xce,0x1f,0xc1,0x33,0x91,
1414 0xfe,0x59,0xb9,0x3b,0x9e,0x95,0x12,0x89,0x8e,0xc3,0x4b,0x98,0x1b,0x99,0xc5,
1415 0x07,0xe2,0xdf,0x15,0x4c,0x39,0x76,0x06,0xad,0xdb,0x16,0x06,0x49,0xba,0xcd,
1416 0x0f,0x07,0xd6,0xea,0x27,0xa6,0xfe,0x3d,0x88,0xe5,0x97,0x45,0x72,0xb6,0x1c,
1417 0xc0,0x1c,0xb1,0xa2,0x89,0xe8,0x37,0x9e,0xf6,0x2a,0xcf,0xd5,0x1f,0x2f,0x35,
1418 0x5e,0x8f,0x3a,0x9c,0x61,0xb1,0xf1,0x6c,0xff,0x8c,0xb2,0x2f,0x02,0x03,0x01,
1419 0x00,0x01,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x03,0x81,
1420 0x81,0x00,0x85,0x6e,0x35,0x2f,0x2c,0x51,0x4f,0xd6,0x2a,0xe4,0x9e,0xd0,0x4b,
1421 0xe6,0x90,0xfd,0xf7,0x20,0xad,0x76,0x3f,0x93,0xea,0x7f,0x0d,0x1f,0xb3,0x8e,
1422 0xfd,0xe0,0xe1,0xd6,0xd7,0x9c,0x7d,0x46,0x6b,0x15,0x5c,0xe6,0xc9,0x62,0x3b,
1423 0x70,0x4a,0x4b,0xb2,0x82,0xe3,0x55,0x0c,0xc4,0x90,0x44,0x06,0x6c,0x86,0x1c,
1424 0x6d,0x47,0x12,0xda,0x33,0x95,0x5d,0x98,0x43,0xcb,0x7c,0xfa,0x2b,0xee,0xc4,
1425 0x2d,0xc8,0x95,0x33,0x89,0x08,0x3f,0x9f,0x87,0xea,0x20,0x04,0xaf,0x58,0x4b,
1426 0x9d,0xc0,0x7c,0x0a,0x1b,0x05,0x31,0x3b,0xbb,0x13,0x58,0x2e,0x3f,0x61,0x6b,
1427 0x10,0xb4,0xeb,0xb9,0x1a,0x30,0xfd,0xea,0xca,0x29,0x99,0x5f,0x42,0x2b,0x00,
1428 0xb0,0x08,0xc3,0xf0,0xb6,0xd6,0x6b,0xf9,0x35,0x95 };
1429 static const BYTE chain10_1[] = {
1430 0x30,0x82,0x01,0x9b,0x30,0x82,0x01,0x08,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,
1431 0xbf,0x99,0x4f,0x14,0x03,0x77,0x44,0xb8,0x49,0x02,0x70,0xa1,0xb8,0x9c,0xa7,
1432 0x24,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x30,0x10,0x31,
1433 0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x03,0x13,0x05,0x43,0x65,0x72,0x74,0x31,
1434 0x30,0x1e,0x17,0x0d,0x30,0x37,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
1435 0x30,0x5a,0x17,0x0d,0x30,0x37,0x31,0x32,0x33,0x31,0x32,0x33,0x35,0x39,0x35,
1436 0x39,0x5a,0x30,0x10,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x03,0x13,0x05,
1437 0x43,0x65,0x72,0x74,0x31,0x30,0x81,0x9f,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
1438 0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x81,0x8d,0x00,0x30,0x81,0x89,
1439 0x02,0x81,0x81,0x00,0xad,0x7e,0xca,0xf3,0xe5,0x99,0xc2,0x2a,0xca,0x50,0x82,
1440 0x7c,0x2d,0xa4,0x81,0xcd,0x0d,0x0d,0x86,0xd7,0xd8,0xb2,0xde,0xc5,0xc3,0x34,
1441 0x9e,0x07,0x78,0x08,0x11,0x12,0x2d,0x21,0x0a,0x09,0x07,0x14,0x03,0x7a,0xe7,
1442 0x3b,0x58,0xf1,0xde,0x3e,0x01,0x25,0x93,0xab,0x8f,0xce,0x1f,0xc1,0x33,0x91,
1443 0xfe,0x59,0xb9,0x3b,0x9e,0x95,0x12,0x89,0x8e,0xc3,0x4b,0x98,0x1b,0x99,0xc5,
1444 0x07,0xe2,0xdf,0x15,0x4c,0x39,0x76,0x06,0xad,0xdb,0x16,0x06,0x49,0xba,0xcd,
1445 0x0f,0x07,0xd6,0xea,0x27,0xa6,0xfe,0x3d,0x88,0xe5,0x97,0x45,0x72,0xb6,0x1c,
1446 0xc0,0x1c,0xb1,0xa2,0x89,0xe8,0x37,0x9e,0xf6,0x2a,0xcf,0xd5,0x1f,0x2f,0x35,
1447 0x5e,0x8f,0x3a,0x9c,0x61,0xb1,0xf1,0x6c,0xff,0x8c,0xb2,0x2f,0x02,0x03,0x01,
1448 0x00,0x01,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x03,0x81,
1449 0x81,0x00,0xa8,0xec,0x8c,0x34,0xe7,0x2c,0xdf,0x75,0x87,0xc4,0xf7,0xda,0x71,
1450 0x72,0x29,0xb2,0x48,0xa8,0x2a,0xec,0x7b,0x7d,0x19,0xb9,0x5f,0x1d,0xd9,0x91,
1451 0x2b,0xc4,0x28,0x7e,0xd6,0xb5,0x91,0x69,0xa5,0x8a,0x1a,0x1f,0x97,0x98,0x46,
1452 0x9d,0xdf,0x12,0xf6,0x45,0x62,0xad,0x60,0xb6,0xba,0xb0,0xfd,0xf5,0x9f,0xc6,
1453 0x98,0x05,0x4f,0x4d,0x48,0xdc,0xee,0x69,0xbe,0xb8,0xc4,0xc4,0xd7,0x1b,0xb1,
1454 0x1f,0x64,0xd6,0x45,0xa7,0xdb,0xb3,0x87,0x63,0x0f,0x54,0xe1,0x3a,0x6b,0x57,
1455 0x36,0xd7,0x68,0x65,0xcf,0xda,0x57,0x8d,0xcd,0x84,0x75,0x47,0x26,0x2c,0xef,
1456 0x1e,0x8f,0xc7,0x3b,0xee,0x5d,0x03,0xa6,0xdf,0x3a,0x20,0xb2,0xcc,0xc9,0x09,
1457 0x2c,0xfe,0x2b,0x79,0xb0,0xca,0x2c,0x9a,0x81,0x6b };
1458 static const BYTE chain7_1[] = {
1459 0x30,0x82,0x01,0x93,0x30,0x81,0xfd,0xa0,0x03,0x02,0x01,0x02,0x02,0x01,0x01,
1460 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,
1461 0x30,0x10,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x03,0x13,0x05,0x43,0x65,
1462 0x72,0x74,0x31,0x30,0x1e,0x17,0x0d,0x30,0x37,0x30,0x31,0x30,0x31,0x30,0x30,
1463 0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,0x30,0x37,0x31,0x32,0x33,0x31,0x32,0x33,
1464 0x35,0x39,0x35,0x39,0x5a,0x30,0x10,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,
1465 0x03,0x13,0x05,0x43,0x65,0x72,0x74,0x32,0x30,0x81,0x9f,0x30,0x0d,0x06,0x09,
1466 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x81,0x8d,0x00,
1467 0x30,0x81,0x89,0x02,0x81,0x81,0x00,0xb8,0x52,0xda,0xc5,0x4b,0x3f,0xe5,0x33,
1468 0x0e,0x67,0x5f,0x48,0x21,0xdc,0x7e,0xef,0x37,0x33,0xba,0xff,0xb4,0xc6,0xdc,
1469 0xb6,0x17,0x8e,0x20,0x55,0x07,0x12,0xd2,0x7b,0x3c,0xce,0x30,0xc5,0xa7,0x48,
1470 0x9f,0x6e,0xfe,0xb8,0xbe,0xdb,0x9f,0x9b,0x17,0x60,0x16,0xde,0xc6,0x8b,0x47,
1471 0xd1,0x57,0x71,0x3c,0x93,0xfc,0xbd,0xec,0x44,0x32,0x3b,0xb9,0xcf,0x6b,0x05,
1472 0x72,0xa7,0x87,0x8e,0x7e,0xd4,0x9a,0x87,0x1c,0x2f,0xb7,0x82,0x40,0xfc,0x6a,
1473 0x80,0x83,0x68,0x28,0xce,0x84,0xf4,0x0b,0x2e,0x44,0xcb,0x53,0xac,0x85,0x85,
1474 0xb5,0x46,0x36,0x98,0x3c,0x10,0x02,0xaa,0x02,0xbc,0x8b,0xa2,0x23,0xb2,0xd3,
1475 0x51,0x9a,0x22,0x4a,0xe3,0xaa,0x4e,0x7c,0xda,0x38,0xcf,0x49,0x98,0x72,0xa3,
1476 0x02,0x03,0x01,0x00,0x01,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
1477 0x01,0x01,0x05,0x05,0x00,0x03,0x81,0x81,0x00,0x9f,0x69,0xfd,0x26,0xd5,0x4b,
1478 0xe0,0xab,0x12,0x21,0xb9,0xfc,0xf7,0xe0,0x0c,0x09,0x94,0xad,0x27,0xd7,0x9d,
1479 0xa3,0xcc,0x46,0x2a,0x25,0x9a,0x24,0xa7,0x31,0x58,0x78,0xf5,0xfc,0x30,0xe1,
1480 0x6d,0xfd,0x59,0xab,0xbe,0x69,0xa0,0xea,0xe3,0x7d,0x7a,0x7b,0xe5,0x85,0xeb,
1481 0x86,0x6a,0x84,0x3c,0x96,0x01,0x1a,0x70,0xa7,0xb8,0xcb,0xf2,0x11,0xe7,0x52,
1482 0x9c,0x58,0x2d,0xac,0x63,0xce,0x72,0x4b,0xad,0x62,0xa8,0x1d,0x75,0x96,0xe2,
1483 0x27,0xf5,0x6f,0xba,0x91,0xf8,0xf1,0xb0,0xbf,0x90,0x24,0x6d,0xba,0x5d,0xd7,
1484 0x39,0x63,0x3b,0x7c,0x04,0x5d,0x89,0x9d,0x1c,0xf2,0xf7,0xcc,0xdf,0x6e,0x8a,
1485 0x43,0xa9,0xdd,0x86,0x05,0xa2,0xf3,0x22,0x2d,0x1e,0x70,0xa1,0x59,0xd7,0xa5,
1486 0x94,0x7d };
1488 static void testGetIssuerCert(void)
1490 BOOL ret;
1491 PCCERT_CONTEXT parent, child, cert1, cert2;
1492 DWORD flags = 0xffffffff;
1493 HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1494 CERT_STORE_CREATE_NEW_FLAG, NULL);
1496 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1498 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1499 expiredCert, sizeof(expiredCert), CERT_STORE_ADD_ALWAYS, NULL);
1500 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1501 GetLastError());
1503 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1504 childOfExpired, sizeof(childOfExpired), CERT_STORE_ADD_ALWAYS, &child);
1505 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1506 GetLastError());
1508 /* These crash:
1509 parent = CertGetIssuerCertificateFromStore(NULL, NULL, NULL, NULL);
1510 parent = CertGetIssuerCertificateFromStore(store, NULL, NULL, NULL);
1512 parent = CertGetIssuerCertificateFromStore(NULL, NULL, NULL, &flags);
1513 ok(!parent && GetLastError() == E_INVALIDARG,
1514 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1515 parent = CertGetIssuerCertificateFromStore(store, NULL, NULL, &flags);
1516 ok(!parent && GetLastError() == E_INVALIDARG,
1517 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1518 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1519 ok(!parent && GetLastError() == E_INVALIDARG,
1520 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1521 /* Confusing: the caller cannot set either of the
1522 * CERT_STORE_NO_*_FLAGs, as these are not checks,
1523 * they're results:
1525 flags = CERT_STORE_NO_CRL_FLAG | CERT_STORE_NO_ISSUER_FLAG;
1526 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1527 ok(!parent && GetLastError() == E_INVALIDARG,
1528 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1529 /* Perform no checks */
1530 flags = 0;
1531 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1532 ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08x\n",
1533 GetLastError());
1534 if (parent)
1535 CertFreeCertificateContext(parent);
1536 /* Check revocation and signature only */
1537 flags = CERT_STORE_REVOCATION_FLAG | CERT_STORE_SIGNATURE_FLAG;
1538 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1539 ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08x\n",
1540 GetLastError());
1541 /* Confusing: CERT_STORE_REVOCATION_FLAG succeeds when there is no CRL by
1542 * setting CERT_STORE_NO_CRL_FLAG.
1544 ok(flags == (CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG),
1545 "Expected CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG, got %08x\n",
1546 flags);
1547 if (parent)
1548 CertFreeCertificateContext(parent);
1549 /* Checking time validity is not productive, because while most Windows
1550 * versions return 0 (time valid) because the child is not expired,
1551 * Windows 2003 SP1 returns that it is expired. Thus the range of
1552 * possibilities is covered, and a test verifies nothing.
1555 CertFreeCertificateContext(child);
1556 CertCloseStore(store, 0);
1558 flags = 0;
1559 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1560 CERT_STORE_CREATE_NEW_FLAG, NULL);
1561 /* With only the child certificate, no issuer will be found */
1562 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1563 chain7_1, sizeof(chain7_1), CERT_STORE_ADD_ALWAYS, &child);
1564 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
1565 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1566 ok(parent == NULL, "Expected no issuer\n");
1567 /* Adding an issuer allows one (and only one) issuer to be found */
1568 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1569 chain10_1, sizeof(chain10_1), CERT_STORE_ADD_ALWAYS, &cert1);
1570 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
1571 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1572 ok(parent == cert1, "Expected cert1 to be the issuer\n");
1573 parent = CertGetIssuerCertificateFromStore(store, child, parent, &flags);
1574 ok(parent == NULL, "Expected only one issuer\n");
1575 /* Adding a second issuer allows two issuers to be found - and the second
1576 * issuer is found before the first, implying certs are added to the head
1577 * of a list.
1579 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1580 chain10_0, sizeof(chain10_0), CERT_STORE_ADD_ALWAYS, &cert2);
1581 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
1582 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1583 ok(parent == cert2, "Expected cert2 to be the first issuer\n");
1584 parent = CertGetIssuerCertificateFromStore(store, child, parent, &flags);
1585 ok(parent == cert1, "Expected cert1 to be the second issuer\n");
1586 parent = CertGetIssuerCertificateFromStore(store, child, parent, &flags);
1587 ok(parent == NULL, "Expected no more than two issuers\n");
1588 CertFreeCertificateContext(child);
1589 CertFreeCertificateContext(cert1);
1590 CertFreeCertificateContext(cert2);
1591 CertCloseStore(store, 0);
1593 /* Repeat the test, reversing the order in which issuers are added,
1594 * to show it's order-dependent.
1596 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1597 CERT_STORE_CREATE_NEW_FLAG, NULL);
1598 /* With only the child certificate, no issuer will be found */
1599 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1600 chain7_1, sizeof(chain7_1), CERT_STORE_ADD_ALWAYS, &child);
1601 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
1602 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1603 ok(parent == NULL, "Expected no issuer\n");
1604 /* Adding an issuer allows one (and only one) issuer to be found */
1605 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1606 chain10_0, sizeof(chain10_0), CERT_STORE_ADD_ALWAYS, &cert1);
1607 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
1608 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1609 ok(parent == cert1, "Expected cert1 to be the issuer\n");
1610 parent = CertGetIssuerCertificateFromStore(store, child, parent, &flags);
1611 ok(parent == NULL, "Expected only one issuer\n");
1612 /* Adding a second issuer allows two issuers to be found - and the second
1613 * issuer is found before the first, implying certs are added to the head
1614 * of a list.
1616 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1617 chain10_1, sizeof(chain10_1), CERT_STORE_ADD_ALWAYS, &cert2);
1618 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
1619 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1620 ok(parent == cert2, "Expected cert2 to be the first issuer\n");
1621 parent = CertGetIssuerCertificateFromStore(store, child, parent, &flags);
1622 ok(parent == cert1, "Expected cert1 to be the second issuer\n");
1623 parent = CertGetIssuerCertificateFromStore(store, child, parent, &flags);
1624 ok(parent == NULL, "Expected no more than two issuers\n");
1625 CertFreeCertificateContext(child);
1626 CertFreeCertificateContext(cert1);
1627 CertFreeCertificateContext(cert2);
1628 CertCloseStore(store, 0);
1631 static void testCryptHashCert(void)
1633 static const BYTE emptyHash[] = { 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b,
1634 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07,
1635 0x09 };
1636 static const BYTE knownHash[] = { 0xae, 0x9d, 0xbf, 0x6d, 0xf5, 0x46, 0xee,
1637 0x8b, 0xc5, 0x7a, 0x13, 0xba, 0xc2, 0xb1, 0x04, 0xf2, 0xbf, 0x52, 0xa8,
1638 0xa2 };
1639 static const BYTE toHash[] = "abcdefghijklmnopqrstuvwxyz0123456789.,;!?:";
1640 BOOL ret;
1641 BYTE hash[20];
1642 DWORD hashLen = sizeof(hash);
1644 /* NULL buffer and nonzero length crashes
1645 ret = CryptHashCertificate(0, 0, 0, NULL, size, hash, &hashLen);
1646 empty hash length also crashes
1647 ret = CryptHashCertificate(0, 0, 0, buf, size, hash, NULL);
1649 /* Test empty hash */
1650 ret = CryptHashCertificate(0, 0, 0, toHash, sizeof(toHash), NULL,
1651 &hashLen);
1652 ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
1653 ok(hashLen == sizeof(hash), "Got unexpected size of hash %d\n", hashLen);
1654 /* Test with empty buffer */
1655 ret = CryptHashCertificate(0, 0, 0, NULL, 0, hash, &hashLen);
1656 ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
1657 ok(!memcmp(hash, emptyHash, sizeof(emptyHash)),
1658 "Unexpected hash of nothing\n");
1659 /* Test a known value */
1660 ret = CryptHashCertificate(0, 0, 0, toHash, sizeof(toHash), hash,
1661 &hashLen);
1662 ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
1663 ok(!memcmp(hash, knownHash, sizeof(knownHash)), "Unexpected hash\n");
1666 static void verifySig(HCRYPTPROV csp, const BYTE *toSign, size_t toSignLen,
1667 const BYTE *sig, unsigned int sigLen)
1669 HCRYPTHASH hash;
1670 BOOL ret = CryptCreateHash(csp, CALG_SHA1, 0, 0, &hash);
1672 ok(ret, "CryptCreateHash failed: %08x\n", GetLastError());
1673 if (ret)
1675 BYTE mySig[64];
1676 DWORD mySigSize = sizeof(mySig);
1678 ret = CryptHashData(hash, toSign, toSignLen, 0);
1679 ok(ret, "CryptHashData failed: %08x\n", GetLastError());
1680 /* use the A variant so the test can run on Win9x */
1681 ret = CryptSignHashA(hash, AT_SIGNATURE, NULL, 0, mySig, &mySigSize);
1682 ok(ret, "CryptSignHash failed: %08x\n", GetLastError());
1683 if (ret)
1685 ok(mySigSize == sigLen, "Expected sig length %d, got %d\n",
1686 sigLen, mySigSize);
1687 ok(!memcmp(mySig, sig, sigLen), "Unexpected signature\n");
1689 CryptDestroyHash(hash);
1693 /* Tests signing the certificate described by toBeSigned with the CSP passed in,
1694 * using the algorithm with OID sigOID. The CSP is assumed to be empty, and a
1695 * keyset named AT_SIGNATURE will be added to it. The signature will be stored
1696 * in sig. sigLen should be at least 64 bytes.
1698 static void testSignCert(HCRYPTPROV csp, const CRYPT_DATA_BLOB *toBeSigned,
1699 LPCSTR sigOID, BYTE *sig, DWORD *sigLen)
1701 BOOL ret;
1702 DWORD size = 0;
1703 CRYPT_ALGORITHM_IDENTIFIER algoID = { NULL, { 0, NULL } };
1704 HCRYPTKEY key;
1706 /* These all crash
1707 ret = CryptSignCertificate(0, 0, 0, NULL, 0, NULL, NULL, NULL, NULL);
1708 ret = CryptSignCertificate(0, 0, 0, NULL, 0, NULL, NULL, NULL, &size);
1709 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
1710 NULL, NULL, NULL, &size);
1712 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
1713 &algoID, NULL, NULL, &size);
1714 ok(!ret && GetLastError() == NTE_BAD_ALGID,
1715 "Expected NTE_BAD_ALGID, got %08x\n", GetLastError());
1716 algoID.pszObjId = (LPSTR)sigOID;
1717 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
1718 &algoID, NULL, NULL, &size);
1719 ok(!ret &&
1720 (GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == NTE_BAD_ALGID),
1721 "Expected ERROR_INVALID_PARAMETER or NTE_BAD_ALGID, got %08x\n",
1722 GetLastError());
1723 ret = CryptSignCertificate(0, AT_SIGNATURE, 0, toBeSigned->pbData,
1724 toBeSigned->cbData, &algoID, NULL, NULL, &size);
1725 ok(!ret &&
1726 (GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == NTE_BAD_ALGID),
1727 "Expected ERROR_INVALID_PARAMETER or NTE_BAD_ALGID, got %08x\n",
1728 GetLastError());
1730 /* No keys exist in the new CSP yet.. */
1731 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
1732 toBeSigned->cbData, &algoID, NULL, NULL, &size);
1733 ok(!ret && (GetLastError() == NTE_BAD_KEYSET || GetLastError() ==
1734 NTE_NO_KEY), "Expected NTE_BAD_KEYSET or NTE_NO_KEY, got %08x\n",
1735 GetLastError());
1736 ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
1737 ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
1738 if (ret)
1740 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
1741 toBeSigned->cbData, &algoID, NULL, NULL, &size);
1742 ok(ret, "CryptSignCertificate failed: %08x\n", GetLastError());
1743 ok(size <= *sigLen, "Expected size <= %d, got %d\n", *sigLen, size);
1744 if (ret)
1746 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
1747 toBeSigned->cbData, &algoID, NULL, sig, &size);
1748 ok(ret, "CryptSignCertificate failed: %08x\n", GetLastError());
1749 if (ret)
1751 *sigLen = size;
1752 verifySig(csp, toBeSigned->pbData, toBeSigned->cbData, sig,
1753 size);
1756 CryptDestroyKey(key);
1760 static void testVerifyCertSig(HCRYPTPROV csp, const CRYPT_DATA_BLOB *toBeSigned,
1761 LPCSTR sigOID, const BYTE *sig, DWORD sigLen)
1763 CERT_SIGNED_CONTENT_INFO info;
1764 LPBYTE cert = NULL;
1765 DWORD size = 0;
1766 BOOL ret;
1768 if (!pCryptEncodeObjectEx)
1770 win_skip("no CryptEncodeObjectEx support\n");
1771 return;
1773 ret = CryptVerifyCertificateSignature(0, 0, NULL, 0, NULL);
1774 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1775 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1776 ret = CryptVerifyCertificateSignature(csp, 0, NULL, 0, NULL);
1777 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1778 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1779 ret = CryptVerifyCertificateSignature(csp, X509_ASN_ENCODING, NULL, 0,
1780 NULL);
1781 ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
1782 GetLastError() == OSS_BAD_ARG),
1783 "Expected CRYPT_E_ASN1_EOD or OSS_BAD_ARG, got %08x\n", GetLastError());
1784 info.ToBeSigned.cbData = toBeSigned->cbData;
1785 info.ToBeSigned.pbData = toBeSigned->pbData;
1786 info.SignatureAlgorithm.pszObjId = (LPSTR)sigOID;
1787 info.SignatureAlgorithm.Parameters.cbData = 0;
1788 info.Signature.cbData = sigLen;
1789 info.Signature.pbData = (BYTE *)sig;
1790 info.Signature.cUnusedBits = 0;
1791 ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, X509_CERT, &info,
1792 CRYPT_ENCODE_ALLOC_FLAG, NULL, &cert, &size);
1793 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1794 if (cert)
1796 PCERT_PUBLIC_KEY_INFO pubKeyInfo = NULL;
1797 DWORD pubKeySize;
1799 if (0)
1801 /* Crashes prior to Vista */
1802 ret = CryptVerifyCertificateSignature(csp, X509_ASN_ENCODING,
1803 cert, size, NULL);
1805 CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
1806 (LPSTR)sigOID, 0, NULL, NULL, &pubKeySize);
1807 pubKeyInfo = HeapAlloc(GetProcessHeap(), 0, pubKeySize);
1808 if (pubKeyInfo)
1810 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
1811 X509_ASN_ENCODING, (LPSTR)sigOID, 0, NULL, pubKeyInfo,
1812 &pubKeySize);
1813 ok(ret, "CryptExportKey failed: %08x\n", GetLastError());
1814 if (ret)
1816 ret = CryptVerifyCertificateSignature(csp, X509_ASN_ENCODING,
1817 cert, size, pubKeyInfo);
1818 ok(ret, "CryptVerifyCertificateSignature failed: %08x\n",
1819 GetLastError());
1821 HeapFree(GetProcessHeap(), 0, pubKeyInfo);
1823 LocalFree(cert);
1827 static void testVerifyCertSigEx(HCRYPTPROV csp, const CRYPT_DATA_BLOB *toBeSigned,
1828 LPCSTR sigOID, const BYTE *sig, DWORD sigLen)
1830 CERT_SIGNED_CONTENT_INFO info;
1831 LPBYTE cert = NULL;
1832 DWORD size = 0;
1833 BOOL ret;
1835 if (!pCryptVerifyCertificateSignatureEx)
1837 win_skip("no CryptVerifyCertificateSignatureEx support\n");
1838 return;
1840 if (!pCryptEncodeObjectEx)
1842 win_skip("no CryptEncodeObjectEx support\n");
1843 return;
1845 ret = pCryptVerifyCertificateSignatureEx(0, 0, 0, NULL, 0, NULL, 0, NULL);
1846 ok(!ret && GetLastError() == E_INVALIDARG,
1847 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1848 ret = pCryptVerifyCertificateSignatureEx(csp, 0, 0, NULL, 0, NULL, 0, NULL);
1849 ok(!ret && GetLastError() == E_INVALIDARG,
1850 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1851 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING, 0, NULL, 0,
1852 NULL, 0, NULL);
1853 ok(!ret && GetLastError() == E_INVALIDARG,
1854 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1855 /* This crashes
1856 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1857 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, NULL, 0, NULL, 0, NULL);
1859 info.ToBeSigned.cbData = toBeSigned->cbData;
1860 info.ToBeSigned.pbData = toBeSigned->pbData;
1861 info.SignatureAlgorithm.pszObjId = (LPSTR)sigOID;
1862 info.SignatureAlgorithm.Parameters.cbData = 0;
1863 info.Signature.cbData = sigLen;
1864 info.Signature.pbData = (BYTE *)sig;
1865 info.Signature.cUnusedBits = 0;
1866 ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, X509_CERT, &info,
1867 CRYPT_ENCODE_ALLOC_FLAG, NULL, &cert, &size);
1868 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1869 if (cert)
1871 CRYPT_DATA_BLOB certBlob = { 0, NULL };
1872 PCERT_PUBLIC_KEY_INFO pubKeyInfo = NULL;
1874 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1875 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
1876 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
1877 "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
1878 certBlob.cbData = 1;
1879 certBlob.pbData = (void *)0xdeadbeef;
1880 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1881 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
1882 ok(!ret && (GetLastError() == STATUS_ACCESS_VIOLATION ||
1883 GetLastError() == CRYPT_E_ASN1_EOD /* Win9x */ ||
1884 GetLastError() == CRYPT_E_ASN1_BADTAG /* Win98 */),
1885 "Expected STATUS_ACCESS_VIOLATION, CRYPT_E_ASN1_EOD, OR CRYPT_E_ASN1_BADTAG, got %08x\n",
1886 GetLastError());
1888 certBlob.cbData = size;
1889 certBlob.pbData = cert;
1890 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1891 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
1892 ok(!ret && GetLastError() == E_INVALIDARG,
1893 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1894 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1895 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
1896 CRYPT_VERIFY_CERT_SIGN_ISSUER_NULL, NULL, 0, NULL);
1897 ok(!ret && GetLastError() == E_INVALIDARG,
1898 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1899 /* This crashes
1900 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1901 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
1902 CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY, NULL, 0, NULL);
1904 CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
1905 (LPSTR)sigOID, 0, NULL, NULL, &size);
1906 pubKeyInfo = HeapAlloc(GetProcessHeap(), 0, size);
1907 if (pubKeyInfo)
1909 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
1910 X509_ASN_ENCODING, (LPSTR)sigOID, 0, NULL, pubKeyInfo, &size);
1911 ok(ret, "CryptExportKey failed: %08x\n", GetLastError());
1912 if (ret)
1914 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1915 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
1916 CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY, pubKeyInfo, 0, NULL);
1917 ok(ret, "CryptVerifyCertificateSignatureEx failed: %08x\n",
1918 GetLastError());
1920 HeapFree(GetProcessHeap(), 0, pubKeyInfo);
1922 LocalFree(cert);
1926 static BYTE emptyCert[] = { 0x30, 0x00 };
1928 static void testCertSigs(void)
1930 HCRYPTPROV csp;
1931 CRYPT_DATA_BLOB toBeSigned = { sizeof(emptyCert), emptyCert };
1932 BOOL ret;
1933 BYTE sig[64];
1934 DWORD sigSize = sizeof(sig);
1936 /* Just in case a previous run failed, delete this thing */
1937 pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
1938 CRYPT_DELETEKEYSET);
1939 ret = pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
1940 CRYPT_NEWKEYSET);
1941 ok(ret, "CryptAcquireContext failed: %08x\n", GetLastError());
1943 testSignCert(csp, &toBeSigned, szOID_RSA_SHA1RSA, sig, &sigSize);
1944 testVerifyCertSig(csp, &toBeSigned, szOID_RSA_SHA1RSA, sig, sigSize);
1945 testVerifyCertSigEx(csp, &toBeSigned, szOID_RSA_SHA1RSA, sig, sigSize);
1947 CryptReleaseContext(csp, 0);
1948 ret = pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
1949 CRYPT_DELETEKEYSET);
1950 ok(ret, "CryptAcquireContext failed: %08x\n", GetLastError());
1953 static const BYTE md5SignedEmptyCert[] = {
1954 0x30,0x56,0x30,0x33,0x02,0x00,0x30,0x02,0x06,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,
1955 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,
1956 0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x07,
1957 0x30,0x02,0x06,0x00,0x03,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,
1958 0x0d,0x02,0x05,0x05,0x00,0x03,0x11,0x00,0xfb,0x0f,0x66,0x82,0x66,0xd9,0xe5,0xf8,
1959 0xd8,0xa2,0x55,0x2b,0xe1,0xa5,0xd9,0x04 };
1960 static const BYTE md5SignedEmptyCertNoNull[] = {
1961 0x30,0x54,0x30,0x33,0x02,0x00,0x30,0x02,0x06,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,
1962 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,
1963 0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x07,
1964 0x30,0x02,0x06,0x00,0x03,0x01,0x00,0x30,0x0a,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,
1965 0x0d,0x02,0x05,0x03,0x11,0x00,0x04,0xd9,0xa5,0xe1,0x2b,0x55,0xa2,0xd8,0xf8,0xe5,
1966 0xd9,0x66,0x82,0x66,0x0f,0xfb };
1968 static void testSignAndEncodeCert(void)
1970 static char oid_rsa_md5rsa[] = szOID_RSA_MD5RSA;
1971 static char oid_rsa_md5[] = szOID_RSA_MD5;
1972 BOOL ret;
1973 DWORD size;
1974 CRYPT_ALGORITHM_IDENTIFIER algID = { 0 };
1975 CERT_INFO info = { 0 };
1977 /* Crash
1978 ret = CryptSignAndEncodeCertificate(0, 0, 0, NULL, NULL, NULL, NULL, NULL,
1979 NULL);
1980 ret = CryptSignAndEncodeCertificate(0, 0, 0, NULL, NULL, NULL, NULL, NULL,
1981 &size);
1983 ret = CryptSignAndEncodeCertificate(0, 0, 0, NULL, NULL, &algID, NULL, NULL,
1984 &size);
1985 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1986 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1987 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING, NULL, NULL,
1988 &algID, NULL, NULL, &size);
1989 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1990 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1991 ret = CryptSignAndEncodeCertificate(0, 0, 0, X509_CERT_TO_BE_SIGNED, NULL,
1992 &algID, NULL, NULL, &size);
1993 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1994 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1995 /* Crashes on some win9x boxes */
1996 if (0)
1998 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1999 X509_CERT_TO_BE_SIGNED, NULL, &algID, NULL, NULL, &size);
2000 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2001 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
2003 /* Crashes
2004 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
2005 X509_CERT_TO_BE_SIGNED, &info, NULL, NULL, NULL, &size);
2007 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
2008 X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, NULL, &size);
2009 ok(!ret &&
2010 (GetLastError() == NTE_BAD_ALGID ||
2011 GetLastError() == OSS_BAD_PTR), /* win9x */
2012 "Expected NTE_BAD_ALGID, got %08x\n", GetLastError());
2013 algID.pszObjId = oid_rsa_md5rsa;
2014 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
2015 X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, NULL, &size);
2016 ok(!ret &&
2017 (GetLastError() == ERROR_INVALID_PARAMETER ||
2018 GetLastError() == NTE_BAD_ALGID ||
2019 GetLastError() == OSS_BAD_PTR), /* Win9x */
2020 "Expected ERROR_INVALID_PARAMETER or NTE_BAD_ALGID, got %08x\n",
2021 GetLastError());
2022 algID.pszObjId = oid_rsa_md5;
2023 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
2024 X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, NULL, &size);
2025 /* oid_rsa_md5 not present in some win2k */
2026 if (ret)
2028 LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, size);
2030 if (buf)
2032 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
2033 X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, buf, &size);
2034 ok(ret, "CryptSignAndEncodeCertificate failed: %08x\n",
2035 GetLastError());
2036 /* Tricky: because the NULL parameters may either be omitted or
2037 * included as an asn.1-encoded NULL (0x05,0x00), two different
2038 * values are allowed.
2040 ok(size == sizeof(md5SignedEmptyCert) ||
2041 size == sizeof(md5SignedEmptyCertNoNull), "Unexpected size %d\n",
2042 size);
2043 if (size == sizeof(md5SignedEmptyCert))
2044 ok(!memcmp(buf, md5SignedEmptyCert, size),
2045 "Unexpected value\n");
2046 else if (size == sizeof(md5SignedEmptyCertNoNull))
2047 ok(!memcmp(buf, md5SignedEmptyCertNoNull, size),
2048 "Unexpected value\n");
2049 HeapFree(GetProcessHeap(), 0, buf);
2054 static void testCreateSelfSignCert(void)
2056 PCCERT_CONTEXT context;
2057 CERT_NAME_BLOB name = { sizeof(subjectName), subjectName };
2058 HCRYPTPROV csp;
2059 BOOL ret;
2060 HCRYPTKEY key;
2061 CRYPT_KEY_PROV_INFO info;
2063 if (!pCertCreateSelfSignCertificate)
2065 win_skip("CertCreateSelfSignCertificate() is not available\n");
2066 return;
2069 /* This crashes:
2070 context = pCertCreateSelfSignCertificate(0, NULL, 0, NULL, NULL, NULL, NULL,
2071 NULL);
2072 * Calling this with no first parameter creates a new key container, which
2073 * lasts beyond the test, so I don't test that. Nb: the generated key
2074 * name is a GUID.
2075 context = pCertCreateSelfSignCertificate(0, &name, 0, NULL, NULL, NULL, NULL,
2076 NULL);
2079 /* Acquire a CSP */
2080 pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
2081 CRYPT_DELETEKEYSET);
2082 ret = pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
2083 CRYPT_NEWKEYSET);
2084 ok(ret, "CryptAcquireContext failed: %08x\n", GetLastError());
2086 context = pCertCreateSelfSignCertificate(csp, &name, 0, NULL, NULL, NULL,
2087 NULL, NULL);
2088 ok(!context && GetLastError() == NTE_NO_KEY,
2089 "Expected NTE_NO_KEY, got %08x\n", GetLastError());
2090 ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
2091 ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
2092 if (ret)
2094 context = pCertCreateSelfSignCertificate(csp, &name, 0, NULL, NULL, NULL,
2095 NULL, NULL);
2096 ok(context != NULL, "CertCreateSelfSignCertificate failed: %08x\n",
2097 GetLastError());
2098 if (context)
2100 DWORD size = 0;
2102 /* The context must have a key provider info property */
2103 ret = CertGetCertificateContextProperty(context,
2104 CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
2105 ok(ret && size, "Expected non-zero key provider info\n");
2106 if (size)
2108 PCRYPT_KEY_PROV_INFO pInfo = HeapAlloc(GetProcessHeap(), 0, size);
2110 if (pInfo)
2112 ret = CertGetCertificateContextProperty(context,
2113 CERT_KEY_PROV_INFO_PROP_ID, pInfo, &size);
2114 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
2115 GetLastError());
2116 if (ret)
2118 /* Sanity-check the key provider */
2119 ok(!lstrcmpW(pInfo->pwszContainerName, cspNameW),
2120 "Unexpected key container\n");
2121 ok(!lstrcmpW(pInfo->pwszProvName, MS_DEF_PROV_W),
2122 "Unexpected provider\n");
2123 ok(pInfo->dwKeySpec == AT_SIGNATURE,
2124 "Expected AT_SIGNATURE, got %d\n", pInfo->dwKeySpec);
2126 HeapFree(GetProcessHeap(), 0, pInfo);
2130 CertFreeCertificateContext(context);
2133 CryptDestroyKey(key);
2136 CryptReleaseContext(csp, 0);
2137 ret = pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
2138 CRYPT_DELETEKEYSET);
2139 ok(ret, "CryptAcquireContext failed: %08x\n", GetLastError());
2141 /* Do the same test with a CSP, AT_KEYEXCHANGE and key info */
2142 pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
2143 CRYPT_DELETEKEYSET);
2144 ret = pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
2145 CRYPT_NEWKEYSET);
2146 ok(ret, "CryptAcquireContext failed: %08x\n", GetLastError());
2147 ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
2148 ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
2150 memset(&info,0,sizeof(info));
2151 info.dwProvType = PROV_RSA_FULL;
2152 info.dwKeySpec = AT_KEYEXCHANGE;
2153 info.pwszProvName = (LPWSTR) MS_DEF_PROV_W;
2154 info.pwszContainerName = cspNameW;
2155 /* This should fail because the CSP doesn't have the specified key. */
2156 SetLastError(0xdeadbeef);
2157 context = pCertCreateSelfSignCertificate(csp, &name, 0, &info, NULL, NULL,
2158 NULL, NULL);
2159 todo_wine
2160 ok(context == NULL, "expected failure\n");
2161 if (context != NULL)
2162 CertFreeCertificateContext(context);
2163 else
2164 ok(GetLastError() == NTE_NO_KEY, "expected NTE_NO_KEY, got %08x\n",
2165 GetLastError());
2166 /* Again, with a CSP, AT_SIGNATURE and key info */
2167 info.dwKeySpec = AT_SIGNATURE;
2168 SetLastError(0xdeadbeef);
2169 context = pCertCreateSelfSignCertificate(csp, &name, 0, &info, NULL, NULL,
2170 NULL, NULL);
2171 ok(context != NULL,
2172 "CertCreateSelfSignCertificate failed: %08x\n", GetLastError());
2173 if (context)
2175 DWORD size = 0;
2177 /* The context must have a key provider info property */
2178 ret = CertGetCertificateContextProperty(context,
2179 CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
2180 ok(ret && size, "Expected non-zero key provider info\n");
2181 if (size)
2183 PCRYPT_KEY_PROV_INFO pInfo = HeapAlloc(GetProcessHeap(), 0, size);
2185 if (pInfo)
2187 ret = CertGetCertificateContextProperty(context,
2188 CERT_KEY_PROV_INFO_PROP_ID, pInfo, &size);
2189 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
2190 GetLastError());
2191 if (ret)
2193 /* Sanity-check the key provider */
2194 ok(!lstrcmpW(pInfo->pwszContainerName, cspNameW),
2195 "Unexpected key container\n");
2196 ok(!lstrcmpW(pInfo->pwszProvName, MS_DEF_PROV_W),
2197 "Unexpected provider\n");
2198 ok(pInfo->dwKeySpec == AT_SIGNATURE,
2199 "Expected AT_SIGNATURE, got %d\n", pInfo->dwKeySpec);
2201 HeapFree(GetProcessHeap(), 0, pInfo);
2205 CertFreeCertificateContext(context);
2207 CryptDestroyKey(key);
2209 CryptReleaseContext(csp, 0);
2210 ret = pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
2211 CRYPT_DELETEKEYSET);
2212 ok(ret, "CryptAcquireContext failed: %08x\n", GetLastError());
2214 /* Do the same test with no CSP, AT_KEYEXCHANGE and key info */
2215 info.dwKeySpec = AT_KEYEXCHANGE;
2216 context = pCertCreateSelfSignCertificate(0, &name, 0, &info, NULL, NULL,
2217 NULL, NULL);
2218 ok(context != NULL, "CertCreateSelfSignCertificate failed: %08x\n",
2219 GetLastError());
2220 if (context)
2222 DWORD size = 0;
2224 /* The context must have a key provider info property */
2225 ret = CertGetCertificateContextProperty(context,
2226 CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
2227 ok(ret && size, "Expected non-zero key provider info\n");
2228 if (size)
2230 PCRYPT_KEY_PROV_INFO pInfo = HeapAlloc(GetProcessHeap(), 0, size);
2232 if (pInfo)
2234 ret = CertGetCertificateContextProperty(context,
2235 CERT_KEY_PROV_INFO_PROP_ID, pInfo, &size);
2236 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
2237 GetLastError());
2238 if (ret)
2240 /* Sanity-check the key provider */
2241 ok(!lstrcmpW(pInfo->pwszContainerName, cspNameW),
2242 "Unexpected key container\n");
2243 ok(!lstrcmpW(pInfo->pwszProvName, MS_DEF_PROV_W),
2244 "Unexpected provider\n");
2245 ok(pInfo->dwKeySpec == AT_KEYEXCHANGE,
2246 "Expected AT_KEYEXCHANGE, got %d\n", pInfo->dwKeySpec);
2248 HeapFree(GetProcessHeap(), 0, pInfo);
2252 CertFreeCertificateContext(context);
2255 pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
2256 CRYPT_DELETEKEYSET);
2259 static void testIntendedKeyUsage(void)
2261 BOOL ret;
2262 CERT_INFO info = { 0 };
2263 static char oid_key_usage[] = szOID_KEY_USAGE;
2264 /* A couple "key usages". Really they're just encoded bits which aren't
2265 * necessarily restricted to the defined key usage values.
2267 static BYTE usage1[] = { 0x03,0x03,0x00,0xff,0xff };
2268 static BYTE usage2[] = { 0x03,0x03,0x01,0xff,0xfe };
2269 static const BYTE expected_usage1[] = { 0xff,0xff,0x00,0x00 };
2270 static const BYTE expected_usage2[] = { 0xff,0xfe,0x00,0x00 };
2271 CERT_EXTENSION ext = { oid_key_usage, TRUE, { sizeof(usage1), usage1 } };
2272 BYTE usage_bytes[4];
2274 if (0)
2276 /* Crash */
2277 CertGetIntendedKeyUsage(0, NULL, NULL, 0);
2279 ret = CertGetIntendedKeyUsage(0, &info, NULL, 0);
2280 ok(!ret, "expected failure\n");
2281 ret = CertGetIntendedKeyUsage(0, &info, usage_bytes, sizeof(usage_bytes));
2282 ok(!ret, "expected failure\n");
2283 ret = CertGetIntendedKeyUsage(X509_ASN_ENCODING, &info, NULL, 0);
2284 ok(!ret, "expected failure\n");
2285 ret = CertGetIntendedKeyUsage(X509_ASN_ENCODING, &info, usage_bytes,
2286 sizeof(usage_bytes));
2287 ok(!ret, "expected failure\n");
2288 info.cExtension = 1;
2289 info.rgExtension = &ext;
2290 ret = CertGetIntendedKeyUsage(X509_ASN_ENCODING, &info, NULL, 0);
2291 ok(!ret, "expected failure\n");
2292 /* The unused bytes are filled with 0. */
2293 ret = CertGetIntendedKeyUsage(X509_ASN_ENCODING, &info, usage_bytes,
2294 sizeof(usage_bytes));
2295 ok(ret, "CertGetIntendedKeyUsage failed: %08x\n", GetLastError());
2296 ok(!memcmp(usage_bytes, expected_usage1, sizeof(expected_usage1)),
2297 "unexpected value\n");
2298 /* The usage bytes are copied in big-endian order. */
2299 ext.Value.cbData = sizeof(usage2);
2300 ext.Value.pbData = usage2;
2301 ret = CertGetIntendedKeyUsage(X509_ASN_ENCODING, &info, usage_bytes,
2302 sizeof(usage_bytes));
2303 ok(ret, "CertGetIntendedKeyUsage failed: %08x\n", GetLastError());
2304 ok(!memcmp(usage_bytes, expected_usage2, sizeof(expected_usage2)),
2305 "unexpected value\n");
2308 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
2309 szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
2311 static void testKeyUsage(void)
2313 BOOL ret;
2314 PCCERT_CONTEXT context;
2315 DWORD size;
2317 /* Test base cases */
2318 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, NULL);
2319 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2320 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
2321 size = 1;
2322 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, &size);
2323 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2324 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
2325 size = 0;
2326 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, &size);
2327 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2328 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
2329 /* These crash
2330 ret = CertSetEnhancedKeyUsage(NULL, NULL);
2331 usage.cUsageIdentifier = 0;
2332 ret = CertSetEnhancedKeyUsage(NULL, &usage);
2334 /* Test with a cert with no enhanced key usage extension */
2335 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
2336 sizeof(bigCert));
2337 ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
2338 GetLastError());
2339 if (context)
2341 static const char oid[] = "1.2.3.4";
2342 BYTE buf[sizeof(CERT_ENHKEY_USAGE) + 2 * (sizeof(LPSTR) + sizeof(oid))];
2343 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
2345 ret = CertGetEnhancedKeyUsage(context, 0, NULL, NULL);
2346 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2347 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
2348 size = 1;
2349 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &size);
2350 if (ret)
2352 /* Windows 2000, ME, or later: even though it succeeded, we expect
2353 * CRYPT_E_NOT_FOUND, which indicates there is no enhanced key
2354 * usage set for this cert (which implies it's valid for all uses.)
2356 ok(GetLastError() == CRYPT_E_NOT_FOUND,
2357 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
2358 ok(size == sizeof(CERT_ENHKEY_USAGE), "Wrong size %d\n", size);
2359 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2360 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2361 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %d\n",
2362 pUsage->cUsageIdentifier);
2364 else
2366 /* Windows NT, 95, or 98: it fails, and the last error is
2367 * CRYPT_E_NOT_FOUND.
2369 ok(GetLastError() == CRYPT_E_NOT_FOUND,
2370 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
2372 /* I can add a usage identifier when no key usage has been set */
2373 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
2374 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
2375 GetLastError());
2376 size = sizeof(buf);
2377 ret = CertGetEnhancedKeyUsage(context,
2378 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
2379 ok(ret && GetLastError() == 0,
2380 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2381 ok(pUsage->cUsageIdentifier == 1, "Expected 1 usage, got %d\n",
2382 pUsage->cUsageIdentifier);
2383 if (pUsage->cUsageIdentifier)
2384 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
2385 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
2386 /* Now set an empty key usage */
2387 pUsage->cUsageIdentifier = 0;
2388 ret = CertSetEnhancedKeyUsage(context, pUsage);
2389 ok(ret, "CertSetEnhancedKeyUsage failed: %08x\n", GetLastError());
2390 /* Shouldn't find it in the cert */
2391 size = sizeof(buf);
2392 ret = CertGetEnhancedKeyUsage(context,
2393 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
2394 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
2395 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
2396 /* Should find it as an extended property */
2397 ret = CertGetEnhancedKeyUsage(context,
2398 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
2399 ok(ret && GetLastError() == 0,
2400 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2401 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %d\n",
2402 pUsage->cUsageIdentifier);
2403 /* Should find it as either */
2404 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2405 ok(ret && GetLastError() == 0,
2406 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2407 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %d\n",
2408 pUsage->cUsageIdentifier);
2409 /* Add a usage identifier */
2410 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
2411 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
2412 GetLastError());
2413 size = sizeof(buf);
2414 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2415 ok(ret && GetLastError() == 0,
2416 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2417 ok(pUsage->cUsageIdentifier == 1, "Expected 1 identifier, got %d\n",
2418 pUsage->cUsageIdentifier);
2419 if (pUsage->cUsageIdentifier)
2420 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
2421 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
2422 /* Re-adding the same usage identifier succeeds, though it only adds
2423 * a duplicate usage identifier on versions prior to Vista
2425 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
2426 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
2427 GetLastError());
2428 size = sizeof(buf);
2429 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2430 ok(ret && GetLastError() == 0,
2431 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2432 ok(pUsage->cUsageIdentifier == 1 || pUsage->cUsageIdentifier == 2,
2433 "Expected 1 or 2 identifiers, got %d\n", pUsage->cUsageIdentifier);
2434 if (pUsage->cUsageIdentifier)
2435 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
2436 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
2437 if (pUsage->cUsageIdentifier >= 2)
2438 ok(!strcmp(pUsage->rgpszUsageIdentifier[1], oid),
2439 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[1]);
2440 /* Now set a NULL extended property--this deletes the property. */
2441 ret = CertSetEnhancedKeyUsage(context, NULL);
2442 ok(ret, "CertSetEnhancedKeyUsage failed: %08x\n", GetLastError());
2443 SetLastError(0xbaadcafe);
2444 size = sizeof(buf);
2445 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2446 ok(ret || broken(!ret && GetLastError() == CRYPT_E_NOT_FOUND /* NT4 */),
2447 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2448 ok(GetLastError() == CRYPT_E_NOT_FOUND,
2449 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
2451 CertFreeCertificateContext(context);
2453 /* Now test with a cert with an enhanced key usage extension */
2454 context = CertCreateCertificateContext(X509_ASN_ENCODING, certWithUsage,
2455 sizeof(certWithUsage));
2456 ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
2457 GetLastError());
2458 if (context)
2460 LPBYTE buf = NULL;
2461 DWORD bufSize = 0, i;
2463 /* The size may depend on what flags are used to query it, so I
2464 * realloc the buffer for each test.
2466 ret = CertGetEnhancedKeyUsage(context,
2467 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, NULL, &bufSize);
2468 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2469 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
2470 if (buf)
2472 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
2474 /* Should find it in the cert */
2475 size = bufSize;
2476 ret = CertGetEnhancedKeyUsage(context,
2477 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
2478 ok(ret && GetLastError() == 0,
2479 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2480 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
2481 pUsage->cUsageIdentifier);
2482 for (i = 0; i < pUsage->cUsageIdentifier; i++)
2483 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
2484 "Expected %s, got %s\n", keyUsages[i],
2485 pUsage->rgpszUsageIdentifier[i]);
2486 HeapFree(GetProcessHeap(), 0, buf);
2488 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
2489 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2490 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
2491 if (buf)
2493 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
2495 /* Should find it as either */
2496 size = bufSize;
2497 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2498 /* In Windows, GetLastError returns CRYPT_E_NOT_FOUND not found
2499 * here, even though the return is successful and the usage id
2500 * count is positive. I don't enforce that here.
2502 ok(ret,
2503 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2504 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
2505 pUsage->cUsageIdentifier);
2506 for (i = 0; i < pUsage->cUsageIdentifier; i++)
2507 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
2508 "Expected %s, got %s\n", keyUsages[i],
2509 pUsage->rgpszUsageIdentifier[i]);
2510 HeapFree(GetProcessHeap(), 0, buf);
2512 /* Shouldn't find it as an extended property */
2513 ret = CertGetEnhancedKeyUsage(context,
2514 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, NULL, &size);
2515 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
2516 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
2517 /* Adding a usage identifier overrides the cert's usage!? */
2518 ret = CertAddEnhancedKeyUsageIdentifier(context, szOID_RSA_RSA);
2519 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
2520 GetLastError());
2521 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
2522 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2523 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
2524 if (buf)
2526 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
2528 /* Should find it as either */
2529 size = bufSize;
2530 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2531 ok(ret,
2532 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2533 ok(pUsage->cUsageIdentifier == 1, "Expected 1 usage, got %d\n",
2534 pUsage->cUsageIdentifier);
2535 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], szOID_RSA_RSA),
2536 "Expected %s, got %s\n", szOID_RSA_RSA,
2537 pUsage->rgpszUsageIdentifier[0]);
2538 HeapFree(GetProcessHeap(), 0, buf);
2540 /* But querying the cert directly returns its usage */
2541 ret = CertGetEnhancedKeyUsage(context,
2542 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, NULL, &bufSize);
2543 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2544 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
2545 if (buf)
2547 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
2549 size = bufSize;
2550 ret = CertGetEnhancedKeyUsage(context,
2551 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
2552 ok(ret,
2553 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2554 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
2555 pUsage->cUsageIdentifier);
2556 for (i = 0; i < pUsage->cUsageIdentifier; i++)
2557 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
2558 "Expected %s, got %s\n", keyUsages[i],
2559 pUsage->rgpszUsageIdentifier[i]);
2560 HeapFree(GetProcessHeap(), 0, buf);
2562 /* And removing the only usage identifier in the extended property
2563 * results in the cert's key usage being found.
2565 ret = CertRemoveEnhancedKeyUsageIdentifier(context, szOID_RSA_RSA);
2566 ok(ret, "CertRemoveEnhancedKeyUsage failed: %08x\n", GetLastError());
2567 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
2568 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2569 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
2570 if (buf)
2572 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
2574 /* Should find it as either */
2575 size = bufSize;
2576 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2577 ok(ret,
2578 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2579 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
2580 pUsage->cUsageIdentifier);
2581 for (i = 0; i < pUsage->cUsageIdentifier; i++)
2582 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
2583 "Expected %s, got %s\n", keyUsages[i],
2584 pUsage->rgpszUsageIdentifier[i]);
2585 HeapFree(GetProcessHeap(), 0, buf);
2588 CertFreeCertificateContext(context);
2592 static const BYTE cert2WithUsage[] = {
2593 0x30,0x81,0x89,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2594 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2595 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2596 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2597 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2598 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2599 0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x25,0x30,0x23,
2600 0x30,0x21,0x06,0x03,0x55,0x1d,0x25,0x01,0x01,0xff,0x04,0x17,0x30,0x15,0x06,
2601 0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x03,0x02,0x06,0x09,0x2a,0x86,0x48,0x86,
2602 0xf7,0x0d,0x01,0x01,0x01 };
2604 static void testGetValidUsages(void)
2606 static const LPCSTR expectedOIDs[] = {
2607 "1.3.6.1.5.5.7.3.3",
2608 "1.3.6.1.5.5.7.3.2",
2609 "1.2.840.113549.1.1.1",
2611 static const LPCSTR expectedOIDs2[] = {
2612 "1.3.6.1.5.5.7.3.2",
2613 "1.2.840.113549.1.1.1",
2615 BOOL ret;
2616 int numOIDs;
2617 DWORD size;
2618 LPSTR *oids = NULL;
2619 PCCERT_CONTEXT contexts[3];
2621 if (!pCertGetValidUsages)
2623 win_skip("CertGetValidUsages() is not available\n");
2624 return;
2627 /* Crash
2628 ret = pCertGetValidUsages(0, NULL, NULL, NULL, NULL);
2629 ret = pCertGetValidUsages(0, NULL, NULL, NULL, &size);
2631 contexts[0] = NULL;
2632 numOIDs = size = 0xdeadbeef;
2633 SetLastError(0xdeadbeef);
2634 ret = pCertGetValidUsages(1, &contexts[0], &numOIDs, NULL, &size);
2635 ok(ret, "CertGetValidUsages failed: %d\n", GetLastError());
2636 ok(numOIDs == -1, "Expected -1, got %d\n", numOIDs);
2637 ok(size == 0, "Expected size 0, got %d\n", size);
2638 contexts[0] = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
2639 sizeof(bigCert));
2640 contexts[1] = CertCreateCertificateContext(X509_ASN_ENCODING, certWithUsage,
2641 sizeof(certWithUsage));
2642 contexts[2] = CertCreateCertificateContext(X509_ASN_ENCODING,
2643 cert2WithUsage, sizeof(cert2WithUsage));
2644 numOIDs = size = 0xdeadbeef;
2645 ret = pCertGetValidUsages(0, NULL, &numOIDs, NULL, &size);
2646 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2647 ok(numOIDs == -1, "Expected -1, got %d\n", numOIDs);
2648 ok(size == 0, "Expected size 0, got %d\n", size);
2649 numOIDs = size = 0xdeadbeef;
2650 ret = pCertGetValidUsages(1, contexts, &numOIDs, NULL, &size);
2651 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2652 ok(numOIDs == -1, "Expected -1, got %d\n", numOIDs);
2653 ok(size == 0, "Expected size 0, got %d\n", size);
2654 ret = pCertGetValidUsages(1, &contexts[1], &numOIDs, NULL, &size);
2655 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2656 ok(numOIDs == 3, "Expected 3, got %d\n", numOIDs);
2657 ok(size, "Expected non-zero size\n");
2658 oids = HeapAlloc(GetProcessHeap(), 0, size);
2659 if (oids)
2661 int i;
2662 DWORD smallSize = 1;
2664 SetLastError(0xdeadbeef);
2665 ret = pCertGetValidUsages(1, &contexts[1], &numOIDs, oids, &smallSize);
2666 ok(!ret && GetLastError() == ERROR_MORE_DATA,
2667 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
2668 ret = pCertGetValidUsages(1, &contexts[1], &numOIDs, oids, &size);
2669 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2670 for (i = 0; i < numOIDs; i++)
2671 ok(!lstrcmpA(oids[i], expectedOIDs[i]), "unexpected OID %s\n",
2672 oids[i]);
2673 HeapFree(GetProcessHeap(), 0, oids);
2675 numOIDs = size = 0xdeadbeef;
2676 /* Oddly enough, this crashes when the number of contexts is not 1:
2677 ret = pCertGetValidUsages(2, contexts, &numOIDs, NULL, &size);
2678 * but setting size to 0 allows it to succeed:
2680 size = 0;
2681 ret = pCertGetValidUsages(2, contexts, &numOIDs, NULL, &size);
2682 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2683 ok(numOIDs == 3, "Expected 3, got %d\n", numOIDs);
2684 ok(size, "Expected non-zero size\n");
2685 oids = HeapAlloc(GetProcessHeap(), 0, size);
2686 if (oids)
2688 int i;
2690 ret = pCertGetValidUsages(1, &contexts[1], &numOIDs, oids, &size);
2691 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2692 for (i = 0; i < numOIDs; i++)
2693 ok(!lstrcmpA(oids[i], expectedOIDs[i]), "unexpected OID %s\n",
2694 oids[i]);
2695 HeapFree(GetProcessHeap(), 0, oids);
2697 numOIDs = 0xdeadbeef;
2698 size = 0;
2699 ret = pCertGetValidUsages(1, &contexts[2], &numOIDs, NULL, &size);
2700 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2701 ok(numOIDs == 2, "Expected 2, got %d\n", numOIDs);
2702 ok(size, "Expected non-zero size\n");
2703 oids = HeapAlloc(GetProcessHeap(), 0, size);
2704 if (oids)
2706 int i;
2708 ret = pCertGetValidUsages(1, &contexts[2], &numOIDs, oids, &size);
2709 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2710 for (i = 0; i < numOIDs; i++)
2711 ok(!lstrcmpA(oids[i], expectedOIDs2[i]), "unexpected OID %s\n",
2712 oids[i]);
2713 HeapFree(GetProcessHeap(), 0, oids);
2715 numOIDs = 0xdeadbeef;
2716 size = 0;
2717 ret = pCertGetValidUsages(3, contexts, &numOIDs, NULL, &size);
2718 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2719 ok(numOIDs == 2, "Expected 2, got %d\n", numOIDs);
2720 ok(size, "Expected non-zero size\n");
2721 oids = HeapAlloc(GetProcessHeap(), 0, size);
2722 if (oids)
2724 int i;
2726 ret = pCertGetValidUsages(3, contexts, &numOIDs, oids, &size);
2727 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2728 for (i = 0; i < numOIDs; i++)
2729 ok(!lstrcmpA(oids[i], expectedOIDs2[i]), "unexpected OID %s\n",
2730 oids[i]);
2731 HeapFree(GetProcessHeap(), 0, oids);
2733 CertFreeCertificateContext(contexts[0]);
2734 CertFreeCertificateContext(contexts[1]);
2735 CertFreeCertificateContext(contexts[2]);
2738 static BYTE cn[] = {
2739 0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,
2740 0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67 };
2741 static BYTE cnWithLeadingSpace[] = {
2742 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x20,0x4a,
2743 0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67 };
2744 static BYTE cnWithTrailingSpace[] = {
2745 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,
2746 0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x20 };
2747 static BYTE cnWithIntermediateSpace[] = {
2748 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,
2749 0x61,0x6e,0x20,0x20,0x4c,0x61,0x6e,0x67 };
2750 static BYTE cnThenO[] = {
2751 0x30,0x2d,0x31,0x2b,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,
2752 0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x30,0x17,0x06,0x03,0x55,0x04,0x0a,0x13,
2753 0x10,0x54,0x68,0x65,0x20,0x57,0x69,0x6e,0x65,0x20,0x50,0x72,0x6f,0x6a,0x65,
2754 0x63,0x74 };
2755 static BYTE oThenCN[] = {
2756 0x30,0x2d,0x31,0x2b,0x30,0x10,0x06,0x03,0x55,0x04,0x0a,0x13,0x09,0x4a,0x75,
2757 0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x30,0x17,0x06,0x03,0x55,0x04,0x03,0x13,
2758 0x10,0x54,0x68,0x65,0x20,0x57,0x69,0x6e,0x65,0x20,0x50,0x72,0x6f,0x6a,0x65,
2759 0x63,0x74 };
2761 static void testCompareCertName(void)
2763 static BYTE bogus[] = { 1, 2, 3, 4 };
2764 static BYTE bogusPrime[] = { 0, 1, 2, 3, 4 };
2765 static BYTE emptyPrime[] = { 0x30, 0x00, 0x01 };
2766 BOOL ret;
2767 CERT_NAME_BLOB blob1, blob2;
2769 /* crashes
2770 ret = CertCompareCertificateName(0, NULL, NULL);
2772 /* An empty name checks against itself.. */
2773 blob1.pbData = emptyCert;
2774 blob1.cbData = sizeof(emptyCert);
2775 ret = CertCompareCertificateName(0, &blob1, &blob1);
2776 ok(ret, "CertCompareCertificateName failed: %08x\n", GetLastError());
2777 /* It doesn't have to be a valid encoded name.. */
2778 blob1.pbData = bogus;
2779 blob1.cbData = sizeof(bogus);
2780 ret = CertCompareCertificateName(0, &blob1, &blob1);
2781 ok(ret, "CertCompareCertificateName failed: %08x\n", GetLastError());
2782 /* Leading zeroes matter.. */
2783 blob2.pbData = bogusPrime;
2784 blob2.cbData = sizeof(bogusPrime);
2785 ret = CertCompareCertificateName(0, &blob1, &blob2);
2786 ok(!ret, "Expected failure\n");
2787 /* As do trailing extra bytes. */
2788 blob2.pbData = emptyPrime;
2789 blob2.cbData = sizeof(emptyPrime);
2790 ret = CertCompareCertificateName(0, &blob1, &blob2);
2791 ok(!ret, "Expected failure\n");
2792 /* Tests to show that CertCompareCertificateName doesn't decode the name
2793 * to remove spaces, or to do an order-independent comparison.
2795 /* Compare CN="Juan Lang" with CN=" Juan Lang" */
2796 blob1.pbData = cn;
2797 blob1.cbData = sizeof(cn);
2798 blob2.pbData = cnWithLeadingSpace;
2799 blob2.cbData = sizeof(cnWithLeadingSpace);
2800 ret = CertCompareCertificateName(0, &blob1, &blob2);
2801 ok(!ret, "Expected failure\n");
2802 ret = CertCompareCertificateName(X509_ASN_ENCODING, &blob1, &blob2);
2803 ok(!ret, "Expected failure\n");
2804 /* Compare CN="Juan Lang" with CN="Juan Lang " */
2805 blob2.pbData = cnWithTrailingSpace;
2806 blob2.cbData = sizeof(cnWithTrailingSpace);
2807 ret = CertCompareCertificateName(0, &blob1, &blob2);
2808 ok(!ret, "Expected failure\n");
2809 ret = CertCompareCertificateName(X509_ASN_ENCODING, &blob1, &blob2);
2810 ok(!ret, "Expected failure\n");
2811 /* Compare CN="Juan Lang" with CN="Juan Lang" */
2812 blob2.pbData = cnWithIntermediateSpace;
2813 blob2.cbData = sizeof(cnWithIntermediateSpace);
2814 ret = CertCompareCertificateName(0, &blob1, &blob2);
2815 ok(!ret, "Expected failure\n");
2816 ret = CertCompareCertificateName(X509_ASN_ENCODING, &blob1, &blob2);
2817 ok(!ret, "Expected failure\n");
2818 /* Compare 'CN="Juan Lang", O="The Wine Project"' with
2819 * 'O="The Wine Project", CN="Juan Lang"'
2821 blob1.pbData = cnThenO;
2822 blob1.cbData = sizeof(cnThenO);
2823 blob2.pbData = oThenCN;
2824 blob2.cbData = sizeof(oThenCN);
2825 ret = CertCompareCertificateName(0, &blob1, &blob2);
2826 ok(!ret, "Expected failure\n");
2827 ret = CertCompareCertificateName(X509_ASN_ENCODING, &blob1, &blob2);
2828 ok(!ret, "Expected failure\n");
2831 static void testIsRDNAttrsInCertificateName(void)
2833 static char oid_1_2_3[] = "1.2.3";
2834 static char oid_common_name[] = szOID_COMMON_NAME;
2835 static char oid_organization[] = szOID_ORGANIZATION_NAME;
2836 static char juan[] = "Juan Lang";
2837 static char juan_with_leading_space[] = " Juan Lang";
2838 static char juan_with_intermediate_space[] = "Juan Lang";
2839 static char juan_with_trailing_space[] = "Juan Lang ";
2840 static char juan_lower_case[] = "juan lang";
2841 static WCHAR juanW[] = { 'J','u','a','n',' ','L','a','n','g',0 };
2842 static char the_wine_project[] = "The Wine Project";
2843 BOOL ret;
2844 CERT_NAME_BLOB name;
2845 CERT_RDN_ATTR attr[2];
2846 CERT_RDN rdn = { 0, NULL };
2848 name.cbData = sizeof(cn);
2849 name.pbData = cn;
2850 if (0)
2852 /* Crash */
2853 CertIsRDNAttrsInCertificateName(0, 0, NULL, NULL);
2854 CertIsRDNAttrsInCertificateName(X509_ASN_ENCODING, 0, &name, NULL);
2856 SetLastError(0xdeadbeef);
2857 ret = CertIsRDNAttrsInCertificateName(0, 0, &name, NULL);
2858 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2859 "expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2860 ret = CertIsRDNAttrsInCertificateName(X509_ASN_ENCODING, 0, &name, &rdn);
2861 ok(ret, "CertIsRDNAttrsInCertificateName failed: %08x\n", GetLastError());
2862 attr[0].pszObjId = oid_1_2_3;
2863 rdn.rgRDNAttr = attr;
2864 rdn.cRDNAttr = 1;
2865 SetLastError(0xdeadbeef);
2866 ret = CertIsRDNAttrsInCertificateName(X509_ASN_ENCODING, 0, &name, &rdn);
2867 ok(!ret && GetLastError() == CRYPT_E_NO_MATCH,
2868 "expected CRYPT_E_NO_MATCH, got %08x\n", GetLastError());
2869 attr[0].pszObjId = oid_common_name;
2870 attr[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
2871 attr[0].Value.cbData = strlen(juan);
2872 attr[0].Value.pbData = (BYTE *)juan;
2873 ret = CertIsRDNAttrsInCertificateName(X509_ASN_ENCODING, 0, &name, &rdn);
2874 ok(ret, "CertIsRDNAttrsInCertificateName failed: %08x\n", GetLastError());
2875 /* Again, spaces are not removed for name comparison. */
2876 attr[0].Value.cbData = strlen(juan_with_leading_space);
2877 attr[0].Value.pbData = (BYTE *)juan_with_leading_space;
2878 SetLastError(0xdeadbeef);
2879 ret = CertIsRDNAttrsInCertificateName(X509_ASN_ENCODING, 0, &name, &rdn);
2880 ok(!ret && GetLastError() == CRYPT_E_NO_MATCH,
2881 "expected CRYPT_E_NO_MATCH, got %08x\n", GetLastError());
2882 attr[0].Value.cbData = strlen(juan_with_intermediate_space);
2883 attr[0].Value.pbData = (BYTE *)juan_with_intermediate_space;
2884 SetLastError(0xdeadbeef);
2885 ret = CertIsRDNAttrsInCertificateName(X509_ASN_ENCODING, 0, &name, &rdn);
2886 ok(!ret && GetLastError() == CRYPT_E_NO_MATCH,
2887 "expected CRYPT_E_NO_MATCH, got %08x\n", GetLastError());
2888 attr[0].Value.cbData = strlen(juan_with_trailing_space);
2889 attr[0].Value.pbData = (BYTE *)juan_with_trailing_space;
2890 SetLastError(0xdeadbeef);
2891 ret = CertIsRDNAttrsInCertificateName(X509_ASN_ENCODING, 0, &name, &rdn);
2892 ok(!ret && GetLastError() == CRYPT_E_NO_MATCH,
2893 "expected CRYPT_E_NO_MATCH, got %08x\n", GetLastError());
2894 /* The lower case name isn't matched unless a case insensitive match is
2895 * specified.
2897 attr[0].Value.cbData = strlen(juan_lower_case);
2898 attr[0].Value.pbData = (BYTE *)juan_lower_case;
2899 SetLastError(0xdeadbeef);
2900 ret = CertIsRDNAttrsInCertificateName(X509_ASN_ENCODING, 0, &name, &rdn);
2901 ok(!ret && GetLastError() == CRYPT_E_NO_MATCH,
2902 "expected CRYPT_E_NO_MATCH, got %08x\n", GetLastError());
2903 ret = CertIsRDNAttrsInCertificateName(X509_ASN_ENCODING,
2904 CERT_CASE_INSENSITIVE_IS_RDN_ATTRS_FLAG, &name, &rdn);
2905 ok(ret ||
2906 broken(!ret && GetLastError() == CRYPT_E_NO_MATCH), /* Older crypt32 */
2907 "CertIsRDNAttrsInCertificateName failed: %08x\n", GetLastError());
2908 /* The values don't match unless they have the same RDN type */
2909 attr[0].dwValueType = CERT_RDN_UNICODE_STRING;
2910 attr[0].Value.cbData = lstrlenW(juanW) * sizeof(WCHAR);
2911 attr[0].Value.pbData = (BYTE *)juanW;
2912 SetLastError(0xdeadbeef);
2913 ret = CertIsRDNAttrsInCertificateName(X509_ASN_ENCODING, 0, &name, &rdn);
2914 ok(!ret && GetLastError() == CRYPT_E_NO_MATCH,
2915 "expected CRYPT_E_NO_MATCH, got %08x\n", GetLastError());
2916 SetLastError(0xdeadbeef);
2917 ret = CertIsRDNAttrsInCertificateName(X509_ASN_ENCODING,
2918 CERT_UNICODE_IS_RDN_ATTRS_FLAG, &name, &rdn);
2919 ok(!ret && GetLastError() == CRYPT_E_NO_MATCH,
2920 "expected CRYPT_E_NO_MATCH, got %08x\n", GetLastError());
2921 attr[0].dwValueType = CERT_RDN_IA5_STRING;
2922 attr[0].Value.cbData = strlen(juan);
2923 attr[0].Value.pbData = (BYTE *)juan;
2924 SetLastError(0xdeadbeef);
2925 ret = CertIsRDNAttrsInCertificateName(X509_ASN_ENCODING, 0, &name, &rdn);
2926 ok(!ret && GetLastError() == CRYPT_E_NO_MATCH,
2927 "expected CRYPT_E_NO_MATCH, got %08x\n", GetLastError());
2928 /* All attributes must be present */
2929 attr[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
2930 attr[0].Value.cbData = strlen(juan);
2931 attr[0].Value.pbData = (BYTE *)juan;
2932 attr[1].pszObjId = oid_organization;
2933 attr[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
2934 attr[1].Value.cbData = strlen(the_wine_project);
2935 attr[1].Value.pbData = (BYTE *)the_wine_project;
2936 rdn.cRDNAttr = 2;
2937 SetLastError(0xdeadbeef);
2938 ret = CertIsRDNAttrsInCertificateName(X509_ASN_ENCODING, 0, &name, &rdn);
2939 ok(!ret && GetLastError() == CRYPT_E_NO_MATCH,
2940 "expected CRYPT_E_NO_MATCH, got %08x\n", GetLastError());
2941 /* Order also matters */
2942 name.pbData = cnThenO;
2943 name.cbData = sizeof(cnThenO);
2944 ret = CertIsRDNAttrsInCertificateName(X509_ASN_ENCODING, 0, &name, &rdn);
2945 ok(ret, "CertIsRDNAttrsInCertificateName failed: %08x\n", GetLastError());
2946 name.pbData = oThenCN;
2947 name.cbData = sizeof(oThenCN);
2948 SetLastError(0xdeadbeef);
2949 ret = CertIsRDNAttrsInCertificateName(X509_ASN_ENCODING, 0, &name, &rdn);
2950 ok(!ret && GetLastError() == CRYPT_E_NO_MATCH,
2951 "expected CRYPT_E_NO_MATCH, got %08x\n", GetLastError());
2954 static BYTE int1[] = { 0x88, 0xff, 0xff, 0xff };
2955 static BYTE int2[] = { 0x88, 0xff };
2956 static BYTE int3[] = { 0x23, 0xff };
2957 static BYTE int4[] = { 0x7f, 0x00 };
2958 static BYTE int5[] = { 0x7f };
2959 static BYTE int6[] = { 0x80, 0x00, 0x00, 0x00 };
2960 static BYTE int7[] = { 0x80, 0x00 };
2962 static struct IntBlobTest
2964 CRYPT_INTEGER_BLOB blob1;
2965 CRYPT_INTEGER_BLOB blob2;
2966 BOOL areEqual;
2967 } intBlobs[] = {
2968 { { sizeof(int1), int1 }, { sizeof(int2), int2 }, TRUE },
2969 { { sizeof(int3), int3 }, { sizeof(int3), int3 }, TRUE },
2970 { { sizeof(int4), int4 }, { sizeof(int5), int5 }, TRUE },
2971 { { sizeof(int6), int6 }, { sizeof(int7), int7 }, TRUE },
2972 { { sizeof(int1), int1 }, { sizeof(int7), int7 }, FALSE },
2975 static void testCompareIntegerBlob(void)
2977 DWORD i;
2978 BOOL ret;
2980 for (i = 0; i < sizeof(intBlobs) / sizeof(intBlobs[0]); i++)
2982 ret = CertCompareIntegerBlob(&intBlobs[i].blob1, &intBlobs[i].blob2);
2983 ok(ret == intBlobs[i].areEqual,
2984 "%d: expected blobs %s compare\n", i, intBlobs[i].areEqual ?
2985 "to" : "not to");
2989 static void testComparePublicKeyInfo(void)
2991 BOOL ret;
2992 CERT_PUBLIC_KEY_INFO info1 = { { 0 } }, info2 = { { 0 } };
2993 static CHAR oid_rsa_rsa[] = szOID_RSA_RSA;
2994 static CHAR oid_rsa_sha1rsa[] = szOID_RSA_SHA1RSA;
2995 static CHAR oid_x957_dsa[] = szOID_X957_DSA;
2996 static BYTE bits1[] = { 1, 0 };
2997 static BYTE bits2[] = { 0 };
2998 static BYTE bits3[] = { 1 };
2999 static BYTE bits4[] = { 0x30,8, 2,1,0x81, 2,3,1,0,1 };
3000 static BYTE bits5[] = { 0x30,9, 2,2,0,0x81, 2,3,1,0,1 };
3001 static BYTE bits6[] = { 0x30,9, 2,2,0,0x82, 2,3,1,0,1 };
3003 /* crashes
3004 ret = CertComparePublicKeyInfo(0, NULL, NULL);
3006 /* Empty public keys compare */
3007 ret = CertComparePublicKeyInfo(0, &info1, &info2);
3008 ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
3009 /* Different OIDs appear to compare */
3010 info1.Algorithm.pszObjId = oid_rsa_rsa;
3011 info2.Algorithm.pszObjId = oid_rsa_sha1rsa;
3012 ret = CertComparePublicKeyInfo(0, &info1, &info2);
3013 ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
3014 info2.Algorithm.pszObjId = oid_x957_dsa;
3015 ret = CertComparePublicKeyInfo(0, &info1, &info2);
3016 ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
3017 info1.PublicKey.cbData = sizeof(bits1);
3018 info1.PublicKey.pbData = bits1;
3019 info1.PublicKey.cUnusedBits = 0;
3020 info2.PublicKey.cbData = sizeof(bits1);
3021 info2.PublicKey.pbData = bits1;
3022 info2.PublicKey.cUnusedBits = 0;
3023 ret = CertComparePublicKeyInfo(0, &info1, &info2);
3024 ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
3025 info2.Algorithm.pszObjId = oid_rsa_rsa;
3026 info1.PublicKey.cbData = sizeof(bits4);
3027 info1.PublicKey.pbData = bits4;
3028 info1.PublicKey.cUnusedBits = 0;
3029 info2.PublicKey.cbData = sizeof(bits5);
3030 info2.PublicKey.pbData = bits5;
3031 info2.PublicKey.cUnusedBits = 0;
3032 ret = CertComparePublicKeyInfo(0, &info1, &info2);
3033 ok(!ret, "CertComparePublicKeyInfo: as raw binary: keys should be unequal\n");
3034 ret = CertComparePublicKeyInfo(X509_ASN_ENCODING, &info1, &info2);
3035 ok(ret ||
3036 broken(!ret), /* win9x */
3037 "CertComparePublicKeyInfo: as ASN.1 encoded: keys should be equal\n");
3038 info1.PublicKey.cUnusedBits = 1;
3039 info2.PublicKey.cUnusedBits = 5;
3040 ret = CertComparePublicKeyInfo(X509_ASN_ENCODING, &info1, &info2);
3041 ok(ret ||
3042 broken(!ret), /* win9x */
3043 "CertComparePublicKeyInfo: ASN.1 encoding should ignore cUnusedBits\n");
3044 info1.PublicKey.cUnusedBits = 0;
3045 info2.PublicKey.cUnusedBits = 0;
3046 info1.PublicKey.cbData--; /* kill one byte, make ASN.1 encoded data invalid */
3047 ret = CertComparePublicKeyInfo(X509_ASN_ENCODING, &info1, &info2);
3048 ok(!ret, "CertComparePublicKeyInfo: comparing bad ASN.1 encoded key should fail\n");
3049 /* Even though they compare in their used bits, these do not compare */
3050 info1.PublicKey.cbData = sizeof(bits2);
3051 info1.PublicKey.pbData = bits2;
3052 info1.PublicKey.cUnusedBits = 0;
3053 info2.PublicKey.cbData = sizeof(bits3);
3054 info2.PublicKey.pbData = bits3;
3055 info2.PublicKey.cUnusedBits = 1;
3056 ret = CertComparePublicKeyInfo(0, &info1, &info2);
3057 /* Simple (non-comparing) case */
3058 ok(!ret, "Expected keys not to compare\n");
3059 info2.PublicKey.cbData = sizeof(bits1);
3060 info2.PublicKey.pbData = bits1;
3061 info2.PublicKey.cUnusedBits = 0;
3062 ret = CertComparePublicKeyInfo(0, &info1, &info2);
3063 ok(!ret, "Expected keys not to compare\n");
3064 /* ASN.1 encoded non-comparing case */
3065 info1.PublicKey.cbData = sizeof(bits5);
3066 info1.PublicKey.pbData = bits5;
3067 info1.PublicKey.cUnusedBits = 0;
3068 info2.PublicKey.cbData = sizeof(bits6);
3069 info2.PublicKey.pbData = bits6;
3070 info2.PublicKey.cUnusedBits = 0;
3071 ret = CertComparePublicKeyInfo(X509_ASN_ENCODING, &info1, &info2);
3072 ok(!ret, "CertComparePublicKeyInfo: different keys should be unequal\n");
3075 static void testHashPublicKeyInfo(void)
3077 BOOL ret;
3078 CERT_PUBLIC_KEY_INFO info = { { 0 } };
3079 DWORD len;
3081 /* Crash
3082 ret = CryptHashPublicKeyInfo(0, 0, 0, 0, NULL, NULL, NULL);
3083 ret = CryptHashPublicKeyInfo(0, 0, 0, 0, &info, NULL, NULL);
3085 ret = CryptHashPublicKeyInfo(0, 0, 0, 0, NULL, NULL, &len);
3086 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
3087 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
3088 /* Crashes on some win9x boxes */
3089 if (0)
3091 ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, NULL, NULL, &len);
3092 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3093 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3095 ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, &info, NULL, &len);
3096 ok(ret ||
3097 broken(!ret), /* win9x */
3098 "CryptHashPublicKeyInfo failed: %08x\n", GetLastError());
3099 if (ret)
3101 ok(len == 16, "Expected hash size 16, got %d\n", len);
3102 if (len == 16)
3104 static const BYTE emptyHash[] = { 0xb8,0x51,0x3a,0x31,0x0e,0x9f,0x40,
3105 0x36,0x9c,0x92,0x45,0x1b,0x9d,0xc8,0xf9,0xf6 };
3106 BYTE buf[16];
3108 ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, &info, buf,
3109 &len);
3110 ok(ret, "CryptHashPublicKeyInfo failed: %08x\n", GetLastError());
3111 ok(!memcmp(buf, emptyHash, len), "Unexpected hash\n");
3116 static const BYTE md5SignedEmptyCertHash[] = { 0xfb,0x0f,0x66,0x82,0x66,0xd9,
3117 0xe5,0xf8,0xd8,0xa2,0x55,0x2b,0xe1,0xa5,0xd9,0x04 };
3119 static void testHashToBeSigned(void)
3121 BOOL ret;
3122 DWORD size;
3123 BYTE hash[16];
3125 /* Crash */
3126 if (0)
3128 CryptHashToBeSigned(0, 0, NULL, 0, NULL, NULL);
3130 SetLastError(0xdeadbeef);
3131 ret = CryptHashToBeSigned(0, 0, NULL, 0, NULL, &size);
3132 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
3133 "expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
3134 SetLastError(0xdeadbeef);
3135 ret = CryptHashToBeSigned(0, X509_ASN_ENCODING, NULL, 0, NULL, &size);
3136 ok(!ret &&
3137 (GetLastError() == CRYPT_E_ASN1_EOD ||
3138 GetLastError() == OSS_BAD_ARG), /* win9x */
3139 "expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
3140 /* Can't sign anything: has to be asn.1 encoded, at least */
3141 SetLastError(0xdeadbeef);
3142 ret = CryptHashToBeSigned(0, X509_ASN_ENCODING, int1, sizeof(int1),
3143 NULL, &size);
3144 ok(!ret &&
3145 (GetLastError() == CRYPT_E_ASN1_BADTAG ||
3146 GetLastError() == OSS_MORE_INPUT), /* win9x */
3147 "expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
3148 /* Can't be empty, either */
3149 SetLastError(0xdeadbeef);
3150 ret = CryptHashToBeSigned(0, X509_ASN_ENCODING, emptyCert,
3151 sizeof(emptyCert), NULL, &size);
3152 ok(!ret &&
3153 (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
3154 GetLastError() == OSS_DATA_ERROR), /* win9x */
3155 "expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
3156 /* Signing a cert works */
3157 ret = CryptHashToBeSigned(0, X509_ASN_ENCODING, md5SignedEmptyCert,
3158 sizeof(md5SignedEmptyCert), NULL, &size);
3159 ok(ret ||
3160 broken(!ret), /* win9x */
3161 "CryptHashToBeSigned failed: %08x\n", GetLastError());
3162 if (ret)
3164 ok(size == sizeof(md5SignedEmptyCertHash), "unexpected size %d\n", size);
3167 ret = CryptHashToBeSigned(0, X509_ASN_ENCODING, md5SignedEmptyCert,
3168 sizeof(md5SignedEmptyCert), hash, &size);
3169 ok(ret || broken(!ret && GetLastError() == NTE_BAD_ALGID) /* NT4 */,
3170 "CryptHashToBeSigned failed: %08x\n", GetLastError());
3172 ok(!memcmp(hash, md5SignedEmptyCertHash, size), "unexpected value\n");
3175 static void testCompareCert(void)
3177 CERT_INFO info1 = { 0 }, info2 = { 0 };
3178 BOOL ret;
3180 /* Crashes */
3181 if (0)
3182 CertCompareCertificate(X509_ASN_ENCODING, NULL, NULL);
3184 /* Certs with the same issuer and serial number are equal, even if they
3185 * differ in other respects (like subject).
3187 info1.SerialNumber.pbData = serialNum;
3188 info1.SerialNumber.cbData = sizeof(serialNum);
3189 info1.Issuer.pbData = subjectName;
3190 info1.Issuer.cbData = sizeof(subjectName);
3191 info1.Subject.pbData = subjectName2;
3192 info1.Subject.cbData = sizeof(subjectName2);
3193 info2.SerialNumber.pbData = serialNum;
3194 info2.SerialNumber.cbData = sizeof(serialNum);
3195 info2.Issuer.pbData = subjectName;
3196 info2.Issuer.cbData = sizeof(subjectName);
3197 info2.Subject.pbData = subjectName;
3198 info2.Subject.cbData = sizeof(subjectName);
3199 ret = CertCompareCertificate(X509_ASN_ENCODING, &info1, &info2);
3200 ok(ret, "Expected certs to be equal\n");
3202 info2.Issuer.pbData = subjectName2;
3203 info2.Issuer.cbData = sizeof(subjectName2);
3204 ret = CertCompareCertificate(X509_ASN_ENCODING, &info1, &info2);
3205 ok(!ret, "Expected certs not to be equal\n");
3208 static void testVerifySubjectCert(void)
3210 BOOL ret;
3211 DWORD flags;
3212 PCCERT_CONTEXT context1, context2;
3214 /* Crashes
3215 ret = CertVerifySubjectCertificateContext(NULL, NULL, NULL);
3217 flags = 0;
3218 ret = CertVerifySubjectCertificateContext(NULL, NULL, &flags);
3219 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
3220 GetLastError());
3221 flags = CERT_STORE_NO_CRL_FLAG;
3222 ret = CertVerifySubjectCertificateContext(NULL, NULL, &flags);
3223 ok(!ret && GetLastError() == E_INVALIDARG,
3224 "Expected E_INVALIDARG, got %08x\n", GetLastError());
3226 flags = 0;
3227 context1 = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
3228 sizeof(bigCert));
3229 ret = CertVerifySubjectCertificateContext(NULL, context1, &flags);
3230 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
3231 GetLastError());
3232 ret = CertVerifySubjectCertificateContext(context1, NULL, &flags);
3233 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
3234 GetLastError());
3235 ret = CertVerifySubjectCertificateContext(context1, context1, &flags);
3236 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
3237 GetLastError());
3239 context2 = CertCreateCertificateContext(X509_ASN_ENCODING,
3240 bigCertWithDifferentSubject, sizeof(bigCertWithDifferentSubject));
3241 SetLastError(0xdeadbeef);
3242 ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
3243 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
3244 GetLastError());
3245 flags = CERT_STORE_REVOCATION_FLAG;
3246 ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
3247 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
3248 GetLastError());
3249 ok(flags == (CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG),
3250 "Expected CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG, got %08x\n",
3251 flags);
3252 flags = CERT_STORE_SIGNATURE_FLAG;
3253 ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
3254 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
3255 GetLastError());
3256 ok(flags == CERT_STORE_SIGNATURE_FLAG,
3257 "Expected CERT_STORE_SIGNATURE_FLAG, got %08x\n", flags);
3258 CertFreeCertificateContext(context2);
3260 CertFreeCertificateContext(context1);
3263 static const BYTE rootWithKeySignAndCRLSign[] = {
3264 0x30,0x82,0x01,0xdf,0x30,0x82,0x01,0x4c,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,
3265 0x5b,0xc7,0x0b,0x27,0x99,0xbb,0x2e,0x99,0x47,0x9d,0x45,0x4e,0x7c,0x1a,0xca,
3266 0xe8,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x30,0x10,0x31,
3267 0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x03,0x13,0x05,0x43,0x65,0x72,0x74,0x31,
3268 0x30,0x1e,0x17,0x0d,0x30,0x37,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
3269 0x30,0x5a,0x17,0x0d,0x30,0x37,0x31,0x32,0x33,0x31,0x32,0x33,0x35,0x39,0x35,
3270 0x39,0x5a,0x30,0x10,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x03,0x13,0x05,
3271 0x43,0x65,0x72,0x74,0x31,0x30,0x81,0x9f,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
3272 0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x81,0x8d,0x00,0x30,0x81,0x89,
3273 0x02,0x81,0x81,0x00,0xad,0x7e,0xca,0xf3,0xe5,0x99,0xc2,0x2a,0xca,0x50,0x82,
3274 0x7c,0x2d,0xa4,0x81,0xcd,0x0d,0x0d,0x86,0xd7,0xd8,0xb2,0xde,0xc5,0xc3,0x34,
3275 0x9e,0x07,0x78,0x08,0x11,0x12,0x2d,0x21,0x0a,0x09,0x07,0x14,0x03,0x7a,0xe7,
3276 0x3b,0x58,0xf1,0xde,0x3e,0x01,0x25,0x93,0xab,0x8f,0xce,0x1f,0xc1,0x33,0x91,
3277 0xfe,0x59,0xb9,0x3b,0x9e,0x95,0x12,0x89,0x8e,0xc3,0x4b,0x98,0x1b,0x99,0xc5,
3278 0x07,0xe2,0xdf,0x15,0x4c,0x39,0x76,0x06,0xad,0xdb,0x16,0x06,0x49,0xba,0xcd,
3279 0x0f,0x07,0xd6,0xea,0x27,0xa6,0xfe,0x3d,0x88,0xe5,0x97,0x45,0x72,0xb6,0x1c,
3280 0xc0,0x1c,0xb1,0xa2,0x89,0xe8,0x37,0x9e,0xf6,0x2a,0xcf,0xd5,0x1f,0x2f,0x35,
3281 0x5e,0x8f,0x3a,0x9c,0x61,0xb1,0xf1,0x6c,0xff,0x8c,0xb2,0x2f,0x02,0x03,0x01,
3282 0x00,0x01,0xa3,0x42,0x30,0x40,0x30,0x0e,0x06,0x03,0x55,0x1d,0x0f,0x01,0x01,
3283 0xff,0x04,0x04,0x03,0x02,0x00,0x06,0x30,0x0f,0x06,0x03,0x55,0x1d,0x13,0x01,
3284 0x01,0xff,0x04,0x05,0x30,0x03,0x01,0x01,0xff,0x30,0x1d,0x06,0x03,0x55,0x1d,
3285 0x0e,0x04,0x16,0x04,0x14,0x14,0x8c,0x16,0xbb,0xbe,0x70,0xa2,0x28,0x89,0xa0,
3286 0x58,0xff,0x98,0xbd,0xa8,0x24,0x2b,0x8a,0xe9,0x9a,0x30,0x09,0x06,0x05,0x2b,
3287 0x0e,0x03,0x02,0x1d,0x05,0x00,0x03,0x81,0x81,0x00,0x74,0xcb,0x21,0xfd,0x2d,
3288 0x25,0xdc,0xa5,0xaa,0xa1,0x26,0xdc,0x8b,0x40,0x11,0x64,0xae,0x5c,0x71,0x3c,
3289 0x28,0xbc,0xf9,0xb3,0xcb,0xa5,0x94,0xb2,0x8d,0x4c,0x23,0x2b,0x9b,0xde,0x2c,
3290 0x4c,0x30,0x04,0xc6,0x88,0x10,0x2f,0x53,0xfd,0x6c,0x82,0xf1,0x13,0xfb,0xda,
3291 0x27,0x75,0x25,0x48,0xe4,0x72,0x09,0x2a,0xee,0xb4,0x1e,0xc9,0x55,0xf5,0xf7,
3292 0x82,0x91,0xd8,0x4b,0xe4,0x3a,0xfe,0x97,0x87,0xdf,0xfb,0x15,0x5a,0x12,0x3e,
3293 0x12,0xe6,0xad,0x40,0x0b,0xcf,0xee,0x1a,0x44,0xe0,0x83,0xb2,0x67,0x94,0xd4,
3294 0x2e,0x7c,0xf2,0x06,0x9d,0xb3,0x3b,0x7e,0x2f,0xda,0x25,0x66,0x7e,0xa7,0x1f,
3295 0x45,0xd4,0xf5,0xe3,0xdf,0x2a,0xf1,0x18,0x28,0x20,0xb5,0xf8,0xf5,0x8d,0x7a,
3296 0x2e,0x84,0xee };
3297 static const BYTE eeCert[] = {
3298 0x30,0x82,0x01,0xb9,0x30,0x82,0x01,0x22,0xa0,0x03,0x02,0x01,0x02,0x02,0x01,
3299 0x01,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,
3300 0x00,0x30,0x10,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x03,0x13,0x05,0x43,
3301 0x65,0x72,0x74,0x31,0x30,0x1e,0x17,0x0d,0x30,0x37,0x30,0x35,0x30,0x31,0x30,
3302 0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,0x30,0x37,0x31,0x30,0x30,0x31,0x30,
3303 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x10,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,
3304 0x04,0x03,0x13,0x05,0x43,0x65,0x72,0x74,0x32,0x30,0x81,0x9f,0x30,0x0d,0x06,
3305 0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x81,0x8d,
3306 0x00,0x30,0x81,0x89,0x02,0x81,0x81,0x00,0xb8,0x52,0xda,0xc5,0x4b,0x3f,0xe5,
3307 0x33,0x0e,0x67,0x5f,0x48,0x21,0xdc,0x7e,0xef,0x37,0x33,0xba,0xff,0xb4,0xc6,
3308 0xdc,0xb6,0x17,0x8e,0x20,0x55,0x07,0x12,0xd2,0x7b,0x3c,0xce,0x30,0xc5,0xa7,
3309 0x48,0x9f,0x6e,0xfe,0xb8,0xbe,0xdb,0x9f,0x9b,0x17,0x60,0x16,0xde,0xc6,0x8b,
3310 0x47,0xd1,0x57,0x71,0x3c,0x93,0xfc,0xbd,0xec,0x44,0x32,0x3b,0xb9,0xcf,0x6b,
3311 0x05,0x72,0xa7,0x87,0x8e,0x7e,0xd4,0x9a,0x87,0x1c,0x2f,0xb7,0x82,0x40,0xfc,
3312 0x6a,0x80,0x83,0x68,0x28,0xce,0x84,0xf4,0x0b,0x2e,0x44,0xcb,0x53,0xac,0x85,
3313 0x85,0xb5,0x46,0x36,0x98,0x3c,0x10,0x02,0xaa,0x02,0xbc,0x8b,0xa2,0x23,0xb2,
3314 0xd3,0x51,0x9a,0x22,0x4a,0xe3,0xaa,0x4e,0x7c,0xda,0x38,0xcf,0x49,0x98,0x72,
3315 0xa3,0x02,0x03,0x01,0x00,0x01,0xa3,0x23,0x30,0x21,0x30,0x1f,0x06,0x03,0x55,
3316 0x1d,0x23,0x04,0x18,0x30,0x18,0x80,0x14,0x14,0x8c,0x16,0xbb,0xbe,0x70,0xa2,
3317 0x28,0x89,0xa0,0x58,0xff,0x98,0xbd,0xa8,0x24,0x2b,0x8a,0xe9,0x9a,0x30,0x0d,
3318 0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x03,0x81,
3319 0x81,0x00,0x8a,0x49,0xa9,0x86,0x5e,0xc9,0x33,0x7e,0xfd,0xab,0x64,0x1f,0x6d,
3320 0x00,0xd7,0x9b,0xec,0xd1,0x5b,0x38,0xcc,0xd6,0xf3,0xf2,0xb4,0x75,0x70,0x00,
3321 0x82,0x9d,0x37,0x58,0xe1,0xcd,0x2c,0x61,0xb3,0x28,0xe7,0x8a,0x00,0xbe,0x6e,
3322 0xca,0xe8,0x55,0xd5,0xad,0x3a,0xea,0xaf,0x13,0x20,0x1c,0x44,0xfc,0xb4,0xf9,
3323 0x29,0x2b,0xdc,0x8a,0x2d,0x1b,0x27,0x9e,0xb9,0x3b,0x4a,0x71,0x9d,0x47,0x7d,
3324 0xf7,0x92,0x6b,0x21,0x7f,0xfa,0x88,0x79,0x94,0x33,0xf6,0xdd,0x92,0x04,0x92,
3325 0xd6,0x5e,0x0a,0x74,0xf2,0x85,0xa6,0xd5,0x3c,0x28,0xc0,0x89,0x5d,0xda,0xf3,
3326 0xa6,0x01,0xc2,0xe9,0xa3,0xc1,0xb7,0x21,0x08,0xba,0x18,0x07,0x45,0xeb,0x77,
3327 0x7d,0xcd,0xc6,0xe7,0x2a,0x7b,0x46,0xd2,0x3d,0xb5 };
3328 static const BYTE rootSignedCRL[] = {
3329 0x30,0x82,0x01,0x1f,0x30,0x81,0x89,0x02,0x01,0x01,0x30,0x0d,0x06,0x09,0x2a,
3330 0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x30,0x10,0x31,0x0e,0x30,
3331 0x0c,0x06,0x03,0x55,0x04,0x03,0x13,0x05,0x43,0x65,0x72,0x74,0x31,0x17,0x0d,
3332 0x30,0x37,0x30,0x39,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,
3333 0x30,0x37,0x31,0x32,0x33,0x31,0x32,0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x14,
3334 0x30,0x12,0x02,0x01,0x01,0x17,0x0d,0x30,0x37,0x30,0x39,0x30,0x31,0x30,0x30,
3335 0x30,0x30,0x30,0x30,0x5a,0xa0,0x2f,0x30,0x2d,0x30,0x0a,0x06,0x03,0x55,0x1d,
3336 0x14,0x04,0x03,0x02,0x01,0x01,0x30,0x1f,0x06,0x03,0x55,0x1d,0x23,0x04,0x18,
3337 0x30,0x18,0x80,0x14,0x14,0x8c,0x16,0xbb,0xbe,0x70,0xa2,0x28,0x89,0xa0,0x58,
3338 0xff,0x98,0xbd,0xa8,0x24,0x2b,0x8a,0xe9,0x9a,0x30,0x0d,0x06,0x09,0x2a,0x86,
3339 0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x03,0x81,0x81,0x00,0xa3,0xcf,
3340 0x17,0x5d,0x7a,0x08,0xab,0x11,0x1a,0xbd,0x5c,0xde,0x9a,0x22,0x92,0x38,0xe6,
3341 0x96,0xcc,0xb1,0xc5,0x42,0x86,0xa6,0xae,0xad,0xa3,0x1a,0x2b,0xa0,0xb0,0x65,
3342 0xaa,0x9c,0xd7,0x2d,0x44,0x8c,0xae,0x61,0xc7,0x30,0x17,0x89,0x84,0x3b,0x4a,
3343 0x8f,0x17,0x08,0x06,0x37,0x1c,0xf7,0x2d,0x4e,0x47,0x07,0x61,0x50,0xd9,0x06,
3344 0xd1,0x46,0xed,0x0a,0xbb,0xc3,0x9b,0x36,0x0b,0xa7,0x27,0x2f,0x2b,0x55,0xce,
3345 0x2a,0xa5,0x60,0xc6,0x53,0x28,0xe8,0xee,0xad,0x0e,0x2b,0xe8,0xd7,0x5f,0xc9,
3346 0xa5,0xed,0xf9,0x77,0xb0,0x3c,0x81,0xcf,0xcc,0x49,0xb2,0x1a,0xc3,0xfd,0x34,
3347 0xd5,0xbc,0xb0,0xd5,0xa5,0x9c,0x1b,0x72,0xc3,0x0f,0xa3,0xe3,0x3c,0xf0,0xc3,
3348 0x91,0xe8,0x93,0x4f,0xd4,0x2f };
3350 static void testVerifyRevocation(void)
3352 BOOL ret;
3353 CERT_REVOCATION_STATUS status = { 0 };
3354 PCCERT_CONTEXT certs[2];
3355 CERT_REVOCATION_PARA revPara = { sizeof(revPara), 0 };
3357 /* Crash
3358 ret = CertVerifyRevocation(0, 0, 0, NULL, 0, NULL, NULL);
3360 SetLastError(0xdeadbeef);
3361 ret = CertVerifyRevocation(0, 0, 0, NULL, 0, NULL, &status);
3362 ok(!ret && GetLastError() == E_INVALIDARG,
3363 "Expected E_INVALIDARG, got %08x\n", GetLastError());
3364 status.cbSize = sizeof(status);
3365 ret = CertVerifyRevocation(0, 0, 0, NULL, 0, NULL, &status);
3366 ok(ret, "CertVerifyRevocation failed: %08x\n", GetLastError());
3367 ret = CertVerifyRevocation(0, 2, 0, NULL, 0, NULL, &status);
3368 ok(ret, "CertVerifyRevocation failed: %08x\n", GetLastError());
3369 ret = CertVerifyRevocation(2, 0, 0, NULL, 0, NULL, &status);
3370 ok(ret, "CertVerifyRevocation failed: %08x\n", GetLastError());
3371 certs[0] = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
3372 sizeof(bigCert));
3373 SetLastError(0xdeadbeef);
3374 ret = CertVerifyRevocation(0, 0, 1, (void **)certs, 0, NULL, &status);
3375 ok(!ret && GetLastError() == CRYPT_E_NO_REVOCATION_DLL,
3376 "Expected CRYPT_E_NO_REVOCATION_DLL, got %08x\n", GetLastError());
3377 SetLastError(0xdeadbeef);
3378 ret = CertVerifyRevocation(0, 2, 1, (void **)certs, 0, NULL, &status);
3379 ok(!ret && GetLastError() == CRYPT_E_NO_REVOCATION_DLL,
3380 "Expected CRYPT_E_NO_REVOCATION_DLL, got %08x\n", GetLastError());
3382 CertFreeCertificateContext(certs[0]);
3384 certs[0] = CertCreateCertificateContext(X509_ASN_ENCODING,
3385 rootWithKeySignAndCRLSign, sizeof(rootWithKeySignAndCRLSign));
3386 certs[1] = CertCreateCertificateContext(X509_ASN_ENCODING,
3387 eeCert, sizeof(eeCert));
3388 /* The root cert itself can't be checked for revocation */
3389 SetLastError(0xdeadbeef);
3390 ret = CertVerifyRevocation(X509_ASN_ENCODING, CERT_CONTEXT_REVOCATION_TYPE,
3391 1, (void **)certs, 0, NULL, &status);
3392 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3394 win_skip("CERT_CONTEXT_REVOCATION_TYPE unsupported, skipping\n");
3395 return;
3397 ok(!ret && GetLastError() == CRYPT_E_NO_REVOCATION_CHECK,
3398 "expected CRYPT_E_NO_REVOCATION_CHECK, got %08x\n", GetLastError());
3399 ok(status.dwError == CRYPT_E_NO_REVOCATION_CHECK,
3400 "expected CRYPT_E_NO_REVOCATION_CHECK, got %08x\n", status.dwError);
3401 ok(status.dwIndex == 0, "expected index 0, got %d\n", status.dwIndex);
3402 /* Neither can the end cert */
3403 SetLastError(0xdeadbeef);
3404 ret = CertVerifyRevocation(X509_ASN_ENCODING, CERT_CONTEXT_REVOCATION_TYPE,
3405 1, (void **)&certs[1], 0, NULL, &status);
3406 ok(!ret && (GetLastError() == CRYPT_E_NO_REVOCATION_CHECK /* Win9x */ ||
3407 GetLastError() == CRYPT_E_REVOCATION_OFFLINE),
3408 "expected CRYPT_E_NO_REVOCATION_CHECK or CRYPT_E_REVOCATION_OFFLINE, got %08x\n",
3409 GetLastError());
3410 ok(status.dwError == CRYPT_E_NO_REVOCATION_CHECK /* Win9x */ ||
3411 status.dwError == CRYPT_E_REVOCATION_OFFLINE,
3412 "expected CRYPT_E_NO_REVOCATION_CHECK or CRYPT_E_REVOCATION_OFFLINE, got %08x\n",
3413 status.dwError);
3414 ok(status.dwIndex == 0, "expected index 0, got %d\n", status.dwIndex);
3415 /* Both certs together can't, either (they're not CRLs) */
3416 SetLastError(0xdeadbeef);
3417 ret = CertVerifyRevocation(X509_ASN_ENCODING, CERT_CONTEXT_REVOCATION_TYPE,
3418 2, (void **)certs, 0, NULL, &status);
3419 ok(!ret && (GetLastError() == CRYPT_E_NO_REVOCATION_CHECK ||
3420 GetLastError() == CRYPT_E_REVOCATION_OFFLINE /* WinME */),
3421 "expected CRYPT_E_NO_REVOCATION_CHECK or CRYPT_E_REVOCATION_OFFLINE, got %08x\n",
3422 GetLastError());
3423 ok(status.dwError == CRYPT_E_NO_REVOCATION_CHECK ||
3424 status.dwError == CRYPT_E_REVOCATION_OFFLINE /* WinME */,
3425 "expected CRYPT_E_NO_REVOCATION_CHECK or CRYPT_E_REVOCATION_OFFLINE, got %08x\n",
3426 status.dwError);
3427 ok(status.dwIndex == 0, "expected index 0, got %d\n", status.dwIndex);
3428 ok(status.dwIndex == 0, "expected index 0, got %d\n", status.dwIndex);
3429 /* Now add a CRL to the hCrlStore */
3430 revPara.hCrlStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
3431 CERT_STORE_CREATE_NEW_FLAG, NULL);
3432 CertAddEncodedCRLToStore(revPara.hCrlStore, X509_ASN_ENCODING,
3433 rootSignedCRL, sizeof(rootSignedCRL), CERT_STORE_ADD_ALWAYS, NULL);
3434 SetLastError(0xdeadbeef);
3435 ret = CertVerifyRevocation(X509_ASN_ENCODING, CERT_CONTEXT_REVOCATION_TYPE,
3436 2, (void **)certs, 0, &revPara, &status);
3437 ok(!ret && (GetLastError() == CRYPT_E_NO_REVOCATION_CHECK ||
3438 GetLastError() == CRYPT_E_REVOCATION_OFFLINE /* WinME */),
3439 "expected CRYPT_E_NO_REVOCATION_CHECK or CRYPT_E_REVOCATION_OFFLINE, got %08x\n",
3440 GetLastError());
3441 ok(status.dwError == CRYPT_E_NO_REVOCATION_CHECK ||
3442 status.dwError == CRYPT_E_REVOCATION_OFFLINE /* WinME */,
3443 "expected CRYPT_E_NO_REVOCATION_CHECK or CRYPT_E_REVOCATION_OFFLINE, got %08x\n",
3444 status.dwError);
3445 ok(status.dwIndex == 0, "expected index 0, got %d\n", status.dwIndex);
3446 /* Specifying CERT_VERIFY_REV_CHAIN_FLAG doesn't change things either */
3447 SetLastError(0xdeadbeef);
3448 ret = CertVerifyRevocation(X509_ASN_ENCODING, CERT_CONTEXT_REVOCATION_TYPE,
3449 2, (void **)certs, CERT_VERIFY_REV_CHAIN_FLAG, &revPara, &status);
3450 ok(!ret && GetLastError() == CRYPT_E_NO_REVOCATION_CHECK,
3451 "expected CRYPT_E_NO_REVOCATION_CHECK, got %08x\n", GetLastError());
3452 ok(status.dwError == CRYPT_E_NO_REVOCATION_CHECK,
3453 "expected CRYPT_E_NO_REVOCATION_CHECK, got %08x\n", status.dwError);
3454 ok(status.dwIndex == 0, "expected index 0, got %d\n", status.dwIndex);
3455 /* Again, specifying the issuer cert: no change */
3456 revPara.pIssuerCert = certs[0];
3457 SetLastError(0xdeadbeef);
3458 ret = CertVerifyRevocation(X509_ASN_ENCODING, CERT_CONTEXT_REVOCATION_TYPE,
3459 1, (void **)&certs[1], 0, &revPara, &status);
3460 /* Win2k thinks the cert is revoked, and it is, except the CRL is out of
3461 * date, hence the revocation status should be unknown.
3463 ok(!ret && (GetLastError() == CRYPT_E_NO_REVOCATION_CHECK ||
3464 broken(GetLastError() == CRYPT_E_REVOKED /* Win2k */)),
3465 "expected CRYPT_E_NO_REVOCATION_CHECK, got %08x\n", GetLastError());
3466 ok(status.dwError == CRYPT_E_NO_REVOCATION_CHECK ||
3467 broken(status.dwError == CRYPT_E_REVOKED /* Win2k */),
3468 "expected CRYPT_E_NO_REVOCATION_CHECK, got %08x\n", status.dwError);
3469 ok(status.dwIndex == 0, "expected index 0, got %d\n", status.dwIndex);
3470 CertCloseStore(revPara.hCrlStore, 0);
3471 CertFreeCertificateContext(certs[1]);
3472 CertFreeCertificateContext(certs[0]);
3475 static BYTE privKey[] = {
3476 0x07, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x52, 0x53, 0x41, 0x32, 0x00,
3477 0x02, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x79, 0x10, 0x1c, 0xd0, 0x6b, 0x10,
3478 0x18, 0x30, 0x94, 0x61, 0xdc, 0x0e, 0xcb, 0x96, 0x4e, 0x21, 0x3f, 0x79, 0xcd,
3479 0xa9, 0x17, 0x62, 0xbc, 0xbb, 0x61, 0x4c, 0xe0, 0x75, 0x38, 0x6c, 0xf3, 0xde,
3480 0x60, 0x86, 0x03, 0x97, 0x65, 0xeb, 0x1e, 0x6b, 0xdb, 0x53, 0x85, 0xad, 0x68,
3481 0x21, 0xf1, 0x5d, 0xe7, 0x1f, 0xe6, 0x53, 0xb4, 0xbb, 0x59, 0x3e, 0x14, 0x27,
3482 0xb1, 0x83, 0xa7, 0x3a, 0x54, 0xe2, 0x8f, 0x65, 0x8e, 0x6a, 0x4a, 0xcf, 0x3b,
3483 0x1f, 0x65, 0xff, 0xfe, 0xf1, 0x31, 0x3a, 0x37, 0x7a, 0x8b, 0xcb, 0xc6, 0xd4,
3484 0x98, 0x50, 0x36, 0x67, 0xe4, 0xa1, 0xe8, 0x7e, 0x8a, 0xc5, 0x23, 0xf2, 0x77,
3485 0xf5, 0x37, 0x61, 0x49, 0x72, 0x59, 0xe8, 0x3d, 0xf7, 0x60, 0xb2, 0x77, 0xca,
3486 0x78, 0x54, 0x6d, 0x65, 0x9e, 0x03, 0x97, 0x1b, 0x61, 0xbd, 0x0c, 0xd8, 0x06,
3487 0x63, 0xe2, 0xc5, 0x48, 0xef, 0xb3, 0xe2, 0x6e, 0x98, 0x7d, 0xbd, 0x4e, 0x72,
3488 0x91, 0xdb, 0x31, 0x57, 0xe3, 0x65, 0x3a, 0x49, 0xca, 0xec, 0xd2, 0x02, 0x4e,
3489 0x22, 0x7e, 0x72, 0x8e, 0xf9, 0x79, 0x84, 0x82, 0xdf, 0x7b, 0x92, 0x2d, 0xaf,
3490 0xc9, 0xe4, 0x33, 0xef, 0x89, 0x5c, 0x66, 0x99, 0xd8, 0x80, 0x81, 0x47, 0x2b,
3491 0xb1, 0x66, 0x02, 0x84, 0x59, 0x7b, 0xc3, 0xbe, 0x98, 0x45, 0x4a, 0x3d, 0xdd,
3492 0xea, 0x2b, 0xdf, 0x4e, 0xb4, 0x24, 0x6b, 0xec, 0xe7, 0xd9, 0x0c, 0x45, 0xb8,
3493 0xbe, 0xca, 0x69, 0x37, 0x92, 0x4c, 0x38, 0x6b, 0x96, 0x6d, 0xcd, 0x86, 0x67,
3494 0x5c, 0xea, 0x54, 0x94, 0xa4, 0xca, 0xa4, 0x02, 0xa5, 0x21, 0x4d, 0xae, 0x40,
3495 0x8f, 0x9d, 0x51, 0x83, 0xf2, 0x3f, 0x33, 0xc1, 0x72, 0xb4, 0x1d, 0x94, 0x6e,
3496 0x7d, 0xe4, 0x27, 0x3f, 0xea, 0xff, 0xe5, 0x9b, 0xa7, 0x5e, 0x55, 0x8e, 0x0d,
3497 0x69, 0x1c, 0x7a, 0xff, 0x81, 0x9d, 0x53, 0x52, 0x97, 0x9a, 0x76, 0x79, 0xda,
3498 0x93, 0x32, 0x16, 0xec, 0x69, 0x51, 0x1a, 0x4e, 0xc3, 0xf1, 0x72, 0x80, 0x78,
3499 0x5e, 0x66, 0x4a, 0x8d, 0x85, 0x2f, 0x3f, 0xb2, 0xa7 };
3501 static const BYTE exportedPublicKeyBlob[] = {
3502 0x06,0x02,0x00,0x00,0x00,0xa4,0x00,0x00,0x52,0x53,0x41,0x31,0x00,0x02,0x00,0x00,
3503 0x01,0x00,0x01,0x00,0x79,0x10,0x1c,0xd0,0x6b,0x10,0x18,0x30,0x94,0x61,0xdc,0x0e,
3504 0xcb,0x96,0x4e,0x21,0x3f,0x79,0xcd,0xa9,0x17,0x62,0xbc,0xbb,0x61,0x4c,0xe0,0x75,
3505 0x38,0x6c,0xf3,0xde,0x60,0x86,0x03,0x97,0x65,0xeb,0x1e,0x6b,0xdb,0x53,0x85,0xad,
3506 0x68,0x21,0xf1,0x5d,0xe7,0x1f,0xe6,0x53,0xb4,0xbb,0x59,0x3e,0x14,0x27,0xb1,0x83,
3507 0xa7,0x3a,0x54,0xe2 };
3509 static const BYTE asnEncodedPublicKey[] = {
3510 0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7,0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,
3511 0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21,0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,
3512 0x65,0x97,0x03,0x86,0x60,0xde,0xf3,0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,
3513 0x17,0xa9,0xcd,0x79,0x3f,0x21,0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,
3514 0x6b,0xd0,0x1c,0x10,0x79,0x02,0x03,0x01,0x00,0x01 };
3516 static void testAcquireCertPrivateKey(void)
3518 BOOL ret;
3519 PCCERT_CONTEXT cert;
3520 HCRYPTPROV csp;
3521 DWORD size, keySpec;
3522 BOOL callerFree;
3523 CRYPT_KEY_PROV_INFO keyProvInfo;
3524 HCRYPTKEY key;
3525 WCHAR ms_def_prov_w[MAX_PATH];
3527 if (!pCryptAcquireCertificatePrivateKey)
3529 win_skip("CryptAcquireCertificatePrivateKey() is not available\n");
3530 return;
3533 lstrcpyW(ms_def_prov_w, MS_DEF_PROV_W);
3535 keyProvInfo.pwszContainerName = cspNameW;
3536 keyProvInfo.pwszProvName = ms_def_prov_w;
3537 keyProvInfo.dwProvType = PROV_RSA_FULL;
3538 keyProvInfo.dwFlags = 0;
3539 keyProvInfo.cProvParam = 0;
3540 keyProvInfo.rgProvParam = NULL;
3541 keyProvInfo.dwKeySpec = AT_SIGNATURE;
3543 pCryptAcquireContextA(NULL, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
3544 CRYPT_DELETEKEYSET);
3546 cert = CertCreateCertificateContext(X509_ASN_ENCODING, selfSignedCert,
3547 sizeof(selfSignedCert));
3549 /* Crash
3550 ret = pCryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, NULL, NULL);
3551 ret = pCryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, NULL,
3552 &callerFree);
3553 ret = pCryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, &keySpec,
3554 NULL);
3555 ret = pCryptAcquireCertificatePrivateKey(NULL, 0, NULL, &csp, NULL, NULL);
3556 ret = pCryptAcquireCertificatePrivateKey(NULL, 0, NULL, &csp, &keySpec,
3557 &callerFree);
3558 ret = pCryptAcquireCertificatePrivateKey(cert, 0, NULL, NULL, NULL, NULL);
3561 /* Missing private key */
3562 ret = pCryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, NULL, NULL);
3563 ok(!ret && GetLastError() == CRYPT_E_NO_KEY_PROPERTY,
3564 "Expected CRYPT_E_NO_KEY_PROPERTY, got %08x\n", GetLastError());
3565 ret = pCryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, &keySpec,
3566 &callerFree);
3567 ok(!ret && GetLastError() == CRYPT_E_NO_KEY_PROPERTY,
3568 "Expected CRYPT_E_NO_KEY_PROPERTY, got %08x\n", GetLastError());
3569 CertSetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, 0,
3570 &keyProvInfo);
3571 ret = pCryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, &keySpec,
3572 &callerFree);
3573 ok(!ret && GetLastError() == CRYPT_E_NO_KEY_PROPERTY,
3574 "Expected CRYPT_E_NO_KEY_PROPERTY, got %08x\n", GetLastError());
3576 pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
3577 CRYPT_NEWKEYSET);
3578 ret = CryptImportKey(csp, privKey, sizeof(privKey), 0, 0, &key);
3579 ok(ret, "CryptImportKey failed: %08x\n", GetLastError());
3580 if (ret)
3582 HCRYPTPROV certCSP;
3583 DWORD size;
3584 CERT_KEY_CONTEXT keyContext;
3586 /* Don't cache provider */
3587 ret = pCryptAcquireCertificatePrivateKey(cert, 0, NULL, &certCSP,
3588 &keySpec, &callerFree);
3589 ok(ret ||
3590 broken(!ret), /* win95 */
3591 "CryptAcquireCertificatePrivateKey failed: %08x\n",
3592 GetLastError());
3593 if (ret)
3595 ok(callerFree, "Expected callerFree to be TRUE\n");
3596 CryptReleaseContext(certCSP, 0);
3599 ret = pCryptAcquireCertificatePrivateKey(cert, 0, NULL, &certCSP,
3600 NULL, NULL);
3601 ok(ret ||
3602 broken(!ret), /* win95 */
3603 "CryptAcquireCertificatePrivateKey failed: %08x\n",
3604 GetLastError());
3605 CryptReleaseContext(certCSP, 0);
3607 /* Use the key prov info's caching (there shouldn't be any) */
3608 ret = pCryptAcquireCertificatePrivateKey(cert,
3609 CRYPT_ACQUIRE_USE_PROV_INFO_FLAG, NULL, &certCSP, &keySpec,
3610 &callerFree);
3611 ok(ret ||
3612 broken(!ret), /* win95 */
3613 "CryptAcquireCertificatePrivateKey failed: %08x\n",
3614 GetLastError());
3615 if (ret)
3617 ok(callerFree, "Expected callerFree to be TRUE\n");
3618 CryptReleaseContext(certCSP, 0);
3621 /* Cache it (and check that it's cached) */
3622 ret = pCryptAcquireCertificatePrivateKey(cert,
3623 CRYPT_ACQUIRE_CACHE_FLAG, NULL, &certCSP, &keySpec, &callerFree);
3624 ok(ret ||
3625 broken(!ret), /* win95 */
3626 "CryptAcquireCertificatePrivateKey failed: %08x\n",
3627 GetLastError());
3628 ok(!callerFree, "Expected callerFree to be FALSE\n");
3629 size = sizeof(keyContext);
3630 ret = CertGetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID,
3631 &keyContext, &size);
3632 ok(ret ||
3633 broken(!ret), /* win95 */
3634 "CertGetCertificateContextProperty failed: %08x\n",
3635 GetLastError());
3637 /* Remove the cached provider */
3638 CryptReleaseContext(keyContext.hCryptProv, 0);
3639 CertSetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID, 0,
3640 NULL);
3641 /* Allow caching via the key prov info */
3642 keyProvInfo.dwFlags = CERT_SET_KEY_CONTEXT_PROP_ID;
3643 CertSetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, 0,
3644 &keyProvInfo);
3645 /* Now use the key prov info's caching */
3646 ret = pCryptAcquireCertificatePrivateKey(cert,
3647 CRYPT_ACQUIRE_USE_PROV_INFO_FLAG, NULL, &certCSP, &keySpec,
3648 &callerFree);
3649 ok(ret ||
3650 broken(!ret), /* win95 */
3651 "CryptAcquireCertificatePrivateKey failed: %08x\n",
3652 GetLastError());
3653 ok(!callerFree, "Expected callerFree to be FALSE\n");
3654 size = sizeof(keyContext);
3655 ret = CertGetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID,
3656 &keyContext, &size);
3657 ok(ret ||
3658 broken(!ret), /* win95 */
3659 "CertGetCertificateContextProperty failed: %08x\n",
3660 GetLastError());
3661 CryptReleaseContext(certCSP, 0);
3663 CryptDestroyKey(key);
3666 /* Some sanity-checking on public key exporting */
3667 ret = CryptImportPublicKeyInfo(csp, X509_ASN_ENCODING,
3668 &cert->pCertInfo->SubjectPublicKeyInfo, &key);
3669 ok(ret, "CryptImportPublicKeyInfo failed: %08x\n", GetLastError());
3670 if (ret)
3672 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &size);
3673 ok(ret, "CryptExportKey failed: %08x\n", GetLastError());
3674 if (ret)
3676 LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, size), encodedKey;
3678 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, buf, &size);
3679 ok(ret, "CryptExportKey failed: %08x\n", GetLastError());
3680 ok(size == sizeof(exportedPublicKeyBlob), "Unexpected size %d\n",
3681 size);
3682 ok(!memcmp(buf, exportedPublicKeyBlob, size), "Unexpected value\n");
3683 ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, RSA_CSP_PUBLICKEYBLOB,
3684 buf, CRYPT_ENCODE_ALLOC_FLAG, NULL, &encodedKey, &size);
3685 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3686 if (ret)
3688 ok(size == sizeof(asnEncodedPublicKey), "Unexpected size %d\n",
3689 size);
3690 ok(!memcmp(encodedKey, asnEncodedPublicKey, size),
3691 "Unexpected value\n");
3692 LocalFree(encodedKey);
3694 HeapFree(GetProcessHeap(), 0, buf);
3696 CryptDestroyKey(key);
3698 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
3699 NULL, 0, NULL, NULL, &size);
3700 ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
3701 if (ret)
3703 PCERT_PUBLIC_KEY_INFO info = HeapAlloc(GetProcessHeap(), 0, size);
3705 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
3706 NULL, 0, NULL, info, &size);
3707 ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
3708 if (ret)
3710 ok(info->PublicKey.cbData == sizeof(asnEncodedPublicKey),
3711 "Unexpected size %d\n", info->PublicKey.cbData);
3712 ok(!memcmp(info->PublicKey.pbData, asnEncodedPublicKey,
3713 info->PublicKey.cbData), "Unexpected value\n");
3715 HeapFree(GetProcessHeap(), 0, info);
3718 CryptReleaseContext(csp, 0);
3719 pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
3720 CRYPT_DELETEKEYSET);
3722 CertFreeCertificateContext(cert);
3725 static void testGetPublicKeyLength(void)
3727 static char oid_rsa_rsa[] = szOID_RSA_RSA;
3728 static char oid_rsa_dh[] = szOID_RSA_DH;
3729 static char bogusOID[] = "1.2.3";
3730 DWORD ret;
3731 CERT_PUBLIC_KEY_INFO info = { { 0 } };
3732 BYTE bogusKey[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
3733 BYTE key[] = { 0x30,0x0f,0x02,0x08,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
3734 0x02,0x03,0x01,0x00,0x01 };
3736 /* Crashes
3737 ret = CertGetPublicKeyLength(0, NULL);
3739 /* With an empty public key info */
3740 SetLastError(0xdeadbeef);
3741 ret = CertGetPublicKeyLength(0, &info);
3742 ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
3743 "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
3744 ret, GetLastError());
3745 SetLastError(0xdeadbeef);
3746 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
3747 ok(ret == 0 &&
3748 (GetLastError() == CRYPT_E_ASN1_EOD ||
3749 GetLastError() == OSS_BAD_ARG), /* win9x */
3750 "Expected length 0 and CRYPT_E_ASN1_EOD, got length %d, %08x\n",
3751 ret, GetLastError());
3752 /* With a nearly-empty public key info */
3753 info.Algorithm.pszObjId = oid_rsa_rsa;
3754 SetLastError(0xdeadbeef);
3755 ret = CertGetPublicKeyLength(0, &info);
3756 ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
3757 "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
3758 ret, GetLastError());
3759 SetLastError(0xdeadbeef);
3760 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
3761 ok(ret == 0 &&
3762 (GetLastError() == CRYPT_E_ASN1_EOD ||
3763 GetLastError() == OSS_BAD_ARG), /* win9x */
3764 "Expected length 0 and CRYPT_E_ASN1_EOD, got length %d, %08x\n",
3765 ret, GetLastError());
3766 /* With a bogus key */
3767 info.PublicKey.cbData = sizeof(bogusKey);
3768 info.PublicKey.pbData = bogusKey;
3769 SetLastError(0xdeadbeef);
3770 ret = CertGetPublicKeyLength(0, &info);
3771 ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
3772 "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
3773 ret, GetLastError());
3774 SetLastError(0xdeadbeef);
3775 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
3776 ok(ret == 0 &&
3777 (GetLastError() == CRYPT_E_ASN1_BADTAG ||
3778 GetLastError() == OSS_PDU_MISMATCH), /* win9x */
3779 "Expected length 0 and CRYPT_E_ASN1_BADTAGTAG, got length %d, %08x\n",
3780 ret, GetLastError());
3781 /* With a believable RSA key but a bogus OID */
3782 info.Algorithm.pszObjId = bogusOID;
3783 info.PublicKey.cbData = sizeof(key);
3784 info.PublicKey.pbData = key;
3785 SetLastError(0xdeadbeef);
3786 ret = CertGetPublicKeyLength(0, &info);
3787 ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
3788 "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
3789 ret, GetLastError());
3790 SetLastError(0xdeadbeef);
3791 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
3792 ok(ret == 56 || broken(ret == 0 && GetLastError() == NTE_BAD_LEN) /* Win7 */,
3793 "Expected length 56, got %d\n", ret);
3794 /* An RSA key with the DH OID */
3795 info.Algorithm.pszObjId = oid_rsa_dh;
3796 SetLastError(0xdeadbeef);
3797 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
3798 ok(ret == 0 &&
3799 (GetLastError() == CRYPT_E_ASN1_BADTAG ||
3800 GetLastError() == E_INVALIDARG), /* win9x */
3801 "Expected length 0 and CRYPT_E_ASN1_BADTAG, got length %d, %08x\n",
3802 ret, GetLastError());
3803 /* With the RSA OID */
3804 info.Algorithm.pszObjId = oid_rsa_rsa;
3805 SetLastError(0xdeadbeef);
3806 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
3807 ok(ret == 56 || broken(ret == 0 && GetLastError() == NTE_BAD_LEN) /* Win7 */,
3808 "Expected length 56, got %d\n", ret);
3809 /* With the RSA OID and a message encoding */
3810 info.Algorithm.pszObjId = oid_rsa_rsa;
3811 SetLastError(0xdeadbeef);
3812 ret = CertGetPublicKeyLength(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, &info);
3813 ok(ret == 56 || broken(ret == 0 && GetLastError() == NTE_BAD_LEN) /* Win7 */,
3814 "Expected length 56, got %d\n", ret);
3817 START_TEST(cert)
3819 init_function_pointers();
3821 testAddCert();
3822 testCertProperties();
3823 testCreateCert();
3824 testDupCert();
3825 testFindCert();
3826 testGetSubjectCert();
3827 testGetIssuerCert();
3829 testCryptHashCert();
3830 testCertSigs();
3831 testSignAndEncodeCert();
3832 testCreateSelfSignCert();
3833 testIntendedKeyUsage();
3834 testKeyUsage();
3835 testGetValidUsages();
3836 testCompareCertName();
3837 testCompareIntegerBlob();
3838 testComparePublicKeyInfo();
3839 testHashPublicKeyInfo();
3840 testHashToBeSigned();
3841 testCompareCert();
3842 testVerifySubjectCert();
3843 testVerifyRevocation();
3844 testAcquireCertPrivateKey();
3845 testGetPublicKeyLength();
3846 testIsRDNAttrsInCertificateName();