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
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); \
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)
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,
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,
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,
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,
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,
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)
148 HCERTSTORE collection;
149 PCCERT_CONTEXT context;
150 PCCERT_CONTEXT copyContext;
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());
159 /* Weird--bad add disposition leads to an access violation in Windows.
160 * Both tests crash on some win9x boxes.
164 ret = CertAddEncodedCertificateToStore(0, X509_ASN_ENCODING, bigCert,
165 sizeof(bigCert), 0, NULL);
166 ok(!ret && (GetLastError() == STATUS_ACCESS_VIOLATION ||
167 GetLastError() == E_INVALIDARG),
168 "Expected STATUS_ACCESS_VIOLATION or E_INVALIDARG, got %08x\n",
170 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
171 bigCert, sizeof(bigCert), 0, NULL);
172 ok(!ret && (GetLastError() == STATUS_ACCESS_VIOLATION ||
173 GetLastError() == E_INVALIDARG),
174 "Expected STATUS_ACCESS_VIOLATION or E_INVALIDARG, got %08x\n",
178 /* Weird--can add a cert to the NULL store (does this have special
182 ret = CertAddEncodedCertificateToStore(0, X509_ASN_ENCODING, bigCert,
183 sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
184 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
187 CertFreeCertificateContext(context);
189 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
190 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
191 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
193 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
194 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, NULL);
195 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
197 /* This has the same name as bigCert, so finding isn't done by name */
198 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
199 certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, &context);
200 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
202 ok(context != NULL, "Expected a context\n");
205 CRYPT_DATA_BLOB hash = { sizeof(bigCert2Hash), bigCert2Hash };
207 /* Duplicate (AddRef) the context so we can still use it after
208 * deleting it from the store.
210 CertDuplicateCertificateContext(context);
211 CertDeleteCertificateFromStore(context);
212 /* Set the same hash as bigCert2, and try to readd it */
213 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID,
215 ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
217 ret = CertAddCertificateContextToStore(store, context,
218 CERT_STORE_ADD_NEW, NULL);
219 /* The failure is a bit odd (CRYPT_E_ASN1_BADTAG), so just check
222 ok(!ret, "Expected failure\n");
223 CertFreeCertificateContext(context);
225 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert2,
227 ok(context != NULL, "Expected a context\n");
230 /* Try to readd bigCert2 to the store */
231 ret = CertAddCertificateContextToStore(store, context,
232 CERT_STORE_ADD_NEW, NULL);
233 ok(!ret && GetLastError() == CRYPT_E_EXISTS,
234 "Expected CRYPT_E_EXISTS, got %08x\n", GetLastError());
235 CertFreeCertificateContext(context);
238 /* Adding a cert with the same issuer name and serial number (but
239 * different subject) as an existing cert succeeds.
242 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
243 bigCert2WithDifferentSerial, sizeof(bigCert2WithDifferentSerial),
244 CERT_STORE_ADD_NEW, &context);
245 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
248 CertDeleteCertificateFromStore(context);
250 /* Adding a cert with the same subject name and serial number (but
251 * different issuer) as an existing cert succeeds.
254 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
255 bigCertWithDifferentSubject, sizeof(bigCertWithDifferentSubject),
256 CERT_STORE_ADD_NEW, &context);
257 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
260 CertDeleteCertificateFromStore(context);
262 /* Adding a cert with the same issuer name and serial number (but
263 * different otherwise) as an existing cert succeeds.
266 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
267 bigCertWithDifferentIssuer, sizeof(bigCertWithDifferentIssuer),
268 CERT_STORE_ADD_NEW, &context);
269 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
272 CertDeleteCertificateFromStore(context);
274 collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
275 CERT_STORE_CREATE_NEW_FLAG, NULL);
276 ok(collection != NULL, "CertOpenStore failed: %08x\n", GetLastError());
277 if (collection && pCertAddStoreToCollection)
279 /* Add store to the collection, but disable updates */
280 pCertAddStoreToCollection(collection, store, 0, 0);
282 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert2,
284 ok(context != NULL, "Expected a context\n");
287 /* Try to readd bigCert2 to the collection */
288 ret = CertAddCertificateContextToStore(collection, context,
289 CERT_STORE_ADD_NEW, NULL);
290 ok(!ret && GetLastError() == CRYPT_E_EXISTS,
291 "Expected CRYPT_E_EXISTS, got %08x\n", GetLastError());
292 /* Replacing an existing certificate context is allowed, even
293 * though updates to the collection aren't..
295 ret = CertAddCertificateContextToStore(collection, context,
296 CERT_STORE_ADD_REPLACE_EXISTING, NULL);
297 ok(ret, "CertAddCertificateContextToStore failed: %08x\n",
299 /* use the existing certificate and ask for a copy of the context*/
301 ret = CertAddCertificateContextToStore(collection, context,
302 CERT_STORE_ADD_USE_EXISTING, ©Context);
303 ok(ret, "CertAddCertificateContextToStore failed: %08x\n",
305 ok(copyContext != NULL, "Expected on output a non NULL copyContext\n");
307 CertFreeCertificateContext(copyContext);
308 /* but adding a new certificate isn't allowed. */
309 ret = CertAddCertificateContextToStore(collection, context,
310 CERT_STORE_ADD_ALWAYS, NULL);
311 ok(!ret && GetLastError() == E_ACCESSDENIED,
312 "Expected E_ACCESSDENIED, got %08x\n", GetLastError());
313 CertFreeCertificateContext(context);
316 CertCloseStore(collection, 0);
319 CertCloseStore(store, 0);
322 static void checkHash(const BYTE *data, DWORD dataLen, ALG_ID algID,
323 PCCERT_CONTEXT context, DWORD propID)
325 BYTE hash[20] = { 0 }, hashProperty[20];
328 DWORD dwSizeWithNull;
330 memset(hash, 0, sizeof(hash));
331 memset(hashProperty, 0, sizeof(hashProperty));
333 ret = CryptHashCertificate(0, algID, 0, data, dataLen, hash, &size);
334 ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
335 ret = CertGetCertificateContextProperty(context, propID, NULL,
337 ok(ret, "algID %08x, propID %d: CertGetCertificateContextProperty failed: %08x\n",
338 algID, propID, GetLastError());
339 ret = CertGetCertificateContextProperty(context, propID, hashProperty,
341 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
343 ok(!memcmp(hash, hashProperty, size), "Unexpected hash for property %d\n",
345 ok(size == dwSizeWithNull, "Unexpected length of hash for property: received %d instead of %d\n",
346 dwSizeWithNull,size);
349 static WCHAR cspNameW[] = { 'W','i','n','e','C','r','y','p','t','T','e','m','p',0 };
350 static const BYTE v1CertWithPubKey[] = {
351 0x30,0x81,0x95,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
352 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
353 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
354 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
355 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
356 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
357 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
358 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
359 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,
360 0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,
362 static const BYTE v1CertWithSubjectKeyId[] = {
363 0x30,0x7b,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
364 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
365 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
366 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
367 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
368 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
369 0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x17,0x30,0x15,0x30,
370 0x13,0x06,0x03,0x55,0x1d,0x0e,0x04,0x0c,0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,
371 0x4c,0x61,0x6e,0x67,0x00 };
372 static const BYTE subjectKeyId[] = {
373 0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
375 static void testCertProperties(void)
377 PCCERT_CONTEXT context = CertCreateCertificateContext(X509_ASN_ENCODING,
378 bigCert, sizeof(bigCert));
379 DWORD propID, numProps, access, size;
381 BYTE hash[20] = { 0 }, hashProperty[20];
382 CRYPT_DATA_BLOB blob;
383 CERT_KEY_CONTEXT keyContext;
385 ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
391 propID = CertEnumCertificateContextProperties(NULL, 0);
397 propID = CertEnumCertificateContextProperties(context, propID);
400 } while (propID != 0);
401 ok(numProps == 0, "Expected 0 properties, got %d\n", numProps);
403 /* Tests with a NULL cert context. Prop ID 0 fails.. */
404 ret = CertSetCertificateContextProperty(NULL, 0, 0, NULL);
405 ok(!ret && GetLastError() == E_INVALIDARG,
406 "Expected E_INVALIDARG, got %08x\n", GetLastError());
407 /* while this just crashes.
408 ret = CertSetCertificateContextProperty(NULL,
409 CERT_KEY_PROV_HANDLE_PROP_ID, 0, NULL);
412 ret = CertSetCertificateContextProperty(context, 0, 0, NULL);
413 ok(!ret && GetLastError() == E_INVALIDARG,
414 "Expected E_INVALIDARG, got %08x\n", GetLastError());
415 /* Can't set the cert property directly, this crashes.
416 ret = CertSetCertificateContextProperty(context,
417 CERT_CERT_PROP_ID, 0, bigCert2);
421 ret = CertGetCertificateContextProperty(context,
422 CERT_ACCESS_STATE_PROP_ID, 0, NULL);
423 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
425 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
430 ret = CertGetCertificateContextProperty(context,
431 CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
432 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
433 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
434 /* And, an implicit property */
435 size = sizeof(access);
436 ret = CertGetCertificateContextProperty(context,
437 CERT_ACCESS_STATE_PROP_ID, &access, &size);
438 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
440 ok(!(access & CERT_ACCESS_STATE_WRITE_PERSIST_FLAG),
441 "Didn't expect a persisted cert\n");
442 /* Trying to set this "read only" property crashes.
443 access |= CERT_ACCESS_STATE_WRITE_PERSIST_FLAG;
444 ret = CertSetCertificateContextProperty(context,
445 CERT_ACCESS_STATE_PROP_ID, 0, &access);
448 /* Can I set the hash to an invalid hash? */
450 blob.cbData = sizeof(hash);
451 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID, 0,
453 ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
455 size = sizeof(hashProperty);
456 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
457 hashProperty, &size);
458 ok(!memcmp(hashProperty, hash, sizeof(hash)), "Unexpected hash\n");
459 /* Delete the (bogus) hash, and get the real one */
460 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID, 0,
462 ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
464 checkHash(bigCert, sizeof(bigCert), CALG_SHA1, context,
467 /* Now that the hash property is set, we should get one property when
473 propID = CertEnumCertificateContextProperties(context, propID);
476 } while (propID != 0);
477 ok(numProps == 1, "Expected 1 properties, got %d\n", numProps);
479 /* Check a few other implicit properties */
480 checkHash(bigCert, sizeof(bigCert), CALG_MD5, context,
481 CERT_MD5_HASH_PROP_ID);
483 /* Test key contexts and handles and such */
485 ret = CertGetCertificateContextProperty(context, CERT_KEY_CONTEXT_PROP_ID,
487 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
488 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
489 size = sizeof(CERT_KEY_CONTEXT);
490 ret = CertGetCertificateContextProperty(context, CERT_KEY_CONTEXT_PROP_ID,
492 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
493 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
494 ret = CertGetCertificateContextProperty(context, CERT_KEY_CONTEXT_PROP_ID,
496 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
497 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
498 /* Key context with an invalid size */
499 keyContext.cbSize = 0;
500 ret = CertSetCertificateContextProperty(context, CERT_KEY_CONTEXT_PROP_ID,
502 ok(!ret && GetLastError() == E_INVALIDARG,
503 "Expected E_INVALIDARG, got %08x\n", GetLastError());
504 size = sizeof(keyContext);
505 ret = CertGetCertificateContextProperty(context, CERT_KEY_CONTEXT_PROP_ID,
507 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
508 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
509 keyContext.cbSize = sizeof(keyContext);
510 keyContext.hCryptProv = 0;
511 keyContext.dwKeySpec = AT_SIGNATURE;
512 ret = CertSetCertificateContextProperty(context, CERT_KEY_CONTEXT_PROP_ID,
514 ok(ret, "CertSetCertificateContextProperty failed: %08x\n", GetLastError());
515 /* Now that that's set, the key prov handle property is also gettable.
517 size = sizeof(DWORD);
518 ret = CertGetCertificateContextProperty(context,
519 CERT_KEY_PROV_HANDLE_PROP_ID, &keyContext.hCryptProv, &size);
520 ok(ret, "Expected to get the CERT_KEY_PROV_HANDLE_PROP_ID, got %08x\n",
522 /* Remove the key prov handle property.. */
523 ret = CertSetCertificateContextProperty(context,
524 CERT_KEY_PROV_HANDLE_PROP_ID, 0, NULL);
525 ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
527 /* and the key context's CSP is set to NULL. */
528 size = sizeof(keyContext);
529 ret = CertGetCertificateContextProperty(context,
530 CERT_KEY_CONTEXT_PROP_ID, &keyContext, &size);
531 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
533 ok(keyContext.hCryptProv == 0, "Expected no hCryptProv\n");
535 /* According to MSDN the subject key id can be stored as a property,
536 * as a subject key extension, or as the SHA1 hash of the public key,
537 * but this cert has none of them:
539 ret = CertGetCertificateContextProperty(context,
540 CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size);
541 ok(!ret && GetLastError() == ERROR_INVALID_DATA,
542 "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
543 CertFreeCertificateContext(context);
544 /* This cert does have a public key, but its subject key identifier still
545 * isn't available: */
546 context = CertCreateCertificateContext(X509_ASN_ENCODING,
547 v1CertWithPubKey, sizeof(v1CertWithPubKey));
548 ret = CertGetCertificateContextProperty(context,
549 CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size);
550 ok(!ret && GetLastError() == ERROR_INVALID_DATA,
551 "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
552 CertFreeCertificateContext(context);
553 /* This cert with a subject key extension can have its key identifier
554 * property retrieved:
556 context = CertCreateCertificateContext(X509_ASN_ENCODING,
557 v1CertWithSubjectKeyId, sizeof(v1CertWithSubjectKeyId));
558 ret = CertGetCertificateContextProperty(context,
559 CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size);
560 ok(ret, "CertGetCertificateContextProperty failed: %08x\n", GetLastError());
563 LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, size);
567 ret = CertGetCertificateContextProperty(context,
568 CERT_KEY_IDENTIFIER_PROP_ID, buf, &size);
569 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
571 ok(!memcmp(buf, subjectKeyId, size), "Unexpected subject key id\n");
572 HeapFree(GetProcessHeap(), 0, buf);
575 CertFreeCertificateContext(context);
578 static void testDupCert(void)
581 PCCERT_CONTEXT context, dupContext;
584 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
585 CERT_STORE_CREATE_NEW_FLAG, NULL);
586 ok(store != NULL, "CertOpenStore failed: %d\n", GetLastError());
590 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
591 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
592 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
594 ok(context != NULL, "Expected a valid cert context\n");
597 ok(context->cbCertEncoded == sizeof(bigCert),
598 "Wrong cert size %d\n", context->cbCertEncoded);
599 ok(!memcmp(context->pbCertEncoded, bigCert, sizeof(bigCert)),
600 "Unexpected encoded cert in context\n");
601 ok(context->hCertStore == store, "Unexpected store\n");
603 dupContext = CertDuplicateCertificateContext(context);
604 ok(dupContext != NULL, "Expected valid duplicate\n");
605 /* Not only is it a duplicate, it's identical: the address is the
608 ok(dupContext == context, "Expected identical context addresses\n");
609 CertFreeCertificateContext(dupContext);
610 CertFreeCertificateContext(context);
612 CertCloseStore(store, 0);
615 static BYTE subjectName3[] = { 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
616 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x52, 0x6f, 0x62, 0x20, 0x20, 0x4c, 0x61,
618 static const BYTE iTunesCert0[] = {
619 0x30,0x82,0x03,0xc4,0x30,0x82,0x03,0x2d,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,
620 0x47,0xbf,0x19,0x95,0xdf,0x8d,0x52,0x46,0x43,0xf7,0xdb,0x6d,0x48,0x0d,0x31,
621 0xa4,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,
622 0x00,0x30,0x81,0x8b,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,
623 0x5a,0x41,0x31,0x15,0x30,0x13,0x06,0x03,0x55,0x04,0x08,0x13,0x0c,0x57,0x65,
624 0x73,0x74,0x65,0x72,0x6e,0x20,0x43,0x61,0x70,0x65,0x31,0x14,0x30,0x12,0x06,
625 0x03,0x55,0x04,0x07,0x13,0x0b,0x44,0x75,0x72,0x62,0x61,0x6e,0x76,0x69,0x6c,
626 0x6c,0x65,0x31,0x0f,0x30,0x0d,0x06,0x03,0x55,0x04,0x0a,0x13,0x06,0x54,0x68,
627 0x61,0x77,0x74,0x65,0x31,0x1d,0x30,0x1b,0x06,0x03,0x55,0x04,0x0b,0x13,0x14,
628 0x54,0x68,0x61,0x77,0x74,0x65,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,
629 0x61,0x74,0x69,0x6f,0x6e,0x31,0x1f,0x30,0x1d,0x06,0x03,0x55,0x04,0x03,0x13,
630 0x16,0x54,0x68,0x61,0x77,0x74,0x65,0x20,0x54,0x69,0x6d,0x65,0x73,0x74,0x61,
631 0x6d,0x70,0x69,0x6e,0x67,0x20,0x43,0x41,0x30,0x1e,0x17,0x0d,0x30,0x33,0x31,
632 0x32,0x30,0x34,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,0x31,0x33,0x31,
633 0x32,0x30,0x33,0x32,0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x53,0x31,0x0b,0x30,
634 0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x17,0x30,0x15,0x06,
635 0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x2c,
636 0x20,0x49,0x6e,0x63,0x2e,0x31,0x2b,0x30,0x29,0x06,0x03,0x55,0x04,0x03,0x13,
637 0x22,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x54,0x69,0x6d,0x65,0x20,
638 0x53,0x74,0x61,0x6d,0x70,0x69,0x6e,0x67,0x20,0x53,0x65,0x72,0x76,0x69,0x63,
639 0x65,0x73,0x20,0x43,0x41,0x30,0x82,0x01,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,
640 0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0f,0x00,0x30,
641 0x82,0x01,0x0a,0x02,0x82,0x01,0x01,0x00,0xa9,0xca,0xb2,0xa4,0xcc,0xcd,0x20,
642 0xaf,0x0a,0x7d,0x89,0xac,0x87,0x75,0xf0,0xb4,0x4e,0xf1,0xdf,0xc1,0x0f,0xbf,
643 0x67,0x61,0xbd,0xa3,0x64,0x1c,0xda,0xbb,0xf9,0xca,0x33,0xab,0x84,0x30,0x89,
644 0x58,0x7e,0x8c,0xdb,0x6b,0xdd,0x36,0x9e,0x0f,0xbf,0xd1,0xec,0x78,0xf2,0x77,
645 0xa6,0x7e,0x6f,0x3c,0xbf,0x93,0xaf,0x0d,0xba,0x68,0xf4,0x6c,0x94,0xca,0xbd,
646 0x52,0x2d,0xab,0x48,0x3d,0xf5,0xb6,0xd5,0x5d,0x5f,0x1b,0x02,0x9f,0xfa,0x2f,
647 0x6b,0x1e,0xa4,0xf7,0xa3,0x9a,0xa6,0x1a,0xc8,0x02,0xe1,0x7f,0x4c,0x52,0xe3,
648 0x0e,0x60,0xec,0x40,0x1c,0x7e,0xb9,0x0d,0xde,0x3f,0xc7,0xb4,0xdf,0x87,0xbd,
649 0x5f,0x7a,0x6a,0x31,0x2e,0x03,0x99,0x81,0x13,0xa8,0x47,0x20,0xce,0x31,0x73,
650 0x0d,0x57,0x2d,0xcd,0x78,0x34,0x33,0x95,0x12,0x99,0x12,0xb9,0xde,0x68,0x2f,
651 0xaa,0xe6,0xe3,0xc2,0x8a,0x8c,0x2a,0xc3,0x8b,0x21,0x87,0x66,0xbd,0x83,0x58,
652 0x57,0x6f,0x75,0xbf,0x3c,0xaa,0x26,0x87,0x5d,0xca,0x10,0x15,0x3c,0x9f,0x84,
653 0xea,0x54,0xc1,0x0a,0x6e,0xc4,0xfe,0xc5,0x4a,0xdd,0xb9,0x07,0x11,0x97,0x22,
654 0x7c,0xdb,0x3e,0x27,0xd1,0x1e,0x78,0xec,0x9f,0x31,0xc9,0xf1,0xe6,0x22,0x19,
655 0xdb,0xc4,0xb3,0x47,0x43,0x9a,0x1a,0x5f,0xa0,0x1e,0x90,0xe4,0x5e,0xf5,0xee,
656 0x7c,0xf1,0x7d,0xab,0x62,0x01,0x8f,0xf5,0x4d,0x0b,0xde,0xd0,0x22,0x56,0xa8,
657 0x95,0xcd,0xae,0x88,0x76,0xae,0xee,0xba,0x0d,0xf3,0xe4,0x4d,0xd9,0xa0,0xfb,
658 0x68,0xa0,0xae,0x14,0x3b,0xb3,0x87,0xc1,0xbb,0x02,0x03,0x01,0x00,0x01,0xa3,
659 0x81,0xdb,0x30,0x81,0xd8,0x30,0x34,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,
660 0x01,0x01,0x04,0x28,0x30,0x26,0x30,0x24,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,
661 0x07,0x30,0x01,0x86,0x18,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6f,0x63,0x73,
662 0x70,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x30,
663 0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,
664 0xff,0x02,0x01,0x00,0x30,0x41,0x06,0x03,0x55,0x1d,0x1f,0x04,0x3a,0x30,0x38,
665 0x30,0x36,0xa0,0x34,0xa0,0x32,0x86,0x30,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
666 0x63,0x72,0x6c,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,
667 0x6d,0x2f,0x54,0x68,0x61,0x77,0x74,0x65,0x54,0x69,0x6d,0x65,0x73,0x74,0x61,
668 0x6d,0x70,0x69,0x6e,0x67,0x43,0x41,0x2e,0x63,0x72,0x6c,0x30,0x13,0x06,0x03,
669 0x55,0x1d,0x25,0x04,0x0c,0x30,0x0a,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,
670 0x03,0x08,0x30,0x0e,0x06,0x03,0x55,0x1d,0x0f,0x01,0x01,0xff,0x04,0x04,0x03,
671 0x02,0x01,0x06,0x30,0x24,0x06,0x03,0x55,0x1d,0x11,0x04,0x1d,0x30,0x1b,0xa4,
672 0x19,0x30,0x17,0x31,0x15,0x30,0x13,0x06,0x03,0x55,0x04,0x03,0x13,0x0c,0x54,
673 0x53,0x41,0x32,0x30,0x34,0x38,0x2d,0x31,0x2d,0x35,0x33,0x30,0x0d,0x06,0x09,
674 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x03,0x81,0x81,0x00,
675 0x4a,0x6b,0xf9,0xea,0x58,0xc2,0x44,0x1c,0x31,0x89,0x79,0x99,0x2b,0x96,0xbf,
676 0x82,0xac,0x01,0xd6,0x1c,0x4c,0xcd,0xb0,0x8a,0x58,0x6e,0xdf,0x08,0x29,0xa3,
677 0x5e,0xc8,0xca,0x93,0x13,0xe7,0x04,0x52,0x0d,0xef,0x47,0x27,0x2f,0x00,0x38,
678 0xb0,0xe4,0xc9,0x93,0x4e,0x9a,0xd4,0x22,0x62,0x15,0xf7,0x3f,0x37,0x21,0x4f,
679 0x70,0x31,0x80,0xf1,0x8b,0x38,0x87,0xb3,0xe8,0xe8,0x97,0x00,0xfe,0xcf,0x55,
680 0x96,0x4e,0x24,0xd2,0xa9,0x27,0x4e,0x7a,0xae,0xb7,0x61,0x41,0xf3,0x2a,0xce,
681 0xe7,0xc9,0xd9,0x5e,0xdd,0xbb,0x2b,0x85,0x3e,0xb5,0x9d,0xb5,0xd9,0xe1,0x57,
682 0xff,0xbe,0xb4,0xc5,0x7e,0xf5,0xcf,0x0c,0x9e,0xf0,0x97,0xfe,0x2b,0xd3,0x3b,
683 0x52,0x1b,0x1b,0x38,0x27,0xf7,0x3f,0x4a };
684 static const BYTE iTunesCert1[] = {
685 0x30,0x82,0x03,0xff,0x30,0x82,0x02,0xe7,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,
686 0x0d,0xe9,0x2b,0xf0,0xd4,0xd8,0x29,0x88,0x18,0x32,0x05,0x09,0x5e,0x9a,0x76,
687 0x88,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,
688 0x00,0x30,0x53,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,
689 0x53,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,
690 0x69,0x53,0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x2b,0x30,0x29,
691 0x06,0x03,0x55,0x04,0x03,0x13,0x22,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,
692 0x20,0x54,0x69,0x6d,0x65,0x20,0x53,0x74,0x61,0x6d,0x70,0x69,0x6e,0x67,0x20,
693 0x53,0x65,0x72,0x76,0x69,0x63,0x65,0x73,0x20,0x43,0x41,0x30,0x1e,0x17,0x0d,
694 0x30,0x33,0x31,0x32,0x30,0x34,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,
695 0x30,0x38,0x31,0x32,0x30,0x33,0x32,0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x57,
696 0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x17,
697 0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,0x69,
698 0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x2f,0x30,0x2d,0x06,0x03,0x55,
699 0x04,0x03,0x13,0x26,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x54,0x69,
700 0x6d,0x65,0x20,0x53,0x74,0x61,0x6d,0x70,0x69,0x6e,0x67,0x20,0x53,0x65,0x72,
701 0x76,0x69,0x63,0x65,0x73,0x20,0x53,0x69,0x67,0x6e,0x65,0x72,0x30,0x82,0x01,
702 0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,
703 0x00,0x03,0x82,0x01,0x0f,0x00,0x30,0x82,0x01,0x0a,0x02,0x82,0x01,0x01,0x00,
704 0xb2,0x50,0x28,0x48,0xdd,0xd3,0x68,0x7a,0x84,0x18,0x44,0x66,0x75,0x5d,0x7e,
705 0xc4,0xb8,0x9f,0x63,0x26,0xff,0x3d,0x43,0x9c,0x7c,0x11,0x38,0x10,0x25,0x55,
706 0x73,0xd9,0x75,0x27,0x69,0xfd,0x4e,0xb9,0x20,0x5c,0xd3,0x0a,0xf9,0xa0,0x1b,
707 0x2a,0xed,0x55,0x56,0x21,0x61,0xd8,0x1e,0xdb,0xe4,0xbc,0x33,0x6b,0xc7,0xef,
708 0xdd,0xa3,0x37,0x65,0x8e,0x1b,0x93,0x0c,0xb6,0x53,0x1e,0x5c,0x7c,0x66,0x35,
709 0x5f,0x05,0x8a,0x45,0xfe,0x76,0x4e,0xdf,0x53,0x80,0xa2,0x81,0x20,0x9d,0xae,
710 0x88,0x5c,0xa2,0x08,0xf7,0xe5,0x30,0xf9,0xee,0x22,0x37,0x4c,0x42,0x0a,0xce,
711 0xdf,0xc6,0x1f,0xc4,0xd6,0x55,0xe9,0x81,0x3f,0xb5,0x52,0xa3,0x2c,0xaa,0x01,
712 0x7a,0xf2,0xa2,0xaa,0x8d,0x35,0xfe,0x9f,0xe6,0x5d,0x6a,0x05,0x9f,0x3d,0x6b,
713 0xe3,0xbf,0x96,0xc0,0xfe,0xcc,0x60,0xf9,0x40,0xe7,0x07,0xa0,0x44,0xeb,0x81,
714 0x51,0x6e,0xa5,0x2a,0xf2,0xb6,0x8a,0x10,0x28,0xed,0x8f,0xdc,0x06,0xa0,0x86,
715 0x50,0x9a,0x7b,0x4a,0x08,0x0d,0x30,0x1d,0xca,0x10,0x9e,0x6b,0xf7,0xe9,0x58,
716 0xae,0x04,0xa9,0x40,0x99,0xb2,0x28,0xe8,0x8f,0x16,0xac,0x3c,0xe3,0x53,0x6f,
717 0x4b,0xd3,0x35,0x9d,0xb5,0x6f,0x64,0x1d,0xb3,0x96,0x2c,0xbb,0x3d,0xe7,0x79,
718 0xeb,0x6d,0x7a,0xf9,0x16,0xe6,0x26,0xad,0xaf,0xef,0x99,0x53,0xb7,0x40,0x2c,
719 0x95,0xb8,0x79,0xaa,0xfe,0xd4,0x52,0xab,0x29,0x74,0x7e,0x42,0xec,0x39,0x1e,
720 0xa2,0x6a,0x16,0xe6,0x59,0xbb,0x24,0x68,0xd8,0x00,0x80,0x43,0x10,0x87,0x80,
721 0x6b,0x02,0x03,0x01,0x00,0x01,0xa3,0x81,0xca,0x30,0x81,0xc7,0x30,0x34,0x06,
722 0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x28,0x30,0x26,0x30,0x24,
723 0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x18,0x68,0x74,0x74,
724 0x70,0x3a,0x2f,0x2f,0x6f,0x63,0x73,0x70,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,
725 0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x30,0x0c,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
726 0xff,0x04,0x02,0x30,0x00,0x30,0x33,0x06,0x03,0x55,0x1d,0x1f,0x04,0x2c,0x30,
727 0x2a,0x30,0x28,0xa0,0x26,0xa0,0x24,0x86,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,
728 0x2f,0x63,0x72,0x6c,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,
729 0x6f,0x6d,0x2f,0x74,0x73,0x73,0x2d,0x63,0x61,0x2e,0x63,0x72,0x6c,0x30,0x16,
730 0x06,0x03,0x55,0x1d,0x25,0x01,0x01,0xff,0x04,0x0c,0x30,0x0a,0x06,0x08,0x2b,
731 0x06,0x01,0x05,0x05,0x07,0x03,0x08,0x30,0x0e,0x06,0x03,0x55,0x1d,0x0f,0x01,
732 0x01,0xff,0x04,0x04,0x03,0x02,0x06,0xc0,0x30,0x24,0x06,0x03,0x55,0x1d,0x11,
733 0x04,0x1d,0x30,0x1b,0xa4,0x19,0x30,0x17,0x31,0x15,0x30,0x13,0x06,0x03,0x55,
734 0x04,0x03,0x13,0x0c,0x54,0x53,0x41,0x32,0x30,0x34,0x38,0x2d,0x31,0x2d,0x35,
735 0x34,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,
736 0x00,0x03,0x82,0x01,0x01,0x00,0x87,0x78,0x70,0xda,0x4e,0x52,0x01,0x20,0x5b,
737 0xe0,0x79,0xc9,0x82,0x30,0xc4,0xfd,0xb9,0x19,0x96,0xbd,0x91,0x00,0xc3,0xbd,
738 0xcd,0xcd,0xc6,0xf4,0x0e,0xd8,0xff,0xf9,0x4d,0xc0,0x33,0x62,0x30,0x11,0xc5,
739 0xf5,0x74,0x1b,0xd4,0x92,0xde,0x5f,0x9c,0x20,0x13,0xb1,0x7c,0x45,0xbe,0x50,
740 0xcd,0x83,0xe7,0x80,0x17,0x83,0xa7,0x27,0x93,0x67,0x13,0x46,0xfb,0xca,0xb8,
741 0x98,0x41,0x03,0xcc,0x9b,0x51,0x5b,0x05,0x8b,0x7f,0xa8,0x6f,0xf3,0x1b,0x50,
742 0x1b,0x24,0x2e,0xf2,0x69,0x8d,0x6c,0x22,0xf7,0xbb,0xca,0x16,0x95,0xed,0x0c,
743 0x74,0xc0,0x68,0x77,0xd9,0xeb,0x99,0x62,0x87,0xc1,0x73,0x90,0xf8,0x89,0x74,
744 0x7a,0x23,0xab,0xa3,0x98,0x7b,0x97,0xb1,0xf7,0x8f,0x29,0x71,0x4d,0x2e,0x75,
745 0x1b,0x48,0x41,0xda,0xf0,0xb5,0x0d,0x20,0x54,0xd6,0x77,0xa0,0x97,0x82,0x63,
746 0x69,0xfd,0x09,0xcf,0x8a,0xf0,0x75,0xbb,0x09,0x9b,0xd9,0xf9,0x11,0x55,0x26,
747 0x9a,0x61,0x32,0xbe,0x7a,0x02,0xb0,0x7b,0x86,0xbe,0xa2,0xc3,0x8b,0x22,0x2c,
748 0x78,0xd1,0x35,0x76,0xbc,0x92,0x73,0x5c,0xf9,0xb9,0xe6,0x4c,0x15,0x0a,0x23,
749 0xcc,0xe4,0xd2,0xd4,0x34,0x2e,0x49,0x40,0x15,0x3c,0x0f,0x60,0x7a,0x24,0xc6,
750 0xa5,0x66,0xef,0x96,0xcf,0x70,0xeb,0x3e,0xe7,0xf4,0x0d,0x7e,0xdc,0xd1,0x7c,
751 0xa3,0x76,0x71,0x69,0xc1,0x9c,0x4f,0x47,0x30,0x35,0x21,0xb1,0xa2,0xaf,0x1a,
752 0x62,0x3c,0x2b,0xd9,0x8e,0xaa,0x2a,0x07,0x7b,0xd8,0x18,0xb3,0x5c,0x7b,0xe2,
753 0x9d,0xa5,0x6f,0xfe,0x3c,0x89,0xad };
754 static const BYTE iTunesCert2[] = {
755 0x30,0x82,0x04,0xbf,0x30,0x82,0x04,0x28,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,
756 0x41,0x91,0xa1,0x5a,0x39,0x78,0xdf,0xcf,0x49,0x65,0x66,0x38,0x1d,0x4c,0x75,
757 0xc2,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,
758 0x00,0x30,0x5f,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,
759 0x53,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,
760 0x69,0x53,0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x37,0x30,0x35,
761 0x06,0x03,0x55,0x04,0x0b,0x13,0x2e,0x43,0x6c,0x61,0x73,0x73,0x20,0x33,0x20,
762 0x50,0x75,0x62,0x6c,0x69,0x63,0x20,0x50,0x72,0x69,0x6d,0x61,0x72,0x79,0x20,
763 0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x41,
764 0x75,0x74,0x68,0x6f,0x72,0x69,0x74,0x79,0x30,0x1e,0x17,0x0d,0x30,0x34,0x30,
765 0x37,0x31,0x36,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,0x31,0x34,0x30,
766 0x37,0x31,0x35,0x32,0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x81,0xb4,0x31,0x0b,
767 0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x17,0x30,0x15,
768 0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,
769 0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x1f,0x30,0x1d,0x06,0x03,0x55,0x04,0x0b,
770 0x13,0x16,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x54,0x72,0x75,0x73,
771 0x74,0x20,0x4e,0x65,0x74,0x77,0x6f,0x72,0x6b,0x31,0x3b,0x30,0x39,0x06,0x03,
772 0x55,0x04,0x0b,0x13,0x32,0x54,0x65,0x72,0x6d,0x73,0x20,0x6f,0x66,0x20,0x75,
773 0x73,0x65,0x20,0x61,0x74,0x20,0x68,0x74,0x74,0x70,0x73,0x3a,0x2f,0x2f,0x77,
774 0x77,0x77,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,
775 0x2f,0x72,0x70,0x61,0x20,0x28,0x63,0x29,0x30,0x34,0x31,0x2e,0x30,0x2c,0x06,
776 0x03,0x55,0x04,0x03,0x13,0x25,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,
777 0x43,0x6c,0x61,0x73,0x73,0x20,0x33,0x20,0x43,0x6f,0x64,0x65,0x20,0x53,0x69,
778 0x67,0x6e,0x69,0x6e,0x67,0x20,0x32,0x30,0x30,0x34,0x20,0x43,0x41,0x30,0x82,
779 0x01,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,
780 0x05,0x00,0x03,0x82,0x01,0x0f,0x00,0x30,0x82,0x01,0x0a,0x02,0x82,0x01,0x01,
781 0x00,0xbe,0xbc,0xee,0xbc,0x7e,0xef,0x83,0xeb,0xe0,0x37,0x4f,0xfb,0x03,0x10,
782 0x38,0xbe,0x08,0xd2,0x8c,0x7d,0x9d,0xfa,0x92,0x7f,0x19,0x0c,0xc2,0x6b,0xee,
783 0x42,0x52,0x8c,0xde,0xd3,0x1c,0x48,0x13,0x25,0xea,0xc1,0x63,0x7a,0xf9,0x51,
784 0x65,0xee,0xd3,0xaa,0x3b,0xf5,0xf0,0x94,0x9c,0x2b,0xfb,0xf2,0x66,0xd4,0x24,
785 0xda,0xf7,0xf5,0x9f,0x6e,0x19,0x39,0x36,0xbc,0xd0,0xa3,0x76,0x08,0x1e,0x22,
786 0x27,0x24,0x6c,0x38,0x91,0x27,0xe2,0x84,0x49,0xae,0x1b,0x8a,0xa1,0xfd,0x25,
787 0x82,0x2c,0x10,0x30,0xe8,0x71,0xab,0x28,0xe8,0x77,0x4a,0x51,0xf1,0xec,0xcd,
788 0xf8,0xf0,0x54,0xd4,0x6f,0xc0,0xe3,0x6d,0x0a,0x8f,0xd9,0xd8,0x64,0x8d,0x63,
789 0xb2,0x2d,0x4e,0x27,0xf6,0x85,0x0e,0xfe,0x6d,0xe3,0x29,0x99,0xe2,0x85,0x47,
790 0x7c,0x2d,0x86,0x7f,0xe8,0x57,0x8f,0xad,0x67,0xc2,0x33,0x32,0x91,0x13,0x20,
791 0xfc,0xa9,0x23,0x14,0x9a,0x6d,0xc2,0x84,0x4b,0x76,0x68,0x04,0xd5,0x71,0x2c,
792 0x5d,0x21,0xfa,0x88,0x0d,0x26,0xfd,0x1f,0x2d,0x91,0x2b,0xe7,0x01,0x55,0x4d,
793 0xf2,0x6d,0x35,0x28,0x82,0xdf,0xd9,0x6b,0x5c,0xb6,0xd6,0xd9,0xaa,0x81,0xfd,
794 0x5f,0xcd,0x83,0xba,0x63,0x9d,0xd0,0x22,0xfc,0xa9,0x3b,0x42,0x69,0xb2,0x8e,
795 0x3a,0xb5,0xbc,0xb4,0x9e,0x0f,0x5e,0xc4,0xea,0x2c,0x82,0x8b,0x28,0xfd,0x53,
796 0x08,0x96,0xdd,0xb5,0x01,0x20,0xd1,0xf9,0xa5,0x18,0xe7,0xc0,0xee,0x51,0x70,
797 0x37,0xe1,0xb6,0x05,0x48,0x52,0x48,0x6f,0x38,0xea,0xc3,0xe8,0x6c,0x7b,0x44,
798 0x84,0xbb,0x02,0x03,0x01,0x00,0x01,0xa3,0x82,0x01,0xa0,0x30,0x82,0x01,0x9c,
799 0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,
800 0x01,0xff,0x02,0x01,0x00,0x30,0x44,0x06,0x03,0x55,0x1d,0x20,0x04,0x3d,0x30,
801 0x3b,0x30,0x39,0x06,0x0b,0x60,0x86,0x48,0x01,0x86,0xf8,0x45,0x01,0x07,0x17,
802 0x03,0x30,0x2a,0x30,0x28,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x02,0x01,
803 0x16,0x1c,0x68,0x74,0x74,0x70,0x73,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x76,
804 0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x2f,0x72,0x70,0x61,
805 0x30,0x31,0x06,0x03,0x55,0x1d,0x1f,0x04,0x2a,0x30,0x28,0x30,0x26,0xa0,0x24,
806 0xa0,0x22,0x86,0x20,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x63,0x72,0x6c,0x2e,
807 0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x2f,0x70,0x63,
808 0x61,0x33,0x2e,0x63,0x72,0x6c,0x30,0x1d,0x06,0x03,0x55,0x1d,0x25,0x04,0x16,
809 0x30,0x14,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x03,0x02,0x06,0x08,0x2b,
810 0x06,0x01,0x05,0x05,0x07,0x03,0x03,0x30,0x0e,0x06,0x03,0x55,0x1d,0x0f,0x01,
811 0x01,0xff,0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x11,0x06,0x09,0x60,0x86,0x48,
812 0x01,0x86,0xf8,0x42,0x01,0x01,0x04,0x04,0x03,0x02,0x00,0x01,0x30,0x29,0x06,
813 0x03,0x55,0x1d,0x11,0x04,0x22,0x30,0x20,0xa4,0x1e,0x30,0x1c,0x31,0x1a,0x30,
814 0x18,0x06,0x03,0x55,0x04,0x03,0x13,0x11,0x43,0x6c,0x61,0x73,0x73,0x33,0x43,
815 0x41,0x32,0x30,0x34,0x38,0x2d,0x31,0x2d,0x34,0x33,0x30,0x1d,0x06,0x03,0x55,
816 0x1d,0x0e,0x04,0x16,0x04,0x14,0x08,0xf5,0x51,0xe8,0xfb,0xfe,0x3d,0x3d,0x64,
817 0x36,0x7c,0x68,0xcf,0x5b,0x78,0xa8,0xdf,0xb9,0xc5,0x37,0x30,0x81,0x80,0x06,
818 0x03,0x55,0x1d,0x23,0x04,0x79,0x30,0x77,0xa1,0x63,0xa4,0x61,0x30,0x5f,0x31,
819 0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x17,0x30,
820 0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,0x69,0x67,
821 0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x37,0x30,0x35,0x06,0x03,0x55,0x04,
822 0x0b,0x13,0x2e,0x43,0x6c,0x61,0x73,0x73,0x20,0x33,0x20,0x50,0x75,0x62,0x6c,
823 0x69,0x63,0x20,0x50,0x72,0x69,0x6d,0x61,0x72,0x79,0x20,0x43,0x65,0x72,0x74,
824 0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x41,0x75,0x74,0x68,0x6f,
825 0x72,0x69,0x74,0x79,0x82,0x10,0x70,0xba,0xe4,0x1d,0x10,0xd9,0x29,0x34,0xb6,
826 0x38,0xca,0x7b,0x03,0xcc,0xba,0xbf,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,
827 0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x03,0x81,0x81,0x00,0xae,0x3a,0x17,0xb8,
828 0x4a,0x7b,0x55,0xfa,0x64,0x55,0xec,0x40,0xa4,0xed,0x49,0x41,0x90,0x99,0x9c,
829 0x89,0xbc,0xaf,0x2e,0x1d,0xca,0x78,0x23,0xf9,0x1c,0x19,0x0f,0x7f,0xeb,0x68,
830 0xbc,0x32,0xd9,0x88,0x38,0xde,0xdc,0x3f,0xd3,0x89,0xb4,0x3f,0xb1,0x82,0x96,
831 0xf1,0xa4,0x5a,0xba,0xed,0x2e,0x26,0xd3,0xde,0x7c,0x01,0x6e,0x00,0x0a,0x00,
832 0xa4,0x06,0x92,0x11,0x48,0x09,0x40,0xf9,0x1c,0x18,0x79,0x67,0x23,0x24,0xe0,
833 0xbb,0xd5,0xe1,0x50,0xae,0x1b,0xf5,0x0e,0xdd,0xe0,0x2e,0x81,0xcd,0x80,0xa3,
834 0x6c,0x52,0x4f,0x91,0x75,0x55,0x8a,0xba,0x22,0xf2,0xd2,0xea,0x41,0x75,0x88,
835 0x2f,0x63,0x55,0x7d,0x1e,0x54,0x5a,0x95,0x59,0xca,0xd9,0x34,0x81,0xc0,0x5f,
836 0x5e,0xf6,0x7a,0xb5 };
837 static const BYTE iTunesCert3[] = {
838 0x30,0x82,0x04,0xf1,0x30,0x82,0x03,0xd9,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,
839 0x0f,0x1a,0xa0,0xe0,0x9b,0x9b,0x61,0xa6,0xb6,0xfe,0x40,0xd2,0xdf,0x6a,0xf6,
840 0x8d,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,
841 0x00,0x30,0x81,0xb4,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,
842 0x55,0x53,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,
843 0x72,0x69,0x53,0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x1f,0x30,
844 0x1d,0x06,0x03,0x55,0x04,0x0b,0x13,0x16,0x56,0x65,0x72,0x69,0x53,0x69,0x67,
845 0x6e,0x20,0x54,0x72,0x75,0x73,0x74,0x20,0x4e,0x65,0x74,0x77,0x6f,0x72,0x6b,
846 0x31,0x3b,0x30,0x39,0x06,0x03,0x55,0x04,0x0b,0x13,0x32,0x54,0x65,0x72,0x6d,
847 0x73,0x20,0x6f,0x66,0x20,0x75,0x73,0x65,0x20,0x61,0x74,0x20,0x68,0x74,0x74,
848 0x70,0x73,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,
849 0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x2f,0x72,0x70,0x61,0x20,0x28,0x63,0x29,0x30,
850 0x34,0x31,0x2e,0x30,0x2c,0x06,0x03,0x55,0x04,0x03,0x13,0x25,0x56,0x65,0x72,
851 0x69,0x53,0x69,0x67,0x6e,0x20,0x43,0x6c,0x61,0x73,0x73,0x20,0x33,0x20,0x43,
852 0x6f,0x64,0x65,0x20,0x53,0x69,0x67,0x6e,0x69,0x6e,0x67,0x20,0x32,0x30,0x30,
853 0x34,0x20,0x43,0x41,0x30,0x1e,0x17,0x0d,0x30,0x36,0x30,0x31,0x31,0x37,0x30,
854 0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,0x30,0x38,0x30,0x31,0x32,0x32,0x32,
855 0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x81,0xb4,0x31,0x0b,0x30,0x09,0x06,0x03,
856 0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,
857 0x08,0x13,0x0a,0x43,0x61,0x6c,0x69,0x66,0x6f,0x72,0x6e,0x69,0x61,0x31,0x12,
858 0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x13,0x09,0x43,0x75,0x70,0x65,0x72,0x74,
859 0x69,0x6e,0x6f,0x31,0x1d,0x30,0x1b,0x06,0x03,0x55,0x04,0x0a,0x14,0x14,0x41,
860 0x70,0x70,0x6c,0x65,0x20,0x43,0x6f,0x6d,0x70,0x75,0x74,0x65,0x72,0x2c,0x20,
861 0x49,0x6e,0x63,0x2e,0x31,0x3e,0x30,0x3c,0x06,0x03,0x55,0x04,0x0b,0x13,0x35,
862 0x44,0x69,0x67,0x69,0x74,0x61,0x6c,0x20,0x49,0x44,0x20,0x43,0x6c,0x61,0x73,
863 0x73,0x20,0x33,0x20,0x2d,0x20,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,
864 0x20,0x53,0x6f,0x66,0x74,0x77,0x61,0x72,0x65,0x20,0x56,0x61,0x6c,0x69,0x64,
865 0x61,0x74,0x69,0x6f,0x6e,0x20,0x76,0x32,0x31,0x1d,0x30,0x1b,0x06,0x03,0x55,
866 0x04,0x03,0x14,0x14,0x41,0x70,0x70,0x6c,0x65,0x20,0x43,0x6f,0x6d,0x70,0x75,
867 0x74,0x65,0x72,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x30,0x81,0x9f,0x30,0x0d,0x06,
868 0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x81,0x8d,
869 0x00,0x30,0x81,0x89,0x02,0x81,0x81,0x00,0xd3,0xab,0x3b,0x7f,0xec,0x48,0x84,
870 0xce,0xa8,0x1a,0x12,0xf3,0x3c,0x87,0xcb,0x24,0x58,0x96,0x02,0x87,0x66,0x49,
871 0xeb,0x89,0xee,0x79,0x44,0x70,0x8d,0xe7,0xd4,0x1f,0x30,0x92,0xc0,0x9c,0x35,
872 0x78,0xc0,0xaf,0x1c,0xb6,0x28,0xd3,0xe0,0xe0,0x9d,0xd3,0x49,0x76,0x73,0x57,
873 0x19,0x4d,0x8d,0x70,0x85,0x64,0x4d,0x1d,0xc6,0x02,0x3e,0xe5,0x2c,0x66,0x07,
874 0xd2,0x27,0x4b,0xd6,0xc8,0x3c,0x93,0xb6,0x15,0x0c,0xde,0x5b,0xd7,0x93,0xdd,
875 0xbe,0x85,0x62,0x34,0x17,0x8a,0x05,0x60,0xf0,0x8a,0x1c,0x5a,0x40,0x21,0x8d,
876 0x51,0x6c,0xb0,0x62,0xd8,0xb5,0xd4,0xf9,0xb1,0xd0,0x58,0x7a,0x7a,0x82,0x55,
877 0xb3,0xf9,0x53,0x71,0xde,0xd2,0xc9,0x37,0x8c,0xf6,0x5a,0x1f,0x2d,0xcd,0x7c,
878 0x67,0x02,0x03,0x01,0x00,0x01,0xa3,0x82,0x01,0x7f,0x30,0x82,0x01,0x7b,0x30,
879 0x09,0x06,0x03,0x55,0x1d,0x13,0x04,0x02,0x30,0x00,0x30,0x0e,0x06,0x03,0x55,
880 0x1d,0x0f,0x01,0x01,0xff,0x04,0x04,0x03,0x02,0x07,0x80,0x30,0x40,0x06,0x03,
881 0x55,0x1d,0x1f,0x04,0x39,0x30,0x37,0x30,0x35,0xa0,0x33,0xa0,0x31,0x86,0x2f,
882 0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x43,0x53,0x43,0x33,0x2d,0x32,0x30,0x30,
883 0x34,0x2d,0x63,0x72,0x6c,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,
884 0x63,0x6f,0x6d,0x2f,0x43,0x53,0x43,0x33,0x2d,0x32,0x30,0x30,0x34,0x2e,0x63,
885 0x72,0x6c,0x30,0x44,0x06,0x03,0x55,0x1d,0x20,0x04,0x3d,0x30,0x3b,0x30,0x39,
886 0x06,0x0b,0x60,0x86,0x48,0x01,0x86,0xf8,0x45,0x01,0x07,0x17,0x03,0x30,0x2a,
887 0x30,0x28,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x1c,0x68,
888 0x74,0x74,0x70,0x73,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x76,0x65,0x72,0x69,
889 0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x2f,0x72,0x70,0x61,0x30,0x13,0x06,
890 0x03,0x55,0x1d,0x25,0x04,0x0c,0x30,0x0a,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,
891 0x07,0x03,0x03,0x30,0x75,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x01,0x01,
892 0x04,0x69,0x30,0x67,0x30,0x24,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,
893 0x01,0x86,0x18,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6f,0x63,0x73,0x70,0x2e,
894 0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x30,0x3f,0x06,
895 0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x33,0x68,0x74,0x74,0x70,
896 0x3a,0x2f,0x2f,0x43,0x53,0x43,0x33,0x2d,0x32,0x30,0x30,0x34,0x2d,0x61,0x69,
897 0x61,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x2f,
898 0x43,0x53,0x43,0x33,0x2d,0x32,0x30,0x30,0x34,0x2d,0x61,0x69,0x61,0x2e,0x63,
899 0x65,0x72,0x30,0x1f,0x06,0x03,0x55,0x1d,0x23,0x04,0x18,0x30,0x16,0x80,0x14,
900 0x08,0xf5,0x51,0xe8,0xfb,0xfe,0x3d,0x3d,0x64,0x36,0x7c,0x68,0xcf,0x5b,0x78,
901 0xa8,0xdf,0xb9,0xc5,0x37,0x30,0x11,0x06,0x09,0x60,0x86,0x48,0x01,0x86,0xf8,
902 0x42,0x01,0x01,0x04,0x04,0x03,0x02,0x04,0x10,0x30,0x16,0x06,0x0a,0x2b,0x06,
903 0x01,0x04,0x01,0x82,0x37,0x02,0x01,0x1b,0x04,0x08,0x30,0x06,0x01,0x01,0x00,
904 0x01,0x01,0xff,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,
905 0x05,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x6a,0xa6,0x06,0xd0,0x33,0x18,0x64,
906 0xe2,0x69,0x82,0xee,0x6e,0x36,0x9e,0x9d,0x9a,0x0e,0x18,0xa8,0xac,0x9d,0x10,
907 0xed,0x01,0x3c,0xb9,0x61,0x04,0x62,0xf3,0x85,0x8f,0xcc,0x4f,0x2c,0x66,0x35,
908 0x54,0x25,0x45,0x8d,0x95,0x1c,0xd2,0x33,0xbe,0x2e,0xdd,0x7f,0x74,0xaf,0x03,
909 0x7b,0x86,0x63,0xb0,0xc9,0xe6,0xbd,0xc7,0x8e,0xde,0x03,0x18,0x98,0x82,0xc3,
910 0xbb,0xf8,0x15,0x99,0x1a,0xa9,0xdd,0xb9,0x5d,0xb9,0xbd,0x53,0x95,0x25,0x76,
911 0xfb,0x5c,0x53,0x90,0xea,0x01,0x0a,0xa0,0xb1,0xbf,0x09,0x1b,0x97,0x8f,0x40,
912 0xfa,0x85,0x12,0x74,0x01,0xdb,0xf6,0xdb,0x09,0xd6,0x5f,0x4f,0xd7,0x17,0xb4,
913 0xbf,0x9e,0x2f,0x86,0x52,0x5d,0x70,0x24,0x52,0x32,0x1e,0xa5,0x1d,0x39,0x8b,
914 0x66,0xf6,0xba,0x9b,0x69,0x8e,0x12,0x60,0xdb,0xb6,0xcf,0xe6,0x0d,0xd6,0x1c,
915 0x8f,0xd4,0x5b,0x4b,0x00,0xde,0x21,0x93,0xfb,0x6e,0xc7,0x3d,0xb4,0x66,0x0d,
916 0x29,0x0c,0x4e,0xe9,0x3f,0x94,0xd6,0xd6,0xdc,0xec,0xf8,0x53,0x3b,0x62,0xd5,
917 0x97,0x50,0x53,0x84,0x17,0xfe,0xe2,0xed,0x4c,0x23,0x0a,0x49,0xce,0x5b,0xe9,
918 0x70,0x31,0xc1,0x04,0x02,0x02,0x6c,0xb8,0x52,0xcd,0xc7,0x4e,0x70,0xb4,0x13,
919 0xd7,0xe0,0x92,0xba,0x44,0x1a,0x10,0x4c,0x6e,0x45,0xc6,0x86,0x04,0xc6,0x64,
920 0xd3,0x9c,0x6e,0xc1,0x9c,0xac,0x74,0x3d,0x77,0x06,0x5e,0x28,0x28,0x5c,0xf5,
921 0xe0,0x9c,0x19,0xd8,0xba,0x74,0x81,0x2d,0x67,0x77,0x93,0x8d,0xbf,0xd2,0x52,
922 0x00,0xe6,0xa5,0x38,0x4e,0x2e,0x73,0x66,0x7a };
923 static BYTE iTunesIssuer[] = {
924 0x30,0x81,0xb4,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,
925 0x13,0x02,0x55,0x53,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,
926 0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x2c,
927 0x20,0x49,0x6e,0x63,0x2e,0x31,0x1f,0x30,0x1d,0x06,0x03,0x55,
928 0x04,0x0b,0x13,0x16,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,
929 0x20,0x54,0x72,0x75,0x73,0x74,0x20,0x4e,0x65,0x74,0x77,0x6f,
930 0x72,0x6b,0x31,0x3b,0x30,0x39,0x06,0x03,0x55,0x04,0x0b,0x13,
931 0x32,0x54,0x65,0x72,0x6d,0x73,0x20,0x6f,0x66,0x20,0x75,0x73,
932 0x65,0x20,0x61,0x74,0x20,0x68,0x74,0x74,0x70,0x73,0x3a,0x2f,
933 0x2f,0x77,0x77,0x77,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,
934 0x6e,0x2e,0x63,0x6f,0x6d,0x2f,0x72,0x70,0x61,0x20,0x28,0x63,
935 0x29,0x30,0x34,0x31,0x2e,0x30,0x2c,0x06,0x03,0x55,0x04,0x03,
936 0x13,0x25,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x43,
937 0x6c,0x61,0x73,0x73,0x20,0x33,0x20,0x43,0x6f,0x64,0x65,0x20,
938 0x53,0x69,0x67,0x6e,0x69,0x6e,0x67,0x20,0x32,0x30,0x30,0x34,
940 static BYTE iTunesSerialNum[] = {
941 0x8d,0xf6,0x6a,0xdf,0xd2,0x40,0xfe,0xb6,0xa6,0x61,0x9b,0x9b,
942 0xe0,0xa0,0x1a,0x0f };
944 static void testFindCert(void)
947 PCCERT_CONTEXT context = NULL, subject;
949 CERT_INFO certInfo = { 0 };
950 CRYPT_HASH_BLOB blob;
951 BYTE otherSerialNumber[] = { 2 };
953 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
954 CERT_STORE_CREATE_NEW_FLAG, NULL);
955 ok(store != NULL, "CertOpenStore failed: %d\n", GetLastError());
959 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
960 bigCert, sizeof(bigCert), CERT_STORE_ADD_NEW, NULL);
961 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
963 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
964 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, NULL);
965 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
967 /* This has the same name as bigCert */
968 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
969 certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, NULL);
970 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
974 context = CertFindCertificateInStore(NULL, 0, 0, 0, NULL, NULL);
977 /* Check first cert's there, by issuer */
978 certInfo.Subject.pbData = subjectName;
979 certInfo.Subject.cbData = sizeof(subjectName);
980 certInfo.SerialNumber.pbData = serialNum;
981 certInfo.SerialNumber.cbData = sizeof(serialNum);
982 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
983 CERT_FIND_ISSUER_NAME, &certInfo.Subject, NULL);
984 ok(context != NULL, "CertFindCertificateInStore failed: %08x\n",
988 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
989 CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
990 ok(context != NULL, "Expected more than one cert\n");
993 context = CertFindCertificateInStore(store, X509_ASN_ENCODING,
994 0, CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
995 ok(context == NULL, "Expected precisely two certs\n");
999 /* Check second cert's there as well, by subject name */
1000 certInfo.Subject.pbData = subjectName2;
1001 certInfo.Subject.cbData = sizeof(subjectName2);
1002 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1003 CERT_FIND_SUBJECT_NAME, &certInfo.Subject, NULL);
1004 ok(context != NULL, "CertFindCertificateInStore failed: %08x\n",
1008 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1009 CERT_FIND_SUBJECT_NAME, &certInfo.Subject, context);
1010 ok(context == NULL, "Expected one cert only\n");
1013 /* Strange but true: searching for the subject cert requires you to set
1014 * the issuer, not the subject
1016 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1017 CERT_FIND_SUBJECT_CERT, &certInfo.Subject, NULL);
1018 ok(context == NULL, "Expected no certificate\n");
1019 certInfo.Subject.pbData = NULL;
1020 certInfo.Subject.cbData = 0;
1021 certInfo.Issuer.pbData = subjectName2;
1022 certInfo.Issuer.cbData = sizeof(subjectName2);
1023 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1024 CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
1025 ok(context != NULL, "CertFindCertificateInStore failed: %08x\n",
1029 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1030 CERT_FIND_SUBJECT_CERT, &certInfo.Subject, context);
1031 ok(context == NULL, "Expected one cert only\n");
1033 /* A non-matching serial number will not match. */
1034 certInfo.SerialNumber.pbData = otherSerialNumber;
1035 certInfo.SerialNumber.cbData = sizeof(otherSerialNumber);
1036 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1037 CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
1038 ok(context == NULL, "Expected no match\n");
1039 /* No serial number will not match */
1040 certInfo.SerialNumber.cbData = 0;
1041 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1042 CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
1043 ok(context == NULL, "Expected no match\n");
1044 /* A serial number still won't match if the name doesn't */
1045 certInfo.SerialNumber.pbData = serialNum;
1046 certInfo.SerialNumber.cbData = sizeof(serialNum);
1047 certInfo.Issuer.pbData = subjectName3;
1048 certInfo.Issuer.cbData = sizeof(subjectName3);
1049 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1050 CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
1051 ok(context == NULL, "Expected no match\n");
1053 /* The nice thing about hashes, they're unique */
1054 blob.pbData = bigCertHash;
1055 blob.cbData = sizeof(bigCertHash);
1056 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1057 CERT_FIND_SHA1_HASH, &blob, NULL);
1058 ok(context != NULL, "CertFindCertificateInStore failed: %08x\n",
1062 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1063 CERT_FIND_SHA1_HASH, &certInfo.Subject, context);
1064 ok(context == NULL, "Expected one cert only\n");
1067 CertCloseStore(store, 0);
1069 /* Another subject cert search, using iTunes's certs */
1070 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1071 CERT_STORE_CREATE_NEW_FLAG, NULL);
1072 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1073 iTunesCert0, sizeof(iTunesCert0), CERT_STORE_ADD_NEW, NULL);
1074 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1076 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1077 iTunesCert1, sizeof(iTunesCert1), CERT_STORE_ADD_NEW, NULL);
1078 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1080 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1081 iTunesCert2, sizeof(iTunesCert2), CERT_STORE_ADD_NEW, NULL);
1082 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1084 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1085 iTunesCert3, sizeof(iTunesCert3), CERT_STORE_ADD_NEW, &subject);
1086 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1089 /* The certInfo's issuer does not match any subject, but the serial
1090 * number does match a cert whose issuer matches certInfo's issuer.
1091 * This yields a match.
1093 certInfo.SerialNumber.cbData = sizeof(iTunesSerialNum);
1094 certInfo.SerialNumber.pbData = iTunesSerialNum;
1095 certInfo.Issuer.cbData = sizeof(iTunesIssuer);
1096 certInfo.Issuer.pbData = iTunesIssuer;
1097 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1098 CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
1099 ok(context != NULL, "Expected a match\n");
1102 ret = CertCompareCertificateName(context->dwCertEncodingType,
1103 &certInfo.Issuer, &context->pCertInfo->Subject);
1104 ok(!ret, "Expected subject name not to match\n");
1105 ret = CertCompareCertificateName(context->dwCertEncodingType,
1106 &certInfo.Issuer, &context->pCertInfo->Issuer);
1107 ok(ret, "Expected issuer name to match\n");
1108 ret = CertCompareIntegerBlob(&certInfo.SerialNumber,
1109 &context->pCertInfo->SerialNumber);
1110 ok(ret, "Expected serial number to match\n");
1111 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1112 CERT_FIND_SUBJECT_CERT, &certInfo, context);
1113 ok(context == NULL, "Expected one cert only\n");
1116 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1117 CERT_FIND_ISSUER_OF, subject, NULL);
1118 ok(context != NULL, "Expected an issuer\n");
1121 PCCERT_CONTEXT none = CertFindCertificateInStore(store,
1122 X509_ASN_ENCODING, 0, CERT_FIND_ISSUER_OF, context, NULL);
1124 ok(!none, "Expected no parent of issuer\n");
1125 CertFreeCertificateContext(context);
1127 CertFreeCertificateContext(subject);
1128 CertCloseStore(store, 0);
1131 static void testGetSubjectCert(void)
1134 PCCERT_CONTEXT context1, context2;
1135 CERT_INFO info = { 0 };
1138 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1139 CERT_STORE_CREATE_NEW_FLAG, NULL);
1140 ok(store != NULL, "CertOpenStore failed: %d\n", GetLastError());
1144 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1145 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
1146 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1148 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1149 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, &context1);
1150 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1152 ok(context1 != NULL, "Expected a context\n");
1153 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1154 certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, NULL);
1155 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1158 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
1160 ok(!context2 && GetLastError() == E_INVALIDARG,
1161 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1162 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
1164 ok(!context2 && GetLastError() == CRYPT_E_NOT_FOUND,
1165 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1166 info.SerialNumber.cbData = sizeof(serialNum);
1167 info.SerialNumber.pbData = serialNum;
1168 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
1170 ok(!context2 && GetLastError() == CRYPT_E_NOT_FOUND,
1171 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1172 info.Issuer.cbData = sizeof(subjectName2);
1173 info.Issuer.pbData = subjectName2;
1174 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
1176 ok(context2 != NULL,
1177 "CertGetSubjectCertificateFromStore failed: %08x\n", GetLastError());
1178 /* Not only should this find a context, but it should be the same
1179 * (same address) as context1.
1181 ok(context1 == context2, "Expected identical context addresses\n");
1182 CertFreeCertificateContext(context2);
1184 CertFreeCertificateContext(context1);
1185 CertCloseStore(store, 0);
1188 /* This expires in 1970 or so */
1189 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
1190 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
1191 0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
1192 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
1193 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
1194 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
1195 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
1196 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
1197 0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
1198 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
1199 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
1200 0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
1201 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
1202 0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
1203 0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
1204 0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
1205 0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
1206 0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
1207 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
1208 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
1209 0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
1210 0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
1211 0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
1212 0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
1213 0x49, 0xe5, 0xf9, 0x65, 0xf3 };
1215 /* This expires in 2036 or so */
1216 static const BYTE childOfExpired[] = { 0x30, 0x81, 0xcc, 0x30, 0x78, 0xa0,
1217 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
1218 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d,
1219 0x30, 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63,
1220 0x40, 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e,
1221 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x35, 0x30, 0x35,
1222 0x31, 0x37, 0x31, 0x32, 0x34, 0x39, 0x5a, 0x17, 0x0d, 0x33, 0x36, 0x30, 0x35,
1223 0x30, 0x35, 0x31, 0x37, 0x31, 0x32, 0x34, 0x39, 0x5a, 0x30, 0x15, 0x31, 0x13,
1224 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e,
1225 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03,
1226 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
1227 0x01, 0x05, 0x05, 0x00, 0x03, 0x41, 0x00, 0x20, 0x3b, 0xdb, 0x4d, 0x67, 0x50,
1228 0xec, 0x73, 0x9d, 0xf9, 0x85, 0x5d, 0x18, 0xe9, 0xb4, 0x98, 0xe3, 0x31, 0xb7,
1229 0x03, 0x0b, 0xc0, 0x39, 0x93, 0x56, 0x81, 0x0a, 0xfc, 0x78, 0xa8, 0x29, 0x42,
1230 0x5f, 0x69, 0xfb, 0xbc, 0x5b, 0xf2, 0xa6, 0x2a, 0xbe, 0x91, 0x2c, 0xfc, 0x89,
1231 0x69, 0x15, 0x18, 0x58, 0xe5, 0x02, 0x75, 0xf7, 0x2a, 0xb6, 0xa9, 0xfb, 0x47,
1232 0x6a, 0x6e, 0x0a, 0x9b, 0xe9, 0xdc };
1236 * A chain with two issuers, only one of whose dates is valid.
1238 static const BYTE chain10_0[] = {
1239 0x30,0x82,0x01,0x9b,0x30,0x82,0x01,0x08,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,
1240 0x4a,0x30,0x3a,0x42,0xa2,0x5a,0xb3,0x93,0x4d,0x94,0x06,0xad,0x6d,0x1c,0x34,
1241 0xe6,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x30,0x10,0x31,
1242 0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x03,0x13,0x05,0x43,0x65,0x72,0x74,0x31,
1243 0x30,0x1e,0x17,0x0d,0x30,0x36,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
1244 0x30,0x5a,0x17,0x0d,0x30,0x36,0x31,0x32,0x33,0x31,0x32,0x33,0x35,0x39,0x35,
1245 0x39,0x5a,0x30,0x10,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x03,0x13,0x05,
1246 0x43,0x65,0x72,0x74,0x31,0x30,0x81,0x9f,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
1247 0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x81,0x8d,0x00,0x30,0x81,0x89,
1248 0x02,0x81,0x81,0x00,0xad,0x7e,0xca,0xf3,0xe5,0x99,0xc2,0x2a,0xca,0x50,0x82,
1249 0x7c,0x2d,0xa4,0x81,0xcd,0x0d,0x0d,0x86,0xd7,0xd8,0xb2,0xde,0xc5,0xc3,0x34,
1250 0x9e,0x07,0x78,0x08,0x11,0x12,0x2d,0x21,0x0a,0x09,0x07,0x14,0x03,0x7a,0xe7,
1251 0x3b,0x58,0xf1,0xde,0x3e,0x01,0x25,0x93,0xab,0x8f,0xce,0x1f,0xc1,0x33,0x91,
1252 0xfe,0x59,0xb9,0x3b,0x9e,0x95,0x12,0x89,0x8e,0xc3,0x4b,0x98,0x1b,0x99,0xc5,
1253 0x07,0xe2,0xdf,0x15,0x4c,0x39,0x76,0x06,0xad,0xdb,0x16,0x06,0x49,0xba,0xcd,
1254 0x0f,0x07,0xd6,0xea,0x27,0xa6,0xfe,0x3d,0x88,0xe5,0x97,0x45,0x72,0xb6,0x1c,
1255 0xc0,0x1c,0xb1,0xa2,0x89,0xe8,0x37,0x9e,0xf6,0x2a,0xcf,0xd5,0x1f,0x2f,0x35,
1256 0x5e,0x8f,0x3a,0x9c,0x61,0xb1,0xf1,0x6c,0xff,0x8c,0xb2,0x2f,0x02,0x03,0x01,
1257 0x00,0x01,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x03,0x81,
1258 0x81,0x00,0x85,0x6e,0x35,0x2f,0x2c,0x51,0x4f,0xd6,0x2a,0xe4,0x9e,0xd0,0x4b,
1259 0xe6,0x90,0xfd,0xf7,0x20,0xad,0x76,0x3f,0x93,0xea,0x7f,0x0d,0x1f,0xb3,0x8e,
1260 0xfd,0xe0,0xe1,0xd6,0xd7,0x9c,0x7d,0x46,0x6b,0x15,0x5c,0xe6,0xc9,0x62,0x3b,
1261 0x70,0x4a,0x4b,0xb2,0x82,0xe3,0x55,0x0c,0xc4,0x90,0x44,0x06,0x6c,0x86,0x1c,
1262 0x6d,0x47,0x12,0xda,0x33,0x95,0x5d,0x98,0x43,0xcb,0x7c,0xfa,0x2b,0xee,0xc4,
1263 0x2d,0xc8,0x95,0x33,0x89,0x08,0x3f,0x9f,0x87,0xea,0x20,0x04,0xaf,0x58,0x4b,
1264 0x9d,0xc0,0x7c,0x0a,0x1b,0x05,0x31,0x3b,0xbb,0x13,0x58,0x2e,0x3f,0x61,0x6b,
1265 0x10,0xb4,0xeb,0xb9,0x1a,0x30,0xfd,0xea,0xca,0x29,0x99,0x5f,0x42,0x2b,0x00,
1266 0xb0,0x08,0xc3,0xf0,0xb6,0xd6,0x6b,0xf9,0x35,0x95 };
1267 static const BYTE chain10_1[] = {
1268 0x30,0x82,0x01,0x9b,0x30,0x82,0x01,0x08,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,
1269 0xbf,0x99,0x4f,0x14,0x03,0x77,0x44,0xb8,0x49,0x02,0x70,0xa1,0xb8,0x9c,0xa7,
1270 0x24,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x30,0x10,0x31,
1271 0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x03,0x13,0x05,0x43,0x65,0x72,0x74,0x31,
1272 0x30,0x1e,0x17,0x0d,0x30,0x37,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
1273 0x30,0x5a,0x17,0x0d,0x30,0x37,0x31,0x32,0x33,0x31,0x32,0x33,0x35,0x39,0x35,
1274 0x39,0x5a,0x30,0x10,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x03,0x13,0x05,
1275 0x43,0x65,0x72,0x74,0x31,0x30,0x81,0x9f,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
1276 0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x81,0x8d,0x00,0x30,0x81,0x89,
1277 0x02,0x81,0x81,0x00,0xad,0x7e,0xca,0xf3,0xe5,0x99,0xc2,0x2a,0xca,0x50,0x82,
1278 0x7c,0x2d,0xa4,0x81,0xcd,0x0d,0x0d,0x86,0xd7,0xd8,0xb2,0xde,0xc5,0xc3,0x34,
1279 0x9e,0x07,0x78,0x08,0x11,0x12,0x2d,0x21,0x0a,0x09,0x07,0x14,0x03,0x7a,0xe7,
1280 0x3b,0x58,0xf1,0xde,0x3e,0x01,0x25,0x93,0xab,0x8f,0xce,0x1f,0xc1,0x33,0x91,
1281 0xfe,0x59,0xb9,0x3b,0x9e,0x95,0x12,0x89,0x8e,0xc3,0x4b,0x98,0x1b,0x99,0xc5,
1282 0x07,0xe2,0xdf,0x15,0x4c,0x39,0x76,0x06,0xad,0xdb,0x16,0x06,0x49,0xba,0xcd,
1283 0x0f,0x07,0xd6,0xea,0x27,0xa6,0xfe,0x3d,0x88,0xe5,0x97,0x45,0x72,0xb6,0x1c,
1284 0xc0,0x1c,0xb1,0xa2,0x89,0xe8,0x37,0x9e,0xf6,0x2a,0xcf,0xd5,0x1f,0x2f,0x35,
1285 0x5e,0x8f,0x3a,0x9c,0x61,0xb1,0xf1,0x6c,0xff,0x8c,0xb2,0x2f,0x02,0x03,0x01,
1286 0x00,0x01,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x03,0x81,
1287 0x81,0x00,0xa8,0xec,0x8c,0x34,0xe7,0x2c,0xdf,0x75,0x87,0xc4,0xf7,0xda,0x71,
1288 0x72,0x29,0xb2,0x48,0xa8,0x2a,0xec,0x7b,0x7d,0x19,0xb9,0x5f,0x1d,0xd9,0x91,
1289 0x2b,0xc4,0x28,0x7e,0xd6,0xb5,0x91,0x69,0xa5,0x8a,0x1a,0x1f,0x97,0x98,0x46,
1290 0x9d,0xdf,0x12,0xf6,0x45,0x62,0xad,0x60,0xb6,0xba,0xb0,0xfd,0xf5,0x9f,0xc6,
1291 0x98,0x05,0x4f,0x4d,0x48,0xdc,0xee,0x69,0xbe,0xb8,0xc4,0xc4,0xd7,0x1b,0xb1,
1292 0x1f,0x64,0xd6,0x45,0xa7,0xdb,0xb3,0x87,0x63,0x0f,0x54,0xe1,0x3a,0x6b,0x57,
1293 0x36,0xd7,0x68,0x65,0xcf,0xda,0x57,0x8d,0xcd,0x84,0x75,0x47,0x26,0x2c,0xef,
1294 0x1e,0x8f,0xc7,0x3b,0xee,0x5d,0x03,0xa6,0xdf,0x3a,0x20,0xb2,0xcc,0xc9,0x09,
1295 0x2c,0xfe,0x2b,0x79,0xb0,0xca,0x2c,0x9a,0x81,0x6b };
1296 static const BYTE chain7_1[] = {
1297 0x30,0x82,0x01,0x93,0x30,0x81,0xfd,0xa0,0x03,0x02,0x01,0x02,0x02,0x01,0x01,
1298 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,
1299 0x30,0x10,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x03,0x13,0x05,0x43,0x65,
1300 0x72,0x74,0x31,0x30,0x1e,0x17,0x0d,0x30,0x37,0x30,0x31,0x30,0x31,0x30,0x30,
1301 0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,0x30,0x37,0x31,0x32,0x33,0x31,0x32,0x33,
1302 0x35,0x39,0x35,0x39,0x5a,0x30,0x10,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,
1303 0x03,0x13,0x05,0x43,0x65,0x72,0x74,0x32,0x30,0x81,0x9f,0x30,0x0d,0x06,0x09,
1304 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x81,0x8d,0x00,
1305 0x30,0x81,0x89,0x02,0x81,0x81,0x00,0xb8,0x52,0xda,0xc5,0x4b,0x3f,0xe5,0x33,
1306 0x0e,0x67,0x5f,0x48,0x21,0xdc,0x7e,0xef,0x37,0x33,0xba,0xff,0xb4,0xc6,0xdc,
1307 0xb6,0x17,0x8e,0x20,0x55,0x07,0x12,0xd2,0x7b,0x3c,0xce,0x30,0xc5,0xa7,0x48,
1308 0x9f,0x6e,0xfe,0xb8,0xbe,0xdb,0x9f,0x9b,0x17,0x60,0x16,0xde,0xc6,0x8b,0x47,
1309 0xd1,0x57,0x71,0x3c,0x93,0xfc,0xbd,0xec,0x44,0x32,0x3b,0xb9,0xcf,0x6b,0x05,
1310 0x72,0xa7,0x87,0x8e,0x7e,0xd4,0x9a,0x87,0x1c,0x2f,0xb7,0x82,0x40,0xfc,0x6a,
1311 0x80,0x83,0x68,0x28,0xce,0x84,0xf4,0x0b,0x2e,0x44,0xcb,0x53,0xac,0x85,0x85,
1312 0xb5,0x46,0x36,0x98,0x3c,0x10,0x02,0xaa,0x02,0xbc,0x8b,0xa2,0x23,0xb2,0xd3,
1313 0x51,0x9a,0x22,0x4a,0xe3,0xaa,0x4e,0x7c,0xda,0x38,0xcf,0x49,0x98,0x72,0xa3,
1314 0x02,0x03,0x01,0x00,0x01,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
1315 0x01,0x01,0x05,0x05,0x00,0x03,0x81,0x81,0x00,0x9f,0x69,0xfd,0x26,0xd5,0x4b,
1316 0xe0,0xab,0x12,0x21,0xb9,0xfc,0xf7,0xe0,0x0c,0x09,0x94,0xad,0x27,0xd7,0x9d,
1317 0xa3,0xcc,0x46,0x2a,0x25,0x9a,0x24,0xa7,0x31,0x58,0x78,0xf5,0xfc,0x30,0xe1,
1318 0x6d,0xfd,0x59,0xab,0xbe,0x69,0xa0,0xea,0xe3,0x7d,0x7a,0x7b,0xe5,0x85,0xeb,
1319 0x86,0x6a,0x84,0x3c,0x96,0x01,0x1a,0x70,0xa7,0xb8,0xcb,0xf2,0x11,0xe7,0x52,
1320 0x9c,0x58,0x2d,0xac,0x63,0xce,0x72,0x4b,0xad,0x62,0xa8,0x1d,0x75,0x96,0xe2,
1321 0x27,0xf5,0x6f,0xba,0x91,0xf8,0xf1,0xb0,0xbf,0x90,0x24,0x6d,0xba,0x5d,0xd7,
1322 0x39,0x63,0x3b,0x7c,0x04,0x5d,0x89,0x9d,0x1c,0xf2,0xf7,0xcc,0xdf,0x6e,0x8a,
1323 0x43,0xa9,0xdd,0x86,0x05,0xa2,0xf3,0x22,0x2d,0x1e,0x70,0xa1,0x59,0xd7,0xa5,
1326 static void testGetIssuerCert(void)
1329 PCCERT_CONTEXT parent, child, cert1, cert2;
1330 DWORD flags = 0xffffffff;
1331 HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1332 CERT_STORE_CREATE_NEW_FLAG, NULL);
1334 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1336 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1337 expiredCert, sizeof(expiredCert), CERT_STORE_ADD_ALWAYS, NULL);
1338 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1341 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1342 childOfExpired, sizeof(childOfExpired), CERT_STORE_ADD_ALWAYS, &child);
1343 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1347 parent = CertGetIssuerCertificateFromStore(NULL, NULL, NULL, NULL);
1348 parent = CertGetIssuerCertificateFromStore(store, NULL, NULL, NULL);
1350 parent = CertGetIssuerCertificateFromStore(NULL, NULL, NULL, &flags);
1351 ok(!parent && GetLastError() == E_INVALIDARG,
1352 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1353 parent = CertGetIssuerCertificateFromStore(store, NULL, NULL, &flags);
1354 ok(!parent && GetLastError() == E_INVALIDARG,
1355 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1356 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1357 ok(!parent && GetLastError() == E_INVALIDARG,
1358 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1359 /* Confusing: the caller cannot set either of the
1360 * CERT_STORE_NO_*_FLAGs, as these are not checks,
1363 flags = CERT_STORE_NO_CRL_FLAG | CERT_STORE_NO_ISSUER_FLAG;
1364 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1365 ok(!parent && GetLastError() == E_INVALIDARG,
1366 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1367 /* Perform no checks */
1369 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1370 ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08x\n",
1373 CertFreeCertificateContext(parent);
1374 /* Check revocation and signature only */
1375 flags = CERT_STORE_REVOCATION_FLAG | CERT_STORE_SIGNATURE_FLAG;
1376 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1377 ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08x\n",
1379 /* Confusing: CERT_STORE_REVOCATION_FLAG succeeds when there is no CRL by
1380 * setting CERT_STORE_NO_CRL_FLAG.
1382 ok(flags == (CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG),
1383 "Expected CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG, got %08x\n",
1386 CertFreeCertificateContext(parent);
1387 /* Checking time validity is not productive, because while most Windows
1388 * versions return 0 (time valid) because the child is not expired,
1389 * Windows 2003 SP1 returns that it is expired. Thus the range of
1390 * possibilities is covered, and a test verifies nothing.
1393 CertFreeCertificateContext(child);
1394 CertCloseStore(store, 0);
1397 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1398 CERT_STORE_CREATE_NEW_FLAG, NULL);
1399 /* With only the child certificate, no issuer will be found */
1400 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1401 chain7_1, sizeof(chain7_1), CERT_STORE_ADD_ALWAYS, &child);
1402 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1403 ok(parent == NULL, "Expected no issuer\n");
1404 /* Adding an issuer allows one (and only one) issuer to be found */
1405 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1406 chain10_1, sizeof(chain10_1), CERT_STORE_ADD_ALWAYS, &cert1);
1407 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1408 ok(parent == cert1, "Expected cert1 to be the issuer\n");
1409 parent = CertGetIssuerCertificateFromStore(store, child, parent, &flags);
1410 ok(parent == NULL, "Expected only one issuer\n");
1411 /* Adding a second issuer allows two issuers to be found - and the second
1412 * issuer is found before the first, implying certs are added to the head
1415 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1416 chain10_0, sizeof(chain10_0), CERT_STORE_ADD_ALWAYS, &cert2);
1417 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1418 ok(parent == cert2, "Expected cert2 to be the first issuer\n");
1419 parent = CertGetIssuerCertificateFromStore(store, child, parent, &flags);
1420 ok(parent == cert1, "Expected cert1 to be the second issuer\n");
1421 parent = CertGetIssuerCertificateFromStore(store, child, parent, &flags);
1422 ok(parent == NULL, "Expected no more than two issuers\n");
1423 CertFreeCertificateContext(child);
1424 CertFreeCertificateContext(cert1);
1425 CertFreeCertificateContext(cert2);
1426 CertCloseStore(store, 0);
1428 /* Repeat the test, reversing the order in which issuers are added,
1429 * to show it's order-dependent.
1431 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1432 CERT_STORE_CREATE_NEW_FLAG, NULL);
1433 /* With only the child certificate, no issuer will be found */
1434 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1435 chain7_1, sizeof(chain7_1), CERT_STORE_ADD_ALWAYS, &child);
1436 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1437 ok(parent == NULL, "Expected no issuer\n");
1438 /* Adding an issuer allows one (and only one) issuer to be found */
1439 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1440 chain10_0, sizeof(chain10_0), CERT_STORE_ADD_ALWAYS, &cert1);
1441 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1442 ok(parent == cert1, "Expected cert1 to be the issuer\n");
1443 parent = CertGetIssuerCertificateFromStore(store, child, parent, &flags);
1444 ok(parent == NULL, "Expected only one issuer\n");
1445 /* Adding a second issuer allows two issuers to be found - and the second
1446 * issuer is found before the first, implying certs are added to the head
1449 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1450 chain10_1, sizeof(chain10_1), CERT_STORE_ADD_ALWAYS, &cert2);
1451 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1452 ok(parent == cert2, "Expected cert2 to be the first issuer\n");
1453 parent = CertGetIssuerCertificateFromStore(store, child, parent, &flags);
1454 ok(parent == cert1, "Expected cert1 to be the second issuer\n");
1455 parent = CertGetIssuerCertificateFromStore(store, child, parent, &flags);
1456 ok(parent == NULL, "Expected no more than two issuers\n");
1457 CertFreeCertificateContext(child);
1458 CertFreeCertificateContext(cert1);
1459 CertFreeCertificateContext(cert2);
1460 CertCloseStore(store, 0);
1463 static void testCryptHashCert(void)
1465 static const BYTE emptyHash[] = { 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b,
1466 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07,
1468 static const BYTE knownHash[] = { 0xae, 0x9d, 0xbf, 0x6d, 0xf5, 0x46, 0xee,
1469 0x8b, 0xc5, 0x7a, 0x13, 0xba, 0xc2, 0xb1, 0x04, 0xf2, 0xbf, 0x52, 0xa8,
1471 static const BYTE toHash[] = "abcdefghijklmnopqrstuvwxyz0123456789.,;!?:";
1474 DWORD hashLen = sizeof(hash);
1476 /* NULL buffer and nonzero length crashes
1477 ret = CryptHashCertificate(0, 0, 0, NULL, size, hash, &hashLen);
1478 empty hash length also crashes
1479 ret = CryptHashCertificate(0, 0, 0, buf, size, hash, NULL);
1481 /* Test empty hash */
1482 ret = CryptHashCertificate(0, 0, 0, toHash, sizeof(toHash), NULL,
1484 ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
1485 ok(hashLen == sizeof(hash), "Got unexpected size of hash %d\n", hashLen);
1486 /* Test with empty buffer */
1487 ret = CryptHashCertificate(0, 0, 0, NULL, 0, hash, &hashLen);
1488 ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
1489 ok(!memcmp(hash, emptyHash, sizeof(emptyHash)),
1490 "Unexpected hash of nothing\n");
1491 /* Test a known value */
1492 ret = CryptHashCertificate(0, 0, 0, toHash, sizeof(toHash), hash,
1494 ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
1495 ok(!memcmp(hash, knownHash, sizeof(knownHash)), "Unexpected hash\n");
1498 static void verifySig(HCRYPTPROV csp, const BYTE *toSign, size_t toSignLen,
1499 const BYTE *sig, unsigned int sigLen)
1502 BOOL ret = CryptCreateHash(csp, CALG_SHA1, 0, 0, &hash);
1504 ok(ret, "CryptCreateHash failed: %08x\n", GetLastError());
1508 DWORD mySigSize = sizeof(mySig);
1510 ret = CryptHashData(hash, toSign, toSignLen, 0);
1511 ok(ret, "CryptHashData failed: %08x\n", GetLastError());
1512 /* use the A variant so the test can run on Win9x */
1513 ret = CryptSignHashA(hash, AT_SIGNATURE, NULL, 0, mySig, &mySigSize);
1514 ok(ret, "CryptSignHash failed: %08x\n", GetLastError());
1517 ok(mySigSize == sigLen, "Expected sig length %d, got %d\n",
1519 ok(!memcmp(mySig, sig, sigLen), "Unexpected signature\n");
1521 CryptDestroyHash(hash);
1525 /* Tests signing the certificate described by toBeSigned with the CSP passed in,
1526 * using the algorithm with OID sigOID. The CSP is assumed to be empty, and a
1527 * keyset named AT_SIGNATURE will be added to it. The signing key will be
1528 * stored in *key, and the signature will be stored in sig. sigLen should be
1529 * at least 64 bytes.
1531 static void testSignCert(HCRYPTPROV csp, const CRYPT_DATA_BLOB *toBeSigned,
1532 LPCSTR sigOID, HCRYPTKEY *key, BYTE *sig, DWORD *sigLen)
1536 CRYPT_ALGORITHM_IDENTIFIER algoID = { NULL, { 0, NULL } };
1539 ret = CryptSignCertificate(0, 0, 0, NULL, 0, NULL, NULL, NULL, NULL);
1540 ret = CryptSignCertificate(0, 0, 0, NULL, 0, NULL, NULL, NULL, &size);
1541 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
1542 NULL, NULL, NULL, &size);
1544 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
1545 &algoID, NULL, NULL, &size);
1546 ok(!ret && GetLastError() == NTE_BAD_ALGID,
1547 "Expected NTE_BAD_ALGID, got %08x\n", GetLastError());
1548 algoID.pszObjId = (LPSTR)sigOID;
1549 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
1550 &algoID, NULL, NULL, &size);
1551 ok(!ret && (GetLastError() == ERROR_INVALID_PARAMETER || NTE_BAD_ALGID),
1552 "Expected ERROR_INVALID_PARAMETER or NTE_BAD_ALGID, got %08x\n",
1554 ret = CryptSignCertificate(0, AT_SIGNATURE, 0, toBeSigned->pbData,
1555 toBeSigned->cbData, &algoID, NULL, NULL, &size);
1556 ok(!ret && (GetLastError() == ERROR_INVALID_PARAMETER || NTE_BAD_ALGID),
1557 "Expected ERROR_INVALID_PARAMETER or NTE_BAD_ALGID, got %08x\n",
1560 /* No keys exist in the new CSP yet.. */
1561 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
1562 toBeSigned->cbData, &algoID, NULL, NULL, &size);
1563 ok(!ret && (GetLastError() == NTE_BAD_KEYSET || GetLastError() ==
1564 NTE_NO_KEY), "Expected NTE_BAD_KEYSET or NTE_NO_KEY, got %08x\n",
1566 ret = CryptGenKey(csp, AT_SIGNATURE, 0, key);
1567 ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
1570 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
1571 toBeSigned->cbData, &algoID, NULL, NULL, &size);
1572 ok(ret, "CryptSignCertificate failed: %08x\n", GetLastError());
1573 ok(size <= *sigLen, "Expected size <= %d, got %d\n", *sigLen, size);
1576 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
1577 toBeSigned->cbData, &algoID, NULL, sig, &size);
1578 ok(ret, "CryptSignCertificate failed: %08x\n", GetLastError());
1582 verifySig(csp, toBeSigned->pbData, toBeSigned->cbData, sig,
1589 static void testVerifyCertSig(HCRYPTPROV csp, const CRYPT_DATA_BLOB *toBeSigned,
1590 LPCSTR sigOID, const BYTE *sig, DWORD sigLen)
1592 CERT_SIGNED_CONTENT_INFO info;
1597 if (!pCryptVerifyCertificateSignatureEx)
1599 skip("no CryptVerifyCertificateSignatureEx support\n");
1602 if (!pCryptEncodeObjectEx)
1604 skip("no CryptEncodeObjectEx support\n");
1607 ret = pCryptVerifyCertificateSignatureEx(0, 0, 0, NULL, 0, NULL, 0, NULL);
1608 ok(!ret && GetLastError() == E_INVALIDARG,
1609 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1610 ret = pCryptVerifyCertificateSignatureEx(csp, 0, 0, NULL, 0, NULL, 0, NULL);
1611 ok(!ret && GetLastError() == E_INVALIDARG,
1612 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1613 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING, 0, NULL, 0,
1615 ok(!ret && GetLastError() == E_INVALIDARG,
1616 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1618 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1619 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, NULL, 0, NULL, 0, NULL);
1621 info.ToBeSigned.cbData = toBeSigned->cbData;
1622 info.ToBeSigned.pbData = toBeSigned->pbData;
1623 info.SignatureAlgorithm.pszObjId = (LPSTR)sigOID;
1624 info.SignatureAlgorithm.Parameters.cbData = 0;
1625 info.Signature.cbData = sigLen;
1626 info.Signature.pbData = (BYTE *)sig;
1627 info.Signature.cUnusedBits = 0;
1628 ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, X509_CERT, &info,
1629 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&cert, &size);
1630 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1633 CRYPT_DATA_BLOB certBlob = { 0, NULL };
1634 PCERT_PUBLIC_KEY_INFO pubKeyInfo = NULL;
1636 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1637 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
1638 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
1639 "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
1640 certBlob.cbData = 1;
1641 certBlob.pbData = (void *)0xdeadbeef;
1642 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1643 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
1644 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1645 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1646 certBlob.cbData = size;
1647 certBlob.pbData = cert;
1648 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1649 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
1650 ok(!ret && GetLastError() == E_INVALIDARG,
1651 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1652 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1653 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
1654 CRYPT_VERIFY_CERT_SIGN_ISSUER_NULL, NULL, 0, NULL);
1655 ok(!ret && GetLastError() == E_INVALIDARG,
1656 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1658 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1659 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
1660 CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY, NULL, 0, NULL);
1662 CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
1663 (LPSTR)sigOID, 0, NULL, NULL, &size);
1664 pubKeyInfo = HeapAlloc(GetProcessHeap(), 0, size);
1667 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
1668 X509_ASN_ENCODING, (LPSTR)sigOID, 0, NULL, pubKeyInfo, &size);
1669 ok(ret, "CryptExportKey failed: %08x\n", GetLastError());
1672 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1673 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
1674 CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY, pubKeyInfo, 0, NULL);
1675 ok(ret, "CryptVerifyCertificateSignatureEx failed: %08x\n",
1678 HeapFree(GetProcessHeap(), 0, pubKeyInfo);
1684 static BYTE emptyCert[] = { 0x30, 0x00 };
1686 static void testCertSigs(void)
1689 CRYPT_DATA_BLOB toBeSigned = { sizeof(emptyCert), emptyCert };
1693 DWORD sigSize = sizeof(sig);
1695 /* Just in case a previous run failed, delete this thing */
1696 pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1697 CRYPT_DELETEKEYSET);
1698 ret = pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1700 ok(ret, "CryptAcquireContext failed: %08x\n", GetLastError());
1702 testSignCert(csp, &toBeSigned, szOID_RSA_SHA1RSA, &key, sig, &sigSize);
1703 testVerifyCertSig(csp, &toBeSigned, szOID_RSA_SHA1RSA, sig, sigSize);
1705 CryptDestroyKey(key);
1706 CryptReleaseContext(csp, 0);
1707 ret = pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1708 CRYPT_DELETEKEYSET);
1711 static const BYTE md5SignedEmptyCert[] = {
1712 0x30,0x56,0x30,0x33,0x02,0x00,0x30,0x02,0x06,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,
1713 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,
1714 0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x07,
1715 0x30,0x02,0x06,0x00,0x03,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,
1716 0x0d,0x02,0x05,0x05,0x00,0x03,0x11,0x00,0xfb,0x0f,0x66,0x82,0x66,0xd9,0xe5,0xf8,
1717 0xd8,0xa2,0x55,0x2b,0xe1,0xa5,0xd9,0x04 };
1718 static const BYTE md5SignedEmptyCertNoNull[] = {
1719 0x30,0x54,0x30,0x33,0x02,0x00,0x30,0x02,0x06,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,
1720 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,
1721 0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x07,
1722 0x30,0x02,0x06,0x00,0x03,0x01,0x00,0x30,0x0a,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,
1723 0x0d,0x02,0x05,0x03,0x11,0x00,0x04,0xd9,0xa5,0xe1,0x2b,0x55,0xa2,0xd8,0xf8,0xe5,
1724 0xd9,0x66,0x82,0x66,0x0f,0xfb };
1726 static void testSignAndEncodeCert(void)
1728 static char oid_rsa_md5rsa[] = szOID_RSA_MD5RSA;
1729 static char oid_rsa_md5[] = szOID_RSA_MD5;
1732 CRYPT_ALGORITHM_IDENTIFIER algID = { 0 };
1733 CERT_INFO info = { 0 };
1736 ret = CryptSignAndEncodeCertificate(0, 0, 0, NULL, NULL, NULL, NULL, NULL,
1738 ret = CryptSignAndEncodeCertificate(0, 0, 0, NULL, NULL, NULL, NULL, NULL,
1741 ret = CryptSignAndEncodeCertificate(0, 0, 0, NULL, NULL, &algID, NULL, NULL,
1743 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1744 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1745 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING, NULL, 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, 0, X509_CERT_TO_BE_SIGNED, NULL,
1750 &algID, NULL, NULL, &size);
1751 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1752 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1753 /* Crashes on some win9x boxes */
1756 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1757 X509_CERT_TO_BE_SIGNED, NULL, &algID, NULL, NULL, &size);
1758 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1759 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1762 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1763 X509_CERT_TO_BE_SIGNED, &info, NULL, NULL, NULL, &size);
1765 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1766 X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, NULL, &size);
1767 ok(!ret && GetLastError() == NTE_BAD_ALGID,
1768 "Expected NTE_BAD_ALGID, got %08x\n", GetLastError());
1769 algID.pszObjId = oid_rsa_md5rsa;
1770 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1771 X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, NULL, &size);
1772 ok(!ret && (GetLastError() == ERROR_INVALID_PARAMETER || NTE_BAD_ALGID),
1773 "Expected ERROR_INVALID_PARAMETER or NTE_BAD_ALGID, got %08x\n",
1775 algID.pszObjId = oid_rsa_md5;
1776 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1777 X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, NULL, &size);
1778 /* oid_rsa_md5 not present in some win2k */
1781 LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, size);
1785 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1786 X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, buf, &size);
1787 ok(ret, "CryptSignAndEncodeCertificate failed: %08x\n",
1789 /* Tricky: because the NULL parameters may either be omitted or
1790 * included as an asn.1-encoded NULL (0x05,0x00), two different
1791 * values are allowed.
1793 ok(size == sizeof(md5SignedEmptyCert) ||
1794 size == sizeof(md5SignedEmptyCertNoNull), "Unexpected size %d\n",
1796 if (size == sizeof(md5SignedEmptyCert))
1797 ok(!memcmp(buf, md5SignedEmptyCert, size),
1798 "Unexpected value\n");
1799 else if (size == sizeof(md5SignedEmptyCertNoNull))
1800 ok(!memcmp(buf, md5SignedEmptyCertNoNull, size),
1801 "Unexpected value\n");
1802 HeapFree(GetProcessHeap(), 0, buf);
1807 static void testCreateSelfSignCert(void)
1809 PCCERT_CONTEXT context;
1810 CERT_NAME_BLOB name = { sizeof(subjectName), subjectName };
1814 CRYPT_KEY_PROV_INFO info;
1816 if (!pCertCreateSelfSignCertificate)
1818 skip("CertCreateSelfSignCertificate() is not available\n");
1823 context = pCertCreateSelfSignCertificate(0, NULL, 0, NULL, NULL, NULL, NULL,
1825 * Calling this with no first parameter creates a new key container, which
1826 * lasts beyond the test, so I don't test that. Nb: the generated key
1828 context = pCertCreateSelfSignCertificate(0, &name, 0, NULL, NULL, NULL, NULL,
1833 pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1834 CRYPT_DELETEKEYSET);
1835 ret = pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1837 ok(ret, "CryptAcquireContext failed: %08x\n", GetLastError());
1839 context = pCertCreateSelfSignCertificate(csp, &name, 0, NULL, NULL, NULL,
1841 ok(!context && GetLastError() == NTE_NO_KEY,
1842 "Expected NTE_NO_KEY, got %08x\n", GetLastError());
1843 ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
1844 ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
1847 context = pCertCreateSelfSignCertificate(csp, &name, 0, NULL, NULL, NULL,
1849 ok(context != NULL, "CertCreateSelfSignCertificate failed: %08x\n",
1854 PCRYPT_KEY_PROV_INFO info;
1856 /* The context must have a key provider info property */
1857 ret = CertGetCertificateContextProperty(context,
1858 CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
1859 ok(ret && size, "Expected non-zero key provider info\n");
1862 info = HeapAlloc(GetProcessHeap(), 0, size);
1865 ret = CertGetCertificateContextProperty(context,
1866 CERT_KEY_PROV_INFO_PROP_ID, info, &size);
1867 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
1871 /* Sanity-check the key provider */
1872 ok(!lstrcmpW(info->pwszContainerName, cspNameW),
1873 "Unexpected key container\n");
1874 ok(!lstrcmpW(info->pwszProvName, MS_DEF_PROV_W),
1875 "Unexpected provider\n");
1876 ok(info->dwKeySpec == AT_SIGNATURE,
1877 "Expected AT_SIGNATURE, got %d\n", info->dwKeySpec);
1879 HeapFree(GetProcessHeap(), 0, info);
1883 CertFreeCertificateContext(context);
1886 CryptDestroyKey(key);
1889 CryptReleaseContext(csp, 0);
1890 ret = pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1891 CRYPT_DELETEKEYSET);
1893 /* do the same test with AT_KEYEXCHANGE and key info*/
1894 memset(&info,0,sizeof(info));
1895 info.dwProvType = PROV_RSA_FULL;
1896 info.dwKeySpec = AT_KEYEXCHANGE;
1897 info.pwszProvName = (LPWSTR) MS_DEF_PROV_W;
1898 info.pwszContainerName = cspNameW;
1899 context = pCertCreateSelfSignCertificate(0, &name, 0, &info, NULL, NULL,
1901 ok(context != NULL, "CertCreateSelfSignCertificate failed: %08x\n",
1906 PCRYPT_KEY_PROV_INFO info;
1908 /* The context must have a key provider info property */
1909 ret = CertGetCertificateContextProperty(context,
1910 CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
1911 ok(ret && size, "Expected non-zero key provider info\n");
1914 info = HeapAlloc(GetProcessHeap(), 0, size);
1917 ret = CertGetCertificateContextProperty(context,
1918 CERT_KEY_PROV_INFO_PROP_ID, info, &size);
1919 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
1923 /* Sanity-check the key provider */
1924 ok(!lstrcmpW(info->pwszContainerName, cspNameW),
1925 "Unexpected key container\n");
1926 ok(!lstrcmpW(info->pwszProvName, MS_DEF_PROV_W),
1927 "Unexpected provider\n");
1928 ok(info->dwKeySpec == AT_KEYEXCHANGE,
1929 "Expected AT_KEYEXCHANGE, got %d\n", info->dwKeySpec);
1931 HeapFree(GetProcessHeap(), 0, info);
1935 CertFreeCertificateContext(context);
1938 pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1939 CRYPT_DELETEKEYSET);
1942 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
1943 szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
1945 static void testKeyUsage(void)
1948 PCCERT_CONTEXT context;
1951 /* Test base cases */
1952 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, NULL);
1953 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1954 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1956 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, &size);
1957 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1958 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1960 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, &size);
1961 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1962 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1964 ret = CertSetEnhancedKeyUsage(NULL, NULL);
1965 usage.cUsageIdentifier = 0;
1966 ret = CertSetEnhancedKeyUsage(NULL, &usage);
1968 /* Test with a cert with no enhanced key usage extension */
1969 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
1971 ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
1975 static const char oid[] = "1.2.3.4";
1976 BYTE buf[sizeof(CERT_ENHKEY_USAGE) + 2 * (sizeof(LPSTR) + sizeof(oid))];
1977 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1979 ret = CertGetEnhancedKeyUsage(context, 0, NULL, NULL);
1980 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1981 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1983 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &size);
1986 /* Windows 2000, ME, or later: even though it succeeded, we expect
1987 * CRYPT_E_NOT_FOUND, which indicates there is no enhanced key
1988 * usage set for this cert (which implies it's valid for all uses.)
1990 ok(GetLastError() == CRYPT_E_NOT_FOUND,
1991 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1992 ok(size == sizeof(CERT_ENHKEY_USAGE), "Wrong size %d\n", size);
1993 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1994 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1995 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %d\n",
1996 pUsage->cUsageIdentifier);
2000 /* Windows NT, 95, or 98: it fails, and the last error is
2001 * CRYPT_E_NOT_FOUND.
2003 ok(GetLastError() == CRYPT_E_NOT_FOUND,
2004 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
2006 /* I can add a usage identifier when no key usage has been set */
2007 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
2008 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
2011 ret = CertGetEnhancedKeyUsage(context,
2012 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
2013 ok(ret && GetLastError() == 0,
2014 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2015 ok(pUsage->cUsageIdentifier == 1, "Expected 1 usage, got %d\n",
2016 pUsage->cUsageIdentifier);
2017 if (pUsage->cUsageIdentifier)
2018 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
2019 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
2020 /* Now set an empty key usage */
2021 pUsage->cUsageIdentifier = 0;
2022 ret = CertSetEnhancedKeyUsage(context, pUsage);
2023 ok(ret, "CertSetEnhancedKeyUsage failed: %08x\n", GetLastError());
2024 /* Shouldn't find it in the cert */
2026 ret = CertGetEnhancedKeyUsage(context,
2027 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
2028 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
2029 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
2030 /* Should find it as an extended property */
2031 ret = CertGetEnhancedKeyUsage(context,
2032 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
2033 ok(ret && GetLastError() == 0,
2034 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2035 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %d\n",
2036 pUsage->cUsageIdentifier);
2037 /* Should find it as either */
2038 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2039 ok(ret && GetLastError() == 0,
2040 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2041 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %d\n",
2042 pUsage->cUsageIdentifier);
2043 /* Add a usage identifier */
2044 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
2045 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
2048 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2049 ok(ret && GetLastError() == 0,
2050 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2051 ok(pUsage->cUsageIdentifier == 1, "Expected 1 identifier, got %d\n",
2052 pUsage->cUsageIdentifier);
2053 if (pUsage->cUsageIdentifier)
2054 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
2055 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
2056 /* Re-adding the same usage identifier succeeds, though it only adds
2057 * a duplicate usage identifier on versions prior to Vista
2059 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
2060 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
2063 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2064 ok(ret && GetLastError() == 0,
2065 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2066 ok(pUsage->cUsageIdentifier == 1 || pUsage->cUsageIdentifier == 2,
2067 "Expected 1 or 2 identifiers, got %d\n", pUsage->cUsageIdentifier);
2068 if (pUsage->cUsageIdentifier)
2069 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
2070 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
2071 if (pUsage->cUsageIdentifier >= 2)
2072 ok(!strcmp(pUsage->rgpszUsageIdentifier[1], oid),
2073 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[1]);
2074 /* Now set a NULL extended property--this deletes the property. */
2075 ret = CertSetEnhancedKeyUsage(context, NULL);
2076 ok(ret, "CertSetEnhancedKeyUsage failed: %08x\n", GetLastError());
2077 SetLastError(0xbaadcafe);
2079 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2080 ok(GetLastError() == CRYPT_E_NOT_FOUND,
2081 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
2083 CertFreeCertificateContext(context);
2085 /* Now test with a cert with an enhanced key usage extension */
2086 context = CertCreateCertificateContext(X509_ASN_ENCODING, certWithUsage,
2087 sizeof(certWithUsage));
2088 ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
2093 DWORD bufSize = 0, i;
2095 /* The size may depend on what flags are used to query it, so I
2096 * realloc the buffer for each test.
2098 ret = CertGetEnhancedKeyUsage(context,
2099 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, NULL, &bufSize);
2100 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2101 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
2104 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
2106 /* Should find it in the cert */
2108 ret = CertGetEnhancedKeyUsage(context,
2109 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
2110 ok(ret && GetLastError() == 0,
2111 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2112 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
2113 pUsage->cUsageIdentifier);
2114 for (i = 0; i < pUsage->cUsageIdentifier; i++)
2115 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
2116 "Expected %s, got %s\n", keyUsages[i],
2117 pUsage->rgpszUsageIdentifier[i]);
2118 HeapFree(GetProcessHeap(), 0, buf);
2120 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
2121 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2122 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
2125 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
2127 /* Should find it as either */
2129 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2130 /* In Windows, GetLastError returns CRYPT_E_NOT_FOUND not found
2131 * here, even though the return is successful and the usage id
2132 * count is positive. I don't enforce that here.
2135 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2136 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
2137 pUsage->cUsageIdentifier);
2138 for (i = 0; i < pUsage->cUsageIdentifier; i++)
2139 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
2140 "Expected %s, got %s\n", keyUsages[i],
2141 pUsage->rgpszUsageIdentifier[i]);
2142 HeapFree(GetProcessHeap(), 0, buf);
2144 /* Shouldn't find it as an extended property */
2145 ret = CertGetEnhancedKeyUsage(context,
2146 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, NULL, &size);
2147 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
2148 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
2149 /* Adding a usage identifier overrides the cert's usage!? */
2150 ret = CertAddEnhancedKeyUsageIdentifier(context, szOID_RSA_RSA);
2151 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
2153 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
2154 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2155 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
2158 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
2160 /* Should find it as either */
2162 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2164 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2165 ok(pUsage->cUsageIdentifier == 1, "Expected 1 usage, got %d\n",
2166 pUsage->cUsageIdentifier);
2167 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], szOID_RSA_RSA),
2168 "Expected %s, got %s\n", szOID_RSA_RSA,
2169 pUsage->rgpszUsageIdentifier[0]);
2170 HeapFree(GetProcessHeap(), 0, buf);
2172 /* But querying the cert directly returns its usage */
2173 ret = CertGetEnhancedKeyUsage(context,
2174 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, NULL, &bufSize);
2175 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2176 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
2179 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
2182 ret = CertGetEnhancedKeyUsage(context,
2183 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
2185 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2186 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
2187 pUsage->cUsageIdentifier);
2188 for (i = 0; i < pUsage->cUsageIdentifier; i++)
2189 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
2190 "Expected %s, got %s\n", keyUsages[i],
2191 pUsage->rgpszUsageIdentifier[i]);
2192 HeapFree(GetProcessHeap(), 0, buf);
2194 /* And removing the only usage identifier in the extended property
2195 * results in the cert's key usage being found.
2197 ret = CertRemoveEnhancedKeyUsageIdentifier(context, szOID_RSA_RSA);
2198 ok(ret, "CertRemoveEnhancedKeyUsage failed: %08x\n", GetLastError());
2199 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
2200 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2201 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
2204 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
2206 /* Should find it as either */
2208 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2210 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2211 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
2212 pUsage->cUsageIdentifier);
2213 for (i = 0; i < pUsage->cUsageIdentifier; i++)
2214 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
2215 "Expected %s, got %s\n", keyUsages[i],
2216 pUsage->rgpszUsageIdentifier[i]);
2217 HeapFree(GetProcessHeap(), 0, buf);
2220 CertFreeCertificateContext(context);
2224 static const BYTE cert2WithUsage[] = {
2225 0x30,0x81,0x89,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2226 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2227 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2228 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2229 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2230 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2231 0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x25,0x30,0x23,
2232 0x30,0x21,0x06,0x03,0x55,0x1d,0x25,0x01,0x01,0xff,0x04,0x17,0x30,0x15,0x06,
2233 0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x03,0x02,0x06,0x09,0x2a,0x86,0x48,0x86,
2234 0xf7,0x0d,0x01,0x01,0x01 };
2236 static void testGetValidUsages(void)
2238 static const LPCSTR expectedOIDs[] = {
2239 "1.3.6.1.5.5.7.3.3",
2240 "1.3.6.1.5.5.7.3.2",
2241 "1.2.840.113549.1.1.1",
2243 static const LPCSTR expectedOIDs2[] = {
2244 "1.3.6.1.5.5.7.3.2",
2245 "1.2.840.113549.1.1.1",
2251 PCCERT_CONTEXT contexts[3];
2253 if (!pCertGetValidUsages)
2255 skip("CertGetValidUsages() is not available\n");
2260 ret = pCertGetValidUsages(0, NULL, NULL, NULL, NULL);
2261 ret = pCertGetValidUsages(0, NULL, NULL, NULL, &size);
2264 numOIDs = size = 0xdeadbeef;
2265 SetLastError(0xdeadbeef);
2266 ret = pCertGetValidUsages(1, &contexts[0], &numOIDs, NULL, &size);
2267 ok(ret, "CertGetValidUsages failed: %d\n", GetLastError());
2268 ok(numOIDs == -1, "Expected -1, got %d\n", numOIDs);
2269 ok(size == 0, "Expected size 0, got %d\n", size);
2270 contexts[0] = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
2272 contexts[1] = CertCreateCertificateContext(X509_ASN_ENCODING, certWithUsage,
2273 sizeof(certWithUsage));
2274 contexts[2] = CertCreateCertificateContext(X509_ASN_ENCODING,
2275 cert2WithUsage, sizeof(cert2WithUsage));
2276 numOIDs = size = 0xdeadbeef;
2277 ret = pCertGetValidUsages(0, NULL, &numOIDs, NULL, &size);
2278 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2279 ok(numOIDs == -1, "Expected -1, got %d\n", numOIDs);
2280 ok(size == 0, "Expected size 0, got %d\n", size);
2281 numOIDs = size = 0xdeadbeef;
2282 ret = pCertGetValidUsages(1, contexts, &numOIDs, NULL, &size);
2283 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2284 ok(numOIDs == -1, "Expected -1, got %d\n", numOIDs);
2285 ok(size == 0, "Expected size 0, got %d\n", size);
2286 ret = pCertGetValidUsages(1, &contexts[1], &numOIDs, NULL, &size);
2287 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2288 ok(numOIDs == 3, "Expected 3, got %d\n", numOIDs);
2289 ok(size, "Expected non-zero size\n");
2290 oids = HeapAlloc(GetProcessHeap(), 0, size);
2294 DWORD smallSize = 1;
2296 SetLastError(0xdeadbeef);
2297 ret = pCertGetValidUsages(1, &contexts[1], &numOIDs, oids, &smallSize);
2298 ok(!ret && GetLastError() == ERROR_MORE_DATA,
2299 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
2300 ret = pCertGetValidUsages(1, &contexts[1], &numOIDs, oids, &size);
2301 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2302 for (i = 0; i < numOIDs; i++)
2303 ok(!lstrcmpA(oids[i], expectedOIDs[i]), "unexpected OID %s\n",
2305 HeapFree(GetProcessHeap(), 0, oids);
2307 numOIDs = size = 0xdeadbeef;
2308 /* Oddly enough, this crashes when the number of contexts is not 1:
2309 ret = pCertGetValidUsages(2, contexts, &numOIDs, NULL, &size);
2310 * but setting size to 0 allows it to succeed:
2313 ret = pCertGetValidUsages(2, contexts, &numOIDs, NULL, &size);
2314 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2315 ok(numOIDs == 3, "Expected 3, got %d\n", numOIDs);
2316 ok(size, "Expected non-zero size\n");
2317 oids = HeapAlloc(GetProcessHeap(), 0, size);
2322 ret = pCertGetValidUsages(1, &contexts[1], &numOIDs, oids, &size);
2323 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2324 for (i = 0; i < numOIDs; i++)
2325 ok(!lstrcmpA(oids[i], expectedOIDs[i]), "unexpected OID %s\n",
2327 HeapFree(GetProcessHeap(), 0, oids);
2329 numOIDs = 0xdeadbeef;
2331 ret = pCertGetValidUsages(1, &contexts[2], &numOIDs, NULL, &size);
2332 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2333 ok(numOIDs == 2, "Expected 2, got %d\n", numOIDs);
2334 ok(size, "Expected non-zero size\n");
2335 oids = HeapAlloc(GetProcessHeap(), 0, size);
2340 ret = pCertGetValidUsages(1, &contexts[2], &numOIDs, oids, &size);
2341 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2342 for (i = 0; i < numOIDs; i++)
2343 ok(!lstrcmpA(oids[i], expectedOIDs2[i]), "unexpected OID %s\n",
2345 HeapFree(GetProcessHeap(), 0, oids);
2347 numOIDs = 0xdeadbeef;
2349 ret = pCertGetValidUsages(3, contexts, &numOIDs, NULL, &size);
2350 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2351 ok(numOIDs == 2, "Expected 2, got %d\n", numOIDs);
2352 ok(size, "Expected non-zero size\n");
2353 oids = HeapAlloc(GetProcessHeap(), 0, size);
2358 ret = pCertGetValidUsages(3, contexts, &numOIDs, oids, &size);
2359 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2360 for (i = 0; i < numOIDs; i++)
2361 ok(!lstrcmpA(oids[i], expectedOIDs2[i]), "unexpected OID %s\n",
2363 HeapFree(GetProcessHeap(), 0, oids);
2365 CertFreeCertificateContext(contexts[0]);
2366 CertFreeCertificateContext(contexts[1]);
2367 CertFreeCertificateContext(contexts[2]);
2370 static void testCompareCertName(void)
2372 static BYTE bogus[] = { 1, 2, 3, 4 };
2373 static BYTE bogusPrime[] = { 0, 1, 2, 3, 4 };
2374 static BYTE emptyPrime[] = { 0x30, 0x00, 0x01 };
2376 CERT_NAME_BLOB blob1, blob2;
2379 ret = CertCompareCertificateName(0, NULL, NULL);
2381 /* An empty name checks against itself.. */
2382 blob1.pbData = emptyCert;
2383 blob1.cbData = sizeof(emptyCert);
2384 ret = CertCompareCertificateName(0, &blob1, &blob1);
2385 ok(ret, "CertCompareCertificateName failed: %08x\n", GetLastError());
2386 /* It doesn't have to be a valid encoded name.. */
2387 blob1.pbData = bogus;
2388 blob1.cbData = sizeof(bogus);
2389 ret = CertCompareCertificateName(0, &blob1, &blob1);
2390 ok(ret, "CertCompareCertificateName failed: %08x\n", GetLastError());
2391 /* Leading zeroes matter.. */
2392 blob2.pbData = bogusPrime;
2393 blob2.cbData = sizeof(bogusPrime);
2394 ret = CertCompareCertificateName(0, &blob1, &blob2);
2395 ok(!ret, "Expected failure\n");
2396 /* As do trailing extra bytes. */
2397 blob2.pbData = emptyPrime;
2398 blob2.cbData = sizeof(emptyPrime);
2399 ret = CertCompareCertificateName(0, &blob1, &blob2);
2400 ok(!ret, "Expected failure\n");
2403 static BYTE int1[] = { 0x88, 0xff, 0xff, 0xff };
2404 static BYTE int2[] = { 0x88, 0xff };
2405 static BYTE int3[] = { 0x23, 0xff };
2406 static BYTE int4[] = { 0x7f, 0x00 };
2407 static BYTE int5[] = { 0x7f };
2408 static BYTE int6[] = { 0x80, 0x00, 0x00, 0x00 };
2409 static BYTE int7[] = { 0x80, 0x00 };
2411 static struct IntBlobTest
2413 CRYPT_INTEGER_BLOB blob1;
2414 CRYPT_INTEGER_BLOB blob2;
2417 { { sizeof(int1), int1 }, { sizeof(int2), int2 }, TRUE },
2418 { { sizeof(int3), int3 }, { sizeof(int3), int3 }, TRUE },
2419 { { sizeof(int4), int4 }, { sizeof(int5), int5 }, TRUE },
2420 { { sizeof(int6), int6 }, { sizeof(int7), int7 }, TRUE },
2421 { { sizeof(int1), int1 }, { sizeof(int7), int7 }, FALSE },
2424 static void testCompareIntegerBlob(void)
2429 for (i = 0; i < sizeof(intBlobs) / sizeof(intBlobs[0]); i++)
2431 ret = CertCompareIntegerBlob(&intBlobs[i].blob1, &intBlobs[i].blob2);
2432 ok(ret == intBlobs[i].areEqual,
2433 "%d: expected blobs %s compare\n", i, intBlobs[i].areEqual ?
2438 static void testComparePublicKeyInfo(void)
2441 CERT_PUBLIC_KEY_INFO info1 = { { 0 } }, info2 = { { 0 } };
2442 static CHAR oid_rsa_rsa[] = szOID_RSA_RSA;
2443 static CHAR oid_rsa_sha1rsa[] = szOID_RSA_SHA1RSA;
2444 static CHAR oid_x957_dsa[] = szOID_X957_DSA;
2445 static BYTE bits1[] = { 1, 0 };
2446 static BYTE bits2[] = { 0 };
2447 static BYTE bits3[] = { 1 };
2448 static BYTE bits4[] = { 0x30,8, 2,1,0x81, 2,3,1,0,1 };
2449 static BYTE bits5[] = { 0x30,9, 2,2,0,0x81, 2,3,1,0,1 };
2450 static BYTE bits6[] = { 0x30,9, 2,2,0,0x82, 2,3,1,0,1 };
2453 ret = CertComparePublicKeyInfo(0, NULL, NULL);
2455 /* Empty public keys compare */
2456 ret = CertComparePublicKeyInfo(0, &info1, &info2);
2457 ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
2458 /* Different OIDs appear to compare */
2459 info1.Algorithm.pszObjId = oid_rsa_rsa;
2460 info2.Algorithm.pszObjId = oid_rsa_sha1rsa;
2461 ret = CertComparePublicKeyInfo(0, &info1, &info2);
2462 ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
2463 info2.Algorithm.pszObjId = oid_x957_dsa;
2464 ret = CertComparePublicKeyInfo(0, &info1, &info2);
2465 ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
2466 info1.PublicKey.cbData = sizeof(bits1);
2467 info1.PublicKey.pbData = bits1;
2468 info1.PublicKey.cUnusedBits = 0;
2469 info2.PublicKey.cbData = sizeof(bits1);
2470 info2.PublicKey.pbData = bits1;
2471 info2.PublicKey.cUnusedBits = 0;
2472 ret = CertComparePublicKeyInfo(0, &info1, &info2);
2473 ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
2474 info2.Algorithm.pszObjId = oid_rsa_rsa;
2475 info1.PublicKey.cbData = sizeof(bits4);
2476 info1.PublicKey.pbData = bits4;
2477 info1.PublicKey.cUnusedBits = 0;
2478 info2.PublicKey.cbData = sizeof(bits5);
2479 info2.PublicKey.pbData = bits5;
2480 info2.PublicKey.cUnusedBits = 0;
2481 ret = CertComparePublicKeyInfo(0, &info1, &info2);
2482 ok(!ret, "CertComparePublicKeyInfo: as raw binary: keys should be unequal\n");
2483 ret = CertComparePublicKeyInfo(X509_ASN_ENCODING, &info1, &info2);
2484 ok(ret, "CertComparePublicKeyInfo: as ASN.1 encoded: keys should be equal\n");
2485 info1.PublicKey.cUnusedBits = 1;
2486 info2.PublicKey.cUnusedBits = 5;
2487 ret = CertComparePublicKeyInfo(X509_ASN_ENCODING, &info1, &info2);
2488 ok(ret, "CertComparePublicKeyInfo: ASN.1 encoding should ignore cUnusedBits\n");
2489 info1.PublicKey.cUnusedBits = 0;
2490 info2.PublicKey.cUnusedBits = 0;
2491 info1.PublicKey.cbData--; /* kill one byte, make ASN.1 encoded data invalid */
2492 ret = CertComparePublicKeyInfo(X509_ASN_ENCODING, &info1, &info2);
2493 ok(!ret, "CertComparePublicKeyInfo: comparing bad ASN.1 encoded key should fail\n");
2494 /* Even though they compare in their used bits, these do not compare */
2495 info1.PublicKey.cbData = sizeof(bits2);
2496 info1.PublicKey.pbData = bits2;
2497 info1.PublicKey.cUnusedBits = 0;
2498 info2.PublicKey.cbData = sizeof(bits3);
2499 info2.PublicKey.pbData = bits3;
2500 info2.PublicKey.cUnusedBits = 1;
2501 ret = CertComparePublicKeyInfo(0, &info1, &info2);
2502 /* Simple (non-comparing) case */
2503 ok(!ret, "Expected keys not to compare\n");
2504 info2.PublicKey.cbData = sizeof(bits1);
2505 info2.PublicKey.pbData = bits1;
2506 info2.PublicKey.cUnusedBits = 0;
2507 ret = CertComparePublicKeyInfo(0, &info1, &info2);
2508 ok(!ret, "Expected keys not to compare\n");
2509 /* ASN.1 encoded non-comparing case */
2510 info1.PublicKey.cbData = sizeof(bits5);
2511 info1.PublicKey.pbData = bits5;
2512 info1.PublicKey.cUnusedBits = 0;
2513 info2.PublicKey.cbData = sizeof(bits6);
2514 info2.PublicKey.pbData = bits6;
2515 info2.PublicKey.cUnusedBits = 0;
2516 ret = CertComparePublicKeyInfo(X509_ASN_ENCODING, &info1, &info2);
2517 ok(!ret, "CertComparePublicKeyInfo: different keys should be unequal\n");
2520 static void testHashPublicKeyInfo(void)
2523 CERT_PUBLIC_KEY_INFO info = { { 0 } };
2527 ret = CryptHashPublicKeyInfo(0, 0, 0, 0, NULL, NULL, NULL);
2528 ret = CryptHashPublicKeyInfo(0, 0, 0, 0, &info, NULL, NULL);
2530 ret = CryptHashPublicKeyInfo(0, 0, 0, 0, NULL, NULL, &len);
2531 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2532 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2533 /* Crashes on some win9x boxes */
2536 ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, NULL, NULL, &len);
2537 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2538 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
2540 ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, &info, NULL, &len);
2541 ok(ret, "CryptHashPublicKeyInfo failed: %08x\n", GetLastError());
2542 ok(len == 16, "Expected hash size 16, got %d\n", len);
2545 static const BYTE emptyHash[] = { 0xb8,0x51,0x3a,0x31,0x0e,0x9f,0x40,
2546 0x36,0x9c,0x92,0x45,0x1b,0x9d,0xc8,0xf9,0xf6 };
2549 ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, &info, buf,
2551 ok(ret, "CryptHashPublicKeyInfo failed: %08x\n", GetLastError());
2552 ok(!memcmp(buf, emptyHash, len), "Unexpected hash\n");
2556 static void testCompareCert(void)
2558 CERT_INFO info1 = { 0 }, info2 = { 0 };
2562 ret = CertCompareCertificate(X509_ASN_ENCODING, NULL, NULL);
2565 /* Certs with the same issuer and serial number are equal, even if they
2566 * differ in other respects (like subject).
2568 info1.SerialNumber.pbData = serialNum;
2569 info1.SerialNumber.cbData = sizeof(serialNum);
2570 info1.Issuer.pbData = subjectName;
2571 info1.Issuer.cbData = sizeof(subjectName);
2572 info1.Subject.pbData = subjectName2;
2573 info1.Subject.cbData = sizeof(subjectName2);
2574 info2.SerialNumber.pbData = serialNum;
2575 info2.SerialNumber.cbData = sizeof(serialNum);
2576 info2.Issuer.pbData = subjectName;
2577 info2.Issuer.cbData = sizeof(subjectName);
2578 info2.Subject.pbData = subjectName;
2579 info2.Subject.cbData = sizeof(subjectName);
2580 ret = CertCompareCertificate(X509_ASN_ENCODING, &info1, &info2);
2581 ok(ret, "Expected certs to be equal\n");
2583 info2.Issuer.pbData = subjectName2;
2584 info2.Issuer.cbData = sizeof(subjectName2);
2585 ret = CertCompareCertificate(X509_ASN_ENCODING, &info1, &info2);
2586 ok(!ret, "Expected certs not to be equal\n");
2589 static void testVerifySubjectCert(void)
2593 PCCERT_CONTEXT context1, context2;
2596 ret = CertVerifySubjectCertificateContext(NULL, NULL, NULL);
2599 ret = CertVerifySubjectCertificateContext(NULL, NULL, &flags);
2600 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
2602 flags = CERT_STORE_NO_CRL_FLAG;
2603 ret = CertVerifySubjectCertificateContext(NULL, NULL, &flags);
2604 ok(!ret && GetLastError() == E_INVALIDARG,
2605 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2608 context1 = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
2610 ret = CertVerifySubjectCertificateContext(NULL, context1, &flags);
2611 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
2613 ret = CertVerifySubjectCertificateContext(context1, NULL, &flags);
2614 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
2616 ret = CertVerifySubjectCertificateContext(context1, context1, &flags);
2617 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
2620 context2 = CertCreateCertificateContext(X509_ASN_ENCODING,
2621 bigCertWithDifferentSubject, sizeof(bigCertWithDifferentSubject));
2622 SetLastError(0xdeadbeef);
2623 ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
2624 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
2626 flags = CERT_STORE_REVOCATION_FLAG;
2627 ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
2628 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
2630 ok(flags == (CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG),
2631 "Expected CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG, got %08x\n",
2633 flags = CERT_STORE_SIGNATURE_FLAG;
2634 ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
2635 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
2637 ok(flags == CERT_STORE_SIGNATURE_FLAG,
2638 "Expected CERT_STORE_SIGNATURE_FLAG, got %08x\n", flags);
2639 CertFreeCertificateContext(context2);
2641 CertFreeCertificateContext(context1);
2644 static void testVerifyRevocation(void)
2647 CERT_REVOCATION_STATUS status = { 0 };
2648 PCCERT_CONTEXT cert = CertCreateCertificateContext(X509_ASN_ENCODING,
2649 bigCert, sizeof(bigCert));
2652 ret = CertVerifyRevocation(0, 0, 0, NULL, 0, NULL, NULL);
2654 SetLastError(0xdeadbeef);
2655 ret = CertVerifyRevocation(0, 0, 0, NULL, 0, NULL, &status);
2656 ok(!ret && GetLastError() == E_INVALIDARG,
2657 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2658 status.cbSize = sizeof(status);
2659 ret = CertVerifyRevocation(0, 0, 0, NULL, 0, NULL, &status);
2660 ok(ret, "CertVerifyRevocation failed: %08x\n", GetLastError());
2661 ret = CertVerifyRevocation(0, 2, 0, NULL, 0, NULL, &status);
2662 ok(ret, "CertVerifyRevocation failed: %08x\n", GetLastError());
2663 ret = CertVerifyRevocation(2, 0, 0, NULL, 0, NULL, &status);
2664 ok(ret, "CertVerifyRevocation failed: %08x\n", GetLastError());
2665 SetLastError(0xdeadbeef);
2666 ret = CertVerifyRevocation(0, 0, 1, (void **)&cert, 0, NULL, &status);
2667 ok(!ret && GetLastError() == CRYPT_E_NO_REVOCATION_DLL,
2668 "Expected CRYPT_E_NO_REVOCATION_DLL, got %08x\n", GetLastError());
2669 SetLastError(0xdeadbeef);
2670 ret = CertVerifyRevocation(0, 2, 1, (void **)&cert, 0, NULL, &status);
2671 ok(!ret && GetLastError() == CRYPT_E_NO_REVOCATION_DLL,
2672 "Expected CRYPT_E_NO_REVOCATION_DLL, got %08x\n", GetLastError());
2674 CertFreeCertificateContext(cert);
2677 static BYTE privKey[] = {
2678 0x07, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x52, 0x53, 0x41, 0x32, 0x00,
2679 0x02, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x79, 0x10, 0x1c, 0xd0, 0x6b, 0x10,
2680 0x18, 0x30, 0x94, 0x61, 0xdc, 0x0e, 0xcb, 0x96, 0x4e, 0x21, 0x3f, 0x79, 0xcd,
2681 0xa9, 0x17, 0x62, 0xbc, 0xbb, 0x61, 0x4c, 0xe0, 0x75, 0x38, 0x6c, 0xf3, 0xde,
2682 0x60, 0x86, 0x03, 0x97, 0x65, 0xeb, 0x1e, 0x6b, 0xdb, 0x53, 0x85, 0xad, 0x68,
2683 0x21, 0xf1, 0x5d, 0xe7, 0x1f, 0xe6, 0x53, 0xb4, 0xbb, 0x59, 0x3e, 0x14, 0x27,
2684 0xb1, 0x83, 0xa7, 0x3a, 0x54, 0xe2, 0x8f, 0x65, 0x8e, 0x6a, 0x4a, 0xcf, 0x3b,
2685 0x1f, 0x65, 0xff, 0xfe, 0xf1, 0x31, 0x3a, 0x37, 0x7a, 0x8b, 0xcb, 0xc6, 0xd4,
2686 0x98, 0x50, 0x36, 0x67, 0xe4, 0xa1, 0xe8, 0x7e, 0x8a, 0xc5, 0x23, 0xf2, 0x77,
2687 0xf5, 0x37, 0x61, 0x49, 0x72, 0x59, 0xe8, 0x3d, 0xf7, 0x60, 0xb2, 0x77, 0xca,
2688 0x78, 0x54, 0x6d, 0x65, 0x9e, 0x03, 0x97, 0x1b, 0x61, 0xbd, 0x0c, 0xd8, 0x06,
2689 0x63, 0xe2, 0xc5, 0x48, 0xef, 0xb3, 0xe2, 0x6e, 0x98, 0x7d, 0xbd, 0x4e, 0x72,
2690 0x91, 0xdb, 0x31, 0x57, 0xe3, 0x65, 0x3a, 0x49, 0xca, 0xec, 0xd2, 0x02, 0x4e,
2691 0x22, 0x7e, 0x72, 0x8e, 0xf9, 0x79, 0x84, 0x82, 0xdf, 0x7b, 0x92, 0x2d, 0xaf,
2692 0xc9, 0xe4, 0x33, 0xef, 0x89, 0x5c, 0x66, 0x99, 0xd8, 0x80, 0x81, 0x47, 0x2b,
2693 0xb1, 0x66, 0x02, 0x84, 0x59, 0x7b, 0xc3, 0xbe, 0x98, 0x45, 0x4a, 0x3d, 0xdd,
2694 0xea, 0x2b, 0xdf, 0x4e, 0xb4, 0x24, 0x6b, 0xec, 0xe7, 0xd9, 0x0c, 0x45, 0xb8,
2695 0xbe, 0xca, 0x69, 0x37, 0x92, 0x4c, 0x38, 0x6b, 0x96, 0x6d, 0xcd, 0x86, 0x67,
2696 0x5c, 0xea, 0x54, 0x94, 0xa4, 0xca, 0xa4, 0x02, 0xa5, 0x21, 0x4d, 0xae, 0x40,
2697 0x8f, 0x9d, 0x51, 0x83, 0xf2, 0x3f, 0x33, 0xc1, 0x72, 0xb4, 0x1d, 0x94, 0x6e,
2698 0x7d, 0xe4, 0x27, 0x3f, 0xea, 0xff, 0xe5, 0x9b, 0xa7, 0x5e, 0x55, 0x8e, 0x0d,
2699 0x69, 0x1c, 0x7a, 0xff, 0x81, 0x9d, 0x53, 0x52, 0x97, 0x9a, 0x76, 0x79, 0xda,
2700 0x93, 0x32, 0x16, 0xec, 0x69, 0x51, 0x1a, 0x4e, 0xc3, 0xf1, 0x72, 0x80, 0x78,
2701 0x5e, 0x66, 0x4a, 0x8d, 0x85, 0x2f, 0x3f, 0xb2, 0xa7 };
2703 static const BYTE selfSignedCert[] = {
2704 0x30, 0x82, 0x01, 0x1f, 0x30, 0x81, 0xce, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
2705 0x10, 0xeb, 0x0d, 0x57, 0x2a, 0x9c, 0x09, 0xba, 0xa4, 0x4a, 0xb7, 0x25, 0x49,
2706 0xd9, 0x3e, 0xb5, 0x73, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d,
2707 0x05, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
2708 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30,
2709 0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x36, 0x32, 0x39, 0x30, 0x35, 0x30, 0x30,
2710 0x34, 0x36, 0x5a, 0x17, 0x0d, 0x30, 0x37, 0x30, 0x36, 0x32, 0x39, 0x31, 0x31,
2711 0x30, 0x30, 0x34, 0x36, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
2712 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e,
2713 0x67, 0x00, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
2714 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
2715 0x00, 0xe2, 0x54, 0x3a, 0xa7, 0x83, 0xb1, 0x27, 0x14, 0x3e, 0x59, 0xbb, 0xb4,
2716 0x53, 0xe6, 0x1f, 0xe7, 0x5d, 0xf1, 0x21, 0x68, 0xad, 0x85, 0x53, 0xdb, 0x6b,
2717 0x1e, 0xeb, 0x65, 0x97, 0x03, 0x86, 0x60, 0xde, 0xf3, 0x6c, 0x38, 0x75, 0xe0,
2718 0x4c, 0x61, 0xbb, 0xbc, 0x62, 0x17, 0xa9, 0xcd, 0x79, 0x3f, 0x21, 0x4e, 0x96,
2719 0xcb, 0x0e, 0xdc, 0x61, 0x94, 0x30, 0x18, 0x10, 0x6b, 0xd0, 0x1c, 0x10, 0x79,
2720 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
2721 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x25, 0x90, 0x53, 0x34, 0xd9, 0x56, 0x41,
2722 0x5e, 0xdb, 0x7e, 0x01, 0x36, 0xec, 0x27, 0x61, 0x5e, 0xb7, 0x4d, 0x90, 0x66,
2723 0xa2, 0xe1, 0x9d, 0x58, 0x76, 0xd4, 0x9c, 0xba, 0x2c, 0x84, 0xc6, 0x83, 0x7a,
2724 0x22, 0x0d, 0x03, 0x69, 0x32, 0x1a, 0x6d, 0xcb, 0x0c, 0x15, 0xb3, 0x6b, 0xc7,
2725 0x0a, 0x8c, 0xb4, 0x5c, 0x34, 0x78, 0xe0, 0x3c, 0x9c, 0xe9, 0xf3, 0x30, 0x9f,
2726 0xa8, 0x76, 0x57, 0x92, 0x36 };
2728 static const BYTE exportedPublicKeyBlob[] = {
2729 0x06,0x02,0x00,0x00,0x00,0xa4,0x00,0x00,0x52,0x53,0x41,0x31,0x00,0x02,0x00,0x00,
2730 0x01,0x00,0x01,0x00,0x79,0x10,0x1c,0xd0,0x6b,0x10,0x18,0x30,0x94,0x61,0xdc,0x0e,
2731 0xcb,0x96,0x4e,0x21,0x3f,0x79,0xcd,0xa9,0x17,0x62,0xbc,0xbb,0x61,0x4c,0xe0,0x75,
2732 0x38,0x6c,0xf3,0xde,0x60,0x86,0x03,0x97,0x65,0xeb,0x1e,0x6b,0xdb,0x53,0x85,0xad,
2733 0x68,0x21,0xf1,0x5d,0xe7,0x1f,0xe6,0x53,0xb4,0xbb,0x59,0x3e,0x14,0x27,0xb1,0x83,
2734 0xa7,0x3a,0x54,0xe2 };
2736 static const BYTE asnEncodedPublicKey[] = {
2737 0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7,0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,
2738 0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21,0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,
2739 0x65,0x97,0x03,0x86,0x60,0xde,0xf3,0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,
2740 0x17,0xa9,0xcd,0x79,0x3f,0x21,0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,
2741 0x6b,0xd0,0x1c,0x10,0x79,0x02,0x03,0x01,0x00,0x01 };
2743 static void testAcquireCertPrivateKey(void)
2746 PCCERT_CONTEXT cert;
2748 DWORD size, keySpec;
2750 CRYPT_KEY_PROV_INFO keyProvInfo;
2752 WCHAR ms_def_prov_w[MAX_PATH];
2754 if (!pCryptAcquireCertificatePrivateKey)
2756 skip("CryptAcquireCertificatePrivateKey() is not available\n");
2760 lstrcpyW(ms_def_prov_w, MS_DEF_PROV_W);
2762 keyProvInfo.pwszContainerName = cspNameW;
2763 keyProvInfo.pwszProvName = ms_def_prov_w;
2764 keyProvInfo.dwProvType = PROV_RSA_FULL;
2765 keyProvInfo.dwFlags = 0;
2766 keyProvInfo.cProvParam = 0;
2767 keyProvInfo.rgProvParam = NULL;
2768 keyProvInfo.dwKeySpec = AT_SIGNATURE;
2770 pCryptAcquireContextW(NULL, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
2771 CRYPT_DELETEKEYSET);
2773 cert = CertCreateCertificateContext(X509_ASN_ENCODING, selfSignedCert,
2774 sizeof(selfSignedCert));
2777 ret = pCryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, NULL, NULL);
2778 ret = pCryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, NULL,
2780 ret = pCryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, &keySpec,
2782 ret = pCryptAcquireCertificatePrivateKey(NULL, 0, NULL, &csp, NULL, NULL);
2783 ret = pCryptAcquireCertificatePrivateKey(NULL, 0, NULL, &csp, &keySpec,
2785 ret = pCryptAcquireCertificatePrivateKey(cert, 0, NULL, NULL, NULL, NULL);
2788 /* Missing private key */
2789 ret = pCryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, NULL, NULL);
2790 ok(!ret && GetLastError() == CRYPT_E_NO_KEY_PROPERTY,
2791 "Expected CRYPT_E_NO_KEY_PROPERTY, got %08x\n", GetLastError());
2792 ret = pCryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, &keySpec,
2794 ok(!ret && GetLastError() == CRYPT_E_NO_KEY_PROPERTY,
2795 "Expected CRYPT_E_NO_KEY_PROPERTY, got %08x\n", GetLastError());
2796 CertSetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, 0,
2798 ret = pCryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, &keySpec,
2800 ok(!ret && GetLastError() == CRYPT_E_NO_KEY_PROPERTY,
2801 "Expected CRYPT_E_NO_KEY_PROPERTY, got %08x\n", GetLastError());
2803 pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
2805 ret = CryptImportKey(csp, privKey, sizeof(privKey), 0, 0, &key);
2806 ok(ret, "CryptImportKey failed: %08x\n", GetLastError());
2811 CERT_KEY_CONTEXT keyContext;
2813 /* Don't cache provider */
2814 ret = pCryptAcquireCertificatePrivateKey(cert, 0, NULL, &certCSP,
2815 &keySpec, &callerFree);
2816 ok(ret, "CryptAcquireCertificatePrivateKey failed: %08x\n",
2818 ok(callerFree, "Expected callerFree to be TRUE\n");
2819 CryptReleaseContext(certCSP, 0);
2820 ret = pCryptAcquireCertificatePrivateKey(cert, 0, NULL, &certCSP,
2822 ok(ret, "CryptAcquireCertificatePrivateKey failed: %08x\n",
2824 CryptReleaseContext(certCSP, 0);
2826 /* Use the key prov info's caching (there shouldn't be any) */
2827 ret = pCryptAcquireCertificatePrivateKey(cert,
2828 CRYPT_ACQUIRE_USE_PROV_INFO_FLAG, NULL, &certCSP, &keySpec,
2830 ok(ret, "CryptAcquireCertificatePrivateKey failed: %08x\n",
2832 ok(callerFree, "Expected callerFree to be TRUE\n");
2833 CryptReleaseContext(certCSP, 0);
2835 /* Cache it (and check that it's cached) */
2836 ret = pCryptAcquireCertificatePrivateKey(cert,
2837 CRYPT_ACQUIRE_CACHE_FLAG, NULL, &certCSP, &keySpec, &callerFree);
2838 ok(ret, "CryptAcquireCertificatePrivateKey failed: %08x\n",
2840 ok(!callerFree, "Expected callerFree to be FALSE\n");
2841 size = sizeof(keyContext);
2842 ret = CertGetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID,
2843 &keyContext, &size);
2844 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
2847 /* Remove the cached provider */
2848 CryptReleaseContext(keyContext.hCryptProv, 0);
2849 CertSetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID, 0,
2851 /* Allow caching via the key prov info */
2852 keyProvInfo.dwFlags = CERT_SET_KEY_CONTEXT_PROP_ID;
2853 CertSetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, 0,
2855 /* Now use the key prov info's caching */
2856 ret = pCryptAcquireCertificatePrivateKey(cert,
2857 CRYPT_ACQUIRE_USE_PROV_INFO_FLAG, NULL, &certCSP, &keySpec,
2859 ok(ret, "CryptAcquireCertificatePrivateKey failed: %08x\n",
2861 ok(!callerFree, "Expected callerFree to be FALSE\n");
2862 size = sizeof(keyContext);
2863 ret = CertGetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID,
2864 &keyContext, &size);
2865 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
2867 CryptReleaseContext(certCSP, 0);
2869 CryptDestroyKey(key);
2872 /* Some sanity-checking on public key exporting */
2873 ret = CryptImportPublicKeyInfo(csp, X509_ASN_ENCODING,
2874 &cert->pCertInfo->SubjectPublicKeyInfo, &key);
2875 ok(ret, "CryptImportPublicKeyInfo failed: %08x\n", GetLastError());
2878 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &size);
2879 ok(ret, "CryptExportKey failed: %08x\n", GetLastError());
2882 LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, size), encodedKey;
2884 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, buf, &size);
2885 ok(ret, "CryptExportKey failed: %08x\n", GetLastError());
2886 ok(size == sizeof(exportedPublicKeyBlob), "Unexpected size %d\n",
2888 ok(!memcmp(buf, exportedPublicKeyBlob, size), "Unexpected value\n");
2889 ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, RSA_CSP_PUBLICKEYBLOB,
2890 buf, CRYPT_ENCODE_ALLOC_FLAG, NULL, &encodedKey, &size);
2891 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2894 ok(size == sizeof(asnEncodedPublicKey), "Unexpected size %d\n",
2896 ok(!memcmp(encodedKey, asnEncodedPublicKey, size),
2897 "Unexpected value\n");
2898 LocalFree(encodedKey);
2900 HeapFree(GetProcessHeap(), 0, buf);
2902 CryptDestroyKey(key);
2904 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
2905 NULL, 0, NULL, NULL, &size);
2906 ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
2909 PCERT_PUBLIC_KEY_INFO info = HeapAlloc(GetProcessHeap(), 0, size);
2911 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
2912 NULL, 0, NULL, info, &size);
2913 ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
2916 ok(info->PublicKey.cbData == sizeof(asnEncodedPublicKey),
2917 "Unexpected size %d\n", info->PublicKey.cbData);
2918 ok(!memcmp(info->PublicKey.pbData, asnEncodedPublicKey,
2919 info->PublicKey.cbData), "Unexpected value\n");
2921 HeapFree(GetProcessHeap(), 0, info);
2924 CryptReleaseContext(csp, 0);
2925 pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
2926 CRYPT_DELETEKEYSET);
2928 CertFreeCertificateContext(cert);
2931 static void testGetPublicKeyLength(void)
2933 static char oid_rsa_rsa[] = szOID_RSA_RSA;
2934 static char oid_rsa_dh[] = szOID_RSA_DH;
2935 static char bogusOID[] = "1.2.3";
2937 CERT_PUBLIC_KEY_INFO info = { { 0 } };
2938 BYTE bogusKey[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
2939 BYTE key[] = { 0x30,0x0f,0x02,0x08,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
2940 0x02,0x03,0x01,0x00,0x01 };
2943 ret = CertGetPublicKeyLength(0, NULL);
2945 /* With an empty public key info */
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 nearly-empty public key info */
2957 info.Algorithm.pszObjId = oid_rsa_rsa;
2958 SetLastError(0xdeadbeef);
2959 ret = CertGetPublicKeyLength(0, &info);
2960 ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
2961 "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
2962 ret, GetLastError());
2963 SetLastError(0xdeadbeef);
2964 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
2965 ok(ret == 0 && GetLastError() == CRYPT_E_ASN1_EOD,
2966 "Expected length 0 and CRYPT_E_ASN1_EOD, got length %d, %08x\n",
2967 ret, GetLastError());
2968 /* With a bogus key */
2969 info.PublicKey.cbData = sizeof(bogusKey);
2970 info.PublicKey.pbData = bogusKey;
2971 SetLastError(0xdeadbeef);
2972 ret = CertGetPublicKeyLength(0, &info);
2973 ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
2974 "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
2975 ret, GetLastError());
2976 SetLastError(0xdeadbeef);
2977 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
2978 ok(ret == 0 && GetLastError() == CRYPT_E_ASN1_BADTAG,
2979 "Expected length 0 and CRYPT_E_ASN1_BADTAGTAG, got length %d, %08x\n",
2980 ret, GetLastError());
2981 /* With a believable RSA key but a bogus OID */
2982 info.Algorithm.pszObjId = bogusOID;
2983 info.PublicKey.cbData = sizeof(key);
2984 info.PublicKey.pbData = key;
2985 SetLastError(0xdeadbeef);
2986 ret = CertGetPublicKeyLength(0, &info);
2987 ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
2988 "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
2989 ret, GetLastError());
2990 SetLastError(0xdeadbeef);
2991 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
2992 ok(ret == 56, "Expected length 56, got %d\n", ret);
2993 /* An RSA key with the DH OID */
2994 info.Algorithm.pszObjId = oid_rsa_dh;
2995 SetLastError(0xdeadbeef);
2996 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
2997 ok(ret == 0 && GetLastError() == CRYPT_E_ASN1_BADTAG,
2998 "Expected length 0 and CRYPT_E_ASN1_BADTAG, got length %d, %08x\n",
2999 ret, GetLastError());
3000 /* With the RSA OID */
3001 info.Algorithm.pszObjId = oid_rsa_rsa;
3002 SetLastError(0xdeadbeef);
3003 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
3004 ok(ret == 56, "Expected length 56, got %d\n", ret);
3005 /* With the RSA OID and a message encoding */
3006 info.Algorithm.pszObjId = oid_rsa_rsa;
3007 SetLastError(0xdeadbeef);
3008 ret = CertGetPublicKeyLength(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, &info);
3009 ok(ret == 56, "Expected length 56, got %d\n", ret);
3014 init_function_pointers();
3017 testCertProperties();
3020 testGetSubjectCert();
3021 testGetIssuerCert();
3023 testCryptHashCert();
3025 testSignAndEncodeCert();
3026 testCreateSelfSignCert();
3028 testGetValidUsages();
3029 testCompareCertName();
3030 testCompareIntegerBlob();
3031 testComparePublicKeyInfo();
3032 testHashPublicKeyInfo();
3034 testVerifySubjectCert();
3035 testVerifyRevocation();
3036 testAcquireCertPrivateKey();
3037 testGetPublicKeyLength();