2 * crypt32 cert store function 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 /* The following aren't defined in wincrypt.h, as they're "reserved" */
33 #define CERT_CERT_PROP_ID 32
34 #define CERT_CRL_PROP_ID 33
35 #define CERT_CTL_PROP_ID 34
37 struct CertPropIDHeader
44 static const BYTE emptyCert[] = { 0x30, 0x00 };
45 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
46 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
47 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
48 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
49 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
50 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
51 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
52 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
53 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
54 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
55 static const BYTE subjectName[] = { 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
56 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
58 static const BYTE bigCertHash[] = { 0x6e, 0x30, 0x90, 0x71, 0x5f, 0xd9, 0x23,
59 0x56, 0xeb, 0xae, 0x25, 0x40, 0xe6, 0x22, 0xda, 0x19, 0x26, 0x02, 0xa6, 0x08 };
60 static const BYTE signedBigCert[] = {
61 0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
62 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
63 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f,
64 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
65 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
66 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
67 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
68 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3,
69 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
70 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
71 0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
72 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
73 static const BYTE serializedCert[] = { 0x20, 0x00, 0x00, 0x00,
74 0x01, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x30, 0x7a, 0x02, 0x01, 0x01,
75 0x30, 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
76 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67,
77 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31,
78 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
79 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15,
80 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75,
81 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06,
82 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55,
83 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02,
85 static const BYTE signedCRL[] = { 0x30, 0x45, 0x30, 0x2c, 0x30, 0x02, 0x06,
86 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
87 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
88 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
89 0x30, 0x5a, 0x30, 0x02, 0x06, 0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c,
90 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
91 static const BYTE bigCert2[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
92 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
93 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
94 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
95 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
96 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
97 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20,
98 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
99 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
100 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
101 static const BYTE bigCert2WithDifferentSerial[] = { 0x30, 0x7a, 0x02, 0x01,
102 0x02, 0x30, 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
103 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e,
104 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
105 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30,
106 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30,
107 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41,
108 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02,
109 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03,
110 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff,
112 static const BYTE subjectName2[] = { 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
113 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61,
115 static const BYTE bigCert2Hash[] = { 0x4a, 0x7f, 0x32, 0x1f, 0xcf, 0x3b, 0xc0,
116 0x87, 0x48, 0x2b, 0xa1, 0x86, 0x54, 0x18, 0xe4, 0x3a, 0x0e, 0x53, 0x7e, 0x2b };
117 static const BYTE certWithUsage[] = { 0x30, 0x81, 0x93, 0x02, 0x01, 0x01, 0x30,
118 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04,
119 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00,
120 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
121 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
122 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31,
123 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61,
124 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00,
125 0x03, 0x01, 0x00, 0xa3, 0x2f, 0x30, 0x2d, 0x30, 0x2b, 0x06, 0x03, 0x55, 0x1d,
126 0x25, 0x01, 0x01, 0xff, 0x04, 0x21, 0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01,
127 0x05, 0x05, 0x07, 0x03, 0x03, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
128 0x03, 0x02, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
129 static const BYTE serialNum[] = { 1 };
130 static const BYTE bigCertWithDifferentSubject[] = { 0x30, 0x7a, 0x02, 0x01, 0x01,
131 0x30, 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
132 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67,
133 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31,
134 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
135 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15,
136 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c,
137 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06,
138 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55,
139 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02,
141 static const BYTE bigCertWithDifferentIssuer[] = { 0x30, 0x7a, 0x02, 0x01,
142 0x01, 0x30, 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
143 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e,
144 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
145 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30,
146 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30,
147 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
148 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02,
149 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03,
150 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff,
153 static void testAddCert(void)
157 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
158 CERT_STORE_CREATE_NEW_FLAG, NULL);
159 ok(store != NULL, "CertOpenStore failed: %ld\n", GetLastError());
162 HCERTSTORE collection;
163 PCCERT_CONTEXT context;
166 /* Weird--bad add disposition leads to an access violation in Windows.
168 ret = CertAddEncodedCertificateToStore(0, X509_ASN_ENCODING, bigCert,
169 sizeof(bigCert), 0, NULL);
170 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
171 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
172 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
173 bigCert, sizeof(bigCert), 0, NULL);
174 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
175 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
177 /* Weird--can add a cert to the NULL store (does this have special
181 ret = CertAddEncodedCertificateToStore(0, X509_ASN_ENCODING, bigCert,
182 sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
183 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
186 CertFreeCertificateContext(context);
188 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
189 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
190 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
192 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
193 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, NULL);
194 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
196 /* This has the same name as bigCert, so finding isn't done by name */
197 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
198 certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, &context);
199 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
201 ok(context != NULL, "Expected a context\n");
204 CRYPT_DATA_BLOB hash = { sizeof(bigCert2Hash),
205 (LPBYTE)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: %08lx\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 %08lx\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: %08lx\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: %08lx\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: %08lx\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: %08lx\n", GetLastError());
279 /* Add store to the collection, but disable updates */
280 CertAddStoreToCollection(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 %08lx\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: %08lx\n",
299 /* but adding a new certificate isn't allowed. */
300 ret = CertAddCertificateContextToStore(collection, context,
301 CERT_STORE_ADD_ALWAYS, NULL);
302 ok(!ret && GetLastError() == E_ACCESSDENIED,
303 "Expected E_ACCESSDENIED, got %08lx\n", GetLastError());
304 CertFreeCertificateContext(context);
307 CertCloseStore(collection, 0);
310 CertCloseStore(store, 0);
314 static void testDupCert(void)
318 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
319 CERT_STORE_CREATE_NEW_FLAG, NULL);
320 ok(store != NULL, "CertOpenStore failed: %ld\n", GetLastError());
323 PCCERT_CONTEXT context, dupContext;
326 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
327 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
328 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
330 ok(context != NULL, "Expected a valid cert context\n");
333 ok(context->cbCertEncoded == sizeof(bigCert),
334 "Wrong cert size %ld\n", context->cbCertEncoded);
335 ok(!memcmp(context->pbCertEncoded, bigCert, sizeof(bigCert)),
336 "Unexpected encoded cert in context\n");
337 ok(context->hCertStore == store, "Unexpected store\n");
339 dupContext = CertDuplicateCertificateContext(context);
340 ok(dupContext != NULL, "Expected valid duplicate\n");
341 /* Not only is it a duplicate, it's identical: the address is the
344 ok(dupContext == context, "Expected identical context addresses\n");
345 CertFreeCertificateContext(dupContext);
346 CertFreeCertificateContext(context);
348 CertCloseStore(store, 0);
352 static void testFindCert(void)
356 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
357 CERT_STORE_CREATE_NEW_FLAG, NULL);
358 ok(store != NULL, "CertOpenStore failed: %ld\n", GetLastError());
361 PCCERT_CONTEXT context = NULL;
363 CERT_INFO certInfo = { 0 };
364 CRYPT_HASH_BLOB blob;
366 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
367 bigCert, sizeof(bigCert), CERT_STORE_ADD_NEW, NULL);
368 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
370 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
371 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, NULL);
372 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
374 /* This has the same name as bigCert */
375 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
376 certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, NULL);
377 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
381 context = CertFindCertificateInStore(NULL, 0, 0, 0, NULL, NULL);
384 /* Check first cert's there, by issuer */
385 certInfo.Subject.pbData = (LPBYTE)subjectName;
386 certInfo.Subject.cbData = sizeof(subjectName);
387 certInfo.SerialNumber.pbData = (LPBYTE)serialNum;
388 certInfo.SerialNumber.cbData = sizeof(serialNum);
389 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
390 CERT_FIND_ISSUER_NAME, &certInfo.Subject, NULL);
391 ok(context != NULL, "CertFindCertificateInStore failed: %08lx\n",
395 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
396 CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
397 ok(context != NULL, "Expected more than one cert\n");
400 context = CertFindCertificateInStore(store, X509_ASN_ENCODING,
401 0, CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
402 ok(context == NULL, "Expected precisely two certs\n");
406 /* Check second cert's there as well, by subject name */
407 certInfo.Subject.pbData = (LPBYTE)subjectName2;
408 certInfo.Subject.cbData = sizeof(subjectName2);
409 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
410 CERT_FIND_SUBJECT_NAME, &certInfo.Subject, NULL);
411 ok(context != NULL, "CertFindCertificateInStore failed: %08lx\n",
415 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
416 CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
417 ok(context == NULL, "Expected one cert only\n");
420 /* Strange but true: searching for the subject cert requires you to set
421 * the issuer, not the subject
423 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
424 CERT_FIND_SUBJECT_CERT, &certInfo.Subject, NULL);
425 ok(context == NULL, "Expected no certificate\n");
426 certInfo.Subject.pbData = NULL;
427 certInfo.Subject.cbData = 0;
428 certInfo.Issuer.pbData = (LPBYTE)subjectName2;
429 certInfo.Issuer.cbData = sizeof(subjectName2);
430 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
431 CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
432 ok(context != NULL, "CertFindCertificateInStore failed: %08lx\n",
436 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
437 CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
438 ok(context == NULL, "Expected one cert only\n");
441 /* The nice thing about hashes, they're unique */
442 blob.pbData = (LPBYTE)bigCertHash;
443 blob.cbData = sizeof(bigCertHash);
444 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
445 CERT_FIND_SHA1_HASH, &blob, NULL);
446 ok(context != NULL, "CertFindCertificateInStore failed: %08lx\n",
450 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
451 CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
452 ok(context == NULL, "Expected one cert only\n");
455 CertCloseStore(store, 0);
459 static void testGetSubjectCert(void)
463 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
464 CERT_STORE_CREATE_NEW_FLAG, NULL);
465 ok(store != NULL, "CertOpenStore failed: %ld\n", GetLastError());
468 PCCERT_CONTEXT context1, context2;
469 CERT_INFO info = { 0 };
472 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
473 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
474 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
476 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
477 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, &context1);
478 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
480 ok(context1 != NULL, "Expected a context\n");
481 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
482 certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, NULL);
483 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
486 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
488 ok(!context2 && GetLastError() == E_INVALIDARG,
489 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
490 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
492 ok(!context2 && GetLastError() == CRYPT_E_NOT_FOUND,
493 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
494 info.SerialNumber.cbData = sizeof(serialNum);
495 info.SerialNumber.pbData = (LPBYTE)serialNum;
496 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
498 ok(!context2 && GetLastError() == CRYPT_E_NOT_FOUND,
499 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
500 info.Issuer.cbData = sizeof(subjectName2);
501 info.Issuer.pbData = (LPBYTE)subjectName2;
502 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
505 "CertGetSubjectCertificateFromStore failed: %08lx\n", GetLastError());
506 /* Not only should this find a context, but it should be the same
507 * (same address) as context1.
509 ok(context1 == context2, "Expected identical context addresses\n");
510 CertFreeCertificateContext(context2);
512 CertFreeCertificateContext(context1);
513 CertCloseStore(store, 0);
517 /* This expires in 1970 or so */
518 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
519 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
520 0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
521 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
522 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
523 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
524 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
525 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
526 0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
527 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
528 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
529 0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
530 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
531 0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
532 0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
533 0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
534 0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
535 0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
536 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
537 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
538 0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
539 0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
540 0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
541 0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
542 0x49, 0xe5, 0xf9, 0x65, 0xf3 };
544 /* This expires in 2036 or so */
545 static const BYTE childOfExpired[] = { 0x30, 0x81, 0xcc, 0x30, 0x78, 0xa0,
546 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
547 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d,
548 0x30, 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63,
549 0x40, 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e,
550 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x35, 0x30, 0x35,
551 0x31, 0x37, 0x31, 0x32, 0x34, 0x39, 0x5a, 0x17, 0x0d, 0x33, 0x36, 0x30, 0x35,
552 0x30, 0x35, 0x31, 0x37, 0x31, 0x32, 0x34, 0x39, 0x5a, 0x30, 0x15, 0x31, 0x13,
553 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e,
554 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03,
555 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
556 0x01, 0x05, 0x05, 0x00, 0x03, 0x41, 0x00, 0x20, 0x3b, 0xdb, 0x4d, 0x67, 0x50,
557 0xec, 0x73, 0x9d, 0xf9, 0x85, 0x5d, 0x18, 0xe9, 0xb4, 0x98, 0xe3, 0x31, 0xb7,
558 0x03, 0x0b, 0xc0, 0x39, 0x93, 0x56, 0x81, 0x0a, 0xfc, 0x78, 0xa8, 0x29, 0x42,
559 0x5f, 0x69, 0xfb, 0xbc, 0x5b, 0xf2, 0xa6, 0x2a, 0xbe, 0x91, 0x2c, 0xfc, 0x89,
560 0x69, 0x15, 0x18, 0x58, 0xe5, 0x02, 0x75, 0xf7, 0x2a, 0xb6, 0xa9, 0xfb, 0x47,
561 0x6a, 0x6e, 0x0a, 0x9b, 0xe9, 0xdc };
563 static void testGetIssuerCert(void)
566 PCCERT_CONTEXT parent, child;
567 DWORD flags = 0xffffffff;
568 HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
569 CERT_STORE_CREATE_NEW_FLAG, NULL);
571 ok(store != NULL, "CertOpenStore failed: %08lx\n", GetLastError());
573 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
574 expiredCert, sizeof(expiredCert), CERT_STORE_ADD_ALWAYS, NULL);
575 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
578 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
579 childOfExpired, sizeof(childOfExpired), CERT_STORE_ADD_ALWAYS, &child);
580 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
584 parent = CertGetIssuerCertificateFromStore(NULL, NULL, NULL, NULL);
585 parent = CertGetIssuerCertificateFromStore(store, NULL, NULL, NULL);
587 parent = CertGetIssuerCertificateFromStore(NULL, NULL, NULL, &flags);
588 ok(!parent && GetLastError() == E_INVALIDARG,
589 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
590 parent = CertGetIssuerCertificateFromStore(store, NULL, NULL, &flags);
591 ok(!parent && GetLastError() == E_INVALIDARG,
592 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
593 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
594 ok(!parent && GetLastError() == E_INVALIDARG,
595 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
596 /* Confusing: the caller cannot set either of the
597 * CERT_STORE_NO_*_FLAGs, as these are not checks,
600 flags = CERT_STORE_NO_CRL_FLAG | CERT_STORE_NO_ISSUER_FLAG;
601 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
602 ok(!parent && GetLastError() == E_INVALIDARG,
603 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
604 /* Perform no checks */
606 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
607 ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08lx\n",
610 CertFreeCertificateContext(parent);
611 /* Check revocation and signature only */
612 flags = CERT_STORE_REVOCATION_FLAG | CERT_STORE_SIGNATURE_FLAG;
613 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
614 ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08lx\n",
616 /* Confusing: CERT_STORE_REVOCATION_FLAG succeeds when there is no CRL by
617 * setting CERT_STORE_NO_CRL_FLAG.
619 ok(flags == (CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG),
620 "Expected CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG, got %08lx\n",
623 CertFreeCertificateContext(parent);
624 /* Now check just the time */
625 flags = CERT_STORE_TIME_VALIDITY_FLAG;
626 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
627 ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08lx\n",
629 /* Oops: the child is not expired, so the time validity check actually
630 * succeeds, even though the signing cert is expired.
632 ok(!flags, "Expected check to succeed, got %08lx\n", flags);
634 CertFreeCertificateContext(parent);
636 CertFreeCertificateContext(child);
637 CertCloseStore(store, 0);
640 static void testMemStore(void)
642 HCERTSTORE store1, store2;
643 PCCERT_CONTEXT context;
647 store1 = CertOpenStore(0, 0, 0, 0, NULL);
648 ok(!store1 && GetLastError() == ERROR_FILE_NOT_FOUND,
649 "Expected ERROR_FILE_NOT_FOUND, got %ld\n", GetLastError());
651 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
652 CERT_STORE_DELETE_FLAG, NULL);
653 ok(!store1 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
654 "Expected ERROR_CALL_NOT_IMPLEMENTED, got %ld\n", GetLastError());
657 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
658 CERT_STORE_CREATE_NEW_FLAG, NULL);
659 ok(store1 != NULL, "CertOpenStore failed: %ld\n", GetLastError());
660 /* open existing doesn't */
661 store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
662 CERT_STORE_OPEN_EXISTING_FLAG, NULL);
663 ok(store2 != NULL, "CertOpenStore failed: %ld\n", GetLastError());
664 ok(store1 != store2, "Expected different stores\n");
666 /* add a bogus (empty) cert */
668 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING, emptyCert,
669 sizeof(emptyCert), CERT_STORE_ADD_ALWAYS, &context);
670 /* Windows returns CRYPT_E_ASN1_EOD, but accept CRYPT_E_ASN1_CORRUPT as
671 * well (because matching errors is tough in this case)
673 ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD || GetLastError() ==
674 CRYPT_E_ASN1_CORRUPT),
675 "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %08lx\n",
677 /* add a "signed" cert--the signature isn't a real signature, so this adds
678 * without any check of the signature's validity
680 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
681 signedBigCert, sizeof(signedBigCert), CERT_STORE_ADD_ALWAYS, &context);
682 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
683 ok(context != NULL, "Expected a valid cert context\n");
686 ok(context->cbCertEncoded == sizeof(signedBigCert),
687 "Wrong cert size %ld\n", context->cbCertEncoded);
688 ok(!memcmp(context->pbCertEncoded, signedBigCert,
689 sizeof(signedBigCert)), "Unexpected encoded cert in context\n");
690 /* remove it, the rest of the tests will work on an unsigned cert */
691 ret = CertDeleteCertificateFromStore(context);
692 ok(ret, "CertDeleteCertificateFromStore failed: %08lx\n",
695 /* try adding a "signed" CRL as a cert */
696 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
697 signedCRL, sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, &context);
698 ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG || GetLastError() ==
699 CRYPT_E_ASN1_CORRUPT),
700 "Expected CRYPT_E_ASN1_BADTAG or CRYPT_E_ASN1_CORRUPT, got %08lx\n",
702 /* add a cert to store1 */
703 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING, bigCert,
704 sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
705 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
706 ok(context != NULL, "Expected a valid cert context\n");
712 ok(context->cbCertEncoded == sizeof(bigCert),
713 "Wrong cert size %ld\n", context->cbCertEncoded);
714 ok(!memcmp(context->pbCertEncoded, bigCert, sizeof(bigCert)),
715 "Unexpected encoded cert in context\n");
716 ok(context->hCertStore == store1, "Unexpected store\n");
718 /* check serializing this element */
720 ret = CertSerializeCertificateStoreElement(NULL, 0, NULL, NULL);
721 ret = CertSerializeCertificateStoreElement(context, 0, NULL, NULL);
722 ret = CertSerializeCertificateStoreElement(NULL, 0, NULL, &size);
724 /* apparently flags are ignored */
725 ret = CertSerializeCertificateStoreElement(context, 1, NULL, &size);
726 ok(ret, "CertSerializeCertificateStoreElement failed: %08lx\n",
728 buf = HeapAlloc(GetProcessHeap(), 0, size);
731 ret = CertSerializeCertificateStoreElement(context, 0, buf, &size);
732 ok(size == sizeof(serializedCert), "Wrong size %ld\n", size);
733 ok(!memcmp(serializedCert, buf, size),
734 "Unexpected serialized cert\n");
735 HeapFree(GetProcessHeap(), 0, buf);
738 ret = CertFreeCertificateContext(context);
739 ok(ret, "CertFreeCertificateContext failed: %08lx\n", GetLastError());
741 /* verify the cert's in store1 */
742 context = CertEnumCertificatesInStore(store1, NULL);
743 ok(context != NULL, "Expected a valid context\n");
744 context = CertEnumCertificatesInStore(store1, context);
745 ok(!context && GetLastError() == CRYPT_E_NOT_FOUND,
746 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
747 /* verify store2 (the "open existing" mem store) is still empty */
748 context = CertEnumCertificatesInStore(store2, NULL);
749 ok(!context, "Expected an empty store\n");
750 /* delete the cert from store1, and check it's empty */
751 context = CertEnumCertificatesInStore(store1, NULL);
754 /* Deleting a bitwise copy crashes with an access to an uninitialized
755 * pointer, so a cert context has some special data out there in memory
758 memcpy(©, context, sizeof(copy));
759 ret = CertDeleteCertificateFromStore(©);
761 PCCERT_CONTEXT copy = CertDuplicateCertificateContext(context);
763 ok(copy != NULL, "CertDuplicateCertificateContext failed: %08lx\n",
765 ret = CertDeleteCertificateFromStore(context);
766 ok(ret, "CertDeleteCertificateFromStore failed: %08lx\n",
768 /* try deleting a copy */
769 ret = CertDeleteCertificateFromStore(copy);
770 ok(ret, "CertDeleteCertificateFromStore failed: %08lx\n",
772 /* check that the store is empty */
773 context = CertEnumCertificatesInStore(store1, NULL);
774 ok(!context, "Expected an empty store\n");
777 /* close an empty store */
778 ret = CertCloseStore(NULL, 0);
779 ok(ret, "CertCloseStore failed: %ld\n", GetLastError());
780 ret = CertCloseStore(store1, 0);
781 ok(ret, "CertCloseStore failed: %ld\n", GetLastError());
782 ret = CertCloseStore(store2, 0);
783 ok(ret, "CertCloseStore failed: %ld\n", GetLastError());
785 /* This seems nonsensical, but you can open a read-only mem store, only
788 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
789 CERT_STORE_READONLY_FLAG, NULL);
790 ok(store1 != NULL, "CertOpenStore failed: %ld\n", GetLastError());
791 /* yep, this succeeds */
792 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING, bigCert,
793 sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
794 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
795 ok(context != NULL, "Expected a valid cert context\n");
798 ok(context->cbCertEncoded == sizeof(bigCert),
799 "Wrong cert size %ld\n", context->cbCertEncoded);
800 ok(!memcmp(context->pbCertEncoded, bigCert, sizeof(bigCert)),
801 "Unexpected encoded cert in context\n");
802 ok(context->hCertStore == store1, "Unexpected store\n");
803 ret = CertDeleteCertificateFromStore(context);
804 ok(ret, "CertDeleteCertificateFromStore failed: %08lx\n",
807 CertCloseStore(store1, 0);
810 static void testCollectionStore(void)
812 HCERTSTORE store1, store2, collection, collection2;
813 PCCERT_CONTEXT context;
816 collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
817 CERT_STORE_CREATE_NEW_FLAG, NULL);
819 /* Try adding a cert to any empty collection */
820 ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
821 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
822 ok(!ret && GetLastError() == E_ACCESSDENIED,
823 "Expected E_ACCESSDENIED, got %08lx\n", GetLastError());
825 /* Create and add a cert to a memory store */
826 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
827 CERT_STORE_CREATE_NEW_FLAG, NULL);
828 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
829 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
830 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
831 /* Add the memory store to the collection, without allowing adding */
832 ret = CertAddStoreToCollection(collection, store1, 0, 0);
833 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
834 /* Verify the cert is in the collection */
835 context = CertEnumCertificatesInStore(collection, NULL);
836 ok(context != NULL, "Expected a valid context\n");
839 ok(context->hCertStore == collection, "Unexpected store\n");
840 CertFreeCertificateContext(context);
842 /* Check that adding to the collection isn't allowed */
843 ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
844 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_ALWAYS, NULL);
845 ok(!ret && GetLastError() == E_ACCESSDENIED,
846 "Expected E_ACCESSDENIED, got %08lx\n", GetLastError());
848 /* Create a new memory store */
849 store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
850 CERT_STORE_CREATE_NEW_FLAG, NULL);
851 /* Try adding a store to a non-collection store */
852 ret = CertAddStoreToCollection(store1, store2,
853 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
854 ok(!ret && GetLastError() == E_INVALIDARG,
855 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
856 /* Try adding some bogus stores */
857 /* This crashes in Windows
858 ret = CertAddStoreToCollection(0, store2,
859 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
861 /* This "succeeds"... */
862 ret = CertAddStoreToCollection(collection, 0,
863 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
864 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
865 /* while this crashes.
866 ret = CertAddStoreToCollection(collection, 1,
867 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
870 /* Add it to the collection, this time allowing adding */
871 ret = CertAddStoreToCollection(collection, store2,
872 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
873 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
874 /* Check that adding to the collection is allowed */
875 ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
876 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_ALWAYS, NULL);
877 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
878 /* Now check that it was actually added to store2 */
879 context = CertEnumCertificatesInStore(store2, NULL);
880 ok(context != NULL, "Expected a valid context\n");
883 ok(context->hCertStore == store2, "Unexpected store\n");
884 CertFreeCertificateContext(context);
886 /* Check that the collection has both bigCert and bigCert2. bigCert comes
887 * first because store1 was added first.
889 context = CertEnumCertificatesInStore(collection, NULL);
890 ok(context != NULL, "Expected a valid context\n");
893 ok(context->hCertStore == collection, "Unexpected store\n");
894 ok(context->cbCertEncoded == sizeof(bigCert),
895 "Wrong size %ld\n", context->cbCertEncoded);
896 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
897 "Unexpected cert\n");
898 context = CertEnumCertificatesInStore(collection, context);
899 ok(context != NULL, "Expected a valid context\n");
902 ok(context->hCertStore == collection, "Unexpected store\n");
903 ok(context->cbCertEncoded == sizeof(bigCert2),
904 "Wrong size %ld\n", context->cbCertEncoded);
905 ok(!memcmp(context->pbCertEncoded, bigCert2,
906 context->cbCertEncoded), "Unexpected cert\n");
907 context = CertEnumCertificatesInStore(collection, context);
908 ok(!context, "Unexpected cert\n");
911 /* close store2, and check that the collection is unmodified */
912 CertCloseStore(store2, 0);
913 context = CertEnumCertificatesInStore(collection, NULL);
914 ok(context != NULL, "Expected a valid context\n");
917 ok(context->hCertStore == collection, "Unexpected store\n");
918 ok(context->cbCertEncoded == sizeof(bigCert),
919 "Wrong size %ld\n", context->cbCertEncoded);
920 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
921 "Unexpected cert\n");
922 context = CertEnumCertificatesInStore(collection, context);
923 ok(context != NULL, "Expected a valid context\n");
926 ok(context->hCertStore == collection, "Unexpected store\n");
927 ok(context->cbCertEncoded == sizeof(bigCert2),
928 "Wrong size %ld\n", context->cbCertEncoded);
929 ok(!memcmp(context->pbCertEncoded, bigCert2,
930 context->cbCertEncoded), "Unexpected cert\n");
931 context = CertEnumCertificatesInStore(collection, context);
932 ok(!context, "Unexpected cert\n");
936 /* Adding a collection to a collection is legal */
937 collection2 = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
938 CERT_STORE_CREATE_NEW_FLAG, NULL);
939 ret = CertAddStoreToCollection(collection2, collection,
940 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
941 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
942 /* check the contents of collection2 */
943 context = CertEnumCertificatesInStore(collection2, NULL);
944 ok(context != NULL, "Expected a valid context\n");
947 ok(context->hCertStore == collection2, "Unexpected store\n");
948 ok(context->cbCertEncoded == sizeof(bigCert),
949 "Wrong size %ld\n", context->cbCertEncoded);
950 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
951 "Unexpected cert\n");
952 context = CertEnumCertificatesInStore(collection2, context);
953 ok(context != NULL, "Expected a valid context\n");
956 ok(context->hCertStore == collection2, "Unexpected store\n");
957 ok(context->cbCertEncoded == sizeof(bigCert2),
958 "Wrong size %ld\n", context->cbCertEncoded);
959 ok(!memcmp(context->pbCertEncoded, bigCert2,
960 context->cbCertEncoded), "Unexpected cert\n");
961 context = CertEnumCertificatesInStore(collection2, context);
962 ok(!context, "Unexpected cert\n");
966 /* I'd like to test closing the collection in the middle of enumeration,
967 * but my tests have been inconsistent. The first time calling
968 * CertEnumCertificatesInStore on a closed collection succeeded, while the
969 * second crashed. So anything appears to be fair game.
970 * I'd also like to test removing a store from a collection in the middle
971 * of an enumeration, but my tests in Windows have been inconclusive.
972 * In one scenario it worked. In another scenario, about a third of the
973 * time this leads to "random" crashes elsewhere in the code. This
974 * probably means this is not allowed.
977 CertCloseStore(store1, 0);
978 CertCloseStore(collection, 0);
979 CertCloseStore(collection2, 0);
981 /* Add the same cert to two memory stores, then put them in a collection */
982 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
983 CERT_STORE_CREATE_NEW_FLAG, NULL);
984 ok(store1 != 0, "CertOpenStore failed: %08lx\n", GetLastError());
985 store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
986 CERT_STORE_CREATE_NEW_FLAG, NULL);
987 ok(store2 != 0, "CertOpenStore failed: %08lx\n", GetLastError());
989 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
990 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
991 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
992 ret = CertAddEncodedCertificateToStore(store2, X509_ASN_ENCODING,
993 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
994 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
995 collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
996 CERT_STORE_CREATE_NEW_FLAG, NULL);
997 ok(collection != 0, "CertOpenStore failed: %08lx\n", GetLastError());
999 ret = CertAddStoreToCollection(collection, store1,
1000 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
1001 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
1002 ret = CertAddStoreToCollection(collection, store2,
1003 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
1004 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
1006 /* Check that the collection has two copies of the same cert */
1007 context = CertEnumCertificatesInStore(collection, NULL);
1008 ok(context != NULL, "Expected a valid context\n");
1011 ok(context->hCertStore == collection, "Unexpected store\n");
1012 ok(context->cbCertEncoded == sizeof(bigCert),
1013 "Wrong size %ld\n", context->cbCertEncoded);
1014 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
1015 "Unexpected cert\n");
1016 context = CertEnumCertificatesInStore(collection, context);
1017 ok(context != NULL, "Expected a valid context\n");
1020 ok(context->hCertStore == collection, "Unexpected store\n");
1021 ok(context->cbCertEncoded == sizeof(bigCert),
1022 "Wrong size %ld\n", context->cbCertEncoded);
1023 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
1024 "Unexpected cert\n");
1025 context = CertEnumCertificatesInStore(collection, context);
1026 ok(context == NULL, "Unexpected cert\n");
1030 /* The following would check whether I can delete an identical cert, rather
1031 * than one enumerated from the store. It crashes, so that means I must
1032 * only call CertDeleteCertificateFromStore with contexts enumerated from
1034 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
1036 ok(context != NULL, "CertCreateCertificateContext failed: %08lx\n",
1040 ret = CertDeleteCertificateFromStore(collection, context);
1041 printf("ret is %d, GetLastError is %08lx\n", ret, GetLastError());
1042 CertFreeCertificateContext(context);
1046 /* Now check deleting from the collection. */
1047 context = CertEnumCertificatesInStore(collection, NULL);
1048 ok(context != NULL, "Expected a valid context\n");
1051 CertDeleteCertificateFromStore(context);
1052 /* store1 should now be empty */
1053 context = CertEnumCertificatesInStore(store1, NULL);
1054 ok(!context, "Unexpected cert\n");
1055 /* and there should be one certificate in the collection */
1056 context = CertEnumCertificatesInStore(collection, NULL);
1057 ok(context != NULL, "Expected a valid cert\n");
1060 ok(context->hCertStore == collection, "Unexpected store\n");
1061 ok(context->cbCertEncoded == sizeof(bigCert),
1062 "Wrong size %ld\n", context->cbCertEncoded);
1063 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
1064 "Unexpected cert\n");
1066 context = CertEnumCertificatesInStore(collection, context);
1067 ok(context == NULL, "Unexpected cert\n");
1070 /* Finally, test removing stores from the collection. No return value, so
1071 * it's a bit funny to test.
1074 CertRemoveStoreFromCollection(NULL, NULL);
1076 /* This "succeeds," no crash, no last error set */
1077 SetLastError(0xdeadbeef);
1078 CertRemoveStoreFromCollection(store2, collection);
1079 ok(GetLastError() == 0xdeadbeef,
1080 "Didn't expect an error to be set: %08lx\n", GetLastError());
1082 /* After removing store2, the collection should be empty */
1083 SetLastError(0xdeadbeef);
1084 CertRemoveStoreFromCollection(collection, store2);
1085 ok(GetLastError() == 0xdeadbeef,
1086 "Didn't expect an error to be set: %08lx\n", GetLastError());
1087 context = CertEnumCertificatesInStore(collection, NULL);
1088 ok(!context, "Unexpected cert\n");
1090 CertCloseStore(collection, 0);
1091 CertCloseStore(store2, 0);
1092 CertCloseStore(store1, 0);
1095 /* Looks for the property with ID propID in the buffer buf. Returns a pointer
1096 * to its header if found, NULL if not.
1098 static const struct CertPropIDHeader *findPropID(const BYTE *buf, DWORD size,
1101 const struct CertPropIDHeader *ret = NULL;
1102 BOOL failed = FALSE;
1104 while (size && !ret && !failed)
1106 if (size < sizeof(struct CertPropIDHeader))
1110 const struct CertPropIDHeader *hdr =
1111 (const struct CertPropIDHeader *)buf;
1113 size -= sizeof(struct CertPropIDHeader);
1114 buf += sizeof(struct CertPropIDHeader);
1117 else if (hdr->propID == propID)
1129 typedef DWORD (WINAPI *SHDeleteKeyAFunc)(HKEY, LPCSTR);
1131 static void testRegStore(void)
1133 static const char tempKey[] = "Software\\Wine\\CryptTemp";
1139 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, NULL);
1140 ok(!store && GetLastError() == ERROR_INVALID_HANDLE,
1141 "Expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
1142 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, key);
1143 ok(!store && GetLastError() == ERROR_INVALID_HANDLE,
1144 "Expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
1146 /* Opening up any old key works.. */
1147 key = HKEY_CURRENT_USER;
1148 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, key);
1149 /* Not sure if this is a bug in DuplicateHandle, marking todo_wine for now
1151 todo_wine ok(store != 0, "CertOpenStore failed: %08lx\n", GetLastError());
1152 CertCloseStore(store, 0);
1154 rc = RegCreateKeyExA(HKEY_CURRENT_USER, tempKey, 0, NULL, 0, KEY_ALL_ACCESS,
1156 ok(!rc, "RegCreateKeyExA failed: %ld\n", rc);
1162 static const char certificates[] = "Certificates\\";
1163 char subKeyName[sizeof(certificates) + 20 * 2 + 1], *ptr;
1165 PCCERT_CONTEXT context;
1167 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, key);
1168 ok(store != 0, "CertOpenStore failed: %08lx\n", GetLastError());
1169 /* Add a certificate. It isn't persisted right away, since it's only
1170 * added to the cache..
1172 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1173 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_ALWAYS, NULL);
1174 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
1176 /* so flush the cache to force a commit.. */
1177 ret = CertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
1178 ok(ret, "CertControlStore failed: %08lx\n", GetLastError());
1179 /* and check that the expected subkey was written. */
1180 size = sizeof(hash);
1181 ret = CryptHashCertificate(0, 0, 0, bigCert2, sizeof(bigCert2),
1183 ok(ret, "CryptHashCertificate failed: %ld\n", GetLastError());
1184 strcpy(subKeyName, certificates);
1185 for (i = 0, ptr = subKeyName + sizeof(certificates) - 1; i < size;
1187 sprintf(ptr, "%02X", hash[i]);
1188 rc = RegCreateKeyExA(key, subKeyName, 0, NULL, 0, KEY_ALL_ACCESS, NULL,
1190 ok(!rc, "RegCreateKeyExA failed: %ld\n", rc);
1196 RegQueryValueExA(subKey, "Blob", NULL, NULL, NULL, &size);
1197 buf = HeapAlloc(GetProcessHeap(), 0, size);
1200 rc = RegQueryValueExA(subKey, "Blob", NULL, NULL, buf, &size);
1201 ok(!rc, "RegQueryValueExA failed: %ld\n", rc);
1204 const struct CertPropIDHeader *hdr;
1206 /* Both the hash and the cert should be present */
1207 hdr = findPropID(buf, size, CERT_CERT_PROP_ID);
1208 ok(hdr != NULL, "Expected to find a cert property\n");
1211 ok(hdr->cb == sizeof(bigCert2),
1212 "Wrong size %ld of cert property\n", hdr->cb);
1213 ok(!memcmp((BYTE *)hdr + sizeof(*hdr), bigCert2,
1214 hdr->cb), "Unexpected cert in cert property\n");
1216 hdr = findPropID(buf, size, CERT_HASH_PROP_ID);
1217 ok(hdr != NULL, "Expected to find a hash property\n");
1220 ok(hdr->cb == sizeof(hash),
1221 "Wrong size %ld of hash property\n", hdr->cb);
1222 ok(!memcmp((BYTE *)hdr + sizeof(*hdr), hash,
1223 hdr->cb), "Unexpected hash in cert property\n");
1226 HeapFree(GetProcessHeap(), 0, buf);
1228 RegCloseKey(subKey);
1231 /* Remove the existing context */
1232 context = CertEnumCertificatesInStore(store, NULL);
1233 ok(context != NULL, "Expected a cert context\n");
1235 CertDeleteCertificateFromStore(context);
1236 ret = CertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
1237 ok(ret, "CertControlStore failed: %08lx\n", GetLastError());
1239 /* Add a serialized cert with a bogus hash directly to the registry */
1240 memset(hash, 0, sizeof(hash));
1241 strcpy(subKeyName, certificates);
1242 for (i = 0, ptr = subKeyName + sizeof(certificates) - 1;
1243 i < sizeof(hash); i++, ptr += 2)
1244 sprintf(ptr, "%02X", hash[i]);
1245 rc = RegCreateKeyExA(key, subKeyName, 0, NULL, 0, KEY_ALL_ACCESS, NULL,
1247 ok(!rc, "RegCreateKeyExA failed: %ld\n", rc);
1250 BYTE buf[sizeof(struct CertPropIDHeader) * 2 + sizeof(hash) +
1251 sizeof(bigCert)], *ptr;
1252 DWORD certCount = 0;
1253 struct CertPropIDHeader *hdr;
1255 hdr = (struct CertPropIDHeader *)buf;
1256 hdr->propID = CERT_HASH_PROP_ID;
1258 hdr->cb = sizeof(hash);
1259 ptr = buf + sizeof(*hdr);
1260 memcpy(ptr, hash, sizeof(hash));
1261 ptr += sizeof(hash);
1262 hdr = (struct CertPropIDHeader *)ptr;
1263 hdr->propID = CERT_CERT_PROP_ID;
1265 hdr->cb = sizeof(bigCert);
1266 ptr += sizeof(*hdr);
1267 memcpy(ptr, bigCert, sizeof(bigCert));
1269 rc = RegSetValueExA(subKey, "Blob", 0, REG_BINARY, buf,
1271 ok(!rc, "RegSetValueExA failed: %ld\n", rc);
1273 ret = CertControlStore(store, 0, CERT_STORE_CTRL_RESYNC, NULL);
1274 ok(ret, "CertControlStore failed: %08lx\n", GetLastError());
1276 /* Make sure the bogus hash cert gets loaded. */
1280 context = CertEnumCertificatesInStore(store, context);
1283 } while (context != NULL);
1284 ok(certCount == 1, "Expected 1 certificates, got %ld\n", certCount);
1286 RegCloseKey(subKey);
1289 /* Add another serialized cert directly to the registry, this time
1290 * under the correct key name (named with the correct hash value).
1292 size = sizeof(hash);
1293 ret = CryptHashCertificate(0, 0, 0, bigCert2,
1294 sizeof(bigCert2), hash, &size);
1295 ok(ret, "CryptHashCertificate failed: %ld\n", GetLastError());
1296 strcpy(subKeyName, certificates);
1297 for (i = 0, ptr = subKeyName + sizeof(certificates) - 1;
1298 i < sizeof(hash); i++, ptr += 2)
1299 sprintf(ptr, "%02X", hash[i]);
1300 rc = RegCreateKeyExA(key, subKeyName, 0, NULL, 0, KEY_ALL_ACCESS, NULL,
1302 ok(!rc, "RegCreateKeyExA failed: %ld\n", rc);
1305 BYTE buf[sizeof(struct CertPropIDHeader) * 2 + sizeof(hash) +
1306 sizeof(bigCert2)], *ptr;
1307 DWORD certCount = 0;
1308 PCCERT_CONTEXT context;
1309 struct CertPropIDHeader *hdr;
1311 /* First try with a bogus hash... */
1312 hdr = (struct CertPropIDHeader *)buf;
1313 hdr->propID = CERT_HASH_PROP_ID;
1315 hdr->cb = sizeof(hash);
1316 ptr = buf + sizeof(*hdr);
1317 memset(ptr, 0, sizeof(hash));
1318 ptr += sizeof(hash);
1319 hdr = (struct CertPropIDHeader *)ptr;
1320 hdr->propID = CERT_CERT_PROP_ID;
1322 hdr->cb = sizeof(bigCert2);
1323 ptr += sizeof(*hdr);
1324 memcpy(ptr, bigCert2, sizeof(bigCert2));
1326 rc = RegSetValueExA(subKey, "Blob", 0, REG_BINARY, buf,
1328 ok(!rc, "RegSetValueExA failed: %ld\n", rc);
1330 ret = CertControlStore(store, 0, CERT_STORE_CTRL_RESYNC, NULL);
1331 ok(ret, "CertControlStore failed: %08lx\n", GetLastError());
1333 /* and make sure just one cert still gets loaded. */
1337 context = CertEnumCertificatesInStore(store, context);
1340 } while (context != NULL);
1341 ok(certCount == 1, "Expected 1 certificates, got %ld\n", certCount);
1343 /* Try again with the correct hash... */
1344 ptr = buf + sizeof(*hdr);
1345 memcpy(ptr, hash, sizeof(hash));
1347 rc = RegSetValueExA(subKey, "Blob", 0, REG_BINARY, buf,
1349 ok(!rc, "RegSetValueExA failed: %ld\n", rc);
1351 ret = CertControlStore(store, 0, CERT_STORE_CTRL_RESYNC, NULL);
1352 ok(ret, "CertControlStore failed: %08lx\n", GetLastError());
1354 /* and make sure two certs get loaded. */
1358 context = CertEnumCertificatesInStore(store, context);
1361 } while (context != NULL);
1362 ok(certCount == 2, "Expected 2 certificates, got %ld\n", certCount);
1364 RegCloseKey(subKey);
1366 CertCloseStore(store, 0);
1367 /* Is delete allowed on a reg store? */
1368 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0,
1369 CERT_STORE_DELETE_FLAG, key);
1370 ok(store == NULL, "Expected NULL return from CERT_STORE_DELETE_FLAG\n");
1371 ok(GetLastError() == 0, "CertOpenStore failed: %08lx\n",
1376 /* The CertOpenStore with CERT_STORE_DELETE_FLAG above will delete the
1377 * contents of the key, but not the key itself.
1379 rc = RegCreateKeyExA(HKEY_CURRENT_USER, tempKey, 0, NULL, 0, KEY_ALL_ACCESS,
1381 ok(!rc, "RegCreateKeyExA failed: %ld\n", rc);
1382 ok(disp == REG_OPENED_EXISTING_KEY,
1383 "Expected REG_OPENED_EXISTING_KEY, got %ld\n", disp);
1387 rc = RegDeleteKeyA(HKEY_CURRENT_USER, tempKey);
1390 HMODULE shlwapi = LoadLibraryA("shlwapi");
1392 /* Use shlwapi's SHDeleteKeyA to _really_ blow away the key,
1393 * otherwise subsequent tests will fail.
1397 SHDeleteKeyAFunc pSHDeleteKeyA =
1398 (SHDeleteKeyAFunc)GetProcAddress(shlwapi, "SHDeleteKeyA");
1401 pSHDeleteKeyA(HKEY_CURRENT_USER, tempKey);
1402 FreeLibrary(shlwapi);
1408 static const char MyA[] = { 'M','y',0,0 };
1409 static const WCHAR MyW[] = { 'M','y',0 };
1410 static const WCHAR BogusW[] = { 'B','o','g','u','s',0 };
1411 static const WCHAR BogusPathW[] = { 'S','o','f','t','w','a','r','e','\\',
1412 'M','i','c','r','o','s','o','f','t','\\','S','y','s','t','e','m','C','e','r',
1413 't','i','f','i','c','a','t','e','s','\\','B','o','g','u','s',0 };
1415 static void testSystemRegStore(void)
1417 HCERTSTORE store, memStore;
1419 /* Check with a UNICODE name */
1420 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1421 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyW);
1422 /* Not all OSes support CERT_STORE_PROV_SYSTEM_REGISTRY, so don't continue
1423 * testing if they don't.
1428 /* Check that it isn't a collection store */
1429 memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1430 CERT_STORE_CREATE_NEW_FLAG, NULL);
1433 BOOL ret = CertAddStoreToCollection(store, memStore, 0, 0);
1435 ok(!ret && GetLastError() == E_INVALIDARG,
1436 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1437 CertCloseStore(memStore, 0);
1439 CertCloseStore(store, 0);
1441 /* Check opening a bogus store */
1442 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1443 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, BogusW);
1444 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1445 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1446 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1447 CERT_SYSTEM_STORE_CURRENT_USER, BogusW);
1448 ok(store != 0, "CertOpenStore failed: %08lx\n", GetLastError());
1450 CertCloseStore(store, 0);
1451 /* Now check whether deleting is allowed */
1452 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1453 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_DELETE_FLAG, BogusW);
1454 RegDeleteKeyW(HKEY_CURRENT_USER, BogusPathW);
1456 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0, 0, NULL);
1457 ok(!store && GetLastError() == E_INVALIDARG,
1458 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1459 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1460 CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyA);
1461 ok(!store && GetLastError() == E_INVALIDARG,
1462 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1463 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1464 CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyW);
1465 ok(!store && GetLastError() == E_INVALIDARG,
1466 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1467 /* The name is expected to be UNICODE, check with an ASCII name */
1468 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1469 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyA);
1470 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1471 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1474 static void testSystemStore(void)
1476 static const WCHAR baskslashW[] = { '\\',0 };
1478 WCHAR keyName[MAX_PATH];
1482 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, 0, NULL);
1483 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1484 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1485 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1486 CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyA);
1487 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1488 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1489 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1490 CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyW);
1491 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1492 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1493 /* The name is expected to be UNICODE, first check with an ASCII name */
1494 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1495 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyA);
1496 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1497 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1498 /* Create the expected key */
1499 lstrcpyW(keyName, CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH);
1500 lstrcatW(keyName, baskslashW);
1501 lstrcatW(keyName, MyW);
1502 rc = RegCreateKeyExW(HKEY_CURRENT_USER, keyName, 0, NULL, 0, KEY_READ,
1504 ok(!rc, "RegCreateKeyEx failed: %ld\n", rc);
1507 /* Check opening with a UNICODE name, specifying the create new flag */
1508 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1509 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_CREATE_NEW_FLAG, MyW);
1510 ok(!store && GetLastError() == ERROR_FILE_EXISTS,
1511 "Expected ERROR_FILE_EXISTS, got %08lx\n", GetLastError());
1512 /* Now check opening with a UNICODE name, this time opening existing */
1513 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1514 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyW);
1515 ok(store != 0, "CertOpenStore failed: %08lx\n", GetLastError());
1518 HCERTSTORE memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1519 CERT_STORE_CREATE_NEW_FLAG, NULL);
1521 /* Check that it's a collection store */
1524 BOOL ret = CertAddStoreToCollection(store, memStore, 0, 0);
1526 /* FIXME: this'll fail on NT4, but what error will it give? */
1527 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
1528 CertCloseStore(memStore, 0);
1530 CertCloseStore(store, 0);
1533 /* Check opening a bogus store */
1534 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1535 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, BogusW);
1536 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1537 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1538 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1539 CERT_SYSTEM_STORE_CURRENT_USER, BogusW);
1540 ok(store != 0, "CertOpenStore failed: %08lx\n", GetLastError());
1542 CertCloseStore(store, 0);
1543 /* Now check whether deleting is allowed */
1544 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1545 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_DELETE_FLAG, BogusW);
1546 RegDeleteKeyW(HKEY_CURRENT_USER, BogusPathW);
1549 static void testCertOpenSystemStore(void)
1553 store = CertOpenSystemStoreW(0, NULL);
1554 ok(!store && GetLastError() == E_INVALIDARG,
1555 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1556 /* This succeeds, and on WinXP at least, the Bogus key is created under
1557 * HKCU (but not under HKLM, even when run as an administrator.)
1559 store = CertOpenSystemStoreW(0, BogusW);
1560 ok(store != 0, "CertOpenSystemStore failed: %08lx\n", GetLastError());
1562 CertCloseStore(store, 0);
1563 /* Delete it so other tests succeed next time around */
1564 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1565 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_DELETE_FLAG, BogusW);
1566 RegDeleteKeyW(HKEY_CURRENT_USER, BogusPathW);
1569 static void checkHash(const BYTE *data, DWORD dataLen, ALG_ID algID,
1570 PCCERT_CONTEXT context, DWORD propID)
1572 BYTE hash[20] = { 0 }, hashProperty[20];
1576 memset(hash, 0, sizeof(hash));
1577 memset(hashProperty, 0, sizeof(hashProperty));
1578 size = sizeof(hash);
1579 ret = CryptHashCertificate(0, algID, 0, data, dataLen, hash, &size);
1580 ok(ret, "CryptHashCertificate failed: %08lx\n", GetLastError());
1581 ret = CertGetCertificateContextProperty(context, propID, hashProperty,
1583 ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
1585 ok(!memcmp(hash, hashProperty, size), "Unexpected hash for property %ld\n",
1589 static void testCertProperties(void)
1591 PCCERT_CONTEXT context = CertCreateCertificateContext(X509_ASN_ENCODING,
1592 bigCert, sizeof(bigCert));
1594 ok(context != NULL, "CertCreateCertificateContext failed: %08lx\n",
1598 DWORD propID, numProps, access, size;
1600 BYTE hash[20] = { 0 }, hashProperty[20];
1601 CRYPT_DATA_BLOB blob;
1604 propID = CertEnumCertificateContextProperties(NULL, 0);
1610 propID = CertEnumCertificateContextProperties(context, propID);
1613 } while (propID != 0);
1614 ok(numProps == 0, "Expected 0 properties, got %ld\n", numProps);
1616 /* Tests with a NULL cert context. Prop ID 0 fails.. */
1617 ret = CertSetCertificateContextProperty(NULL, 0, 0, NULL);
1618 ok(!ret && GetLastError() == E_INVALIDARG,
1619 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1620 /* while this just crashes.
1621 ret = CertSetCertificateContextProperty(NULL,
1622 CERT_KEY_PROV_HANDLE_PROP_ID, 0, NULL);
1625 ret = CertSetCertificateContextProperty(context, 0, 0, NULL);
1626 ok(!ret && GetLastError() == E_INVALIDARG,
1627 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1628 /* Can't set the cert property directly, this crashes.
1629 ret = CertSetCertificateContextProperty(context,
1630 CERT_CERT_PROP_ID, 0, bigCert2);
1634 ret = CertGetCertificateContextProperty(context,
1635 CERT_ACCESS_STATE_PROP_ID, 0, NULL);
1636 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
1638 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
1639 hashProperty, NULL);
1641 /* A missing prop */
1643 ret = CertGetCertificateContextProperty(context,
1644 CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
1645 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
1646 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
1647 /* And, an implicit property */
1648 size = sizeof(access);
1649 ret = CertGetCertificateContextProperty(context,
1650 CERT_ACCESS_STATE_PROP_ID, &access, &size);
1651 ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
1653 ok(!(access & CERT_ACCESS_STATE_WRITE_PERSIST_FLAG),
1654 "Didn't expect a persisted cert\n");
1655 /* Trying to set this "read only" property crashes.
1656 access |= CERT_ACCESS_STATE_WRITE_PERSIST_FLAG;
1657 ret = CertSetCertificateContextProperty(context,
1658 CERT_ACCESS_STATE_PROP_ID, 0, &access);
1661 /* Can I set the hash to an invalid hash? */
1663 blob.cbData = sizeof(hash);
1664 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID, 0,
1666 ok(ret, "CertSetCertificateContextProperty failed: %08lx\n",
1668 size = sizeof(hashProperty);
1669 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
1670 hashProperty, &size);
1671 ok(!memcmp(hashProperty, hash, sizeof(hash)), "Unexpected hash\n");
1672 /* Delete the (bogus) hash, and get the real one */
1673 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID, 0,
1675 ok(ret, "CertSetCertificateContextProperty failed: %08lx\n",
1677 checkHash(bigCert, sizeof(bigCert), CALG_SHA1, context,
1680 /* Now that the hash property is set, we should get one property when
1686 propID = CertEnumCertificateContextProperties(context, propID);
1689 } while (propID != 0);
1690 ok(numProps == 1, "Expected 1 properties, got %ld\n", numProps);
1692 /* Check a few other implicit properties */
1693 checkHash(bigCert, sizeof(bigCert), CALG_MD5, context,
1694 CERT_MD5_HASH_PROP_ID);
1696 context->pCertInfo->Subject.pbData,
1697 context->pCertInfo->Subject.cbData,
1698 CALG_MD5, context, CERT_SUBJECT_NAME_MD5_HASH_PROP_ID);
1700 context->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData,
1701 context->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData,
1702 CALG_MD5, context, CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID);
1704 /* Odd: this doesn't fail on other certificates, so there must be
1705 * something weird about this cert that causes it to fail.
1708 ret = CertGetCertificateContextProperty(context,
1709 CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size);
1710 todo_wine ok(!ret && GetLastError() == ERROR_INVALID_DATA,
1711 "Expected ERROR_INVALID_DATA, got %08lx\n", GetLastError());
1713 CertFreeCertificateContext(context);
1717 static void testAddSerialized(void)
1721 BYTE buf[sizeof(struct CertPropIDHeader) * 2 + 20 + sizeof(bigCert)] =
1724 struct CertPropIDHeader *hdr;
1725 PCCERT_CONTEXT context;
1727 ret = CertAddSerializedElementToStore(0, NULL, 0, 0, 0, 0, NULL, NULL);
1728 ok(!ret && GetLastError() == ERROR_END_OF_MEDIA,
1729 "Expected ERROR_END_OF_MEDIA, got %08lx\n", GetLastError());
1731 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1732 CERT_STORE_CREATE_NEW_FLAG, NULL);
1733 ok(store != 0, "CertOpenStore failed: %08lx\n", GetLastError());
1735 ret = CertAddSerializedElementToStore(store, NULL, 0, 0, 0, 0, NULL, NULL);
1736 ok(!ret && GetLastError() == ERROR_END_OF_MEDIA,
1737 "Expected ERROR_END_OF_MEDIA, got %08lx\n", GetLastError());
1739 /* Test with an empty property */
1740 hdr = (struct CertPropIDHeader *)buf;
1741 hdr->propID = CERT_CERT_PROP_ID;
1744 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0,
1746 ok(!ret && GetLastError() == E_INVALIDARG,
1747 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1748 /* Test with a bad size in property header */
1749 hdr->cb = sizeof(bigCert) - 1;
1750 memcpy(buf + sizeof(struct CertPropIDHeader), bigCert, sizeof(bigCert));
1751 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0,
1753 ok(!ret && GetLastError() == E_INVALIDARG,
1754 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1755 ret = CertAddSerializedElementToStore(store, buf,
1756 sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0, 0, NULL,
1758 ok(!ret && GetLastError() == E_INVALIDARG,
1759 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1760 ret = CertAddSerializedElementToStore(store, buf,
1761 sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
1763 ok(!ret && GetLastError() == E_INVALIDARG,
1764 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1765 /* Kosher size in property header, but no context type */
1766 hdr->cb = sizeof(bigCert);
1767 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0,
1769 ok(!ret && GetLastError() == E_INVALIDARG,
1770 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1771 ret = CertAddSerializedElementToStore(store, buf,
1772 sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0, 0, NULL,
1774 ok(!ret && GetLastError() == E_INVALIDARG,
1775 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1776 ret = CertAddSerializedElementToStore(store, buf,
1777 sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
1779 ok(!ret && GetLastError() == E_INVALIDARG,
1780 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1781 /* With a bad context type */
1782 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0,
1783 CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL);
1784 ok(!ret && GetLastError() == E_INVALIDARG,
1785 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1786 ret = CertAddSerializedElementToStore(store, buf,
1787 sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0,
1788 CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL);
1789 ok(!ret && GetLastError() == E_INVALIDARG,
1790 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1791 ret = CertAddSerializedElementToStore(store, buf,
1792 sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
1793 0, CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL);
1794 ok(!ret && GetLastError() == E_INVALIDARG,
1795 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1796 /* Bad unknown field, good type */
1798 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0,
1799 CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1800 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1801 "Expected ERROR_FILE_NOT_FOUND got %08lx\n", GetLastError());
1802 ret = CertAddSerializedElementToStore(store, buf,
1803 sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0,
1804 CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1805 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1806 "Expected ERROR_FILE_NOT_FOUND got %08lx\n", GetLastError());
1807 ret = CertAddSerializedElementToStore(store, buf,
1808 sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
1809 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1810 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1811 "Expected ERROR_FILE_NOT_FOUND got %08lx\n", GetLastError());
1812 /* Most everything okay, but bad add disposition */
1815 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0,
1816 CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1818 ret = CertAddSerializedElementToStore(store, buf,
1819 sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0,
1820 CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1822 /* Everything okay, but buffer's too big */
1823 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf),
1824 CERT_STORE_ADD_NEW, 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1825 ok(ret, "CertAddSerializedElementToStore failed: %08lx\n", GetLastError());
1826 /* Everything okay, check it's not re-added */
1827 ret = CertAddSerializedElementToStore(store, buf,
1828 sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
1829 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1830 ok(!ret && GetLastError() == CRYPT_E_EXISTS,
1831 "Expected CRYPT_E_EXISTS, got %08lx\n", GetLastError());
1833 context = CertEnumCertificatesInStore(store, NULL);
1834 ok(context != NULL, "Expected a cert\n");
1836 CertDeleteCertificateFromStore(context);
1838 /* Try adding with a bogus hash. Oddly enough, it succeeds, and the hash,
1839 * when queried, is the real hash rather than the bogus hash.
1841 hdr = (struct CertPropIDHeader *)(buf + sizeof(struct CertPropIDHeader) +
1843 hdr->propID = CERT_HASH_PROP_ID;
1845 hdr->cb = sizeof(hash);
1846 memset(hash, 0xc, sizeof(hash));
1847 memcpy((LPBYTE)hdr + sizeof(struct CertPropIDHeader), hash, sizeof(hash));
1848 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf),
1849 CERT_STORE_ADD_NEW, 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL,
1850 (const void **)&context);
1851 ok(ret, "CertAddSerializedElementToStore failed: %08lx\n", GetLastError());
1854 BYTE hashVal[20], realHash[20];
1855 DWORD size = sizeof(hashVal);
1857 ret = CryptHashCertificate(0, 0, 0, bigCert, sizeof(bigCert),
1859 ok(ret, "CryptHashCertificate failed: %08lx\n", GetLastError());
1860 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
1862 ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
1864 ok(!memcmp(hashVal, realHash, size), "Unexpected hash\n");
1865 CertFreeCertificateContext(context);
1868 CertCloseStore(store, 0);
1871 static const BYTE CRL[] = { 0x30, 0x2c, 0x30, 0x02, 0x06, 0x00,
1872 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a,
1873 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 0x31,
1874 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
1876 static const BYTE newerCRL[] = { 0x30, 0x2a, 0x30, 0x02, 0x06, 0x00, 0x30,
1877 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
1878 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x17, 0x0d, 0x30, 0x36,
1879 0x30, 0x35, 0x31, 0x36, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
1881 static void testCreateCRL(void)
1883 PCCRL_CONTEXT context;
1885 context = CertCreateCRLContext(0, NULL, 0);
1886 ok(!context && GetLastError() == E_INVALIDARG,
1887 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1888 context = CertCreateCRLContext(X509_ASN_ENCODING, NULL, 0);
1889 ok(!context && GetLastError() == CRYPT_E_ASN1_EOD,
1890 "Expected CRYPT_E_ASN1_EOD, got %08lx\n", GetLastError());
1891 context = CertCreateCRLContext(X509_ASN_ENCODING, bigCert, sizeof(bigCert));
1892 ok(!context && GetLastError() == CRYPT_E_ASN1_CORRUPT,
1893 "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
1894 context = CertCreateCRLContext(X509_ASN_ENCODING, signedCRL,
1895 sizeof(signedCRL) - 1);
1896 ok(!context && (GetLastError() == CRYPT_E_ASN1_EOD ||
1897 GetLastError() == CRYPT_E_ASN1_CORRUPT),
1898 "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %08lx\n",
1900 context = CertCreateCRLContext(X509_ASN_ENCODING, signedCRL,
1902 ok(context != NULL, "CertCreateCRLContext failed: %08lx\n", GetLastError());
1904 CertFreeCRLContext(context);
1905 context = CertCreateCRLContext(X509_ASN_ENCODING, CRL, sizeof(CRL));
1906 ok(context != NULL, "CertCreateCRLContext failed: %08lx\n", GetLastError());
1908 CertFreeCRLContext(context);
1911 static void testAddCRL(void)
1913 HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1914 CERT_STORE_CREATE_NEW_FLAG, NULL);
1915 PCCRL_CONTEXT context;
1920 /* Bad CRL encoding type */
1921 ret = CertAddEncodedCRLToStore(0, 0, NULL, 0, 0, NULL);
1922 ok(!ret && GetLastError() == E_INVALIDARG,
1923 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1924 ret = CertAddEncodedCRLToStore(store, 0, NULL, 0, 0, NULL);
1925 ok(!ret && GetLastError() == E_INVALIDARG,
1926 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1927 ret = CertAddEncodedCRLToStore(0, 0, signedCRL, sizeof(signedCRL), 0, NULL);
1928 ok(!ret && GetLastError() == E_INVALIDARG,
1929 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1930 ret = CertAddEncodedCRLToStore(store, 0, signedCRL, sizeof(signedCRL), 0,
1932 ok(!ret && GetLastError() == E_INVALIDARG,
1933 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1934 ret = CertAddEncodedCRLToStore(0, 0, signedCRL, sizeof(signedCRL),
1935 CERT_STORE_ADD_ALWAYS, NULL);
1936 ok(!ret && GetLastError() == E_INVALIDARG,
1937 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1938 ret = CertAddEncodedCRLToStore(store, 0, signedCRL, sizeof(signedCRL),
1939 CERT_STORE_ADD_ALWAYS, NULL);
1940 ok(!ret && GetLastError() == E_INVALIDARG,
1941 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1944 ret = CertAddEncodedCRLToStore(0, X509_ASN_ENCODING, NULL, 0, 0, NULL);
1945 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
1946 "Expected CRYPT_E_ASN1_EOD, got %08lx\n", GetLastError());
1947 ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, NULL, 0, 0, NULL);
1948 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
1949 "Expected CRYPT_E_ASN1_EOD, got %08lx\n", GetLastError());
1951 /* Weird--bad add disposition leads to an access violation in Windows. */
1952 ret = CertAddEncodedCRLToStore(0, X509_ASN_ENCODING, signedCRL,
1953 sizeof(signedCRL), 0, NULL);
1954 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1955 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
1956 ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, signedCRL,
1957 sizeof(signedCRL), 0, NULL);
1958 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1959 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
1961 /* Weird--can add a CRL to the NULL store (does this have special meaning?)
1964 ret = CertAddEncodedCRLToStore(0, X509_ASN_ENCODING, signedCRL,
1965 sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, &context);
1966 ok(ret, "CertAddEncodedCRLToStore failed: %08lx\n", GetLastError());
1968 CertFreeCRLContext(context);
1970 /* Normal cases: a "signed" CRL is okay.. */
1971 ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, signedCRL,
1972 sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, NULL);
1973 /* and an unsigned one is too. */
1974 ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, CRL, sizeof(CRL),
1975 CERT_STORE_ADD_ALWAYS, NULL);
1976 ok(ret, "CertAddEncodedCRLToStore failed: %08lx\n", GetLastError());
1978 ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, newerCRL,
1979 sizeof(newerCRL), CERT_STORE_ADD_NEW, NULL);
1980 ok(!ret && GetLastError() == CRYPT_E_EXISTS,
1981 "Expected CRYPT_E_EXISTS, got %08lx\n", GetLastError());
1983 /* This should replace (one of) the existing CRL(s). */
1984 ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, newerCRL,
1985 sizeof(newerCRL), CERT_STORE_ADD_NEWER, NULL);
1986 ok(ret, "CertAddEncodedCRLToStore failed: %08lx\n", GetLastError());
1988 CertCloseStore(store, 0);
1991 static void testFindCRL(void)
1993 HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1994 CERT_STORE_CREATE_NEW_FLAG, NULL);
1995 PCCRL_CONTEXT context;
1996 PCCERT_CONTEXT cert;
2001 ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, signedCRL,
2002 sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, NULL);
2003 ok(ret, "CertAddEncodedCRLToStore failed: %08lx\n", GetLastError());
2006 context = CertFindCRLInStore(NULL, 0, 0, 0, NULL, NULL);
2009 /* Find any context */
2010 context = CertFindCRLInStore(store, 0, 0, CRL_FIND_ANY, NULL, NULL);
2011 ok(context != NULL, "Expected a context\n");
2013 CertFreeCRLContext(context);
2014 /* Bogus flags are ignored */
2015 context = CertFindCRLInStore(store, 0, 1234, CRL_FIND_ANY, NULL, NULL);
2016 ok(context != NULL, "Expected a context\n");
2018 CertFreeCRLContext(context);
2019 /* CRL encoding type is ignored too */
2020 context = CertFindCRLInStore(store, 1234, 0, CRL_FIND_ANY, NULL, NULL);
2021 ok(context != NULL, "Expected a context\n");
2023 CertFreeCRLContext(context);
2025 /* This appears to match any cert */
2026 context = CertFindCRLInStore(store, 0, 0, CRL_FIND_ISSUED_BY, NULL, NULL);
2027 ok(context != NULL, "Expected a context\n");
2029 CertFreeCRLContext(context);
2031 /* Try to match an issuer that isn't in the store */
2032 cert = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert2,
2034 ok(cert != NULL, "CertCreateCertificateContext failed: %08lx\n",
2036 context = CertFindCRLInStore(store, 0, 0, CRL_FIND_ISSUED_BY, cert, NULL);
2037 ok(context == NULL, "Expected no matching context\n");
2038 CertFreeCertificateContext(cert);
2040 /* Match an issuer that is in the store */
2041 cert = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
2043 ok(cert != NULL, "CertCreateCertificateContext failed: %08lx\n",
2045 context = CertFindCRLInStore(store, 0, 0, CRL_FIND_ISSUED_BY, cert, NULL);
2046 ok(context != NULL, "Expected a context\n");
2048 CertFreeCRLContext(context);
2049 CertFreeCertificateContext(cert);
2051 CertCloseStore(store, 0);
2054 static void checkCRLHash(const BYTE *data, DWORD dataLen, ALG_ID algID,
2055 PCCRL_CONTEXT context, DWORD propID)
2057 BYTE hash[20] = { 0 }, hashProperty[20];
2061 memset(hash, 0, sizeof(hash));
2062 memset(hashProperty, 0, sizeof(hashProperty));
2063 size = sizeof(hash);
2064 ret = CryptHashCertificate(0, algID, 0, data, dataLen, hash, &size);
2065 ok(ret, "CryptHashCertificate failed: %08lx\n", GetLastError());
2066 ret = CertGetCRLContextProperty(context, propID, hashProperty, &size);
2067 ok(ret, "CertGetCRLContextProperty failed: %08lx\n", GetLastError());
2068 ok(!memcmp(hash, hashProperty, size), "Unexpected hash for property %ld\n",
2072 static void testCRLProperties(void)
2074 PCCRL_CONTEXT context = CertCreateCRLContext(X509_ASN_ENCODING,
2077 ok(context != NULL, "CertCreateCRLContext failed: %08lx\n", GetLastError());
2080 DWORD propID, numProps, access, size;
2082 BYTE hash[20] = { 0 }, hashProperty[20];
2083 CRYPT_DATA_BLOB blob;
2086 propID = CertEnumCRLContextProperties(NULL, 0);
2092 propID = CertEnumCRLContextProperties(context, propID);
2095 } while (propID != 0);
2096 ok(numProps == 0, "Expected 0 properties, got %ld\n", numProps);
2098 /* Tests with a NULL cert context. Prop ID 0 fails.. */
2099 ret = CertSetCRLContextProperty(NULL, 0, 0, NULL);
2100 ok(!ret && GetLastError() == E_INVALIDARG,
2101 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
2102 /* while this just crashes.
2103 ret = CertSetCRLContextProperty(NULL, CERT_KEY_PROV_HANDLE_PROP_ID, 0,
2107 ret = CertSetCRLContextProperty(context, 0, 0, NULL);
2108 ok(!ret && GetLastError() == E_INVALIDARG,
2109 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
2110 /* Can't set the cert property directly, this crashes.
2111 ret = CertSetCRLContextProperty(context, CERT_CRL_PROP_ID, 0, CRL);
2115 ret = CertGetCRLContextProperty(context, CERT_ACCESS_STATE_PROP_ID, 0,
2117 ret = CertGetCRLContextProperty(context, CERT_HASH_PROP_ID, NULL, NULL);
2118 ret = CertGetCRLContextProperty(context, CERT_HASH_PROP_ID,
2119 hashProperty, NULL);
2121 /* A missing prop */
2123 ret = CertGetCRLContextProperty(context, CERT_KEY_PROV_INFO_PROP_ID,
2125 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
2126 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
2127 /* And, an implicit property */
2128 ret = CertGetCRLContextProperty(context, CERT_ACCESS_STATE_PROP_ID,
2130 ok(ret, "CertGetCRLContextProperty failed: %08lx\n", GetLastError());
2131 ret = CertGetCRLContextProperty(context, CERT_ACCESS_STATE_PROP_ID,
2133 ok(ret, "CertGetCRLContextProperty failed: %08lx\n", GetLastError());
2134 ok(!(access & CERT_ACCESS_STATE_WRITE_PERSIST_FLAG),
2135 "Didn't expect a persisted crl\n");
2136 /* Trying to set this "read only" property crashes.
2137 access |= CERT_ACCESS_STATE_WRITE_PERSIST_FLAG;
2138 ret = CertSetCRLContextProperty(context, CERT_ACCESS_STATE_PROP_ID, 0,
2142 /* Can I set the hash to an invalid hash? */
2144 blob.cbData = sizeof(hash);
2145 ret = CertSetCRLContextProperty(context, CERT_HASH_PROP_ID, 0, &blob);
2146 ok(ret, "CertSetCRLContextProperty failed: %08lx\n",
2148 size = sizeof(hashProperty);
2149 ret = CertGetCRLContextProperty(context, CERT_HASH_PROP_ID,
2150 hashProperty, &size);
2151 ok(!memcmp(hashProperty, hash, sizeof(hash)), "Unexpected hash\n");
2152 /* Delete the (bogus) hash, and get the real one */
2153 ret = CertSetCRLContextProperty(context, CERT_HASH_PROP_ID, 0, NULL);
2154 ok(ret, "CertSetCRLContextProperty failed: %08lx\n", GetLastError());
2155 checkCRLHash(CRL, sizeof(CRL), CALG_SHA1, context, CERT_HASH_PROP_ID);
2157 /* Now that the hash property is set, we should get one property when
2163 propID = CertEnumCRLContextProperties(context, propID);
2166 } while (propID != 0);
2167 ok(numProps == 1, "Expected 1 properties, got %ld\n", numProps);
2169 /* Check a few other implicit properties */
2170 checkCRLHash(CRL, sizeof(CRL), CALG_MD5, context,
2171 CERT_MD5_HASH_PROP_ID);
2173 CertFreeCRLContext(context);
2182 testGetSubjectCert();
2183 testGetIssuerCert();
2189 /* various combinations of CertOpenStore */
2191 testCollectionStore();
2193 testSystemRegStore();
2196 testCertOpenSystemStore();
2198 testCertProperties();
2199 testCRLProperties();
2200 testAddSerialized();