2 * crypt32 cert functions tests
4 * Copyright 2005-2006 Juan Lang
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
30 #include "wine/test.h"
32 static BOOL (WINAPI
* pCryptVerifyCertificateSignatureEx
)
33 (HCRYPTPROV
, DWORD
, DWORD
, void *, DWORD
, void *, DWORD
, void *);
35 #define CRYPT_GET_PROC(func) \
36 p ## func = (void *)GetProcAddress(hCrypt32, #func); \
38 trace("GetProcAddress(hCrypt32, \"%s\") failed\n", #func); \
40 static void init_function_pointers(void)
44 pCryptVerifyCertificateSignatureEx
= NULL
;
46 hCrypt32
= GetModuleHandleA("crypt32.dll");
49 CRYPT_GET_PROC(CryptVerifyCertificateSignatureEx
);
52 static BYTE subjectName
[] = { 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
53 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
55 static BYTE serialNum
[] = { 1 };
56 static const BYTE bigCert
[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
57 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
58 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
59 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
60 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
61 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
62 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
63 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
64 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
65 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
66 static BYTE bigCertHash
[] = { 0x6e, 0x30, 0x90, 0x71, 0x5f, 0xd9, 0x23,
67 0x56, 0xeb, 0xae, 0x25, 0x40, 0xe6, 0x22, 0xda, 0x19, 0x26, 0x02, 0xa6, 0x08 };
69 static const BYTE bigCertWithDifferentSubject
[] = { 0x30, 0x7a, 0x02, 0x01, 0x02,
70 0x30, 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
71 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67,
72 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31,
73 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
74 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15,
75 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c,
76 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06,
77 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55,
78 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02,
80 static const BYTE bigCertWithDifferentIssuer
[] = { 0x30, 0x7a, 0x02, 0x01,
81 0x01, 0x30, 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
82 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e,
83 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
84 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30,
85 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30,
86 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
87 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02,
88 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03,
89 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff,
92 static BYTE subjectName2
[] = { 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
93 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61,
95 static const BYTE bigCert2
[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
96 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
97 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
98 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
99 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
100 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
101 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20,
102 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
103 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
104 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
105 static const BYTE bigCert2WithDifferentSerial
[] = { 0x30, 0x7a, 0x02, 0x01,
106 0x02, 0x30, 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
107 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e,
108 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
109 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30,
110 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30,
111 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41,
112 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02,
113 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03,
114 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff,
116 static BYTE bigCert2Hash
[] = { 0x4a, 0x7f, 0x32, 0x1f, 0xcf, 0x3b, 0xc0,
117 0x87, 0x48, 0x2b, 0xa1, 0x86, 0x54, 0x18, 0xe4, 0x3a, 0x0e, 0x53, 0x7e, 0x2b };
119 static const BYTE certWithUsage
[] = { 0x30, 0x81, 0x93, 0x02, 0x01, 0x01, 0x30,
120 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04,
121 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00,
122 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
123 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
124 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31,
125 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61,
126 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00,
127 0x03, 0x01, 0x00, 0xa3, 0x2f, 0x30, 0x2d, 0x30, 0x2b, 0x06, 0x03, 0x55, 0x1d,
128 0x25, 0x01, 0x01, 0xff, 0x04, 0x21, 0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01,
129 0x05, 0x05, 0x07, 0x03, 0x03, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
130 0x03, 0x02, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
132 static void testAddCert(void)
135 HCERTSTORE collection
;
136 PCCERT_CONTEXT context
;
137 PCCERT_CONTEXT copyContext
;
140 store
= CertOpenStore(CERT_STORE_PROV_MEMORY
, 0, 0,
141 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
142 ok(store
!= NULL
, "CertOpenStore failed: %d\n", GetLastError());
146 /* Weird--bad add disposition leads to an access violation in Windows.
148 ret
= CertAddEncodedCertificateToStore(0, X509_ASN_ENCODING
, bigCert
,
149 sizeof(bigCert
), 0, NULL
);
150 ok(!ret
&& GetLastError() == STATUS_ACCESS_VIOLATION
,
151 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
152 ret
= CertAddEncodedCertificateToStore(store
, X509_ASN_ENCODING
,
153 bigCert
, sizeof(bigCert
), 0, NULL
);
154 ok(!ret
&& GetLastError() == STATUS_ACCESS_VIOLATION
,
155 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
157 /* Weird--can add a cert to the NULL store (does this have special
161 ret
= CertAddEncodedCertificateToStore(0, X509_ASN_ENCODING
, bigCert
,
162 sizeof(bigCert
), CERT_STORE_ADD_ALWAYS
, &context
);
163 ok(ret
, "CertAddEncodedCertificateToStore failed: %08x\n",
166 CertFreeCertificateContext(context
);
168 ret
= CertAddEncodedCertificateToStore(store
, X509_ASN_ENCODING
,
169 bigCert
, sizeof(bigCert
), CERT_STORE_ADD_ALWAYS
, NULL
);
170 ok(ret
, "CertAddEncodedCertificateToStore failed: %08x\n",
172 ret
= CertAddEncodedCertificateToStore(store
, X509_ASN_ENCODING
,
173 bigCert2
, sizeof(bigCert2
), CERT_STORE_ADD_NEW
, NULL
);
174 ok(ret
, "CertAddEncodedCertificateToStore failed: %08x\n",
176 /* This has the same name as bigCert, so finding isn't done by name */
177 ret
= CertAddEncodedCertificateToStore(store
, X509_ASN_ENCODING
,
178 certWithUsage
, sizeof(certWithUsage
), CERT_STORE_ADD_NEW
, &context
);
179 ok(ret
, "CertAddEncodedCertificateToStore failed: %08x\n",
181 ok(context
!= NULL
, "Expected a context\n");
184 CRYPT_DATA_BLOB hash
= { sizeof(bigCert2Hash
), bigCert2Hash
};
186 /* Duplicate (AddRef) the context so we can still use it after
187 * deleting it from the store.
189 CertDuplicateCertificateContext(context
);
190 CertDeleteCertificateFromStore(context
);
191 /* Set the same hash as bigCert2, and try to readd it */
192 ret
= CertSetCertificateContextProperty(context
, CERT_HASH_PROP_ID
,
194 ok(ret
, "CertSetCertificateContextProperty failed: %08x\n",
196 ret
= CertAddCertificateContextToStore(store
, context
,
197 CERT_STORE_ADD_NEW
, NULL
);
198 /* The failure is a bit odd (CRYPT_E_ASN1_BADTAG), so just check
201 ok(!ret
, "Expected failure\n");
202 CertFreeCertificateContext(context
);
204 context
= CertCreateCertificateContext(X509_ASN_ENCODING
, bigCert2
,
206 ok(context
!= NULL
, "Expected a context\n");
209 /* Try to readd bigCert2 to the store */
210 ret
= CertAddCertificateContextToStore(store
, context
,
211 CERT_STORE_ADD_NEW
, NULL
);
212 ok(!ret
&& GetLastError() == CRYPT_E_EXISTS
,
213 "Expected CRYPT_E_EXISTS, got %08x\n", GetLastError());
214 CertFreeCertificateContext(context
);
217 /* Adding a cert with the same issuer name and serial number (but
218 * different subject) as an existing cert succeeds.
221 ret
= CertAddEncodedCertificateToStore(store
, X509_ASN_ENCODING
,
222 bigCert2WithDifferentSerial
, sizeof(bigCert2WithDifferentSerial
),
223 CERT_STORE_ADD_NEW
, &context
);
224 ok(ret
, "CertAddEncodedCertificateToStore failed: %08x\n",
227 CertDeleteCertificateFromStore(context
);
229 /* Adding a cert with the same subject name and serial number (but
230 * different issuer) as an existing cert succeeds.
233 ret
= CertAddEncodedCertificateToStore(store
, X509_ASN_ENCODING
,
234 bigCertWithDifferentSubject
, sizeof(bigCertWithDifferentSubject
),
235 CERT_STORE_ADD_NEW
, &context
);
236 ok(ret
, "CertAddEncodedCertificateToStore failed: %08x\n",
239 CertDeleteCertificateFromStore(context
);
241 /* Adding a cert with the same issuer name and serial number (but
242 * different otherwise) as an existing cert succeeds.
245 ret
= CertAddEncodedCertificateToStore(store
, X509_ASN_ENCODING
,
246 bigCertWithDifferentIssuer
, sizeof(bigCertWithDifferentIssuer
),
247 CERT_STORE_ADD_NEW
, &context
);
248 ok(ret
, "CertAddEncodedCertificateToStore failed: %08x\n",
251 CertDeleteCertificateFromStore(context
);
253 collection
= CertOpenStore(CERT_STORE_PROV_COLLECTION
, 0, 0,
254 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
255 ok(collection
!= NULL
, "CertOpenStore failed: %08x\n", GetLastError());
258 /* Add store to the collection, but disable updates */
259 CertAddStoreToCollection(collection
, store
, 0, 0);
261 context
= CertCreateCertificateContext(X509_ASN_ENCODING
, bigCert2
,
263 ok(context
!= NULL
, "Expected a context\n");
266 /* Try to readd bigCert2 to the collection */
267 ret
= CertAddCertificateContextToStore(collection
, context
,
268 CERT_STORE_ADD_NEW
, NULL
);
269 ok(!ret
&& GetLastError() == CRYPT_E_EXISTS
,
270 "Expected CRYPT_E_EXISTS, got %08x\n", GetLastError());
271 /* Replacing an existing certificate context is allowed, even
272 * though updates to the collection aren't..
274 ret
= CertAddCertificateContextToStore(collection
, context
,
275 CERT_STORE_ADD_REPLACE_EXISTING
, NULL
);
276 ok(ret
, "CertAddCertificateContextToStore failed: %08x\n",
278 /* use the existing certificate and ask for a copy of the context*/
280 ret
= CertAddCertificateContextToStore(collection
, context
,
281 CERT_STORE_ADD_USE_EXISTING
, ©Context
);
282 ok(ret
, "CertAddCertificateContextToStore failed: %08x\n",
284 ok(copyContext
!= NULL
, "Expected on output a non NULL copyContext\n");
286 CertFreeCertificateContext(copyContext
);
287 /* but adding a new certificate isn't allowed. */
288 ret
= CertAddCertificateContextToStore(collection
, context
,
289 CERT_STORE_ADD_ALWAYS
, NULL
);
290 ok(!ret
&& GetLastError() == E_ACCESSDENIED
,
291 "Expected E_ACCESSDENIED, got %08x\n", GetLastError());
292 CertFreeCertificateContext(context
);
295 CertCloseStore(collection
, 0);
298 CertCloseStore(store
, 0);
301 static void checkHash(const BYTE
*data
, DWORD dataLen
, ALG_ID algID
,
302 PCCERT_CONTEXT context
, DWORD propID
)
304 BYTE hash
[20] = { 0 }, hashProperty
[20];
307 DWORD dwSizeWithNull
;
309 memset(hash
, 0, sizeof(hash
));
310 memset(hashProperty
, 0, sizeof(hashProperty
));
312 ret
= CryptHashCertificate(0, algID
, 0, data
, dataLen
, hash
, &size
);
313 ok(ret
, "CryptHashCertificate failed: %08x\n", GetLastError());
314 ret
= CertGetCertificateContextProperty(context
, propID
, NULL
,
316 ok(ret
, "CertGetCertificateContextProperty failed: %08x\n",
318 ret
= CertGetCertificateContextProperty(context
, propID
, hashProperty
,
320 ok(ret
, "CertGetCertificateContextProperty failed: %08x\n",
322 ok(!memcmp(hash
, hashProperty
, size
), "Unexpected hash for property %d\n",
324 ok(size
== dwSizeWithNull
, "Unexpected length of hash for property: received %d instead of %d\n",
325 dwSizeWithNull
,size
);
328 static WCHAR cspNameW
[] = { 'W','i','n','e','C','r','y','p','t','T','e','m','p',0 };
330 static void testCertProperties(void)
332 PCCERT_CONTEXT context
= CertCreateCertificateContext(X509_ASN_ENCODING
,
333 bigCert
, sizeof(bigCert
));
334 DWORD propID
, numProps
, access
, size
;
336 BYTE hash
[20] = { 0 }, hashProperty
[20];
337 CRYPT_DATA_BLOB blob
;
338 CERT_KEY_CONTEXT keyContext
;
341 ok(context
!= NULL
, "CertCreateCertificateContext failed: %08x\n",
347 propID = CertEnumCertificateContextProperties(NULL, 0);
353 propID
= CertEnumCertificateContextProperties(context
, propID
);
356 } while (propID
!= 0);
357 ok(numProps
== 0, "Expected 0 properties, got %d\n", numProps
);
359 /* Tests with a NULL cert context. Prop ID 0 fails.. */
360 ret
= CertSetCertificateContextProperty(NULL
, 0, 0, NULL
);
361 ok(!ret
&& GetLastError() == E_INVALIDARG
,
362 "Expected E_INVALIDARG, got %08x\n", GetLastError());
363 /* while this just crashes.
364 ret = CertSetCertificateContextProperty(NULL,
365 CERT_KEY_PROV_HANDLE_PROP_ID, 0, NULL);
368 ret
= CertSetCertificateContextProperty(context
, 0, 0, NULL
);
369 ok(!ret
&& GetLastError() == E_INVALIDARG
,
370 "Expected E_INVALIDARG, got %08x\n", GetLastError());
371 /* Can't set the cert property directly, this crashes.
372 ret = CertSetCertificateContextProperty(context,
373 CERT_CERT_PROP_ID, 0, bigCert2);
377 ret = CertGetCertificateContextProperty(context,
378 CERT_ACCESS_STATE_PROP_ID, 0, NULL);
379 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
381 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
386 ret
= CertGetCertificateContextProperty(context
,
387 CERT_KEY_PROV_INFO_PROP_ID
, NULL
, &size
);
388 ok(!ret
&& GetLastError() == CRYPT_E_NOT_FOUND
,
389 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
390 /* And, an implicit property */
391 size
= sizeof(access
);
392 ret
= CertGetCertificateContextProperty(context
,
393 CERT_ACCESS_STATE_PROP_ID
, &access
, &size
);
394 ok(ret
, "CertGetCertificateContextProperty failed: %08x\n",
396 ok(!(access
& CERT_ACCESS_STATE_WRITE_PERSIST_FLAG
),
397 "Didn't expect a persisted cert\n");
398 /* Trying to set this "read only" property crashes.
399 access |= CERT_ACCESS_STATE_WRITE_PERSIST_FLAG;
400 ret = CertSetCertificateContextProperty(context,
401 CERT_ACCESS_STATE_PROP_ID, 0, &access);
404 /* Can I set the hash to an invalid hash? */
406 blob
.cbData
= sizeof(hash
);
407 ret
= CertSetCertificateContextProperty(context
, CERT_HASH_PROP_ID
, 0,
409 ok(ret
, "CertSetCertificateContextProperty failed: %08x\n",
411 size
= sizeof(hashProperty
);
412 ret
= CertGetCertificateContextProperty(context
, CERT_HASH_PROP_ID
,
413 hashProperty
, &size
);
414 ok(!memcmp(hashProperty
, hash
, sizeof(hash
)), "Unexpected hash\n");
415 /* Delete the (bogus) hash, and get the real one */
416 ret
= CertSetCertificateContextProperty(context
, CERT_HASH_PROP_ID
, 0,
418 ok(ret
, "CertSetCertificateContextProperty failed: %08x\n",
420 checkHash(bigCert
, sizeof(bigCert
), CALG_SHA1
, context
,
423 /* Now that the hash property is set, we should get one property when
429 propID
= CertEnumCertificateContextProperties(context
, propID
);
432 } while (propID
!= 0);
433 ok(numProps
== 1, "Expected 1 properties, got %d\n", numProps
);
435 /* Check a few other implicit properties */
436 checkHash(bigCert
, sizeof(bigCert
), CALG_MD5
, context
,
437 CERT_MD5_HASH_PROP_ID
);
439 context
->pCertInfo
->Subject
.pbData
,
440 context
->pCertInfo
->Subject
.cbData
,
441 CALG_MD5
, context
, CERT_SUBJECT_NAME_MD5_HASH_PROP_ID
);
443 context
->pCertInfo
->SubjectPublicKeyInfo
.PublicKey
.pbData
,
444 context
->pCertInfo
->SubjectPublicKeyInfo
.PublicKey
.cbData
,
445 CALG_MD5
, context
, CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID
);
447 /* Test key identifiers and handles and such */
449 ret
= CertGetCertificateContextProperty(context
,
450 CERT_KEY_IDENTIFIER_PROP_ID
, NULL
, &size
);
451 ok(!ret
&& GetLastError() == ERROR_INVALID_DATA
,
452 "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
453 size
= sizeof(CERT_KEY_CONTEXT
);
454 ret
= CertGetCertificateContextProperty(context
,
455 CERT_KEY_IDENTIFIER_PROP_ID
, NULL
, &size
);
456 ok(!ret
&& GetLastError() == ERROR_INVALID_DATA
,
457 "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
458 ret
= CertGetCertificateContextProperty(context
,
459 CERT_KEY_IDENTIFIER_PROP_ID
, &keyContext
, &size
);
460 ok(!ret
&& GetLastError() == ERROR_INVALID_DATA
,
461 "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
462 /* Key context with an invalid size */
463 keyContext
.cbSize
= 0;
464 ret
= CertSetCertificateContextProperty(context
,
465 CERT_KEY_IDENTIFIER_PROP_ID
, 0, &keyContext
);
466 ok(ret
, "CertSetCertificateContextProperty failed: %08x\n",
468 size
= sizeof(keyContext
);
469 ret
= CertGetCertificateContextProperty(context
,
470 CERT_KEY_IDENTIFIER_PROP_ID
, &keyContext
, &size
);
471 ok(ret
, "CertGetCertificateContextProperty failed: %08x\n",
473 keyContext
.cbSize
= sizeof(keyContext
);
474 keyContext
.hCryptProv
= 0;
475 keyContext
.dwKeySpec
= AT_SIGNATURE
;
477 ret = CertSetCertificateContextProperty(context,
478 CERT_KEY_IDENTIFIER_PROP_ID, 0, &keyContext);
479 ret = CertSetCertificateContextProperty(context,
480 CERT_KEY_IDENTIFIER_PROP_ID, CERT_STORE_NO_CRYPT_RELEASE_FLAG,
483 ret
= CryptAcquireContextW(&csp
, cspNameW
,
484 MS_DEF_PROV_W
, PROV_RSA_FULL
, CRYPT_NEWKEYSET
);
485 ok(ret
, "CryptAcquireContextW failed: %08x\n", GetLastError());
486 keyContext
.hCryptProv
= csp
;
487 ret
= CertSetCertificateContextProperty(context
,
488 CERT_KEY_CONTEXT_PROP_ID
, 0, &keyContext
);
489 ok(ret
, "CertSetCertificateContextProperty failed: %08x\n",
491 /* Now that that's set, the key prov handle property is also gettable.
493 size
= sizeof(DWORD
);
494 ret
= CertGetCertificateContextProperty(context
,
495 CERT_KEY_PROV_HANDLE_PROP_ID
, &keyContext
.hCryptProv
, &size
);
496 ok(ret
, "Expected to get the CERT_KEY_PROV_HANDLE_PROP_ID, got %08x\n",
498 /* Remove the key prov handle property.. */
499 ret
= CertSetCertificateContextProperty(context
,
500 CERT_KEY_PROV_HANDLE_PROP_ID
, 0, NULL
);
501 ok(ret
, "CertSetCertificateContextProperty failed: %08x\n",
503 /* and the key context's CSP is set to NULL. */
504 size
= sizeof(keyContext
);
505 ret
= CertGetCertificateContextProperty(context
,
506 CERT_KEY_CONTEXT_PROP_ID
, &keyContext
, &size
);
507 ok(ret
, "CertGetCertificateContextProperty failed: %08x\n",
509 ok(keyContext
.hCryptProv
== 0, "Expected no hCryptProv\n");
511 CryptReleaseContext(csp
, 0);
513 CertFreeCertificateContext(context
);
516 static void testDupCert(void)
519 PCCERT_CONTEXT context
, dupContext
;
522 store
= CertOpenStore(CERT_STORE_PROV_MEMORY
, 0, 0,
523 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
524 ok(store
!= NULL
, "CertOpenStore failed: %d\n", GetLastError());
528 ret
= CertAddEncodedCertificateToStore(store
, X509_ASN_ENCODING
,
529 bigCert
, sizeof(bigCert
), CERT_STORE_ADD_ALWAYS
, &context
);
530 ok(ret
, "CertAddEncodedCertificateToStore failed: %08x\n",
532 ok(context
!= NULL
, "Expected a valid cert context\n");
535 ok(context
->cbCertEncoded
== sizeof(bigCert
),
536 "Wrong cert size %d\n", context
->cbCertEncoded
);
537 ok(!memcmp(context
->pbCertEncoded
, bigCert
, sizeof(bigCert
)),
538 "Unexpected encoded cert in context\n");
539 ok(context
->hCertStore
== store
, "Unexpected store\n");
541 dupContext
= CertDuplicateCertificateContext(context
);
542 ok(dupContext
!= NULL
, "Expected valid duplicate\n");
543 /* Not only is it a duplicate, it's identical: the address is the
546 ok(dupContext
== context
, "Expected identical context addresses\n");
547 CertFreeCertificateContext(dupContext
);
548 CertFreeCertificateContext(context
);
550 CertCloseStore(store
, 0);
553 static void testFindCert(void)
556 PCCERT_CONTEXT context
= NULL
;
558 CERT_INFO certInfo
= { 0 };
559 CRYPT_HASH_BLOB blob
;
561 store
= CertOpenStore(CERT_STORE_PROV_MEMORY
, 0, 0,
562 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
563 ok(store
!= NULL
, "CertOpenStore failed: %d\n", GetLastError());
567 ret
= CertAddEncodedCertificateToStore(store
, X509_ASN_ENCODING
,
568 bigCert
, sizeof(bigCert
), CERT_STORE_ADD_NEW
, NULL
);
569 ok(ret
, "CertAddEncodedCertificateToStore failed: %08x\n",
571 ret
= CertAddEncodedCertificateToStore(store
, X509_ASN_ENCODING
,
572 bigCert2
, sizeof(bigCert2
), CERT_STORE_ADD_NEW
, NULL
);
573 ok(ret
, "CertAddEncodedCertificateToStore failed: %08x\n",
575 /* This has the same name as bigCert */
576 ret
= CertAddEncodedCertificateToStore(store
, X509_ASN_ENCODING
,
577 certWithUsage
, sizeof(certWithUsage
), CERT_STORE_ADD_NEW
, NULL
);
578 ok(ret
, "CertAddEncodedCertificateToStore failed: %08x\n",
582 context = CertFindCertificateInStore(NULL, 0, 0, 0, NULL, NULL);
585 /* Check first cert's there, by issuer */
586 certInfo
.Subject
.pbData
= subjectName
;
587 certInfo
.Subject
.cbData
= sizeof(subjectName
);
588 certInfo
.SerialNumber
.pbData
= serialNum
;
589 certInfo
.SerialNumber
.cbData
= sizeof(serialNum
);
590 context
= CertFindCertificateInStore(store
, X509_ASN_ENCODING
, 0,
591 CERT_FIND_ISSUER_NAME
, &certInfo
.Subject
, NULL
);
592 ok(context
!= NULL
, "CertFindCertificateInStore failed: %08x\n",
596 context
= CertFindCertificateInStore(store
, X509_ASN_ENCODING
, 0,
597 CERT_FIND_ISSUER_NAME
, &certInfo
.Subject
, context
);
598 ok(context
!= NULL
, "Expected more than one cert\n");
601 context
= CertFindCertificateInStore(store
, X509_ASN_ENCODING
,
602 0, CERT_FIND_ISSUER_NAME
, &certInfo
.Subject
, context
);
603 ok(context
== NULL
, "Expected precisely two certs\n");
607 /* Check second cert's there as well, by subject name */
608 certInfo
.Subject
.pbData
= subjectName2
;
609 certInfo
.Subject
.cbData
= sizeof(subjectName2
);
610 context
= CertFindCertificateInStore(store
, X509_ASN_ENCODING
, 0,
611 CERT_FIND_SUBJECT_NAME
, &certInfo
.Subject
, NULL
);
612 ok(context
!= NULL
, "CertFindCertificateInStore failed: %08x\n",
616 context
= CertFindCertificateInStore(store
, X509_ASN_ENCODING
, 0,
617 CERT_FIND_SUBJECT_NAME
, &certInfo
.Subject
, context
);
618 ok(context
== NULL
, "Expected one cert only\n");
621 /* Strange but true: searching for the subject cert requires you to set
622 * the issuer, not the subject
624 context
= CertFindCertificateInStore(store
, X509_ASN_ENCODING
, 0,
625 CERT_FIND_SUBJECT_CERT
, &certInfo
.Subject
, NULL
);
626 ok(context
== NULL
, "Expected no certificate\n");
627 certInfo
.Subject
.pbData
= NULL
;
628 certInfo
.Subject
.cbData
= 0;
629 certInfo
.Issuer
.pbData
= subjectName2
;
630 certInfo
.Issuer
.cbData
= sizeof(subjectName2
);
631 context
= CertFindCertificateInStore(store
, X509_ASN_ENCODING
, 0,
632 CERT_FIND_SUBJECT_CERT
, &certInfo
, NULL
);
633 ok(context
!= NULL
, "CertFindCertificateInStore failed: %08x\n",
637 context
= CertFindCertificateInStore(store
, X509_ASN_ENCODING
, 0,
638 CERT_FIND_SUBJECT_CERT
, &certInfo
.Subject
, context
);
639 ok(context
== NULL
, "Expected one cert only\n");
642 /* The nice thing about hashes, they're unique */
643 blob
.pbData
= bigCertHash
;
644 blob
.cbData
= sizeof(bigCertHash
);
645 context
= CertFindCertificateInStore(store
, X509_ASN_ENCODING
, 0,
646 CERT_FIND_SHA1_HASH
, &blob
, NULL
);
647 ok(context
!= NULL
, "CertFindCertificateInStore failed: %08x\n",
651 context
= CertFindCertificateInStore(store
, X509_ASN_ENCODING
, 0,
652 CERT_FIND_SHA1_HASH
, &certInfo
.Subject
, context
);
653 ok(context
== NULL
, "Expected one cert only\n");
656 CertCloseStore(store
, 0);
659 static void testGetSubjectCert(void)
662 PCCERT_CONTEXT context1
, context2
;
663 CERT_INFO info
= { 0 };
666 store
= CertOpenStore(CERT_STORE_PROV_MEMORY
, 0, 0,
667 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
668 ok(store
!= NULL
, "CertOpenStore failed: %d\n", GetLastError());
672 ret
= CertAddEncodedCertificateToStore(store
, X509_ASN_ENCODING
,
673 bigCert
, sizeof(bigCert
), CERT_STORE_ADD_ALWAYS
, NULL
);
674 ok(ret
, "CertAddEncodedCertificateToStore failed: %08x\n",
676 ret
= CertAddEncodedCertificateToStore(store
, X509_ASN_ENCODING
,
677 bigCert2
, sizeof(bigCert2
), CERT_STORE_ADD_NEW
, &context1
);
678 ok(ret
, "CertAddEncodedCertificateToStore failed: %08x\n",
680 ok(context1
!= NULL
, "Expected a context\n");
681 ret
= CertAddEncodedCertificateToStore(store
, X509_ASN_ENCODING
,
682 certWithUsage
, sizeof(certWithUsage
), CERT_STORE_ADD_NEW
, NULL
);
683 ok(ret
, "CertAddEncodedCertificateToStore failed: %08x\n",
686 context2
= CertGetSubjectCertificateFromStore(store
, X509_ASN_ENCODING
,
688 ok(!context2
&& GetLastError() == E_INVALIDARG
,
689 "Expected E_INVALIDARG, got %08x\n", GetLastError());
690 context2
= CertGetSubjectCertificateFromStore(store
, X509_ASN_ENCODING
,
692 ok(!context2
&& GetLastError() == CRYPT_E_NOT_FOUND
,
693 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
694 info
.SerialNumber
.cbData
= sizeof(serialNum
);
695 info
.SerialNumber
.pbData
= serialNum
;
696 context2
= CertGetSubjectCertificateFromStore(store
, X509_ASN_ENCODING
,
698 ok(!context2
&& GetLastError() == CRYPT_E_NOT_FOUND
,
699 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
700 info
.Issuer
.cbData
= sizeof(subjectName2
);
701 info
.Issuer
.pbData
= subjectName2
;
702 context2
= CertGetSubjectCertificateFromStore(store
, X509_ASN_ENCODING
,
705 "CertGetSubjectCertificateFromStore failed: %08x\n", GetLastError());
706 /* Not only should this find a context, but it should be the same
707 * (same address) as context1.
709 ok(context1
== context2
, "Expected identical context addresses\n");
710 CertFreeCertificateContext(context2
);
712 CertFreeCertificateContext(context1
);
713 CertCloseStore(store
, 0);
716 /* This expires in 1970 or so */
717 static const BYTE expiredCert
[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
718 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
719 0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
720 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
721 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
722 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
723 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
724 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
725 0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
726 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
727 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
728 0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
729 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
730 0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
731 0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
732 0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
733 0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
734 0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
735 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
736 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
737 0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
738 0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
739 0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
740 0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
741 0x49, 0xe5, 0xf9, 0x65, 0xf3 };
743 /* This expires in 2036 or so */
744 static const BYTE childOfExpired
[] = { 0x30, 0x81, 0xcc, 0x30, 0x78, 0xa0,
745 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
746 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d,
747 0x30, 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63,
748 0x40, 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e,
749 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x35, 0x30, 0x35,
750 0x31, 0x37, 0x31, 0x32, 0x34, 0x39, 0x5a, 0x17, 0x0d, 0x33, 0x36, 0x30, 0x35,
751 0x30, 0x35, 0x31, 0x37, 0x31, 0x32, 0x34, 0x39, 0x5a, 0x30, 0x15, 0x31, 0x13,
752 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e,
753 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03,
754 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
755 0x01, 0x05, 0x05, 0x00, 0x03, 0x41, 0x00, 0x20, 0x3b, 0xdb, 0x4d, 0x67, 0x50,
756 0xec, 0x73, 0x9d, 0xf9, 0x85, 0x5d, 0x18, 0xe9, 0xb4, 0x98, 0xe3, 0x31, 0xb7,
757 0x03, 0x0b, 0xc0, 0x39, 0x93, 0x56, 0x81, 0x0a, 0xfc, 0x78, 0xa8, 0x29, 0x42,
758 0x5f, 0x69, 0xfb, 0xbc, 0x5b, 0xf2, 0xa6, 0x2a, 0xbe, 0x91, 0x2c, 0xfc, 0x89,
759 0x69, 0x15, 0x18, 0x58, 0xe5, 0x02, 0x75, 0xf7, 0x2a, 0xb6, 0xa9, 0xfb, 0x47,
760 0x6a, 0x6e, 0x0a, 0x9b, 0xe9, 0xdc };
762 static void testGetIssuerCert(void)
765 PCCERT_CONTEXT parent
, child
;
766 DWORD flags
= 0xffffffff;
767 HCERTSTORE store
= CertOpenStore(CERT_STORE_PROV_MEMORY
, 0, 0,
768 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
770 ok(store
!= NULL
, "CertOpenStore failed: %08x\n", GetLastError());
772 ret
= CertAddEncodedCertificateToStore(store
, X509_ASN_ENCODING
,
773 expiredCert
, sizeof(expiredCert
), CERT_STORE_ADD_ALWAYS
, NULL
);
774 ok(ret
, "CertAddEncodedCertificateToStore failed: %08x\n",
777 ret
= CertAddEncodedCertificateToStore(store
, X509_ASN_ENCODING
,
778 childOfExpired
, sizeof(childOfExpired
), CERT_STORE_ADD_ALWAYS
, &child
);
779 ok(ret
, "CertAddEncodedCertificateToStore failed: %08x\n",
783 parent = CertGetIssuerCertificateFromStore(NULL, NULL, NULL, NULL);
784 parent = CertGetIssuerCertificateFromStore(store, NULL, NULL, NULL);
786 parent
= CertGetIssuerCertificateFromStore(NULL
, NULL
, NULL
, &flags
);
787 ok(!parent
&& GetLastError() == E_INVALIDARG
,
788 "Expected E_INVALIDARG, got %08x\n", GetLastError());
789 parent
= CertGetIssuerCertificateFromStore(store
, NULL
, NULL
, &flags
);
790 ok(!parent
&& GetLastError() == E_INVALIDARG
,
791 "Expected E_INVALIDARG, got %08x\n", GetLastError());
792 parent
= CertGetIssuerCertificateFromStore(store
, child
, NULL
, &flags
);
793 ok(!parent
&& GetLastError() == E_INVALIDARG
,
794 "Expected E_INVALIDARG, got %08x\n", GetLastError());
795 /* Confusing: the caller cannot set either of the
796 * CERT_STORE_NO_*_FLAGs, as these are not checks,
799 flags
= CERT_STORE_NO_CRL_FLAG
| CERT_STORE_NO_ISSUER_FLAG
;
800 parent
= CertGetIssuerCertificateFromStore(store
, child
, NULL
, &flags
);
801 ok(!parent
&& GetLastError() == E_INVALIDARG
,
802 "Expected E_INVALIDARG, got %08x\n", GetLastError());
803 /* Perform no checks */
805 parent
= CertGetIssuerCertificateFromStore(store
, child
, NULL
, &flags
);
806 ok(parent
!= NULL
, "CertGetIssuerCertificateFromStore failed: %08x\n",
809 CertFreeCertificateContext(parent
);
810 /* Check revocation and signature only */
811 flags
= CERT_STORE_REVOCATION_FLAG
| CERT_STORE_SIGNATURE_FLAG
;
812 parent
= CertGetIssuerCertificateFromStore(store
, child
, NULL
, &flags
);
813 ok(parent
!= NULL
, "CertGetIssuerCertificateFromStore failed: %08x\n",
815 /* Confusing: CERT_STORE_REVOCATION_FLAG succeeds when there is no CRL by
816 * setting CERT_STORE_NO_CRL_FLAG.
818 ok(flags
== (CERT_STORE_REVOCATION_FLAG
| CERT_STORE_NO_CRL_FLAG
),
819 "Expected CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG, got %08x\n",
822 CertFreeCertificateContext(parent
);
823 /* Now check just the time */
824 flags
= CERT_STORE_TIME_VALIDITY_FLAG
;
825 parent
= CertGetIssuerCertificateFromStore(store
, child
, NULL
, &flags
);
826 ok(parent
!= NULL
, "CertGetIssuerCertificateFromStore failed: %08x\n",
828 /* Oops: the child is not expired, so the time validity check actually
829 * succeeds, even though the signing cert is expired.
831 ok(!flags
, "Expected check to succeed, got %08x\n", flags
);
833 CertFreeCertificateContext(parent
);
835 CertFreeCertificateContext(child
);
836 CertCloseStore(store
, 0);
839 static void testCryptHashCert(void)
841 static const BYTE emptyHash
[] = { 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b,
842 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07,
844 static const BYTE knownHash
[] = { 0xae, 0x9d, 0xbf, 0x6d, 0xf5, 0x46, 0xee,
845 0x8b, 0xc5, 0x7a, 0x13, 0xba, 0xc2, 0xb1, 0x04, 0xf2, 0xbf, 0x52, 0xa8,
847 static const BYTE toHash
[] = "abcdefghijklmnopqrstuvwxyz0123456789.,;!?:";
850 DWORD hashLen
= sizeof(hash
);
852 /* NULL buffer and nonzero length crashes
853 ret = CryptHashCertificate(0, 0, 0, NULL, size, hash, &hashLen);
854 empty hash length also crashes
855 ret = CryptHashCertificate(0, 0, 0, buf, size, hash, NULL);
857 /* Test empty hash */
858 ret
= CryptHashCertificate(0, 0, 0, toHash
, sizeof(toHash
), NULL
,
860 ok(ret
, "CryptHashCertificate failed: %08x\n", GetLastError());
861 ok(hashLen
== sizeof(hash
), "Got unexpected size of hash %d\n", hashLen
);
862 /* Test with empty buffer */
863 ret
= CryptHashCertificate(0, 0, 0, NULL
, 0, hash
, &hashLen
);
864 ok(ret
, "CryptHashCertificate failed: %08x\n", GetLastError());
865 ok(!memcmp(hash
, emptyHash
, sizeof(emptyHash
)),
866 "Unexpected hash of nothing\n");
867 /* Test a known value */
868 ret
= CryptHashCertificate(0, 0, 0, toHash
, sizeof(toHash
), hash
,
870 ok(ret
, "CryptHashCertificate failed: %08x\n", GetLastError());
871 ok(!memcmp(hash
, knownHash
, sizeof(knownHash
)), "Unexpected hash\n");
874 static void verifySig(HCRYPTPROV csp
, const BYTE
*toSign
, size_t toSignLen
,
875 const BYTE
*sig
, unsigned int sigLen
)
878 BOOL ret
= CryptCreateHash(csp
, CALG_SHA1
, 0, 0, &hash
);
880 ok(ret
, "CryptCreateHash failed: %08x\n", GetLastError());
884 DWORD mySigSize
= sizeof(mySig
);
886 ret
= CryptHashData(hash
, toSign
, toSignLen
, 0);
887 ok(ret
, "CryptHashData failed: %08x\n", GetLastError());
888 /* use the A variant so the test can run on Win9x */
889 ret
= CryptSignHashA(hash
, AT_SIGNATURE
, NULL
, 0, mySig
, &mySigSize
);
890 ok(ret
, "CryptSignHash failed: %08x\n", GetLastError());
893 ok(mySigSize
== sigLen
, "Expected sig length %d, got %d\n",
895 ok(!memcmp(mySig
, sig
, sigLen
), "Unexpected signature\n");
897 CryptDestroyHash(hash
);
901 /* Tests signing the certificate described by toBeSigned with the CSP passed in,
902 * using the algorithm with OID sigOID. The CSP is assumed to be empty, and a
903 * keyset named AT_SIGNATURE will be added to it. The signing key will be
904 * stored in *key, and the signature will be stored in sig. sigLen should be
907 static void testSignCert(HCRYPTPROV csp
, const CRYPT_DATA_BLOB
*toBeSigned
,
908 LPCSTR sigOID
, HCRYPTKEY
*key
, BYTE
*sig
, DWORD
*sigLen
)
912 CRYPT_ALGORITHM_IDENTIFIER algoID
= { NULL
, { 0, NULL
} };
915 ret = CryptSignCertificate(0, 0, 0, NULL, 0, NULL, NULL, NULL, NULL);
916 ret = CryptSignCertificate(0, 0, 0, NULL, 0, NULL, NULL, NULL, &size);
917 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
918 NULL, NULL, NULL, &size);
920 ret
= CryptSignCertificate(0, 0, 0, toBeSigned
->pbData
, toBeSigned
->cbData
,
921 &algoID
, NULL
, NULL
, &size
);
922 ok(!ret
&& GetLastError() == NTE_BAD_ALGID
,
923 "Expected NTE_BAD_ALGID, got %08x\n", GetLastError());
924 algoID
.pszObjId
= (LPSTR
)sigOID
;
925 ret
= CryptSignCertificate(0, 0, 0, toBeSigned
->pbData
, toBeSigned
->cbData
,
926 &algoID
, NULL
, NULL
, &size
);
927 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
928 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
929 ret
= CryptSignCertificate(0, AT_SIGNATURE
, 0, toBeSigned
->pbData
,
930 toBeSigned
->cbData
, &algoID
, NULL
, NULL
, &size
);
931 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
932 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
934 /* No keys exist in the new CSP yet.. */
935 ret
= CryptSignCertificate(csp
, AT_SIGNATURE
, 0, toBeSigned
->pbData
,
936 toBeSigned
->cbData
, &algoID
, NULL
, NULL
, &size
);
937 ok(!ret
&& (GetLastError() == NTE_BAD_KEYSET
|| GetLastError() ==
938 NTE_NO_KEY
), "Expected NTE_BAD_KEYSET or NTE_NO_KEY, got %08x\n",
940 ret
= CryptGenKey(csp
, AT_SIGNATURE
, 0, key
);
941 ok(ret
, "CryptGenKey failed: %08x\n", GetLastError());
944 ret
= CryptSignCertificate(csp
, AT_SIGNATURE
, 0, toBeSigned
->pbData
,
945 toBeSigned
->cbData
, &algoID
, NULL
, NULL
, &size
);
946 ok(ret
, "CryptSignCertificate failed: %08x\n", GetLastError());
947 ok(size
<= *sigLen
, "Expected size <= %d, got %d\n", *sigLen
, size
);
950 ret
= CryptSignCertificate(csp
, AT_SIGNATURE
, 0, toBeSigned
->pbData
,
951 toBeSigned
->cbData
, &algoID
, NULL
, sig
, &size
);
952 ok(ret
, "CryptSignCertificate failed: %08x\n", GetLastError());
956 verifySig(csp
, toBeSigned
->pbData
, toBeSigned
->cbData
, sig
,
963 static void testVerifyCertSig(HCRYPTPROV csp
, const CRYPT_DATA_BLOB
*toBeSigned
,
964 LPCSTR sigOID
, const BYTE
*sig
, DWORD sigLen
)
966 CERT_SIGNED_CONTENT_INFO info
;
971 if(pCryptVerifyCertificateSignatureEx
) {
972 ret
= pCryptVerifyCertificateSignatureEx(0, 0, 0, NULL
, 0, NULL
, 0, NULL
);
973 ok(!ret
&& GetLastError() == E_INVALIDARG
,
974 "Expected E_INVALIDARG, got %08x\n", GetLastError());
975 ret
= pCryptVerifyCertificateSignatureEx(csp
, 0, 0, NULL
, 0, NULL
, 0, NULL
);
976 ok(!ret
&& GetLastError() == E_INVALIDARG
,
977 "Expected E_INVALIDARG, got %08x\n", GetLastError());
978 ret
= pCryptVerifyCertificateSignatureEx(csp
, X509_ASN_ENCODING
, 0, NULL
, 0,
980 ok(!ret
&& GetLastError() == E_INVALIDARG
,
981 "Expected E_INVALIDARG, got %08x\n", GetLastError());
983 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
984 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, NULL, 0, NULL, 0, NULL);
987 info
.ToBeSigned
.cbData
= toBeSigned
->cbData
;
988 info
.ToBeSigned
.pbData
= toBeSigned
->pbData
;
989 info
.SignatureAlgorithm
.pszObjId
= (LPSTR
)sigOID
;
990 info
.SignatureAlgorithm
.Parameters
.cbData
= 0;
991 info
.Signature
.cbData
= sigLen
;
992 info
.Signature
.pbData
= (BYTE
*)sig
;
993 info
.Signature
.cUnusedBits
= 0;
994 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
, X509_CERT
, &info
,
995 CRYPT_ENCODE_ALLOC_FLAG
, NULL
, (BYTE
*)&cert
, &size
);
996 ok(ret
, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
999 CRYPT_DATA_BLOB certBlob
= { 0, NULL
};
1000 PCERT_PUBLIC_KEY_INFO pubKeyInfo
= NULL
;
1002 if(pCryptVerifyCertificateSignatureEx
) {
1003 ret
= pCryptVerifyCertificateSignatureEx(csp
, X509_ASN_ENCODING
,
1004 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB
, &certBlob
, 0, NULL
, 0, NULL
);
1005 ok(!ret
&& GetLastError() == CRYPT_E_ASN1_EOD
,
1006 "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
1007 certBlob
.cbData
= 1;
1008 certBlob
.pbData
= (void *)0xdeadbeef;
1009 ret
= pCryptVerifyCertificateSignatureEx(csp
, X509_ASN_ENCODING
,
1010 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB
, &certBlob
, 0, NULL
, 0, NULL
);
1011 ok(!ret
&& GetLastError() == STATUS_ACCESS_VIOLATION
,
1012 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1013 certBlob
.cbData
= size
;
1014 certBlob
.pbData
= cert
;
1015 ret
= pCryptVerifyCertificateSignatureEx(csp
, X509_ASN_ENCODING
,
1016 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB
, &certBlob
, 0, NULL
, 0, NULL
);
1017 ok(!ret
&& GetLastError() == E_INVALIDARG
,
1018 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1019 ret
= pCryptVerifyCertificateSignatureEx(csp
, X509_ASN_ENCODING
,
1020 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB
, &certBlob
,
1021 CRYPT_VERIFY_CERT_SIGN_ISSUER_NULL
, NULL
, 0, NULL
);
1022 ok(!ret
&& GetLastError() == E_INVALIDARG
,
1023 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1025 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1026 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
1027 CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY, NULL, 0, NULL);
1030 CryptExportPublicKeyInfoEx(csp
, AT_SIGNATURE
, X509_ASN_ENCODING
,
1031 (LPSTR
)sigOID
, 0, NULL
, NULL
, &size
);
1032 pubKeyInfo
= HeapAlloc(GetProcessHeap(), 0, size
);
1035 ret
= CryptExportPublicKeyInfoEx(csp
, AT_SIGNATURE
,
1036 X509_ASN_ENCODING
, (LPSTR
)sigOID
, 0, NULL
, pubKeyInfo
, &size
);
1037 ok(ret
, "CryptExportKey failed: %08x\n", GetLastError());
1038 if (ret
&& pCryptVerifyCertificateSignatureEx
)
1040 ret
= pCryptVerifyCertificateSignatureEx(csp
, X509_ASN_ENCODING
,
1041 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB
, &certBlob
,
1042 CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY
, pubKeyInfo
, 0, NULL
);
1043 ok(ret
, "CryptVerifyCertificateSignatureEx failed: %08x\n",
1046 HeapFree(GetProcessHeap(), 0, pubKeyInfo
);
1052 static BYTE emptyCert
[] = { 0x30, 0x00 };
1054 static void testCertSigs(void)
1057 CRYPT_DATA_BLOB toBeSigned
= { sizeof(emptyCert
), emptyCert
};
1061 DWORD sigSize
= sizeof(sig
);
1063 /* Just in case a previous run failed, delete this thing */
1064 CryptAcquireContextW(&csp
, cspNameW
, MS_DEF_PROV_W
, PROV_RSA_FULL
,
1065 CRYPT_DELETEKEYSET
);
1066 ret
= CryptAcquireContextW(&csp
, cspNameW
, MS_DEF_PROV_W
, PROV_RSA_FULL
,
1068 ok(ret
, "CryptAcquireContext failed: %08x\n", GetLastError());
1070 testSignCert(csp
, &toBeSigned
, szOID_RSA_SHA1RSA
, &key
, sig
, &sigSize
);
1071 testVerifyCertSig(csp
, &toBeSigned
, szOID_RSA_SHA1RSA
, sig
, sigSize
);
1073 CryptDestroyKey(key
);
1074 CryptReleaseContext(csp
, 0);
1075 ret
= CryptAcquireContextW(&csp
, cspNameW
, MS_DEF_PROV_W
, PROV_RSA_FULL
,
1076 CRYPT_DELETEKEYSET
);
1079 static const BYTE md5SignedEmptyCert
[] = {
1080 0x30,0x56,0x30,0x33,0x02,0x00,0x30,0x02,0x06,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,
1081 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,
1082 0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x07,
1083 0x30,0x02,0x06,0x00,0x03,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,
1084 0x0d,0x02,0x05,0x05,0x00,0x03,0x11,0x00,0xfb,0x0f,0x66,0x82,0x66,0xd9,0xe5,0xf8,
1085 0xd8,0xa2,0x55,0x2b,0xe1,0xa5,0xd9,0x04 };
1086 static const BYTE md5SignedEmptyCertNoNull
[] = {
1087 0x30,0x54,0x30,0x33,0x02,0x00,0x30,0x02,0x06,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,
1088 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,
1089 0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x07,
1090 0x30,0x02,0x06,0x00,0x03,0x01,0x00,0x30,0x0a,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,
1091 0x0d,0x02,0x05,0x03,0x11,0x00,0x04,0xd9,0xa5,0xe1,0x2b,0x55,0xa2,0xd8,0xf8,0xe5,
1092 0xd9,0x66,0x82,0x66,0x0f,0xfb };
1094 static void testSignAndEncodeCert(void)
1096 static char oid_rsa_md5rsa
[] = szOID_RSA_MD5RSA
;
1097 static char oid_rsa_md5
[] = szOID_RSA_MD5
;
1100 CRYPT_ALGORITHM_IDENTIFIER algID
= { 0 };
1101 CERT_INFO info
= { 0 };
1104 ret = CryptSignAndEncodeCertificate(0, 0, 0, NULL, NULL, NULL, NULL, NULL,
1106 ret = CryptSignAndEncodeCertificate(0, 0, 0, NULL, NULL, NULL, NULL, NULL,
1109 ret
= CryptSignAndEncodeCertificate(0, 0, 0, NULL
, NULL
, &algID
, NULL
, NULL
,
1111 ok(!ret
&& GetLastError() == ERROR_FILE_NOT_FOUND
,
1112 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1113 ret
= CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING
, NULL
, NULL
,
1114 &algID
, NULL
, NULL
, &size
);
1115 ok(!ret
&& GetLastError() == ERROR_FILE_NOT_FOUND
,
1116 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1117 ret
= CryptSignAndEncodeCertificate(0, 0, 0, X509_CERT_TO_BE_SIGNED
, NULL
,
1118 &algID
, NULL
, NULL
, &size
);
1119 ok(!ret
&& GetLastError() == ERROR_FILE_NOT_FOUND
,
1120 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1121 ret
= CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING
,
1122 X509_CERT_TO_BE_SIGNED
, NULL
, &algID
, NULL
, NULL
, &size
);
1123 ok(!ret
&& GetLastError() == STATUS_ACCESS_VIOLATION
,
1124 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1126 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1127 X509_CERT_TO_BE_SIGNED, &info, NULL, NULL, NULL, &size);
1129 ret
= CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING
,
1130 X509_CERT_TO_BE_SIGNED
, &info
, &algID
, NULL
, NULL
, &size
);
1131 ok(!ret
&& GetLastError() == NTE_BAD_ALGID
,
1132 "Expected NTE_BAD_ALGID, got %08x\n", GetLastError());
1133 algID
.pszObjId
= oid_rsa_md5rsa
;
1134 ret
= CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING
,
1135 X509_CERT_TO_BE_SIGNED
, &info
, &algID
, NULL
, NULL
, &size
);
1136 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
1137 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1138 algID
.pszObjId
= oid_rsa_md5
;
1139 ret
= CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING
,
1140 X509_CERT_TO_BE_SIGNED
, &info
, &algID
, NULL
, NULL
, &size
);
1141 ok(ret
, "CryptSignAndEncodeCertificate failed: %08x\n", GetLastError());
1144 LPBYTE buf
= HeapAlloc(GetProcessHeap(), 0, size
);
1148 ret
= CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING
,
1149 X509_CERT_TO_BE_SIGNED
, &info
, &algID
, NULL
, buf
, &size
);
1150 ok(ret
, "CryptSignAndEncodeCertificate failed: %08x\n",
1152 /* Tricky: because the NULL parameters may either be omitted or
1153 * included as an asn.1-encoded NULL (0x05,0x00), two different
1154 * values are allowed.
1156 ok(size
== sizeof(md5SignedEmptyCert
) ||
1157 size
== sizeof(md5SignedEmptyCertNoNull
), "Unexpected size %d\n",
1159 if (size
== sizeof(md5SignedEmptyCert
))
1160 ok(!memcmp(buf
, md5SignedEmptyCert
, size
),
1161 "Unexpected value\n");
1162 else if (size
== sizeof(md5SignedEmptyCertNoNull
))
1163 ok(!memcmp(buf
, md5SignedEmptyCertNoNull
, size
),
1164 "Unexpected value\n");
1165 HeapFree(GetProcessHeap(), 0, buf
);
1170 static void testCreateSelfSignCert(void)
1172 PCCERT_CONTEXT context
;
1173 CERT_NAME_BLOB name
= { sizeof(subjectName
), subjectName
};
1177 CRYPT_KEY_PROV_INFO info
;
1180 context = CertCreateSelfSignCertificate(0, NULL, 0, NULL, NULL, NULL, NULL,
1182 * Calling this with no first parameter creates a new key container, which
1183 * lasts beyond the test, so I don't test that. Nb: the generated key
1185 context = CertCreateSelfSignCertificate(0, &name, 0, NULL, NULL, NULL, NULL,
1190 CryptAcquireContextW(&csp
, cspNameW
, MS_DEF_PROV_W
, PROV_RSA_FULL
,
1191 CRYPT_DELETEKEYSET
);
1192 ret
= CryptAcquireContextW(&csp
, cspNameW
, MS_DEF_PROV_W
, PROV_RSA_FULL
,
1194 ok(ret
, "CryptAcquireContext failed: %08x\n", GetLastError());
1196 context
= CertCreateSelfSignCertificate(csp
, &name
, 0, NULL
, NULL
, NULL
,
1198 ok(!context
&& GetLastError() == NTE_NO_KEY
,
1199 "Expected NTE_NO_KEY, got %08x\n", GetLastError());
1200 ret
= CryptGenKey(csp
, AT_SIGNATURE
, 0, &key
);
1201 ok(ret
, "CryptGenKey failed: %08x\n", GetLastError());
1204 context
= CertCreateSelfSignCertificate(csp
, &name
, 0, NULL
, NULL
, NULL
,
1206 ok(context
!= NULL
, "CertCreateSelfSignCertificate failed: %08x\n",
1211 PCRYPT_KEY_PROV_INFO info
;
1213 /* The context must have a key provider info property */
1214 ret
= CertGetCertificateContextProperty(context
,
1215 CERT_KEY_PROV_INFO_PROP_ID
, NULL
, &size
);
1216 ok(ret
&& size
, "Expected non-zero key provider info\n");
1219 info
= HeapAlloc(GetProcessHeap(), 0, size
);
1222 ret
= CertGetCertificateContextProperty(context
,
1223 CERT_KEY_PROV_INFO_PROP_ID
, info
, &size
);
1224 ok(ret
, "CertGetCertificateContextProperty failed: %08x\n",
1228 /* Sanity-check the key provider */
1229 ok(!lstrcmpW(info
->pwszContainerName
, cspNameW
),
1230 "Unexpected key container\n");
1231 ok(!lstrcmpW(info
->pwszProvName
, MS_DEF_PROV_W
),
1232 "Unexpected provider\n");
1233 ok(info
->dwKeySpec
== AT_SIGNATURE
,
1234 "Expected AT_SIGNATURE, got %d\n", info
->dwKeySpec
);
1236 HeapFree(GetProcessHeap(), 0, info
);
1240 CertFreeCertificateContext(context
);
1243 CryptDestroyKey(key
);
1246 CryptReleaseContext(csp
, 0);
1247 ret
= CryptAcquireContextW(&csp
, cspNameW
, MS_DEF_PROV_W
, PROV_RSA_FULL
,
1248 CRYPT_DELETEKEYSET
);
1250 /* do the same test with AT_KEYEXCHANGE and key info*/
1251 memset(&info
,0,sizeof(info
));
1252 info
.dwProvType
= PROV_RSA_FULL
;
1253 info
.dwKeySpec
= AT_KEYEXCHANGE
;
1254 info
.pwszProvName
= (LPWSTR
) MS_DEF_PROV_W
;
1255 info
.pwszContainerName
= cspNameW
;
1256 context
= CertCreateSelfSignCertificate(0, &name
, 0, &info
, NULL
, NULL
,
1258 ok(context
!= NULL
, "CertCreateSelfSignCertificate failed: %08x\n",
1263 PCRYPT_KEY_PROV_INFO info
;
1265 /* The context must have a key provider info property */
1266 ret
= CertGetCertificateContextProperty(context
,
1267 CERT_KEY_PROV_INFO_PROP_ID
, NULL
, &size
);
1268 ok(ret
&& size
, "Expected non-zero key provider info\n");
1271 info
= HeapAlloc(GetProcessHeap(), 0, size
);
1274 ret
= CertGetCertificateContextProperty(context
,
1275 CERT_KEY_PROV_INFO_PROP_ID
, info
, &size
);
1276 ok(ret
, "CertGetCertificateContextProperty failed: %08x\n",
1280 /* Sanity-check the key provider */
1281 ok(!lstrcmpW(info
->pwszContainerName
, cspNameW
),
1282 "Unexpected key container\n");
1283 ok(!lstrcmpW(info
->pwszProvName
, MS_DEF_PROV_W
),
1284 "Unexpected provider\n");
1285 ok(info
->dwKeySpec
== AT_KEYEXCHANGE
,
1286 "Expected AT_KEYEXCHANGE, got %d\n", info
->dwKeySpec
);
1288 HeapFree(GetProcessHeap(), 0, info
);
1292 CertFreeCertificateContext(context
);
1295 CryptAcquireContextW(&csp
, cspNameW
, MS_DEF_PROV_W
, PROV_RSA_FULL
,
1296 CRYPT_DELETEKEYSET
);
1299 static const LPCSTR keyUsages
[] = { szOID_PKIX_KP_CODE_SIGNING
,
1300 szOID_PKIX_KP_CLIENT_AUTH
, szOID_RSA_RSA
};
1302 static void testKeyUsage(void)
1305 PCCERT_CONTEXT context
;
1308 /* Test base cases */
1309 ret
= CertGetEnhancedKeyUsage(NULL
, 0, NULL
, NULL
);
1310 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
1311 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1313 ret
= CertGetEnhancedKeyUsage(NULL
, 0, NULL
, &size
);
1314 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
1315 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1317 ret
= CertGetEnhancedKeyUsage(NULL
, 0, NULL
, &size
);
1318 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
1319 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1321 ret = CertSetEnhancedKeyUsage(NULL, NULL);
1322 usage.cUsageIdentifier = 0;
1323 ret = CertSetEnhancedKeyUsage(NULL, &usage);
1325 /* Test with a cert with no enhanced key usage extension */
1326 context
= CertCreateCertificateContext(X509_ASN_ENCODING
, bigCert
,
1328 ok(context
!= NULL
, "CertCreateCertificateContext failed: %08x\n",
1332 static const char oid
[] = "1.2.3.4";
1333 BYTE buf
[sizeof(CERT_ENHKEY_USAGE
) + 2 * (sizeof(LPSTR
) + sizeof(oid
))];
1334 PCERT_ENHKEY_USAGE pUsage
= (PCERT_ENHKEY_USAGE
)buf
;
1336 ret
= CertGetEnhancedKeyUsage(context
, 0, NULL
, NULL
);
1337 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
,
1338 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1340 ret
= CertGetEnhancedKeyUsage(context
, 0, NULL
, &size
);
1343 /* Windows 2000, ME, or later: even though it succeeded, we expect
1344 * CRYPT_E_NOT_FOUND, which indicates there is no enhanced key
1345 * usage set for this cert (which implies it's valid for all uses.)
1347 ok(GetLastError() == CRYPT_E_NOT_FOUND
,
1348 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1349 ok(size
== sizeof(CERT_ENHKEY_USAGE
), "Wrong size %d\n", size
);
1350 ret
= CertGetEnhancedKeyUsage(context
, 0, pUsage
, &size
);
1351 ok(ret
, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1352 ok(pUsage
->cUsageIdentifier
== 0, "Expected 0 usages, got %d\n",
1353 pUsage
->cUsageIdentifier
);
1357 /* Windows NT, 95, or 98: it fails, and the last error is
1358 * CRYPT_E_NOT_FOUND.
1360 ok(GetLastError() == CRYPT_E_NOT_FOUND
,
1361 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1363 /* I can add a usage identifier when no key usage has been set */
1364 ret
= CertAddEnhancedKeyUsageIdentifier(context
, oid
);
1365 ok(ret
, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
1368 ret
= CertGetEnhancedKeyUsage(context
,
1369 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG
, pUsage
, &size
);
1370 ok(ret
&& GetLastError() == 0,
1371 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1372 ok(pUsage
->cUsageIdentifier
== 1, "Expected 1 usage, got %d\n",
1373 pUsage
->cUsageIdentifier
);
1374 if (pUsage
->cUsageIdentifier
)
1375 ok(!strcmp(pUsage
->rgpszUsageIdentifier
[0], oid
),
1376 "Expected %s, got %s\n", oid
, pUsage
->rgpszUsageIdentifier
[0]);
1377 /* Now set an empty key usage */
1378 pUsage
->cUsageIdentifier
= 0;
1379 ret
= CertSetEnhancedKeyUsage(context
, pUsage
);
1380 ok(ret
, "CertSetEnhancedKeyUsage failed: %08x\n", GetLastError());
1381 /* Shouldn't find it in the cert */
1383 ret
= CertGetEnhancedKeyUsage(context
,
1384 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG
, pUsage
, &size
);
1385 ok(!ret
&& GetLastError() == CRYPT_E_NOT_FOUND
,
1386 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1387 /* Should find it as an extended property */
1388 ret
= CertGetEnhancedKeyUsage(context
,
1389 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG
, pUsage
, &size
);
1390 ok(ret
&& GetLastError() == 0,
1391 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1392 ok(pUsage
->cUsageIdentifier
== 0, "Expected 0 usages, got %d\n",
1393 pUsage
->cUsageIdentifier
);
1394 /* Should find it as either */
1395 ret
= CertGetEnhancedKeyUsage(context
, 0, pUsage
, &size
);
1396 ok(ret
&& GetLastError() == 0,
1397 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1398 ok(pUsage
->cUsageIdentifier
== 0, "Expected 0 usages, got %d\n",
1399 pUsage
->cUsageIdentifier
);
1400 /* Add a usage identifier */
1401 ret
= CertAddEnhancedKeyUsageIdentifier(context
, oid
);
1402 ok(ret
, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
1405 ret
= CertGetEnhancedKeyUsage(context
, 0, pUsage
, &size
);
1406 ok(ret
&& GetLastError() == 0,
1407 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1408 ok(pUsage
->cUsageIdentifier
== 1, "Expected 1 identifier, got %d\n",
1409 pUsage
->cUsageIdentifier
);
1410 if (pUsage
->cUsageIdentifier
)
1411 ok(!strcmp(pUsage
->rgpszUsageIdentifier
[0], oid
),
1412 "Expected %s, got %s\n", oid
, pUsage
->rgpszUsageIdentifier
[0]);
1413 /* Yep, I can re-add the same usage identifier */
1414 ret
= CertAddEnhancedKeyUsageIdentifier(context
, oid
);
1415 ok(ret
, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
1418 ret
= CertGetEnhancedKeyUsage(context
, 0, pUsage
, &size
);
1419 ok(ret
&& GetLastError() == 0,
1420 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1421 ok(pUsage
->cUsageIdentifier
== 2, "Expected 2 identifiers, got %d\n",
1422 pUsage
->cUsageIdentifier
);
1423 if (pUsage
->cUsageIdentifier
)
1424 ok(!strcmp(pUsage
->rgpszUsageIdentifier
[0], oid
),
1425 "Expected %s, got %s\n", oid
, pUsage
->rgpszUsageIdentifier
[0]);
1426 if (pUsage
->cUsageIdentifier
>= 2)
1427 ok(!strcmp(pUsage
->rgpszUsageIdentifier
[1], oid
),
1428 "Expected %s, got %s\n", oid
, pUsage
->rgpszUsageIdentifier
[1]);
1429 /* Now set a NULL extended property--this deletes the property. */
1430 ret
= CertSetEnhancedKeyUsage(context
, NULL
);
1431 ok(ret
, "CertSetEnhancedKeyUsage failed: %08x\n", GetLastError());
1432 SetLastError(0xbaadcafe);
1434 ret
= CertGetEnhancedKeyUsage(context
, 0, pUsage
, &size
);
1435 ok(GetLastError() == CRYPT_E_NOT_FOUND
,
1436 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1438 CertFreeCertificateContext(context
);
1440 /* Now test with a cert with an enhanced key usage extension */
1441 context
= CertCreateCertificateContext(X509_ASN_ENCODING
, certWithUsage
,
1442 sizeof(certWithUsage
));
1443 ok(context
!= NULL
, "CertCreateCertificateContext failed: %08x\n",
1448 DWORD bufSize
= 0, i
;
1450 /* The size may depend on what flags are used to query it, so I
1451 * realloc the buffer for each test.
1453 ret
= CertGetEnhancedKeyUsage(context
,
1454 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG
, NULL
, &bufSize
);
1455 ok(ret
, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1456 buf
= HeapAlloc(GetProcessHeap(), 0, bufSize
);
1459 PCERT_ENHKEY_USAGE pUsage
= (PCERT_ENHKEY_USAGE
)buf
;
1461 /* Should find it in the cert */
1463 ret
= CertGetEnhancedKeyUsage(context
,
1464 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG
, pUsage
, &size
);
1465 ok(ret
&& GetLastError() == 0,
1466 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1467 ok(pUsage
->cUsageIdentifier
== 3, "Expected 3 usages, got %d\n",
1468 pUsage
->cUsageIdentifier
);
1469 for (i
= 0; i
< pUsage
->cUsageIdentifier
; i
++)
1470 ok(!strcmp(pUsage
->rgpszUsageIdentifier
[i
], keyUsages
[i
]),
1471 "Expected %s, got %s\n", keyUsages
[i
],
1472 pUsage
->rgpszUsageIdentifier
[i
]);
1473 HeapFree(GetProcessHeap(), 0, buf
);
1475 ret
= CertGetEnhancedKeyUsage(context
, 0, NULL
, &bufSize
);
1476 ok(ret
, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1477 buf
= HeapAlloc(GetProcessHeap(), 0, bufSize
);
1480 PCERT_ENHKEY_USAGE pUsage
= (PCERT_ENHKEY_USAGE
)buf
;
1482 /* Should find it as either */
1484 ret
= CertGetEnhancedKeyUsage(context
, 0, pUsage
, &size
);
1485 /* In Windows, GetLastError returns CRYPT_E_NOT_FOUND not found
1486 * here, even though the return is successful and the usage id
1487 * count is positive. I don't enforce that here.
1490 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1491 ok(pUsage
->cUsageIdentifier
== 3, "Expected 3 usages, got %d\n",
1492 pUsage
->cUsageIdentifier
);
1493 for (i
= 0; i
< pUsage
->cUsageIdentifier
; i
++)
1494 ok(!strcmp(pUsage
->rgpszUsageIdentifier
[i
], keyUsages
[i
]),
1495 "Expected %s, got %s\n", keyUsages
[i
],
1496 pUsage
->rgpszUsageIdentifier
[i
]);
1497 HeapFree(GetProcessHeap(), 0, buf
);
1499 /* Shouldn't find it as an extended property */
1500 ret
= CertGetEnhancedKeyUsage(context
,
1501 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG
, NULL
, &size
);
1502 ok(!ret
&& GetLastError() == CRYPT_E_NOT_FOUND
,
1503 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1504 /* Adding a usage identifier overrides the cert's usage!? */
1505 ret
= CertAddEnhancedKeyUsageIdentifier(context
, szOID_RSA_RSA
);
1506 ok(ret
, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
1508 ret
= CertGetEnhancedKeyUsage(context
, 0, NULL
, &bufSize
);
1509 ok(ret
, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1510 buf
= HeapAlloc(GetProcessHeap(), 0, bufSize
);
1513 PCERT_ENHKEY_USAGE pUsage
= (PCERT_ENHKEY_USAGE
)buf
;
1515 /* Should find it as either */
1517 ret
= CertGetEnhancedKeyUsage(context
, 0, pUsage
, &size
);
1519 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1520 ok(pUsage
->cUsageIdentifier
== 1, "Expected 1 usage, got %d\n",
1521 pUsage
->cUsageIdentifier
);
1522 ok(!strcmp(pUsage
->rgpszUsageIdentifier
[0], szOID_RSA_RSA
),
1523 "Expected %s, got %s\n", szOID_RSA_RSA
,
1524 pUsage
->rgpszUsageIdentifier
[0]);
1525 HeapFree(GetProcessHeap(), 0, buf
);
1527 /* But querying the cert directly returns its usage */
1528 ret
= CertGetEnhancedKeyUsage(context
,
1529 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG
, NULL
, &bufSize
);
1530 ok(ret
, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1531 buf
= HeapAlloc(GetProcessHeap(), 0, bufSize
);
1534 PCERT_ENHKEY_USAGE pUsage
= (PCERT_ENHKEY_USAGE
)buf
;
1537 ret
= CertGetEnhancedKeyUsage(context
,
1538 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG
, pUsage
, &size
);
1540 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1541 ok(pUsage
->cUsageIdentifier
== 3, "Expected 3 usages, got %d\n",
1542 pUsage
->cUsageIdentifier
);
1543 for (i
= 0; i
< pUsage
->cUsageIdentifier
; i
++)
1544 ok(!strcmp(pUsage
->rgpszUsageIdentifier
[i
], keyUsages
[i
]),
1545 "Expected %s, got %s\n", keyUsages
[i
],
1546 pUsage
->rgpszUsageIdentifier
[i
]);
1547 HeapFree(GetProcessHeap(), 0, buf
);
1549 /* And removing the only usage identifier in the extended property
1550 * results in the cert's key usage being found.
1552 ret
= CertRemoveEnhancedKeyUsageIdentifier(context
, szOID_RSA_RSA
);
1553 ok(ret
, "CertRemoveEnhancedKeyUsage failed: %08x\n", GetLastError());
1554 ret
= CertGetEnhancedKeyUsage(context
, 0, NULL
, &bufSize
);
1555 ok(ret
, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1556 buf
= HeapAlloc(GetProcessHeap(), 0, bufSize
);
1559 PCERT_ENHKEY_USAGE pUsage
= (PCERT_ENHKEY_USAGE
)buf
;
1561 /* Should find it as either */
1563 ret
= CertGetEnhancedKeyUsage(context
, 0, pUsage
, &size
);
1565 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1566 ok(pUsage
->cUsageIdentifier
== 3, "Expected 3 usages, got %d\n",
1567 pUsage
->cUsageIdentifier
);
1568 for (i
= 0; i
< pUsage
->cUsageIdentifier
; i
++)
1569 ok(!strcmp(pUsage
->rgpszUsageIdentifier
[i
], keyUsages
[i
]),
1570 "Expected %s, got %s\n", keyUsages
[i
],
1571 pUsage
->rgpszUsageIdentifier
[i
]);
1572 HeapFree(GetProcessHeap(), 0, buf
);
1575 CertFreeCertificateContext(context
);
1579 static void testCompareCertName(void)
1581 static BYTE bogus
[] = { 1, 2, 3, 4 };
1582 static BYTE bogusPrime
[] = { 0, 1, 2, 3, 4 };
1583 static BYTE emptyPrime
[] = { 0x30, 0x00, 0x01 };
1585 CERT_NAME_BLOB blob1
, blob2
;
1588 ret = CertCompareCertificateName(0, NULL, NULL);
1590 /* An empty name checks against itself.. */
1591 blob1
.pbData
= emptyCert
;
1592 blob1
.cbData
= sizeof(emptyCert
);
1593 ret
= CertCompareCertificateName(0, &blob1
, &blob1
);
1594 ok(ret
, "CertCompareCertificateName failed: %08x\n", GetLastError());
1595 /* It doesn't have to be a valid encoded name.. */
1596 blob1
.pbData
= bogus
;
1597 blob1
.cbData
= sizeof(bogus
);
1598 ret
= CertCompareCertificateName(0, &blob1
, &blob1
);
1599 ok(ret
, "CertCompareCertificateName failed: %08x\n", GetLastError());
1600 /* Leading zeroes matter.. */
1601 blob2
.pbData
= bogusPrime
;
1602 blob2
.cbData
= sizeof(bogusPrime
);
1603 ret
= CertCompareCertificateName(0, &blob1
, &blob2
);
1604 ok(!ret
, "Expected failure\n");
1605 /* As do trailing extra bytes. */
1606 blob2
.pbData
= emptyPrime
;
1607 blob2
.cbData
= sizeof(emptyPrime
);
1608 ret
= CertCompareCertificateName(0, &blob1
, &blob2
);
1609 ok(!ret
, "Expected failure\n");
1612 static BYTE int1
[] = { 0x88, 0xff, 0xff, 0xff };
1613 static BYTE int2
[] = { 0x88, 0xff };
1614 static BYTE int3
[] = { 0x23, 0xff };
1615 static BYTE int4
[] = { 0x7f, 0x00 };
1616 static BYTE int5
[] = { 0x7f };
1617 static BYTE int6
[] = { 0x80, 0x00, 0x00, 0x00 };
1618 static BYTE int7
[] = { 0x80, 0x00 };
1620 static struct IntBlobTest
1622 CRYPT_INTEGER_BLOB blob1
;
1623 CRYPT_INTEGER_BLOB blob2
;
1626 { { sizeof(int1
), int1
}, { sizeof(int2
), int2
}, TRUE
},
1627 { { sizeof(int3
), int3
}, { sizeof(int3
), int3
}, TRUE
},
1628 { { sizeof(int4
), int4
}, { sizeof(int5
), int5
}, TRUE
},
1629 { { sizeof(int6
), int6
}, { sizeof(int7
), int7
}, TRUE
},
1630 { { sizeof(int1
), int1
}, { sizeof(int7
), int7
}, FALSE
},
1633 static void testCompareIntegerBlob(void)
1638 for (i
= 0; i
< sizeof(intBlobs
) / sizeof(intBlobs
[0]); i
++)
1640 ret
= CertCompareIntegerBlob(&intBlobs
[i
].blob1
, &intBlobs
[i
].blob2
);
1641 ok(ret
== intBlobs
[i
].areEqual
,
1642 "%d: expected blobs %s compare\n", i
, intBlobs
[i
].areEqual
?
1647 static void testComparePublicKeyInfo(void)
1650 CERT_PUBLIC_KEY_INFO info1
= { { 0 } }, info2
= { { 0 } };
1651 static CHAR oid_rsa_rsa
[] = szOID_RSA_RSA
;
1652 static CHAR oid_rsa_sha1rsa
[] = szOID_RSA_SHA1RSA
;
1653 static CHAR oid_x957_dsa
[] = szOID_X957_DSA
;
1654 static BYTE bits1
[] = { 1, 0 };
1655 static BYTE bits2
[] = { 0 };
1656 static BYTE bits3
[] = { 1 };
1659 ret = CertComparePublicKeyInfo(0, NULL, NULL);
1661 /* Empty public keys compare */
1662 ret
= CertComparePublicKeyInfo(0, &info1
, &info2
);
1663 ok(ret
, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
1664 /* Different OIDs appear to compare */
1665 info1
.Algorithm
.pszObjId
= oid_rsa_rsa
;
1666 info2
.Algorithm
.pszObjId
= oid_rsa_sha1rsa
;
1667 ret
= CertComparePublicKeyInfo(0, &info1
, &info2
);
1668 ok(ret
, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
1669 info2
.Algorithm
.pszObjId
= oid_x957_dsa
;
1670 ret
= CertComparePublicKeyInfo(0, &info1
, &info2
);
1671 ok(ret
, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
1672 info1
.PublicKey
.cbData
= sizeof(bits1
);
1673 info1
.PublicKey
.pbData
= bits1
;
1674 info1
.PublicKey
.cUnusedBits
= 0;
1675 info2
.PublicKey
.cbData
= sizeof(bits1
);
1676 info2
.PublicKey
.pbData
= bits1
;
1677 info2
.PublicKey
.cUnusedBits
= 0;
1678 ret
= CertComparePublicKeyInfo(0, &info1
, &info2
);
1679 ok(ret
, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
1680 /* Even though they compare in their used bits, these do not compare */
1681 info1
.PublicKey
.cbData
= sizeof(bits2
);
1682 info1
.PublicKey
.pbData
= bits2
;
1683 info1
.PublicKey
.cUnusedBits
= 0;
1684 info2
.PublicKey
.cbData
= sizeof(bits3
);
1685 info2
.PublicKey
.pbData
= bits3
;
1686 info2
.PublicKey
.cUnusedBits
= 1;
1687 ret
= CertComparePublicKeyInfo(0, &info1
, &info2
);
1688 /* Simple (non-comparing) case */
1689 ok(!ret
, "Expected keys not to compare\n");
1690 info2
.PublicKey
.cbData
= sizeof(bits1
);
1691 info2
.PublicKey
.pbData
= bits1
;
1692 info2
.PublicKey
.cUnusedBits
= 0;
1693 ret
= CertComparePublicKeyInfo(0, &info1
, &info2
);
1694 ok(!ret
, "Expected keys not to compare\n");
1697 static void testHashPublicKeyInfo(void)
1700 CERT_PUBLIC_KEY_INFO info
= { { 0 } };
1704 ret = CryptHashPublicKeyInfo(0, 0, 0, 0, NULL, NULL, NULL);
1705 ret = CryptHashPublicKeyInfo(0, 0, 0, 0, &info, NULL, NULL);
1707 ret
= CryptHashPublicKeyInfo(0, 0, 0, 0, NULL
, NULL
, &len
);
1708 ok(!ret
&& GetLastError() == ERROR_FILE_NOT_FOUND
,
1709 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1710 ret
= CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING
, NULL
, NULL
, &len
);
1711 ok(!ret
&& GetLastError() == STATUS_ACCESS_VIOLATION
,
1712 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1713 ret
= CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING
, &info
, NULL
, &len
);
1714 ok(ret
, "CryptHashPublicKeyInfo failed: %08x\n", GetLastError());
1715 ok(len
== 16, "Expected hash size 16, got %d\n", len
);
1718 static const BYTE emptyHash
[] = { 0xb8,0x51,0x3a,0x31,0x0e,0x9f,0x40,
1719 0x36,0x9c,0x92,0x45,0x1b,0x9d,0xc8,0xf9,0xf6 };
1722 ret
= CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING
, &info
, buf
,
1724 ok(ret
, "CryptHashPublicKeyInfo failed: %08x\n", GetLastError());
1725 ok(!memcmp(buf
, emptyHash
, len
), "Unexpected hash\n");
1729 static void testCompareCert(void)
1731 CERT_INFO info1
= { 0 }, info2
= { 0 };
1735 ret = CertCompareCertificate(X509_ASN_ENCODING, NULL, NULL);
1738 /* Certs with the same issuer and serial number are equal, even if they
1739 * differ in other respects (like subject).
1741 info1
.SerialNumber
.pbData
= serialNum
;
1742 info1
.SerialNumber
.cbData
= sizeof(serialNum
);
1743 info1
.Issuer
.pbData
= subjectName
;
1744 info1
.Issuer
.cbData
= sizeof(subjectName
);
1745 info1
.Subject
.pbData
= subjectName2
;
1746 info1
.Subject
.cbData
= sizeof(subjectName2
);
1747 info2
.SerialNumber
.pbData
= serialNum
;
1748 info2
.SerialNumber
.cbData
= sizeof(serialNum
);
1749 info2
.Issuer
.pbData
= subjectName
;
1750 info2
.Issuer
.cbData
= sizeof(subjectName
);
1751 info2
.Subject
.pbData
= subjectName
;
1752 info2
.Subject
.cbData
= sizeof(subjectName
);
1753 ret
= CertCompareCertificate(X509_ASN_ENCODING
, &info1
, &info2
);
1754 ok(ret
, "Expected certs to be equal\n");
1756 info2
.Issuer
.pbData
= subjectName2
;
1757 info2
.Issuer
.cbData
= sizeof(subjectName2
);
1758 ret
= CertCompareCertificate(X509_ASN_ENCODING
, &info1
, &info2
);
1759 ok(!ret
, "Expected certs not to be equal\n");
1762 static void testVerifySubjectCert(void)
1766 PCCERT_CONTEXT context1
, context2
;
1769 ret = CertVerifySubjectCertificateContext(NULL, NULL, NULL);
1772 ret
= CertVerifySubjectCertificateContext(NULL
, NULL
, &flags
);
1773 ok(ret
, "CertVerifySubjectCertificateContext failed; %08x\n",
1775 flags
= CERT_STORE_NO_CRL_FLAG
;
1776 ret
= CertVerifySubjectCertificateContext(NULL
, NULL
, &flags
);
1777 ok(!ret
&& GetLastError() == E_INVALIDARG
,
1778 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1781 context1
= CertCreateCertificateContext(X509_ASN_ENCODING
, bigCert
,
1783 ret
= CertVerifySubjectCertificateContext(NULL
, context1
, &flags
);
1784 ok(ret
, "CertVerifySubjectCertificateContext failed; %08x\n",
1786 ret
= CertVerifySubjectCertificateContext(context1
, NULL
, &flags
);
1787 ok(ret
, "CertVerifySubjectCertificateContext failed; %08x\n",
1789 ret
= CertVerifySubjectCertificateContext(context1
, context1
, &flags
);
1790 ok(ret
, "CertVerifySubjectCertificateContext failed; %08x\n",
1793 context2
= CertCreateCertificateContext(X509_ASN_ENCODING
,
1794 bigCertWithDifferentSubject
, sizeof(bigCertWithDifferentSubject
));
1795 SetLastError(0xdeadbeef);
1796 ret
= CertVerifySubjectCertificateContext(context1
, context2
, &flags
);
1797 ok(ret
, "CertVerifySubjectCertificateContext failed; %08x\n",
1799 flags
= CERT_STORE_REVOCATION_FLAG
;
1800 ret
= CertVerifySubjectCertificateContext(context1
, context2
, &flags
);
1801 ok(ret
, "CertVerifySubjectCertificateContext failed; %08x\n",
1803 ok(flags
== (CERT_STORE_REVOCATION_FLAG
| CERT_STORE_NO_CRL_FLAG
),
1804 "Expected CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG, got %08x\n",
1806 flags
= CERT_STORE_SIGNATURE_FLAG
;
1807 ret
= CertVerifySubjectCertificateContext(context1
, context2
, &flags
);
1808 ok(ret
, "CertVerifySubjectCertificateContext failed; %08x\n",
1810 ok(flags
== CERT_STORE_SIGNATURE_FLAG
,
1811 "Expected CERT_STORE_SIGNATURE_FLAG, got %08x\n", flags
);
1812 CertFreeCertificateContext(context2
);
1814 CertFreeCertificateContext(context1
);
1817 static BYTE privKey
[] = {
1818 0x07, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x52, 0x53, 0x41, 0x32, 0x00,
1819 0x02, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x79, 0x10, 0x1c, 0xd0, 0x6b, 0x10,
1820 0x18, 0x30, 0x94, 0x61, 0xdc, 0x0e, 0xcb, 0x96, 0x4e, 0x21, 0x3f, 0x79, 0xcd,
1821 0xa9, 0x17, 0x62, 0xbc, 0xbb, 0x61, 0x4c, 0xe0, 0x75, 0x38, 0x6c, 0xf3, 0xde,
1822 0x60, 0x86, 0x03, 0x97, 0x65, 0xeb, 0x1e, 0x6b, 0xdb, 0x53, 0x85, 0xad, 0x68,
1823 0x21, 0xf1, 0x5d, 0xe7, 0x1f, 0xe6, 0x53, 0xb4, 0xbb, 0x59, 0x3e, 0x14, 0x27,
1824 0xb1, 0x83, 0xa7, 0x3a, 0x54, 0xe2, 0x8f, 0x65, 0x8e, 0x6a, 0x4a, 0xcf, 0x3b,
1825 0x1f, 0x65, 0xff, 0xfe, 0xf1, 0x31, 0x3a, 0x37, 0x7a, 0x8b, 0xcb, 0xc6, 0xd4,
1826 0x98, 0x50, 0x36, 0x67, 0xe4, 0xa1, 0xe8, 0x7e, 0x8a, 0xc5, 0x23, 0xf2, 0x77,
1827 0xf5, 0x37, 0x61, 0x49, 0x72, 0x59, 0xe8, 0x3d, 0xf7, 0x60, 0xb2, 0x77, 0xca,
1828 0x78, 0x54, 0x6d, 0x65, 0x9e, 0x03, 0x97, 0x1b, 0x61, 0xbd, 0x0c, 0xd8, 0x06,
1829 0x63, 0xe2, 0xc5, 0x48, 0xef, 0xb3, 0xe2, 0x6e, 0x98, 0x7d, 0xbd, 0x4e, 0x72,
1830 0x91, 0xdb, 0x31, 0x57, 0xe3, 0x65, 0x3a, 0x49, 0xca, 0xec, 0xd2, 0x02, 0x4e,
1831 0x22, 0x7e, 0x72, 0x8e, 0xf9, 0x79, 0x84, 0x82, 0xdf, 0x7b, 0x92, 0x2d, 0xaf,
1832 0xc9, 0xe4, 0x33, 0xef, 0x89, 0x5c, 0x66, 0x99, 0xd8, 0x80, 0x81, 0x47, 0x2b,
1833 0xb1, 0x66, 0x02, 0x84, 0x59, 0x7b, 0xc3, 0xbe, 0x98, 0x45, 0x4a, 0x3d, 0xdd,
1834 0xea, 0x2b, 0xdf, 0x4e, 0xb4, 0x24, 0x6b, 0xec, 0xe7, 0xd9, 0x0c, 0x45, 0xb8,
1835 0xbe, 0xca, 0x69, 0x37, 0x92, 0x4c, 0x38, 0x6b, 0x96, 0x6d, 0xcd, 0x86, 0x67,
1836 0x5c, 0xea, 0x54, 0x94, 0xa4, 0xca, 0xa4, 0x02, 0xa5, 0x21, 0x4d, 0xae, 0x40,
1837 0x8f, 0x9d, 0x51, 0x83, 0xf2, 0x3f, 0x33, 0xc1, 0x72, 0xb4, 0x1d, 0x94, 0x6e,
1838 0x7d, 0xe4, 0x27, 0x3f, 0xea, 0xff, 0xe5, 0x9b, 0xa7, 0x5e, 0x55, 0x8e, 0x0d,
1839 0x69, 0x1c, 0x7a, 0xff, 0x81, 0x9d, 0x53, 0x52, 0x97, 0x9a, 0x76, 0x79, 0xda,
1840 0x93, 0x32, 0x16, 0xec, 0x69, 0x51, 0x1a, 0x4e, 0xc3, 0xf1, 0x72, 0x80, 0x78,
1841 0x5e, 0x66, 0x4a, 0x8d, 0x85, 0x2f, 0x3f, 0xb2, 0xa7 };
1843 static const BYTE selfSignedCert
[] = {
1844 0x30, 0x82, 0x01, 0x1f, 0x30, 0x81, 0xce, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
1845 0x10, 0xeb, 0x0d, 0x57, 0x2a, 0x9c, 0x09, 0xba, 0xa4, 0x4a, 0xb7, 0x25, 0x49,
1846 0xd9, 0x3e, 0xb5, 0x73, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d,
1847 0x05, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
1848 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30,
1849 0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x36, 0x32, 0x39, 0x30, 0x35, 0x30, 0x30,
1850 0x34, 0x36, 0x5a, 0x17, 0x0d, 0x30, 0x37, 0x30, 0x36, 0x32, 0x39, 0x31, 0x31,
1851 0x30, 0x30, 0x34, 0x36, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
1852 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e,
1853 0x67, 0x00, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
1854 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
1855 0x00, 0xe2, 0x54, 0x3a, 0xa7, 0x83, 0xb1, 0x27, 0x14, 0x3e, 0x59, 0xbb, 0xb4,
1856 0x53, 0xe6, 0x1f, 0xe7, 0x5d, 0xf1, 0x21, 0x68, 0xad, 0x85, 0x53, 0xdb, 0x6b,
1857 0x1e, 0xeb, 0x65, 0x97, 0x03, 0x86, 0x60, 0xde, 0xf3, 0x6c, 0x38, 0x75, 0xe0,
1858 0x4c, 0x61, 0xbb, 0xbc, 0x62, 0x17, 0xa9, 0xcd, 0x79, 0x3f, 0x21, 0x4e, 0x96,
1859 0xcb, 0x0e, 0xdc, 0x61, 0x94, 0x30, 0x18, 0x10, 0x6b, 0xd0, 0x1c, 0x10, 0x79,
1860 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
1861 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x25, 0x90, 0x53, 0x34, 0xd9, 0x56, 0x41,
1862 0x5e, 0xdb, 0x7e, 0x01, 0x36, 0xec, 0x27, 0x61, 0x5e, 0xb7, 0x4d, 0x90, 0x66,
1863 0xa2, 0xe1, 0x9d, 0x58, 0x76, 0xd4, 0x9c, 0xba, 0x2c, 0x84, 0xc6, 0x83, 0x7a,
1864 0x22, 0x0d, 0x03, 0x69, 0x32, 0x1a, 0x6d, 0xcb, 0x0c, 0x15, 0xb3, 0x6b, 0xc7,
1865 0x0a, 0x8c, 0xb4, 0x5c, 0x34, 0x78, 0xe0, 0x3c, 0x9c, 0xe9, 0xf3, 0x30, 0x9f,
1866 0xa8, 0x76, 0x57, 0x92, 0x36 };
1868 static const BYTE exportedPublicKeyBlob
[] = {
1869 0x06,0x02,0x00,0x00,0x00,0xa4,0x00,0x00,0x52,0x53,0x41,0x31,0x00,0x02,0x00,0x00,
1870 0x01,0x00,0x01,0x00,0x79,0x10,0x1c,0xd0,0x6b,0x10,0x18,0x30,0x94,0x61,0xdc,0x0e,
1871 0xcb,0x96,0x4e,0x21,0x3f,0x79,0xcd,0xa9,0x17,0x62,0xbc,0xbb,0x61,0x4c,0xe0,0x75,
1872 0x38,0x6c,0xf3,0xde,0x60,0x86,0x03,0x97,0x65,0xeb,0x1e,0x6b,0xdb,0x53,0x85,0xad,
1873 0x68,0x21,0xf1,0x5d,0xe7,0x1f,0xe6,0x53,0xb4,0xbb,0x59,0x3e,0x14,0x27,0xb1,0x83,
1874 0xa7,0x3a,0x54,0xe2 };
1876 static const BYTE asnEncodedPublicKey
[] = {
1877 0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7,0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,
1878 0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21,0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,
1879 0x65,0x97,0x03,0x86,0x60,0xde,0xf3,0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,
1880 0x17,0xa9,0xcd,0x79,0x3f,0x21,0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,
1881 0x6b,0xd0,0x1c,0x10,0x79,0x02,0x03,0x01,0x00,0x01 };
1883 static void testAcquireCertPrivateKey(void)
1886 PCCERT_CONTEXT cert
;
1888 DWORD size
, keySpec
;
1890 CRYPT_KEY_PROV_INFO keyProvInfo
;
1892 WCHAR ms_def_prov_w
[MAX_PATH
];
1894 lstrcpyW(ms_def_prov_w
, MS_DEF_PROV_W
);
1896 keyProvInfo
.pwszContainerName
= cspNameW
;
1897 keyProvInfo
.pwszProvName
= ms_def_prov_w
;
1898 keyProvInfo
.dwProvType
= PROV_RSA_FULL
;
1899 keyProvInfo
.dwFlags
= 0;
1900 keyProvInfo
.cProvParam
= 0;
1901 keyProvInfo
.rgProvParam
= NULL
;
1902 keyProvInfo
.dwKeySpec
= AT_SIGNATURE
;
1904 CryptAcquireContextW(NULL
, cspNameW
, MS_DEF_PROV_W
, PROV_RSA_FULL
,
1905 CRYPT_DELETEKEYSET
);
1907 cert
= CertCreateCertificateContext(X509_ASN_ENCODING
, selfSignedCert
,
1908 sizeof(selfSignedCert
));
1911 ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, NULL, NULL);
1912 ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, NULL,
1914 ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, &keySpec,
1916 ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, &csp, NULL, NULL);
1917 ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, &csp, &keySpec,
1919 ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, NULL, NULL, NULL);
1922 /* Missing private key */
1923 ret
= CryptAcquireCertificatePrivateKey(cert
, 0, NULL
, &csp
, NULL
, NULL
);
1924 ok(!ret
&& GetLastError() == CRYPT_E_NO_KEY_PROPERTY
,
1925 "Expected CRYPT_E_NO_KEY_PROPERTY, got %08x\n", GetLastError());
1926 ret
= CryptAcquireCertificatePrivateKey(cert
, 0, NULL
, &csp
, &keySpec
,
1928 ok(!ret
&& GetLastError() == CRYPT_E_NO_KEY_PROPERTY
,
1929 "Expected CRYPT_E_NO_KEY_PROPERTY, got %08x\n", GetLastError());
1930 CertSetCertificateContextProperty(cert
, CERT_KEY_PROV_INFO_PROP_ID
, 0,
1932 ret
= CryptAcquireCertificatePrivateKey(cert
, 0, NULL
, &csp
, &keySpec
,
1934 ok(!ret
&& GetLastError() == CRYPT_E_NO_KEY_PROPERTY
,
1935 "Expected CRYPT_E_NO_KEY_PROPERTY, got %08x\n", GetLastError());
1937 CryptAcquireContextW(&csp
, cspNameW
, MS_DEF_PROV_W
, PROV_RSA_FULL
,
1939 ret
= CryptImportKey(csp
, privKey
, sizeof(privKey
), 0, 0, &key
);
1940 ok(ret
, "CryptImportKey failed: %08x\n", GetLastError());
1945 CERT_KEY_CONTEXT keyContext
;
1947 /* Don't cache provider */
1948 ret
= CryptAcquireCertificatePrivateKey(cert
, 0, NULL
, &certCSP
,
1949 &keySpec
, &callerFree
);
1950 ok(ret
, "CryptAcquireCertificatePrivateKey failed: %08x\n",
1952 ok(callerFree
, "Expected callerFree to be TRUE\n");
1953 CryptReleaseContext(certCSP
, 0);
1954 ret
= CryptAcquireCertificatePrivateKey(cert
, 0, NULL
, &certCSP
,
1956 ok(ret
, "CryptAcquireCertificatePrivateKey failed: %08x\n",
1958 CryptReleaseContext(certCSP
, 0);
1960 /* Use the key prov info's caching (there shouldn't be any) */
1961 ret
= CryptAcquireCertificatePrivateKey(cert
,
1962 CRYPT_ACQUIRE_USE_PROV_INFO_FLAG
, NULL
, &certCSP
, &keySpec
,
1964 ok(ret
, "CryptAcquireCertificatePrivateKey failed: %08x\n",
1966 ok(callerFree
, "Expected callerFree to be TRUE\n");
1967 CryptReleaseContext(certCSP
, 0);
1969 /* Cache it (and check that it's cached) */
1970 ret
= CryptAcquireCertificatePrivateKey(cert
,
1971 CRYPT_ACQUIRE_CACHE_FLAG
, NULL
, &certCSP
, &keySpec
, &callerFree
);
1972 ok(ret
, "CryptAcquireCertificatePrivateKey failed: %08x\n",
1974 ok(!callerFree
, "Expected callerFree to be FALSE\n");
1975 size
= sizeof(keyContext
);
1976 ret
= CertGetCertificateContextProperty(cert
, CERT_KEY_CONTEXT_PROP_ID
,
1977 &keyContext
, &size
);
1978 ok(ret
, "CertGetCertificateContextProperty failed: %08x\n",
1981 /* Remove the cached provider */
1982 CryptReleaseContext(keyContext
.hCryptProv
, 0);
1983 CertSetCertificateContextProperty(cert
, CERT_KEY_CONTEXT_PROP_ID
, 0,
1985 /* Allow caching via the key prov info */
1986 keyProvInfo
.dwFlags
= CERT_SET_KEY_CONTEXT_PROP_ID
;
1987 CertSetCertificateContextProperty(cert
, CERT_KEY_PROV_INFO_PROP_ID
, 0,
1989 /* Now use the key prov info's caching */
1990 ret
= CryptAcquireCertificatePrivateKey(cert
,
1991 CRYPT_ACQUIRE_USE_PROV_INFO_FLAG
, NULL
, &certCSP
, &keySpec
,
1993 ok(ret
, "CryptAcquireCertificatePrivateKey failed: %08x\n",
1995 ok(!callerFree
, "Expected callerFree to be FALSE\n");
1996 size
= sizeof(keyContext
);
1997 ret
= CertGetCertificateContextProperty(cert
, CERT_KEY_CONTEXT_PROP_ID
,
1998 &keyContext
, &size
);
1999 ok(ret
, "CertGetCertificateContextProperty failed: %08x\n",
2002 CryptDestroyKey(key
);
2005 /* Some sanity-checking on public key exporting */
2006 ret
= CryptImportPublicKeyInfo(csp
, X509_ASN_ENCODING
,
2007 &cert
->pCertInfo
->SubjectPublicKeyInfo
, &key
);
2008 ok(ret
, "CryptImportPublicKeyInfo failed: %08x\n", GetLastError());
2011 ret
= CryptExportKey(key
, 0, PUBLICKEYBLOB
, 0, NULL
, &size
);
2012 ok(ret
, "CryptExportKey failed: %08x\n", GetLastError());
2015 LPBYTE buf
= HeapAlloc(GetProcessHeap(), 0, size
), encodedKey
;
2017 ret
= CryptExportKey(key
, 0, PUBLICKEYBLOB
, 0, buf
, &size
);
2018 ok(ret
, "CryptExportKey failed: %08x\n", GetLastError());
2019 ok(size
== sizeof(exportedPublicKeyBlob
), "Unexpected size %d\n",
2021 ok(!memcmp(buf
, exportedPublicKeyBlob
, size
), "Unexpected value\n");
2022 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
, RSA_CSP_PUBLICKEYBLOB
,
2023 buf
, CRYPT_ENCODE_ALLOC_FLAG
, NULL
, &encodedKey
, &size
);
2024 ok(ret
, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2027 ok(size
== sizeof(asnEncodedPublicKey
), "Unexpected size %d\n",
2029 ok(!memcmp(encodedKey
, asnEncodedPublicKey
, size
),
2030 "Unexpected value\n");
2031 LocalFree(encodedKey
);
2033 HeapFree(GetProcessHeap(), 0, buf
);
2035 CryptDestroyKey(key
);
2037 ret
= CryptExportPublicKeyInfoEx(csp
, AT_SIGNATURE
, X509_ASN_ENCODING
,
2038 NULL
, 0, NULL
, NULL
, &size
);
2039 ok(ret
, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
2042 PCERT_PUBLIC_KEY_INFO info
= HeapAlloc(GetProcessHeap(), 0, size
);
2044 ret
= CryptExportPublicKeyInfoEx(csp
, AT_SIGNATURE
, X509_ASN_ENCODING
,
2045 NULL
, 0, NULL
, info
, &size
);
2046 ok(ret
, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
2049 ok(info
->PublicKey
.cbData
== sizeof(asnEncodedPublicKey
),
2050 "Unexpected size %d\n", info
->PublicKey
.cbData
);
2051 ok(!memcmp(info
->PublicKey
.pbData
, asnEncodedPublicKey
,
2052 info
->PublicKey
.cbData
), "Unexpected value\n");
2054 HeapFree(GetProcessHeap(), 0, info
);
2057 CryptReleaseContext(csp
, 0);
2058 CryptAcquireContextW(&csp
, cspNameW
, MS_DEF_PROV_W
, PROV_RSA_FULL
,
2059 CRYPT_DELETEKEYSET
);
2061 CertFreeCertificateContext(cert
);
2064 static void testGetPublicKeyLength(void)
2066 static char oid_rsa_rsa
[] = szOID_RSA_RSA
;
2067 static char oid_rsa_dh
[] = szOID_RSA_DH
;
2068 static char bogusOID
[] = "1.2.3";
2070 CERT_PUBLIC_KEY_INFO info
= { { 0 } };
2071 BYTE bogusKey
[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
2072 BYTE key
[] = { 0x30,0x0f,0x02,0x08,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
2073 0x02,0x03,0x01,0x00,0x01 };
2076 ret = CertGetPublicKeyLength(0, NULL);
2078 /* With an empty public key info */
2079 SetLastError(0xdeadbeef);
2080 ret
= CertGetPublicKeyLength(0, &info
);
2081 ok(ret
== 0 && GetLastError() == ERROR_FILE_NOT_FOUND
,
2082 "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
2083 ret
, GetLastError());
2084 SetLastError(0xdeadbeef);
2085 ret
= CertGetPublicKeyLength(X509_ASN_ENCODING
, &info
);
2086 ok(ret
== 0 && GetLastError() == CRYPT_E_ASN1_EOD
,
2087 "Expected length 0 and CRYPT_E_ASN1_EOD, got length %d, %08x\n",
2088 ret
, GetLastError());
2089 /* With a nearly-empty public key info */
2090 info
.Algorithm
.pszObjId
= oid_rsa_rsa
;
2091 SetLastError(0xdeadbeef);
2092 ret
= CertGetPublicKeyLength(0, &info
);
2093 ok(ret
== 0 && GetLastError() == ERROR_FILE_NOT_FOUND
,
2094 "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
2095 ret
, GetLastError());
2096 SetLastError(0xdeadbeef);
2097 ret
= CertGetPublicKeyLength(X509_ASN_ENCODING
, &info
);
2098 ok(ret
== 0 && GetLastError() == CRYPT_E_ASN1_EOD
,
2099 "Expected length 0 and CRYPT_E_ASN1_EOD, got length %d, %08x\n",
2100 ret
, GetLastError());
2101 /* With a bogus key */
2102 info
.PublicKey
.cbData
= sizeof(bogusKey
);
2103 info
.PublicKey
.pbData
= bogusKey
;
2104 SetLastError(0xdeadbeef);
2105 ret
= CertGetPublicKeyLength(0, &info
);
2106 ok(ret
== 0 && GetLastError() == ERROR_FILE_NOT_FOUND
,
2107 "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
2108 ret
, GetLastError());
2109 SetLastError(0xdeadbeef);
2110 ret
= CertGetPublicKeyLength(X509_ASN_ENCODING
, &info
);
2111 ok(ret
== 0 && GetLastError() == CRYPT_E_ASN1_BADTAG
,
2112 "Expected length 0 and CRYPT_E_ASN1_BADTAGTAG, got length %d, %08x\n",
2113 ret
, GetLastError());
2114 /* With a believable RSA key but a bogus OID */
2115 info
.Algorithm
.pszObjId
= bogusOID
;
2116 info
.PublicKey
.cbData
= sizeof(key
);
2117 info
.PublicKey
.pbData
= key
;
2118 SetLastError(0xdeadbeef);
2119 ret
= CertGetPublicKeyLength(0, &info
);
2120 ok(ret
== 0 && GetLastError() == ERROR_FILE_NOT_FOUND
,
2121 "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
2122 ret
, GetLastError());
2123 SetLastError(0xdeadbeef);
2124 ret
= CertGetPublicKeyLength(X509_ASN_ENCODING
, &info
);
2125 ok(ret
== 56, "Expected length 56, got %d\n", ret
);
2126 /* An RSA key with the DH OID */
2127 info
.Algorithm
.pszObjId
= oid_rsa_dh
;
2128 SetLastError(0xdeadbeef);
2129 ret
= CertGetPublicKeyLength(X509_ASN_ENCODING
, &info
);
2130 ok(ret
== 0 && GetLastError() == CRYPT_E_ASN1_BADTAG
,
2131 "Expected length 0 and CRYPT_E_ASN1_BADTAG, got length %d, %08x\n",
2132 ret
, GetLastError());
2133 /* With the RSA OID */
2134 info
.Algorithm
.pszObjId
= oid_rsa_rsa
;
2135 SetLastError(0xdeadbeef);
2136 ret
= CertGetPublicKeyLength(X509_ASN_ENCODING
, &info
);
2137 ok(ret
== 56, "Expected length 56, got %d\n", ret
);
2142 init_function_pointers();
2145 testCertProperties();
2148 testGetSubjectCert();
2149 testGetIssuerCert();
2151 testCryptHashCert();
2153 testSignAndEncodeCert();
2154 testCreateSelfSignCert();
2156 testCompareCertName();
2157 testCompareIntegerBlob();
2158 testComparePublicKeyInfo();
2159 testHashPublicKeyInfo();
2161 testVerifySubjectCert();
2162 testAcquireCertPrivateKey();
2163 testGetPublicKeyLength();