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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 void testCryptHashCert(void)
54 static const BYTE emptyHash[] = { 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b,
55 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07,
57 static const BYTE knownHash[] = { 0xae, 0x9d, 0xbf, 0x6d, 0xf5, 0x46, 0xee,
58 0x8b, 0xc5, 0x7a, 0x13, 0xba, 0xc2, 0xb1, 0x04, 0xf2, 0xbf, 0x52, 0xa8,
60 static const BYTE toHash[] = "abcdefghijklmnopqrstuvwxyz0123456789.,;!?:";
63 DWORD hashLen = sizeof(hash);
65 /* NULL buffer and nonzero length crashes
66 ret = CryptHashCertificate(0, 0, 0, NULL, size, hash, &hashLen);
67 empty hash length also crashes
68 ret = CryptHashCertificate(0, 0, 0, buf, size, hash, NULL);
71 ret = CryptHashCertificate(0, 0, 0, toHash, sizeof(toHash), NULL,
73 ok(ret, "CryptHashCertificate failed: %08lx\n", GetLastError());
74 ok(hashLen == sizeof(hash),
75 "Got unexpected size of hash %ld, expected %d\n", hashLen, sizeof(hash));
76 /* Test with empty buffer */
77 ret = CryptHashCertificate(0, 0, 0, NULL, 0, hash, &hashLen);
78 ok(ret, "CryptHashCertificate failed: %08lx\n", GetLastError());
79 ok(!memcmp(hash, emptyHash, sizeof(emptyHash)),
80 "Unexpected hash of nothing\n");
81 /* Test a known value */
82 ret = CryptHashCertificate(0, 0, 0, toHash, sizeof(toHash), hash,
84 ok(ret, "CryptHashCertificate failed: %08lx\n", GetLastError());
85 ok(!memcmp(hash, knownHash, sizeof(knownHash)), "Unexpected hash\n");
88 static const char cspName[] = "WineCryptTemp";
90 static void verifySig(HCRYPTPROV csp, const BYTE *toSign, size_t toSignLen,
91 const BYTE *sig, size_t sigLen)
94 BOOL ret = CryptCreateHash(csp, CALG_SHA1, 0, 0, &hash);
96 ok(ret, "CryptCreateHash failed: %08lx\n", GetLastError());
100 DWORD mySigSize = sizeof(mySig);
102 ret = CryptHashData(hash, toSign, toSignLen, 0);
103 ok(ret, "CryptHashData failed: %08lx\n", GetLastError());
104 /* use the A variant so the test can run on Win9x */
105 ret = CryptSignHashA(hash, AT_SIGNATURE, NULL, 0, mySig, &mySigSize);
106 ok(ret, "CryptSignHash failed: %08lx\n", GetLastError());
109 ok(mySigSize == sigLen, "Expected sig length %d, got %ld\n",
111 ok(!memcmp(mySig, sig, sigLen), "Unexpected signature\n");
113 CryptDestroyHash(hash);
117 /* Tests signing the certificate described by toBeSigned with the CSP passed in,
118 * using the algorithm with OID sigOID. The CSP is assumed to be empty, and a
119 * keyset named AT_SIGNATURE will be added to it. The signing key will be
120 * stored in *key, and the signature will be stored in sig. sigLen should be
123 static void testSignCert(HCRYPTPROV csp, const CRYPT_DATA_BLOB *toBeSigned,
124 LPCSTR sigOID, HCRYPTKEY *key, BYTE *sig, DWORD *sigLen)
128 CRYPT_ALGORITHM_IDENTIFIER algoID = { NULL, { 0, NULL } };
131 ret = CryptSignCertificate(0, 0, 0, NULL, 0, NULL, NULL, NULL, NULL);
132 ret = CryptSignCertificate(0, 0, 0, NULL, 0, NULL, NULL, NULL, &size);
133 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
134 NULL, NULL, NULL, &size);
136 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
137 &algoID, NULL, NULL, &size);
138 ok(!ret && GetLastError() == NTE_BAD_ALGID,
139 "Expected NTE_BAD_ALGID, got %08lx\n", GetLastError());
140 algoID.pszObjId = (LPSTR)sigOID;
141 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
142 &algoID, NULL, NULL, &size);
143 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
144 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
145 ret = CryptSignCertificate(0, AT_SIGNATURE, 0, toBeSigned->pbData,
146 toBeSigned->cbData, &algoID, NULL, NULL, &size);
147 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
148 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
150 /* No keys exist in the new CSP yet.. */
151 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
152 toBeSigned->cbData, &algoID, NULL, NULL, &size);
153 ok(!ret && (GetLastError() == NTE_BAD_KEYSET || GetLastError() ==
154 NTE_NO_KEY), "Expected NTE_BAD_KEYSET or NTE_NO_KEY, got %08lx\n",
156 ret = CryptGenKey(csp, AT_SIGNATURE, 0, key);
157 ok(ret, "CryptGenKey failed: %08lx\n", GetLastError());
160 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
161 toBeSigned->cbData, &algoID, NULL, NULL, &size);
162 ok(ret, "CryptSignCertificate failed: %08lx\n", GetLastError());
163 ok(size <= *sigLen, "Expected size <= %ld, got %ld\n", *sigLen, size);
166 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
167 toBeSigned->cbData, &algoID, NULL, sig, &size);
168 ok(ret, "CryptSignCertificate failed: %08lx\n", GetLastError());
172 verifySig(csp, toBeSigned->pbData, toBeSigned->cbData, sig,
179 static void testVerifyCertSig(HCRYPTPROV csp, const CRYPT_DATA_BLOB *toBeSigned,
180 LPCSTR sigOID, const BYTE *sig, DWORD sigLen)
182 CERT_SIGNED_CONTENT_INFO info;
187 if(pCryptVerifyCertificateSignatureEx) {
188 ret = pCryptVerifyCertificateSignatureEx(0, 0, 0, NULL, 0, NULL, 0, NULL);
189 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
190 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
192 ret = pCryptVerifyCertificateSignatureEx(csp, 0, 0, NULL, 0, NULL, 0, NULL);
193 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
194 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
196 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING, 0, NULL, 0,
198 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
199 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
202 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
203 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, NULL, 0, NULL, 0, NULL);
206 info.ToBeSigned.cbData = toBeSigned->cbData;
207 info.ToBeSigned.pbData = toBeSigned->pbData;
208 info.SignatureAlgorithm.pszObjId = (LPSTR)sigOID;
209 info.SignatureAlgorithm.Parameters.cbData = 0;
210 info.Signature.cbData = sigLen;
211 info.Signature.pbData = (BYTE *)sig;
212 info.Signature.cUnusedBits = 0;
213 ret = CryptEncodeObjectEx(X509_ASN_ENCODING, X509_CERT, &info,
214 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&cert, &size);
215 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
218 CRYPT_DATA_BLOB certBlob = { 0, NULL };
219 PCERT_PUBLIC_KEY_INFO pubKeyInfo = NULL;
221 if(pCryptVerifyCertificateSignatureEx) {
222 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
223 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
224 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
225 "Expected CRYPT_E_ASN1_EOD, got %08lx\n", GetLastError());
227 certBlob.pbData = (void *)0xdeadbeef;
228 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
229 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
230 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
231 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
232 certBlob.cbData = size;
233 certBlob.pbData = cert;
234 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
235 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
236 ok(!ret && GetLastError() ==
237 HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
238 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
240 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
241 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
242 CRYPT_VERIFY_CERT_SIGN_ISSUER_NULL, NULL, 0, NULL);
243 ok(!ret && GetLastError() ==
244 HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
245 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
248 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
249 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
250 CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY, NULL, 0, NULL);
253 CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
254 (LPSTR)sigOID, 0, NULL, NULL, &size);
255 pubKeyInfo = HeapAlloc(GetProcessHeap(), 0, size);
258 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
259 X509_ASN_ENCODING, (LPSTR)sigOID, 0, NULL, pubKeyInfo, &size);
260 ok(ret, "CryptExportKey failed: %08lx\n", GetLastError());
261 if (ret && pCryptVerifyCertificateSignatureEx)
263 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
264 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
265 CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY, pubKeyInfo, 0, NULL);
266 ok(ret, "CryptVerifyCertificateSignatureEx failed: %08lx\n",
269 HeapFree(GetProcessHeap(), 0, pubKeyInfo);
275 static const BYTE emptyCert[] = { 0x30, 0x00 };
277 static void testCertSigs(void)
280 CRYPT_DATA_BLOB toBeSigned = { sizeof(emptyCert), (LPBYTE)emptyCert };
284 DWORD sigSize = sizeof(sig);
286 /* Just in case a previous run failed, delete this thing */
287 CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
289 ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
291 ok(ret, "CryptAcquireContext failed: %08lx\n", GetLastError());
293 testSignCert(csp, &toBeSigned, szOID_RSA_SHA1RSA, &key, sig, &sigSize);
294 testVerifyCertSig(csp, &toBeSigned, szOID_RSA_SHA1RSA, sig, sigSize);
296 CryptDestroyKey(key);
297 CryptReleaseContext(csp, 0);
298 ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
304 init_function_pointers();