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 "Expected cert of %d bytes, got %ld\n", sizeof(bigCert),
335 context->cbCertEncoded);
336 ok(!memcmp(context->pbCertEncoded, bigCert, sizeof(bigCert)),
337 "Unexpected encoded cert in context\n");
338 ok(context->hCertStore == store, "Unexpected store\n");
340 dupContext = CertDuplicateCertificateContext(context);
341 ok(dupContext != NULL, "Expected valid duplicate\n");
342 /* Not only is it a duplicate, it's identical: the address is the
345 ok(dupContext == context, "Expected identical context addresses\n");
346 CertFreeCertificateContext(dupContext);
347 CertFreeCertificateContext(context);
349 CertCloseStore(store, 0);
353 static void testFindCert(void)
357 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
358 CERT_STORE_CREATE_NEW_FLAG, NULL);
359 ok(store != NULL, "CertOpenStore failed: %ld\n", GetLastError());
362 PCCERT_CONTEXT context = NULL;
364 CERT_INFO certInfo = { 0 };
365 CRYPT_HASH_BLOB blob;
367 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
368 bigCert, sizeof(bigCert), CERT_STORE_ADD_NEW, NULL);
369 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
371 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
372 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, NULL);
373 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
375 /* This has the same name as bigCert */
376 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
377 certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, NULL);
378 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
382 context = CertFindCertificateInStore(NULL, 0, 0, 0, NULL, NULL);
385 /* Check first cert's there, by issuer */
386 certInfo.Subject.pbData = (LPBYTE)subjectName;
387 certInfo.Subject.cbData = sizeof(subjectName);
388 certInfo.SerialNumber.pbData = (LPBYTE)serialNum;
389 certInfo.SerialNumber.cbData = sizeof(serialNum);
390 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
391 CERT_FIND_ISSUER_NAME, &certInfo.Subject, NULL);
392 ok(context != NULL, "CertFindCertificateInStore failed: %08lx\n",
396 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
397 CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
398 ok(context != NULL, "Expected more than one cert\n");
401 context = CertFindCertificateInStore(store, X509_ASN_ENCODING,
402 0, CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
403 ok(context == NULL, "Expected precisely two certs\n");
407 /* Check second cert's there as well, by subject name */
408 certInfo.Subject.pbData = (LPBYTE)subjectName2;
409 certInfo.Subject.cbData = sizeof(subjectName2);
410 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
411 CERT_FIND_SUBJECT_NAME, &certInfo.Subject, NULL);
412 ok(context != NULL, "CertFindCertificateInStore failed: %08lx\n",
416 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
417 CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
418 ok(context == NULL, "Expected one cert only\n");
421 /* Strange but true: searching for the subject cert requires you to set
422 * the issuer, not the subject
424 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
425 CERT_FIND_SUBJECT_CERT, &certInfo.Subject, NULL);
426 ok(context == NULL, "Expected no certificate\n");
427 certInfo.Subject.pbData = NULL;
428 certInfo.Subject.cbData = 0;
429 certInfo.Issuer.pbData = (LPBYTE)subjectName2;
430 certInfo.Issuer.cbData = sizeof(subjectName2);
431 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
432 CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
433 ok(context != NULL, "CertFindCertificateInStore failed: %08lx\n",
437 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
438 CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
439 ok(context == NULL, "Expected one cert only\n");
442 /* The nice thing about hashes, they're unique */
443 blob.pbData = (LPBYTE)bigCertHash;
444 blob.cbData = sizeof(bigCertHash);
445 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
446 CERT_FIND_SHA1_HASH, &blob, NULL);
447 ok(context != NULL, "CertFindCertificateInStore failed: %08lx\n",
451 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
452 CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
453 ok(context == NULL, "Expected one cert only\n");
456 CertCloseStore(store, 0);
460 static void testGetSubjectCert(void)
464 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
465 CERT_STORE_CREATE_NEW_FLAG, NULL);
466 ok(store != NULL, "CertOpenStore failed: %ld\n", GetLastError());
469 PCCERT_CONTEXT context1, context2;
470 CERT_INFO info = { 0 };
473 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
474 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
475 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
477 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
478 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, &context1);
479 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
481 ok(context1 != NULL, "Expected a context\n");
482 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
483 certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, NULL);
484 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
487 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
489 ok(!context2 && GetLastError() == E_INVALIDARG,
490 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
491 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
493 ok(!context2 && GetLastError() == CRYPT_E_NOT_FOUND,
494 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
495 info.SerialNumber.cbData = sizeof(serialNum);
496 info.SerialNumber.pbData = (LPBYTE)serialNum;
497 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
499 ok(!context2 && GetLastError() == CRYPT_E_NOT_FOUND,
500 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
501 info.Issuer.cbData = sizeof(subjectName2);
502 info.Issuer.pbData = (LPBYTE)subjectName2;
503 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
506 "CertGetSubjectCertificateFromStore failed: %08lx\n", GetLastError());
507 /* Not only should this find a context, but it should be the same
508 * (same address) as context1.
510 ok(context1 == context2, "Expected identical context addresses\n");
511 CertFreeCertificateContext(context2);
513 CertFreeCertificateContext(context1);
514 CertCloseStore(store, 0);
518 /* This expires in 1970 or so */
519 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
520 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
521 0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
522 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
523 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
524 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
525 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
526 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
527 0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
528 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
529 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
530 0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
531 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
532 0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
533 0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
534 0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
535 0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
536 0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
537 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
538 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
539 0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
540 0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
541 0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
542 0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
543 0x49, 0xe5, 0xf9, 0x65, 0xf3 };
545 /* This expires in 2036 or so */
546 static const BYTE childOfExpired[] = { 0x30, 0x81, 0xcc, 0x30, 0x78, 0xa0,
547 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
548 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d,
549 0x30, 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63,
550 0x40, 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e,
551 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x35, 0x30, 0x35,
552 0x31, 0x37, 0x31, 0x32, 0x34, 0x39, 0x5a, 0x17, 0x0d, 0x33, 0x36, 0x30, 0x35,
553 0x30, 0x35, 0x31, 0x37, 0x31, 0x32, 0x34, 0x39, 0x5a, 0x30, 0x15, 0x31, 0x13,
554 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e,
555 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03,
556 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
557 0x01, 0x05, 0x05, 0x00, 0x03, 0x41, 0x00, 0x20, 0x3b, 0xdb, 0x4d, 0x67, 0x50,
558 0xec, 0x73, 0x9d, 0xf9, 0x85, 0x5d, 0x18, 0xe9, 0xb4, 0x98, 0xe3, 0x31, 0xb7,
559 0x03, 0x0b, 0xc0, 0x39, 0x93, 0x56, 0x81, 0x0a, 0xfc, 0x78, 0xa8, 0x29, 0x42,
560 0x5f, 0x69, 0xfb, 0xbc, 0x5b, 0xf2, 0xa6, 0x2a, 0xbe, 0x91, 0x2c, 0xfc, 0x89,
561 0x69, 0x15, 0x18, 0x58, 0xe5, 0x02, 0x75, 0xf7, 0x2a, 0xb6, 0xa9, 0xfb, 0x47,
562 0x6a, 0x6e, 0x0a, 0x9b, 0xe9, 0xdc };
564 static void testGetIssuerCert(void)
567 PCCERT_CONTEXT parent, child;
568 DWORD flags = 0xffffffff;
569 HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
570 CERT_STORE_CREATE_NEW_FLAG, NULL);
572 ok(store != NULL, "CertOpenStore failed: %08lx\n", GetLastError());
574 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
575 expiredCert, sizeof(expiredCert), CERT_STORE_ADD_ALWAYS, NULL);
576 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
579 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
580 childOfExpired, sizeof(childOfExpired), CERT_STORE_ADD_ALWAYS, &child);
581 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
585 parent = CertGetIssuerCertificateFromStore(NULL, NULL, NULL, NULL);
586 parent = CertGetIssuerCertificateFromStore(store, NULL, NULL, NULL);
588 parent = CertGetIssuerCertificateFromStore(NULL, NULL, NULL, &flags);
589 ok(!parent && GetLastError() == E_INVALIDARG,
590 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
591 parent = CertGetIssuerCertificateFromStore(store, NULL, NULL, &flags);
592 ok(!parent && GetLastError() == E_INVALIDARG,
593 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
594 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
595 ok(!parent && GetLastError() == E_INVALIDARG,
596 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
597 /* Confusing: the caller cannot set either of the
598 * CERT_STORE_NO_*_FLAGs, as these are not checks,
601 flags = CERT_STORE_NO_CRL_FLAG | CERT_STORE_NO_ISSUER_FLAG;
602 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
603 ok(!parent && GetLastError() == E_INVALIDARG,
604 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
605 /* Perform no checks */
607 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
608 ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08lx\n",
611 CertFreeCertificateContext(parent);
612 /* Check revocation and signature only */
613 flags = CERT_STORE_REVOCATION_FLAG | CERT_STORE_SIGNATURE_FLAG;
614 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
615 ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08lx\n",
617 /* Confusing: CERT_STORE_REVOCATION_FLAG succeeds when there is no CRL by
618 * setting CERT_STORE_NO_CRL_FLAG.
620 ok(flags == (CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG),
621 "Expected CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG, got %08lx\n",
624 CertFreeCertificateContext(parent);
625 /* Now check just the time */
626 flags = CERT_STORE_TIME_VALIDITY_FLAG;
627 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
628 ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08lx\n",
630 /* Oops: the child is not expired, so the time validity check actually
631 * succeeds, even though the signing cert is expired.
633 ok(!flags, "Expected check to succeed, got %08lx\n", flags);
635 CertFreeCertificateContext(parent);
637 CertFreeCertificateContext(child);
638 CertCloseStore(store, 0);
641 static void testMemStore(void)
643 HCERTSTORE store1, store2;
644 PCCERT_CONTEXT context;
648 store1 = CertOpenStore(0, 0, 0, 0, NULL);
649 ok(!store1 && GetLastError() == ERROR_FILE_NOT_FOUND,
650 "Expected ERROR_FILE_NOT_FOUND, got %ld\n", GetLastError());
652 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
653 CERT_STORE_DELETE_FLAG, NULL);
654 ok(!store1 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
655 "Expected ERROR_CALL_NOT_IMPLEMENTED, got %ld\n", GetLastError());
658 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
659 CERT_STORE_CREATE_NEW_FLAG, NULL);
660 ok(store1 != NULL, "CertOpenStore failed: %ld\n", GetLastError());
661 /* open existing doesn't */
662 store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
663 CERT_STORE_OPEN_EXISTING_FLAG, NULL);
664 ok(store2 != NULL, "CertOpenStore failed: %ld\n", GetLastError());
665 ok(store1 != store2, "Expected different stores\n");
667 /* add a bogus (empty) cert */
669 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING, emptyCert,
670 sizeof(emptyCert), CERT_STORE_ADD_ALWAYS, &context);
671 /* Windows returns CRYPT_E_ASN1_EOD, but accept CRYPT_E_ASN1_CORRUPT as
672 * well (because matching errors is tough in this case)
674 ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD || GetLastError() ==
675 CRYPT_E_ASN1_CORRUPT),
676 "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %08lx\n",
678 /* add a "signed" cert--the signature isn't a real signature, so this adds
679 * without any check of the signature's validity
681 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
682 signedBigCert, sizeof(signedBigCert), CERT_STORE_ADD_ALWAYS, &context);
683 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
684 ok(context != NULL, "Expected a valid cert context\n");
687 ok(context->cbCertEncoded == sizeof(signedBigCert),
688 "Expected cert of %d bytes, got %ld\n", sizeof(signedBigCert),
689 context->cbCertEncoded);
690 ok(!memcmp(context->pbCertEncoded, signedBigCert,
691 sizeof(signedBigCert)), "Unexpected encoded cert in context\n");
692 /* remove it, the rest of the tests will work on an unsigned cert */
693 ret = CertDeleteCertificateFromStore(context);
694 ok(ret, "CertDeleteCertificateFromStore failed: %08lx\n",
697 /* try adding a "signed" CRL as a cert */
698 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
699 signedCRL, sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, &context);
700 ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG || GetLastError() ==
701 CRYPT_E_ASN1_CORRUPT),
702 "Expected CRYPT_E_ASN1_BADTAG or CRYPT_E_ASN1_CORRUPT, got %08lx\n",
704 /* add a cert to store1 */
705 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING, bigCert,
706 sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
707 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
708 ok(context != NULL, "Expected a valid cert context\n");
714 ok(context->cbCertEncoded == sizeof(bigCert),
715 "Expected cert of %d bytes, got %ld\n", sizeof(bigCert),
716 context->cbCertEncoded);
717 ok(!memcmp(context->pbCertEncoded, bigCert, sizeof(bigCert)),
718 "Unexpected encoded cert in context\n");
719 ok(context->hCertStore == store1, "Unexpected store\n");
721 /* check serializing this element */
723 ret = CertSerializeCertificateStoreElement(NULL, 0, NULL, NULL);
724 ret = CertSerializeCertificateStoreElement(context, 0, NULL, NULL);
725 ret = CertSerializeCertificateStoreElement(NULL, 0, NULL, &size);
727 /* apparently flags are ignored */
728 ret = CertSerializeCertificateStoreElement(context, 1, NULL, &size);
729 ok(ret, "CertSerializeCertificateStoreElement failed: %08lx\n",
731 buf = HeapAlloc(GetProcessHeap(), 0, size);
734 ret = CertSerializeCertificateStoreElement(context, 0, buf, &size);
735 ok(size == sizeof(serializedCert), "Expected size %d, got %ld\n",
736 sizeof(serializedCert), size);
737 ok(!memcmp(serializedCert, buf, size),
738 "Unexpected serialized cert\n");
739 HeapFree(GetProcessHeap(), 0, buf);
742 ret = CertFreeCertificateContext(context);
743 ok(ret, "CertFreeCertificateContext failed: %08lx\n", GetLastError());
745 /* verify the cert's in store1 */
746 context = CertEnumCertificatesInStore(store1, NULL);
747 ok(context != NULL, "Expected a valid context\n");
748 context = CertEnumCertificatesInStore(store1, context);
749 ok(!context && GetLastError() == CRYPT_E_NOT_FOUND,
750 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
751 /* verify store2 (the "open existing" mem store) is still empty */
752 context = CertEnumCertificatesInStore(store2, NULL);
753 ok(!context, "Expected an empty store\n");
754 /* delete the cert from store1, and check it's empty */
755 context = CertEnumCertificatesInStore(store1, NULL);
758 /* Deleting a bitwise copy crashes with an access to an uninitialized
759 * pointer, so a cert context has some special data out there in memory
762 memcpy(©, context, sizeof(copy));
763 ret = CertDeleteCertificateFromStore(©);
765 PCCERT_CONTEXT copy = CertDuplicateCertificateContext(context);
767 ok(copy != NULL, "CertDuplicateCertificateContext failed: %08lx\n",
769 ret = CertDeleteCertificateFromStore(context);
770 ok(ret, "CertDeleteCertificateFromStore failed: %08lx\n",
772 /* try deleting a copy */
773 ret = CertDeleteCertificateFromStore(copy);
774 ok(ret, "CertDeleteCertificateFromStore failed: %08lx\n",
776 /* check that the store is empty */
777 context = CertEnumCertificatesInStore(store1, NULL);
778 ok(!context, "Expected an empty store\n");
781 /* close an empty store */
782 ret = CertCloseStore(NULL, 0);
783 ok(ret, "CertCloseStore failed: %ld\n", GetLastError());
784 ret = CertCloseStore(store1, 0);
785 ok(ret, "CertCloseStore failed: %ld\n", GetLastError());
786 ret = CertCloseStore(store2, 0);
787 ok(ret, "CertCloseStore failed: %ld\n", GetLastError());
789 /* This seems nonsensical, but you can open a read-only mem store, only
792 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
793 CERT_STORE_READONLY_FLAG, NULL);
794 ok(store1 != NULL, "CertOpenStore failed: %ld\n", GetLastError());
795 /* yep, this succeeds */
796 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING, bigCert,
797 sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
798 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
799 ok(context != NULL, "Expected a valid cert context\n");
802 ok(context->cbCertEncoded == sizeof(bigCert),
803 "Expected cert of %d bytes, got %ld\n", sizeof(bigCert),
804 context->cbCertEncoded);
805 ok(!memcmp(context->pbCertEncoded, bigCert, sizeof(bigCert)),
806 "Unexpected encoded cert in context\n");
807 ok(context->hCertStore == store1, "Unexpected store\n");
808 ret = CertDeleteCertificateFromStore(context);
809 ok(ret, "CertDeleteCertificateFromStore failed: %08lx\n",
812 CertCloseStore(store1, 0);
815 static void testCollectionStore(void)
817 HCERTSTORE store1, store2, collection, collection2;
818 PCCERT_CONTEXT context;
821 collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
822 CERT_STORE_CREATE_NEW_FLAG, NULL);
824 /* Try adding a cert to any empty collection */
825 ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
826 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
827 ok(!ret && GetLastError() == E_ACCESSDENIED,
828 "Expected E_ACCESSDENIED, got %08lx\n", GetLastError());
830 /* Create and add a cert to a memory store */
831 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
832 CERT_STORE_CREATE_NEW_FLAG, NULL);
833 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
834 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
835 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
836 /* Add the memory store to the collection, without allowing adding */
837 ret = CertAddStoreToCollection(collection, store1, 0, 0);
838 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
839 /* Verify the cert is in the collection */
840 context = CertEnumCertificatesInStore(collection, NULL);
841 ok(context != NULL, "Expected a valid context\n");
844 ok(context->hCertStore == collection, "Unexpected store\n");
845 CertFreeCertificateContext(context);
847 /* Check that adding to the collection isn't allowed */
848 ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
849 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_ALWAYS, NULL);
850 ok(!ret && GetLastError() == E_ACCESSDENIED,
851 "Expected E_ACCESSDENIED, got %08lx\n", GetLastError());
853 /* Create a new memory store */
854 store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
855 CERT_STORE_CREATE_NEW_FLAG, NULL);
856 /* Try adding a store to a non-collection store */
857 ret = CertAddStoreToCollection(store1, store2,
858 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
859 ok(!ret && GetLastError() == E_INVALIDARG,
860 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
861 /* Try adding some bogus stores */
862 /* This crashes in Windows
863 ret = CertAddStoreToCollection(0, store2,
864 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
866 /* This "succeeds"... */
867 ret = CertAddStoreToCollection(collection, 0,
868 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
869 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
870 /* while this crashes.
871 ret = CertAddStoreToCollection(collection, 1,
872 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
875 /* Add it to the collection, this time allowing adding */
876 ret = CertAddStoreToCollection(collection, store2,
877 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
878 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
879 /* Check that adding to the collection is allowed */
880 ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
881 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_ALWAYS, NULL);
882 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
883 /* Now check that it was actually added to store2 */
884 context = CertEnumCertificatesInStore(store2, NULL);
885 ok(context != NULL, "Expected a valid context\n");
888 ok(context->hCertStore == store2, "Unexpected store\n");
889 CertFreeCertificateContext(context);
891 /* Check that the collection has both bigCert and bigCert2. bigCert comes
892 * first because store1 was added first.
894 context = CertEnumCertificatesInStore(collection, NULL);
895 ok(context != NULL, "Expected a valid context\n");
898 ok(context->hCertStore == collection, "Unexpected store\n");
899 ok(context->cbCertEncoded == sizeof(bigCert),
900 "Expected size %d, got %ld\n", sizeof(bigCert),
901 context->cbCertEncoded);
902 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
903 "Unexpected cert\n");
904 context = CertEnumCertificatesInStore(collection, context);
905 ok(context != NULL, "Expected a valid context\n");
908 ok(context->hCertStore == collection, "Unexpected store\n");
909 ok(context->cbCertEncoded == sizeof(bigCert2),
910 "Expected size %d, got %ld\n", sizeof(bigCert2),
911 context->cbCertEncoded);
912 ok(!memcmp(context->pbCertEncoded, bigCert2,
913 context->cbCertEncoded), "Unexpected cert\n");
914 context = CertEnumCertificatesInStore(collection, context);
915 ok(!context, "Unexpected cert\n");
918 /* close store2, and check that the collection is unmodified */
919 CertCloseStore(store2, 0);
920 context = CertEnumCertificatesInStore(collection, NULL);
921 ok(context != NULL, "Expected a valid context\n");
924 ok(context->hCertStore == collection, "Unexpected store\n");
925 ok(context->cbCertEncoded == sizeof(bigCert),
926 "Expected size %d, got %ld\n", sizeof(bigCert),
927 context->cbCertEncoded);
928 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
929 "Unexpected cert\n");
930 context = CertEnumCertificatesInStore(collection, context);
931 ok(context != NULL, "Expected a valid context\n");
934 ok(context->hCertStore == collection, "Unexpected store\n");
935 ok(context->cbCertEncoded == sizeof(bigCert2),
936 "Expected size %d, got %ld\n", sizeof(bigCert2),
937 context->cbCertEncoded);
938 ok(!memcmp(context->pbCertEncoded, bigCert2,
939 context->cbCertEncoded), "Unexpected cert\n");
940 context = CertEnumCertificatesInStore(collection, context);
941 ok(!context, "Unexpected cert\n");
945 /* Adding a collection to a collection is legal */
946 collection2 = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
947 CERT_STORE_CREATE_NEW_FLAG, NULL);
948 ret = CertAddStoreToCollection(collection2, collection,
949 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
950 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
951 /* check the contents of collection2 */
952 context = CertEnumCertificatesInStore(collection2, NULL);
953 ok(context != NULL, "Expected a valid context\n");
956 ok(context->hCertStore == collection2, "Unexpected store\n");
957 ok(context->cbCertEncoded == sizeof(bigCert),
958 "Expected size %d, got %ld\n", sizeof(bigCert),
959 context->cbCertEncoded);
960 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
961 "Unexpected cert\n");
962 context = CertEnumCertificatesInStore(collection2, context);
963 ok(context != NULL, "Expected a valid context\n");
966 ok(context->hCertStore == collection2, "Unexpected store\n");
967 ok(context->cbCertEncoded == sizeof(bigCert2),
968 "Expected size %d, got %ld\n", sizeof(bigCert2),
969 context->cbCertEncoded);
970 ok(!memcmp(context->pbCertEncoded, bigCert2,
971 context->cbCertEncoded), "Unexpected cert\n");
972 context = CertEnumCertificatesInStore(collection2, context);
973 ok(!context, "Unexpected cert\n");
977 /* I'd like to test closing the collection in the middle of enumeration,
978 * but my tests have been inconsistent. The first time calling
979 * CertEnumCertificatesInStore on a closed collection succeeded, while the
980 * second crashed. So anything appears to be fair game.
981 * I'd also like to test removing a store from a collection in the middle
982 * of an enumeration, but my tests in Windows have been inconclusive.
983 * In one scenario it worked. In another scenario, about a third of the
984 * time this leads to "random" crashes elsewhere in the code. This
985 * probably means this is not allowed.
988 CertCloseStore(store1, 0);
989 CertCloseStore(collection, 0);
990 CertCloseStore(collection2, 0);
992 /* Add the same cert to two memory stores, then put them in a collection */
993 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
994 CERT_STORE_CREATE_NEW_FLAG, NULL);
995 ok(store1 != 0, "CertOpenStore failed: %08lx\n", GetLastError());
996 store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
997 CERT_STORE_CREATE_NEW_FLAG, NULL);
998 ok(store2 != 0, "CertOpenStore failed: %08lx\n", GetLastError());
1000 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
1001 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
1002 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
1003 ret = CertAddEncodedCertificateToStore(store2, X509_ASN_ENCODING,
1004 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
1005 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
1006 collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
1007 CERT_STORE_CREATE_NEW_FLAG, NULL);
1008 ok(collection != 0, "CertOpenStore failed: %08lx\n", GetLastError());
1010 ret = CertAddStoreToCollection(collection, store1,
1011 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
1012 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
1013 ret = CertAddStoreToCollection(collection, store2,
1014 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
1015 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
1017 /* Check that the collection has two copies of the same cert */
1018 context = CertEnumCertificatesInStore(collection, NULL);
1019 ok(context != NULL, "Expected a valid context\n");
1022 ok(context->hCertStore == collection, "Unexpected store\n");
1023 ok(context->cbCertEncoded == sizeof(bigCert),
1024 "Expected size %d, got %ld\n", sizeof(bigCert),
1025 context->cbCertEncoded);
1026 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
1027 "Unexpected cert\n");
1028 context = CertEnumCertificatesInStore(collection, context);
1029 ok(context != NULL, "Expected a valid context\n");
1032 ok(context->hCertStore == collection, "Unexpected store\n");
1033 ok(context->cbCertEncoded == sizeof(bigCert),
1034 "Expected size %d, got %ld\n", sizeof(bigCert),
1035 context->cbCertEncoded);
1036 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
1037 "Unexpected cert\n");
1038 context = CertEnumCertificatesInStore(collection, context);
1039 ok(context == NULL, "Unexpected cert\n");
1043 /* The following would check whether I can delete an identical cert, rather
1044 * than one enumerated from the store. It crashes, so that means I must
1045 * only call CertDeleteCertificateFromStore with contexts enumerated from
1047 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
1049 ok(context != NULL, "CertCreateCertificateContext failed: %08lx\n",
1053 ret = CertDeleteCertificateFromStore(collection, context);
1054 printf("ret is %d, GetLastError is %08lx\n", ret, GetLastError());
1055 CertFreeCertificateContext(context);
1059 /* Now check deleting from the collection. */
1060 context = CertEnumCertificatesInStore(collection, NULL);
1061 ok(context != NULL, "Expected a valid context\n");
1064 CertDeleteCertificateFromStore(context);
1065 /* store1 should now be empty */
1066 context = CertEnumCertificatesInStore(store1, NULL);
1067 ok(!context, "Unexpected cert\n");
1068 /* and there should be one certificate in the collection */
1069 context = CertEnumCertificatesInStore(collection, NULL);
1070 ok(context != NULL, "Expected a valid cert\n");
1073 ok(context->hCertStore == collection, "Unexpected store\n");
1074 ok(context->cbCertEncoded == sizeof(bigCert),
1075 "Expected size %d, got %ld\n", sizeof(bigCert),
1076 context->cbCertEncoded);
1077 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
1078 "Unexpected cert\n");
1080 context = CertEnumCertificatesInStore(collection, context);
1081 ok(context == NULL, "Unexpected cert\n");
1084 /* Finally, test removing stores from the collection. No return value, so
1085 * it's a bit funny to test.
1088 CertRemoveStoreFromCollection(NULL, NULL);
1090 /* This "succeeds," no crash, no last error set */
1091 SetLastError(0xdeadbeef);
1092 CertRemoveStoreFromCollection(store2, collection);
1093 ok(GetLastError() == 0xdeadbeef,
1094 "Didn't expect an error to be set: %08lx\n", GetLastError());
1096 /* After removing store2, the collection should be empty */
1097 SetLastError(0xdeadbeef);
1098 CertRemoveStoreFromCollection(collection, store2);
1099 ok(GetLastError() == 0xdeadbeef,
1100 "Didn't expect an error to be set: %08lx\n", GetLastError());
1101 context = CertEnumCertificatesInStore(collection, NULL);
1102 ok(!context, "Unexpected cert\n");
1104 CertCloseStore(collection, 0);
1105 CertCloseStore(store2, 0);
1106 CertCloseStore(store1, 0);
1109 /* Looks for the property with ID propID in the buffer buf. Returns a pointer
1110 * to its header if found, NULL if not.
1112 static const struct CertPropIDHeader *findPropID(const BYTE *buf, DWORD size,
1115 const struct CertPropIDHeader *ret = NULL;
1116 BOOL failed = FALSE;
1118 while (size && !ret && !failed)
1120 if (size < sizeof(struct CertPropIDHeader))
1124 const struct CertPropIDHeader *hdr =
1125 (const struct CertPropIDHeader *)buf;
1127 size -= sizeof(struct CertPropIDHeader);
1128 buf += sizeof(struct CertPropIDHeader);
1131 else if (hdr->propID == propID)
1143 typedef DWORD (WINAPI *SHDeleteKeyAFunc)(HKEY, LPCSTR);
1145 static void testRegStore(void)
1147 static const char tempKey[] = "Software\\Wine\\CryptTemp";
1153 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, NULL);
1154 ok(!store && GetLastError() == ERROR_INVALID_HANDLE,
1155 "Expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
1156 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, key);
1157 ok(!store && GetLastError() == ERROR_INVALID_HANDLE,
1158 "Expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
1160 /* Opening up any old key works.. */
1161 key = HKEY_CURRENT_USER;
1162 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, key);
1163 /* Not sure if this is a bug in DuplicateHandle, marking todo_wine for now
1165 todo_wine ok(store != 0, "CertOpenStore failed: %08lx\n", GetLastError());
1166 CertCloseStore(store, 0);
1168 rc = RegCreateKeyExA(HKEY_CURRENT_USER, tempKey, 0, NULL, 0, KEY_ALL_ACCESS,
1170 ok(!rc, "RegCreateKeyExA failed: %ld\n", rc);
1176 static const char certificates[] = "Certificates\\";
1177 char subKeyName[sizeof(certificates) + 20 * 2 + 1], *ptr;
1179 PCCERT_CONTEXT context;
1181 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, key);
1182 ok(store != 0, "CertOpenStore failed: %08lx\n", GetLastError());
1183 /* Add a certificate. It isn't persisted right away, since it's only
1184 * added to the cache..
1186 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1187 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_ALWAYS, NULL);
1188 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
1190 /* so flush the cache to force a commit.. */
1191 ret = CertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
1192 ok(ret, "CertControlStore failed: %08lx\n", GetLastError());
1193 /* and check that the expected subkey was written. */
1194 size = sizeof(hash);
1195 ret = CryptHashCertificate(0, 0, 0, bigCert2, sizeof(bigCert2),
1197 ok(ret, "CryptHashCertificate failed: %ld\n", GetLastError());
1198 strcpy(subKeyName, certificates);
1199 for (i = 0, ptr = subKeyName + sizeof(certificates) - 1; i < size;
1201 sprintf(ptr, "%02X", hash[i]);
1202 rc = RegCreateKeyExA(key, subKeyName, 0, NULL, 0, KEY_ALL_ACCESS, NULL,
1204 ok(!rc, "RegCreateKeyExA failed: %ld\n", rc);
1210 RegQueryValueExA(subKey, "Blob", NULL, NULL, NULL, &size);
1211 buf = HeapAlloc(GetProcessHeap(), 0, size);
1214 rc = RegQueryValueExA(subKey, "Blob", NULL, NULL, buf, &size);
1215 ok(!rc, "RegQueryValueExA failed: %ld\n", rc);
1218 const struct CertPropIDHeader *hdr;
1220 /* Both the hash and the cert should be present */
1221 hdr = findPropID(buf, size, CERT_CERT_PROP_ID);
1222 ok(hdr != NULL, "Expected to find a cert property\n");
1225 ok(hdr->cb == sizeof(bigCert2),
1226 "Unexpected size %ld of cert property, expected %d\n",
1227 hdr->cb, sizeof(bigCert2));
1228 ok(!memcmp((BYTE *)hdr + sizeof(*hdr), bigCert2,
1229 hdr->cb), "Unexpected cert in cert property\n");
1231 hdr = findPropID(buf, size, CERT_HASH_PROP_ID);
1232 ok(hdr != NULL, "Expected to find a hash property\n");
1235 ok(hdr->cb == sizeof(hash),
1236 "Unexpected size %ld of hash property, expected %d\n",
1237 hdr->cb, sizeof(hash));
1238 ok(!memcmp((BYTE *)hdr + sizeof(*hdr), hash,
1239 hdr->cb), "Unexpected hash in cert property\n");
1242 HeapFree(GetProcessHeap(), 0, buf);
1244 RegCloseKey(subKey);
1247 /* Remove the existing context */
1248 context = CertEnumCertificatesInStore(store, NULL);
1249 ok(context != NULL, "Expected a cert context\n");
1251 CertDeleteCertificateFromStore(context);
1252 ret = CertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
1253 ok(ret, "CertControlStore failed: %08lx\n", GetLastError());
1255 /* Add a serialized cert with a bogus hash directly to the registry */
1256 memset(hash, 0, sizeof(hash));
1257 strcpy(subKeyName, certificates);
1258 for (i = 0, ptr = subKeyName + sizeof(certificates) - 1;
1259 i < sizeof(hash); i++, ptr += 2)
1260 sprintf(ptr, "%02X", hash[i]);
1261 rc = RegCreateKeyExA(key, subKeyName, 0, NULL, 0, KEY_ALL_ACCESS, NULL,
1263 ok(!rc, "RegCreateKeyExA failed: %ld\n", rc);
1266 BYTE buf[sizeof(struct CertPropIDHeader) * 2 + sizeof(hash) +
1267 sizeof(bigCert)], *ptr;
1268 DWORD certCount = 0;
1269 struct CertPropIDHeader *hdr;
1271 hdr = (struct CertPropIDHeader *)buf;
1272 hdr->propID = CERT_HASH_PROP_ID;
1274 hdr->cb = sizeof(hash);
1275 ptr = buf + sizeof(*hdr);
1276 memcpy(ptr, hash, sizeof(hash));
1277 ptr += sizeof(hash);
1278 hdr = (struct CertPropIDHeader *)ptr;
1279 hdr->propID = CERT_CERT_PROP_ID;
1281 hdr->cb = sizeof(bigCert);
1282 ptr += sizeof(*hdr);
1283 memcpy(ptr, bigCert, sizeof(bigCert));
1285 rc = RegSetValueExA(subKey, "Blob", 0, REG_BINARY, buf,
1287 ok(!rc, "RegSetValueExA failed: %ld\n", rc);
1289 ret = CertControlStore(store, 0, CERT_STORE_CTRL_RESYNC, NULL);
1290 ok(ret, "CertControlStore failed: %08lx\n", GetLastError());
1292 /* Make sure the bogus hash cert gets loaded. */
1296 context = CertEnumCertificatesInStore(store, context);
1299 } while (context != NULL);
1300 ok(certCount == 1, "Expected 1 certificates, got %ld\n", certCount);
1302 RegCloseKey(subKey);
1305 /* Add another serialized cert directly to the registry, this time
1306 * under the correct key name (named with the correct hash value).
1308 size = sizeof(hash);
1309 ret = CryptHashCertificate(0, 0, 0, bigCert2,
1310 sizeof(bigCert2), hash, &size);
1311 ok(ret, "CryptHashCertificate failed: %ld\n", GetLastError());
1312 strcpy(subKeyName, certificates);
1313 for (i = 0, ptr = subKeyName + sizeof(certificates) - 1;
1314 i < sizeof(hash); i++, ptr += 2)
1315 sprintf(ptr, "%02X", hash[i]);
1316 rc = RegCreateKeyExA(key, subKeyName, 0, NULL, 0, KEY_ALL_ACCESS, NULL,
1318 ok(!rc, "RegCreateKeyExA failed: %ld\n", rc);
1321 BYTE buf[sizeof(struct CertPropIDHeader) * 2 + sizeof(hash) +
1322 sizeof(bigCert2)], *ptr;
1323 DWORD certCount = 0;
1324 PCCERT_CONTEXT context;
1325 struct CertPropIDHeader *hdr;
1327 /* First try with a bogus hash... */
1328 hdr = (struct CertPropIDHeader *)buf;
1329 hdr->propID = CERT_HASH_PROP_ID;
1331 hdr->cb = sizeof(hash);
1332 ptr = buf + sizeof(*hdr);
1333 memset(ptr, 0, sizeof(hash));
1334 ptr += sizeof(hash);
1335 hdr = (struct CertPropIDHeader *)ptr;
1336 hdr->propID = CERT_CERT_PROP_ID;
1338 hdr->cb = sizeof(bigCert2);
1339 ptr += sizeof(*hdr);
1340 memcpy(ptr, bigCert2, sizeof(bigCert2));
1342 rc = RegSetValueExA(subKey, "Blob", 0, REG_BINARY, buf,
1344 ok(!rc, "RegSetValueExA failed: %ld\n", rc);
1346 ret = CertControlStore(store, 0, CERT_STORE_CTRL_RESYNC, NULL);
1347 ok(ret, "CertControlStore failed: %08lx\n", GetLastError());
1349 /* and make sure just one cert still gets loaded. */
1353 context = CertEnumCertificatesInStore(store, context);
1356 } while (context != NULL);
1357 ok(certCount == 1, "Expected 1 certificates, got %ld\n", certCount);
1359 /* Try again with the correct hash... */
1360 ptr = buf + sizeof(*hdr);
1361 memcpy(ptr, hash, sizeof(hash));
1363 rc = RegSetValueExA(subKey, "Blob", 0, REG_BINARY, buf,
1365 ok(!rc, "RegSetValueExA failed: %ld\n", rc);
1367 ret = CertControlStore(store, 0, CERT_STORE_CTRL_RESYNC, NULL);
1368 ok(ret, "CertControlStore failed: %08lx\n", GetLastError());
1370 /* and make sure two certs get loaded. */
1374 context = CertEnumCertificatesInStore(store, context);
1377 } while (context != NULL);
1378 ok(certCount == 2, "Expected 2 certificates, got %ld\n", certCount);
1380 RegCloseKey(subKey);
1382 CertCloseStore(store, 0);
1383 /* Is delete allowed on a reg store? */
1384 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0,
1385 CERT_STORE_DELETE_FLAG, key);
1386 ok(store == NULL, "Expected NULL return from CERT_STORE_DELETE_FLAG\n");
1387 ok(GetLastError() == 0, "CertOpenStore failed: %08lx\n",
1392 /* The CertOpenStore with CERT_STORE_DELETE_FLAG above will delete the
1393 * contents of the key, but not the key itself.
1395 rc = RegCreateKeyExA(HKEY_CURRENT_USER, tempKey, 0, NULL, 0, KEY_ALL_ACCESS,
1397 ok(!rc, "RegCreateKeyExA failed: %ld\n", rc);
1398 ok(disp == REG_OPENED_EXISTING_KEY,
1399 "Expected REG_OPENED_EXISTING_KEY, got %ld\n", disp);
1403 rc = RegDeleteKeyA(HKEY_CURRENT_USER, tempKey);
1406 HMODULE shlwapi = LoadLibraryA("shlwapi");
1408 /* Use shlwapi's SHDeleteKeyA to _really_ blow away the key,
1409 * otherwise subsequent tests will fail.
1413 SHDeleteKeyAFunc pSHDeleteKeyA =
1414 (SHDeleteKeyAFunc)GetProcAddress(shlwapi, "SHDeleteKeyA");
1417 pSHDeleteKeyA(HKEY_CURRENT_USER, tempKey);
1418 FreeLibrary(shlwapi);
1424 static const char MyA[] = { 'M','y',0,0 };
1425 static const WCHAR MyW[] = { 'M','y',0 };
1426 static const WCHAR BogusW[] = { 'B','o','g','u','s',0 };
1427 static const WCHAR BogusPathW[] = { 'S','o','f','t','w','a','r','e','\\',
1428 'M','i','c','r','o','s','o','f','t','\\','S','y','s','t','e','m','C','e','r',
1429 't','i','f','i','c','a','t','e','s','\\','B','o','g','u','s',0 };
1431 static void testSystemRegStore(void)
1433 HCERTSTORE store, memStore;
1435 /* Check with a UNICODE name */
1436 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1437 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyW);
1438 /* Not all OSes support CERT_STORE_PROV_SYSTEM_REGISTRY, so don't continue
1439 * testing if they don't.
1444 /* Check that it isn't a collection store */
1445 memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1446 CERT_STORE_CREATE_NEW_FLAG, NULL);
1449 BOOL ret = CertAddStoreToCollection(store, memStore, 0, 0);
1451 ok(!ret && GetLastError() == E_INVALIDARG,
1452 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1453 CertCloseStore(memStore, 0);
1455 CertCloseStore(store, 0);
1457 /* Check opening a bogus store */
1458 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1459 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, BogusW);
1460 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1461 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1462 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1463 CERT_SYSTEM_STORE_CURRENT_USER, BogusW);
1464 ok(store != 0, "CertOpenStore failed: %08lx\n", GetLastError());
1466 CertCloseStore(store, 0);
1467 /* Now check whether deleting is allowed */
1468 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1469 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_DELETE_FLAG, BogusW);
1470 RegDeleteKeyW(HKEY_CURRENT_USER, BogusPathW);
1472 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0, 0, NULL);
1473 ok(!store && GetLastError() == E_INVALIDARG,
1474 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1475 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1476 CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyA);
1477 ok(!store && GetLastError() == E_INVALIDARG,
1478 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1479 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1480 CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyW);
1481 ok(!store && GetLastError() == E_INVALIDARG,
1482 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1483 /* The name is expected to be UNICODE, check with an ASCII name */
1484 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1485 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyA);
1486 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1487 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1490 static void testSystemStore(void)
1492 static const WCHAR baskslashW[] = { '\\',0 };
1494 WCHAR keyName[MAX_PATH];
1498 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, 0, NULL);
1499 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1500 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1501 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1502 CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyA);
1503 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1504 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1505 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1506 CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyW);
1507 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1508 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1509 /* The name is expected to be UNICODE, first check with an ASCII name */
1510 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1511 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyA);
1512 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1513 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1514 /* Create the expected key */
1515 lstrcpyW(keyName, CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH);
1516 lstrcatW(keyName, baskslashW);
1517 lstrcatW(keyName, MyW);
1518 rc = RegCreateKeyExW(HKEY_CURRENT_USER, keyName, 0, NULL, 0, KEY_READ,
1520 ok(!rc, "RegCreateKeyEx failed: %ld\n", rc);
1523 /* Check opening with a UNICODE name, specifying the create new flag */
1524 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1525 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_CREATE_NEW_FLAG, MyW);
1526 ok(!store && GetLastError() == ERROR_FILE_EXISTS,
1527 "Expected ERROR_FILE_EXISTS, got %08lx\n", GetLastError());
1528 /* Now check opening with a UNICODE name, this time opening existing */
1529 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1530 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyW);
1531 ok(store != 0, "CertOpenStore failed: %08lx\n", GetLastError());
1534 HCERTSTORE memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1535 CERT_STORE_CREATE_NEW_FLAG, NULL);
1537 /* Check that it's a collection store */
1540 BOOL ret = CertAddStoreToCollection(store, memStore, 0, 0);
1542 /* FIXME: this'll fail on NT4, but what error will it give? */
1543 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
1544 CertCloseStore(memStore, 0);
1546 CertCloseStore(store, 0);
1549 /* Check opening a bogus store */
1550 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1551 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, BogusW);
1552 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1553 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1554 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1555 CERT_SYSTEM_STORE_CURRENT_USER, BogusW);
1556 ok(store != 0, "CertOpenStore failed: %08lx\n", GetLastError());
1558 CertCloseStore(store, 0);
1559 /* Now check whether deleting is allowed */
1560 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1561 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_DELETE_FLAG, BogusW);
1562 RegDeleteKeyW(HKEY_CURRENT_USER, BogusPathW);
1565 static void testCertOpenSystemStore(void)
1569 store = CertOpenSystemStoreW(0, NULL);
1570 ok(!store && GetLastError() == E_INVALIDARG,
1571 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1572 /* This succeeds, and on WinXP at least, the Bogus key is created under
1573 * HKCU (but not under HKLM, even when run as an administrator.)
1575 store = CertOpenSystemStoreW(0, BogusW);
1576 ok(store != 0, "CertOpenSystemStore failed: %08lx\n", GetLastError());
1578 CertCloseStore(store, 0);
1579 /* Delete it so other tests succeed next time around */
1580 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1581 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_DELETE_FLAG, BogusW);
1582 RegDeleteKeyW(HKEY_CURRENT_USER, BogusPathW);
1585 static void checkHash(const BYTE *data, DWORD dataLen, ALG_ID algID,
1586 PCCERT_CONTEXT context, DWORD propID)
1588 BYTE hash[20] = { 0 }, hashProperty[20];
1592 memset(hash, 0, sizeof(hash));
1593 memset(hashProperty, 0, sizeof(hashProperty));
1594 size = sizeof(hash);
1595 ret = CryptHashCertificate(0, algID, 0, data, dataLen, hash, &size);
1596 ok(ret, "CryptHashCertificate failed: %08lx\n", GetLastError());
1597 ret = CertGetCertificateContextProperty(context, propID, hashProperty,
1599 ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
1601 ok(!memcmp(hash, hashProperty, size), "Unexpected hash for property %ld\n",
1605 static void testCertProperties(void)
1607 PCCERT_CONTEXT context = CertCreateCertificateContext(X509_ASN_ENCODING,
1608 bigCert, sizeof(bigCert));
1610 ok(context != NULL, "CertCreateCertificateContext failed: %08lx\n",
1614 DWORD propID, numProps, access, size;
1616 BYTE hash[20] = { 0 }, hashProperty[20];
1617 CRYPT_DATA_BLOB blob;
1620 propID = CertEnumCertificateContextProperties(NULL, 0);
1626 propID = CertEnumCertificateContextProperties(context, propID);
1629 } while (propID != 0);
1630 ok(numProps == 0, "Expected 0 properties, got %ld\n", numProps);
1632 /* Tests with a NULL cert context. Prop ID 0 fails.. */
1633 ret = CertSetCertificateContextProperty(NULL, 0, 0, NULL);
1634 ok(!ret && GetLastError() == E_INVALIDARG,
1635 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1636 /* while this just crashes.
1637 ret = CertSetCertificateContextProperty(NULL,
1638 CERT_KEY_PROV_HANDLE_PROP_ID, 0, NULL);
1641 ret = CertSetCertificateContextProperty(context, 0, 0, NULL);
1642 ok(!ret && GetLastError() == E_INVALIDARG,
1643 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1644 /* Can't set the cert property directly, this crashes.
1645 ret = CertSetCertificateContextProperty(context,
1646 CERT_CERT_PROP_ID, 0, bigCert2);
1650 ret = CertGetCertificateContextProperty(context,
1651 CERT_ACCESS_STATE_PROP_ID, 0, NULL);
1652 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
1654 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
1655 hashProperty, NULL);
1657 /* A missing prop */
1659 ret = CertGetCertificateContextProperty(context,
1660 CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
1661 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
1662 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
1663 /* And, an implicit property */
1664 size = sizeof(access);
1665 ret = CertGetCertificateContextProperty(context,
1666 CERT_ACCESS_STATE_PROP_ID, &access, &size);
1667 ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
1669 ok(!(access & CERT_ACCESS_STATE_WRITE_PERSIST_FLAG),
1670 "Didn't expect a persisted cert\n");
1671 /* Trying to set this "read only" property crashes.
1672 access |= CERT_ACCESS_STATE_WRITE_PERSIST_FLAG;
1673 ret = CertSetCertificateContextProperty(context,
1674 CERT_ACCESS_STATE_PROP_ID, 0, &access);
1677 /* Can I set the hash to an invalid hash? */
1679 blob.cbData = sizeof(hash);
1680 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID, 0,
1682 ok(ret, "CertSetCertificateContextProperty failed: %08lx\n",
1684 size = sizeof(hashProperty);
1685 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
1686 hashProperty, &size);
1687 ok(!memcmp(hashProperty, hash, sizeof(hash)), "Unexpected hash\n");
1688 /* Delete the (bogus) hash, and get the real one */
1689 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID, 0,
1691 ok(ret, "CertSetCertificateContextProperty failed: %08lx\n",
1693 checkHash(bigCert, sizeof(bigCert), CALG_SHA1, context,
1696 /* Now that the hash property is set, we should get one property when
1702 propID = CertEnumCertificateContextProperties(context, propID);
1705 } while (propID != 0);
1706 ok(numProps == 1, "Expected 1 properties, got %ld\n", numProps);
1708 /* Check a few other implicit properties */
1709 checkHash(bigCert, sizeof(bigCert), CALG_MD5, context,
1710 CERT_MD5_HASH_PROP_ID);
1712 context->pCertInfo->Subject.pbData,
1713 context->pCertInfo->Subject.cbData,
1714 CALG_MD5, context, CERT_SUBJECT_NAME_MD5_HASH_PROP_ID);
1716 context->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData,
1717 context->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData,
1718 CALG_MD5, context, CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID);
1720 /* Odd: this doesn't fail on other certificates, so there must be
1721 * something weird about this cert that causes it to fail.
1724 ret = CertGetCertificateContextProperty(context,
1725 CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size);
1726 todo_wine ok(!ret && GetLastError() == ERROR_INVALID_DATA,
1727 "Expected ERROR_INVALID_DATA, got %08lx\n", GetLastError());
1729 CertFreeCertificateContext(context);
1733 static void testAddSerialized(void)
1737 BYTE buf[sizeof(struct CertPropIDHeader) * 2 + 20 + sizeof(bigCert)] =
1740 struct CertPropIDHeader *hdr;
1741 PCCERT_CONTEXT context;
1743 ret = CertAddSerializedElementToStore(0, NULL, 0, 0, 0, 0, NULL, NULL);
1744 ok(!ret && GetLastError() == ERROR_END_OF_MEDIA,
1745 "Expected ERROR_END_OF_MEDIA, got %08lx\n", GetLastError());
1747 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1748 CERT_STORE_CREATE_NEW_FLAG, NULL);
1749 ok(store != 0, "CertOpenStore failed: %08lx\n", GetLastError());
1751 ret = CertAddSerializedElementToStore(store, NULL, 0, 0, 0, 0, NULL, NULL);
1752 ok(!ret && GetLastError() == ERROR_END_OF_MEDIA,
1753 "Expected ERROR_END_OF_MEDIA, got %08lx\n", GetLastError());
1755 /* Test with an empty property */
1756 hdr = (struct CertPropIDHeader *)buf;
1757 hdr->propID = CERT_CERT_PROP_ID;
1760 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0,
1762 ok(!ret && GetLastError() == E_INVALIDARG,
1763 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1764 /* Test with a bad size in property header */
1765 hdr->cb = sizeof(bigCert) - 1;
1766 memcpy(buf + sizeof(struct CertPropIDHeader), bigCert, 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 /* Kosher size in property header, but no context type */
1782 hdr->cb = sizeof(bigCert);
1783 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0,
1785 ok(!ret && GetLastError() == E_INVALIDARG,
1786 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1787 ret = CertAddSerializedElementToStore(store, buf,
1788 sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0, 0, NULL,
1790 ok(!ret && GetLastError() == E_INVALIDARG,
1791 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1792 ret = CertAddSerializedElementToStore(store, buf,
1793 sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
1795 ok(!ret && GetLastError() == E_INVALIDARG,
1796 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1797 /* With a bad context type */
1798 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0,
1799 CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL);
1800 ok(!ret && GetLastError() == E_INVALIDARG,
1801 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1802 ret = CertAddSerializedElementToStore(store, buf,
1803 sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0,
1804 CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL);
1805 ok(!ret && GetLastError() == E_INVALIDARG,
1806 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1807 ret = CertAddSerializedElementToStore(store, buf,
1808 sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
1809 0, CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL);
1810 ok(!ret && GetLastError() == E_INVALIDARG,
1811 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1812 /* Bad unknown field, good type */
1814 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0,
1815 CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1816 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1817 "Expected ERROR_FILE_NOT_FOUND got %08lx\n", GetLastError());
1818 ret = CertAddSerializedElementToStore(store, buf,
1819 sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0,
1820 CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1821 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1822 "Expected ERROR_FILE_NOT_FOUND got %08lx\n", GetLastError());
1823 ret = CertAddSerializedElementToStore(store, buf,
1824 sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
1825 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1826 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1827 "Expected ERROR_FILE_NOT_FOUND got %08lx\n", GetLastError());
1828 /* Most everything okay, but bad add disposition */
1831 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0,
1832 CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1834 ret = CertAddSerializedElementToStore(store, buf,
1835 sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0,
1836 CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1838 /* Everything okay, but buffer's too big */
1839 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf),
1840 CERT_STORE_ADD_NEW, 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1841 ok(ret, "CertAddSerializedElementToStore failed: %08lx\n", GetLastError());
1842 /* Everything okay, check it's not re-added */
1843 ret = CertAddSerializedElementToStore(store, buf,
1844 sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
1845 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1846 ok(!ret && GetLastError() == CRYPT_E_EXISTS,
1847 "Expected CRYPT_E_EXISTS, got %08lx\n", GetLastError());
1849 context = CertEnumCertificatesInStore(store, NULL);
1850 ok(context != NULL, "Expected a cert\n");
1852 CertDeleteCertificateFromStore(context);
1854 /* Try adding with a bogus hash. Oddly enough, it succeeds, and the hash,
1855 * when queried, is the real hash rather than the bogus hash.
1857 hdr = (struct CertPropIDHeader *)(buf + sizeof(struct CertPropIDHeader) +
1859 hdr->propID = CERT_HASH_PROP_ID;
1861 hdr->cb = sizeof(hash);
1862 memset(hash, 0xc, sizeof(hash));
1863 memcpy((LPBYTE)hdr + sizeof(struct CertPropIDHeader), hash, sizeof(hash));
1864 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf),
1865 CERT_STORE_ADD_NEW, 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL,
1866 (const void **)&context);
1867 ok(ret, "CertAddSerializedElementToStore failed: %08lx\n", GetLastError());
1870 BYTE hashVal[20], realHash[20];
1871 DWORD size = sizeof(hashVal);
1873 ret = CryptHashCertificate(0, 0, 0, bigCert, sizeof(bigCert),
1875 ok(ret, "CryptHashCertificate failed: %08lx\n", GetLastError());
1876 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
1878 ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
1880 ok(!memcmp(hashVal, realHash, size), "Unexpected hash\n");
1881 CertFreeCertificateContext(context);
1884 CertCloseStore(store, 0);
1887 static const BYTE CRL[] = { 0x30, 0x2c, 0x30, 0x02, 0x06, 0x00,
1888 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a,
1889 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 0x31,
1890 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
1892 static const BYTE newerCRL[] = { 0x30, 0x2a, 0x30, 0x02, 0x06, 0x00, 0x30,
1893 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
1894 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x17, 0x0d, 0x30, 0x36,
1895 0x30, 0x35, 0x31, 0x36, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
1897 static void testCreateCRL(void)
1899 PCCRL_CONTEXT context;
1901 context = CertCreateCRLContext(0, NULL, 0);
1902 ok(!context && GetLastError() == E_INVALIDARG,
1903 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1904 context = CertCreateCRLContext(X509_ASN_ENCODING, NULL, 0);
1905 ok(!context && GetLastError() == CRYPT_E_ASN1_EOD,
1906 "Expected CRYPT_E_ASN1_EOD, got %08lx\n", GetLastError());
1907 context = CertCreateCRLContext(X509_ASN_ENCODING, bigCert, sizeof(bigCert));
1908 ok(!context && GetLastError() == CRYPT_E_ASN1_CORRUPT,
1909 "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
1910 context = CertCreateCRLContext(X509_ASN_ENCODING, signedCRL,
1911 sizeof(signedCRL) - 1);
1912 ok(!context && (GetLastError() == CRYPT_E_ASN1_EOD ||
1913 GetLastError() == CRYPT_E_ASN1_CORRUPT),
1914 "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %08lx\n",
1916 context = CertCreateCRLContext(X509_ASN_ENCODING, signedCRL,
1918 ok(context != NULL, "CertCreateCRLContext failed: %08lx\n", GetLastError());
1920 CertFreeCRLContext(context);
1921 context = CertCreateCRLContext(X509_ASN_ENCODING, CRL, sizeof(CRL));
1922 ok(context != NULL, "CertCreateCRLContext failed: %08lx\n", GetLastError());
1924 CertFreeCRLContext(context);
1927 static void testAddCRL(void)
1929 HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1930 CERT_STORE_CREATE_NEW_FLAG, NULL);
1931 PCCRL_CONTEXT context;
1936 /* Bad CRL encoding type */
1937 ret = CertAddEncodedCRLToStore(0, 0, NULL, 0, 0, NULL);
1938 ok(!ret && GetLastError() == E_INVALIDARG,
1939 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1940 ret = CertAddEncodedCRLToStore(store, 0, NULL, 0, 0, NULL);
1941 ok(!ret && GetLastError() == E_INVALIDARG,
1942 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1943 ret = CertAddEncodedCRLToStore(0, 0, signedCRL, sizeof(signedCRL), 0, NULL);
1944 ok(!ret && GetLastError() == E_INVALIDARG,
1945 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1946 ret = CertAddEncodedCRLToStore(store, 0, signedCRL, sizeof(signedCRL), 0,
1948 ok(!ret && GetLastError() == E_INVALIDARG,
1949 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1950 ret = CertAddEncodedCRLToStore(0, 0, signedCRL, sizeof(signedCRL),
1951 CERT_STORE_ADD_ALWAYS, NULL);
1952 ok(!ret && GetLastError() == E_INVALIDARG,
1953 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1954 ret = CertAddEncodedCRLToStore(store, 0, signedCRL, sizeof(signedCRL),
1955 CERT_STORE_ADD_ALWAYS, NULL);
1956 ok(!ret && GetLastError() == E_INVALIDARG,
1957 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1960 ret = CertAddEncodedCRLToStore(0, X509_ASN_ENCODING, NULL, 0, 0, NULL);
1961 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
1962 "Expected CRYPT_E_ASN1_EOD, got %08lx\n", GetLastError());
1963 ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, NULL, 0, 0, NULL);
1964 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
1965 "Expected CRYPT_E_ASN1_EOD, got %08lx\n", GetLastError());
1967 /* Weird--bad add disposition leads to an access violation in Windows. */
1968 ret = CertAddEncodedCRLToStore(0, X509_ASN_ENCODING, signedCRL,
1969 sizeof(signedCRL), 0, NULL);
1970 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1971 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
1972 ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, signedCRL,
1973 sizeof(signedCRL), 0, NULL);
1974 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1975 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
1977 /* Weird--can add a CRL to the NULL store (does this have special meaning?)
1980 ret = CertAddEncodedCRLToStore(0, X509_ASN_ENCODING, signedCRL,
1981 sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, &context);
1982 ok(ret, "CertAddEncodedCRLToStore failed: %08lx\n", GetLastError());
1984 CertFreeCRLContext(context);
1986 /* Normal cases: a "signed" CRL is okay.. */
1987 ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, signedCRL,
1988 sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, NULL);
1989 /* and an unsigned one is too. */
1990 ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, CRL, sizeof(CRL),
1991 CERT_STORE_ADD_ALWAYS, NULL);
1992 ok(ret, "CertAddEncodedCRLToStore failed: %08lx\n", GetLastError());
1994 ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, newerCRL,
1995 sizeof(newerCRL), CERT_STORE_ADD_NEW, NULL);
1996 ok(!ret && GetLastError() == CRYPT_E_EXISTS,
1997 "Expected CRYPT_E_EXISTS, got %08lx\n", GetLastError());
1999 /* This should replace (one of) the existing CRL(s). */
2000 ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, newerCRL,
2001 sizeof(newerCRL), CERT_STORE_ADD_NEWER, NULL);
2002 ok(ret, "CertAddEncodedCRLToStore failed: %08lx\n", GetLastError());
2004 CertCloseStore(store, 0);
2007 static void testFindCRL(void)
2009 HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
2010 CERT_STORE_CREATE_NEW_FLAG, NULL);
2011 PCCRL_CONTEXT context;
2012 PCCERT_CONTEXT cert;
2017 ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, signedCRL,
2018 sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, NULL);
2019 ok(ret, "CertAddEncodedCRLToStore failed: %08lx\n", GetLastError());
2022 context = CertFindCRLInStore(NULL, 0, 0, 0, NULL, NULL);
2025 /* Find any context */
2026 context = CertFindCRLInStore(store, 0, 0, CRL_FIND_ANY, NULL, NULL);
2027 ok(context != NULL, "Expected a context\n");
2029 CertFreeCRLContext(context);
2030 /* Bogus flags are ignored */
2031 context = CertFindCRLInStore(store, 0, 1234, CRL_FIND_ANY, NULL, NULL);
2032 ok(context != NULL, "Expected a context\n");
2034 CertFreeCRLContext(context);
2035 /* CRL encoding type is ignored too */
2036 context = CertFindCRLInStore(store, 1234, 0, CRL_FIND_ANY, NULL, NULL);
2037 ok(context != NULL, "Expected a context\n");
2039 CertFreeCRLContext(context);
2041 /* This appears to match any cert */
2042 context = CertFindCRLInStore(store, 0, 0, CRL_FIND_ISSUED_BY, NULL, NULL);
2043 ok(context != NULL, "Expected a context\n");
2045 CertFreeCRLContext(context);
2047 /* Try to match an issuer that isn't in the store */
2048 cert = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert2,
2050 ok(cert != NULL, "CertCreateCertificateContext failed: %08lx\n",
2052 context = CertFindCRLInStore(store, 0, 0, CRL_FIND_ISSUED_BY, cert, NULL);
2053 ok(context == NULL, "Expected no matching context\n");
2054 CertFreeCertificateContext(cert);
2056 /* Match an issuer that is in the store */
2057 cert = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
2059 ok(cert != NULL, "CertCreateCertificateContext failed: %08lx\n",
2061 context = CertFindCRLInStore(store, 0, 0, CRL_FIND_ISSUED_BY, cert, NULL);
2062 ok(context != NULL, "Expected a context\n");
2064 CertFreeCRLContext(context);
2065 CertFreeCertificateContext(cert);
2067 CertCloseStore(store, 0);
2070 static void checkCRLHash(const BYTE *data, DWORD dataLen, ALG_ID algID,
2071 PCCRL_CONTEXT context, DWORD propID)
2073 BYTE hash[20] = { 0 }, hashProperty[20];
2077 memset(hash, 0, sizeof(hash));
2078 memset(hashProperty, 0, sizeof(hashProperty));
2079 size = sizeof(hash);
2080 ret = CryptHashCertificate(0, algID, 0, data, dataLen, hash, &size);
2081 ok(ret, "CryptHashCertificate failed: %08lx\n", GetLastError());
2082 ret = CertGetCRLContextProperty(context, propID, hashProperty, &size);
2083 ok(ret, "CertGetCRLContextProperty failed: %08lx\n", GetLastError());
2084 ok(!memcmp(hash, hashProperty, size), "Unexpected hash for property %ld\n",
2088 static void testCRLProperties(void)
2090 PCCRL_CONTEXT context = CertCreateCRLContext(X509_ASN_ENCODING,
2093 ok(context != NULL, "CertCreateCRLContext failed: %08lx\n", GetLastError());
2096 DWORD propID, numProps, access, size;
2098 BYTE hash[20] = { 0 }, hashProperty[20];
2099 CRYPT_DATA_BLOB blob;
2102 propID = CertEnumCRLContextProperties(NULL, 0);
2108 propID = CertEnumCRLContextProperties(context, propID);
2111 } while (propID != 0);
2112 ok(numProps == 0, "Expected 0 properties, got %ld\n", numProps);
2114 /* Tests with a NULL cert context. Prop ID 0 fails.. */
2115 ret = CertSetCRLContextProperty(NULL, 0, 0, NULL);
2116 ok(!ret && GetLastError() == E_INVALIDARG,
2117 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
2118 /* while this just crashes.
2119 ret = CertSetCRLContextProperty(NULL, CERT_KEY_PROV_HANDLE_PROP_ID, 0,
2123 ret = CertSetCRLContextProperty(context, 0, 0, NULL);
2124 ok(!ret && GetLastError() == E_INVALIDARG,
2125 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
2126 /* Can't set the cert property directly, this crashes.
2127 ret = CertSetCRLContextProperty(context, CERT_CRL_PROP_ID, 0, CRL);
2131 ret = CertGetCRLContextProperty(context, CERT_ACCESS_STATE_PROP_ID, 0,
2133 ret = CertGetCRLContextProperty(context, CERT_HASH_PROP_ID, NULL, NULL);
2134 ret = CertGetCRLContextProperty(context, CERT_HASH_PROP_ID,
2135 hashProperty, NULL);
2137 /* A missing prop */
2139 ret = CertGetCRLContextProperty(context, CERT_KEY_PROV_INFO_PROP_ID,
2141 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
2142 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
2143 /* And, an implicit property */
2144 ret = CertGetCRLContextProperty(context, CERT_ACCESS_STATE_PROP_ID,
2146 ok(ret, "CertGetCRLContextProperty failed: %08lx\n", GetLastError());
2147 ret = CertGetCRLContextProperty(context, CERT_ACCESS_STATE_PROP_ID,
2149 ok(ret, "CertGetCRLContextProperty failed: %08lx\n", GetLastError());
2150 ok(!(access & CERT_ACCESS_STATE_WRITE_PERSIST_FLAG),
2151 "Didn't expect a persisted crl\n");
2152 /* Trying to set this "read only" property crashes.
2153 access |= CERT_ACCESS_STATE_WRITE_PERSIST_FLAG;
2154 ret = CertSetCRLContextProperty(context, CERT_ACCESS_STATE_PROP_ID, 0,
2158 /* Can I set the hash to an invalid hash? */
2160 blob.cbData = sizeof(hash);
2161 ret = CertSetCRLContextProperty(context, CERT_HASH_PROP_ID, 0, &blob);
2162 ok(ret, "CertSetCRLContextProperty failed: %08lx\n",
2164 size = sizeof(hashProperty);
2165 ret = CertGetCRLContextProperty(context, CERT_HASH_PROP_ID,
2166 hashProperty, &size);
2167 ok(!memcmp(hashProperty, hash, sizeof(hash)), "Unexpected hash\n");
2168 /* Delete the (bogus) hash, and get the real one */
2169 ret = CertSetCRLContextProperty(context, CERT_HASH_PROP_ID, 0, NULL);
2170 ok(ret, "CertSetCRLContextProperty failed: %08lx\n", GetLastError());
2171 checkCRLHash(CRL, sizeof(CRL), CALG_SHA1, context, CERT_HASH_PROP_ID);
2173 /* Now that the hash property is set, we should get one property when
2179 propID = CertEnumCRLContextProperties(context, propID);
2182 } while (propID != 0);
2183 ok(numProps == 1, "Expected 1 properties, got %ld\n", numProps);
2185 /* Check a few other implicit properties */
2186 checkCRLHash(CRL, sizeof(CRL), CALG_MD5, context,
2187 CERT_MD5_HASH_PROP_ID);
2189 CertFreeCRLContext(context);
2198 testGetSubjectCert();
2199 testGetIssuerCert();
2205 /* various combinations of CertOpenStore */
2207 testCollectionStore();
2209 testSystemRegStore();
2212 testCertOpenSystemStore();
2214 testCertProperties();
2215 testCRLProperties();
2216 testAddSerialized();