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