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