2 * Copyright 2007 Juan Lang
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "wine/debug.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
28 HCERTSTORE WINAPI CryptGetMessageCertificates(DWORD dwMsgAndCertEncodingType,
29 HCRYPTPROV_LEGACY hCryptProv, DWORD dwFlags, const BYTE* pbSignedBlob,
32 CRYPT_DATA_BLOB blob = { cbSignedBlob, (LPBYTE)pbSignedBlob };
34 TRACE("(%08x, %ld, %d08x %p, %d)\n", dwMsgAndCertEncodingType, hCryptProv,
35 dwFlags, pbSignedBlob, cbSignedBlob);
37 return CertOpenStore(CERT_STORE_PROV_PKCS7, dwMsgAndCertEncodingType,
38 hCryptProv, dwFlags, &blob);
41 LONG WINAPI CryptGetMessageSignerCount(DWORD dwMsgEncodingType,
42 const BYTE *pbSignedBlob, DWORD cbSignedBlob)
47 TRACE("(%08x, %p, %d)\n", dwMsgEncodingType, pbSignedBlob, cbSignedBlob);
49 msg = CryptMsgOpenToDecode(dwMsgEncodingType, 0, 0, 0, NULL, NULL);
52 if (CryptMsgUpdate(msg, pbSignedBlob, cbSignedBlob, TRUE))
54 DWORD size = sizeof(count);
56 CryptMsgGetParam(msg, CMSG_SIGNER_COUNT_PARAM, 0, &count, &size);
63 static CERT_INFO *CRYPT_GetSignerCertInfoFromMsg(HCRYPTMSG msg,
66 CERT_INFO *certInfo = NULL;
69 if (CryptMsgGetParam(msg, CMSG_SIGNER_CERT_INFO_PARAM, dwSignerIndex, NULL,
72 certInfo = CryptMemAlloc(size);
75 if (!CryptMsgGetParam(msg, CMSG_SIGNER_CERT_INFO_PARAM,
76 dwSignerIndex, certInfo, &size))
78 CryptMemFree(certInfo);
84 SetLastError(CRYPT_E_UNEXPECTED_MSG_TYPE);
88 static PCCERT_CONTEXT WINAPI CRYPT_DefaultGetSignerCertificate(void *pvGetArg,
89 DWORD dwCertEncodingType, PCERT_INFO pSignerId, HCERTSTORE hMsgCertStore)
91 return CertFindCertificateInStore(hMsgCertStore, dwCertEncodingType, 0,
92 CERT_FIND_SUBJECT_CERT, pSignerId, NULL);
95 static inline PCCERT_CONTEXT CRYPT_GetSignerCertificate(HCRYPTMSG msg,
96 PCRYPT_VERIFY_MESSAGE_PARA pVerifyPara, PCERT_INFO certInfo, HCERTSTORE store)
98 PFN_CRYPT_GET_SIGNER_CERTIFICATE getCert;
100 if (pVerifyPara->pfnGetSignerCertificate)
101 getCert = pVerifyPara->pfnGetSignerCertificate;
103 getCert = CRYPT_DefaultGetSignerCertificate;
104 return getCert(pVerifyPara->pvGetArg,
105 pVerifyPara->dwMsgAndCertEncodingType, certInfo, store);
108 BOOL WINAPI CryptVerifyDetachedMessageSignature(
109 PCRYPT_VERIFY_MESSAGE_PARA pVerifyPara, DWORD dwSignerIndex,
110 const BYTE *pbDetachedSignBlob, DWORD cbDetachedSignBlob, DWORD cToBeSigned,
111 const BYTE *rgpbToBeSigned[], DWORD rgcbToBeSigned[],
112 PCCERT_CONTEXT *ppSignerCert)
117 TRACE("(%p, %d, %p, %d, %d, %p, %p, %p)\n", pVerifyPara, dwSignerIndex,
118 pbDetachedSignBlob, cbDetachedSignBlob, cToBeSigned, rgpbToBeSigned,
119 rgcbToBeSigned, ppSignerCert);
122 *ppSignerCert = NULL;
124 pVerifyPara->cbSize != sizeof(CRYPT_VERIFY_MESSAGE_PARA) ||
125 GET_CMSG_ENCODING_TYPE(pVerifyPara->dwMsgAndCertEncodingType) !=
128 SetLastError(E_INVALIDARG);
132 msg = CryptMsgOpenToDecode(pVerifyPara->dwMsgAndCertEncodingType,
133 CMSG_DETACHED_FLAG, 0, pVerifyPara->hCryptProv, NULL, NULL);
136 ret = CryptMsgUpdate(msg, pbDetachedSignBlob, cbDetachedSignBlob, TRUE);
141 for (i = 0; ret && i < cToBeSigned; i++)
142 ret = CryptMsgUpdate(msg, rgpbToBeSigned[i], rgcbToBeSigned[i],
143 i == cToBeSigned - 1 ? TRUE : FALSE);
147 CERT_INFO *certInfo = CRYPT_GetSignerCertInfoFromMsg(msg,
153 HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MSG,
154 pVerifyPara->dwMsgAndCertEncodingType,
155 pVerifyPara->hCryptProv, 0, msg);
159 PCCERT_CONTEXT cert = CRYPT_GetSignerCertificate(
160 msg, pVerifyPara, certInfo, store);
164 ret = CryptMsgControl(msg, 0,
165 CMSG_CTRL_VERIFY_SIGNATURE, cert->pCertInfo);
166 if (ret && ppSignerCert)
167 *ppSignerCert = cert;
169 CertFreeCertificateContext(cert);
172 SetLastError(CRYPT_E_NOT_FOUND);
173 CertCloseStore(store, 0);
175 CryptMemFree(certInfo);
180 TRACE("returning %d\n", ret);
184 BOOL WINAPI CryptVerifyMessageSignature(PCRYPT_VERIFY_MESSAGE_PARA pVerifyPara,
185 DWORD dwSignerIndex, const BYTE* pbSignedBlob, DWORD cbSignedBlob,
186 BYTE* pbDecoded, DWORD* pcbDecoded, PCCERT_CONTEXT* ppSignerCert)
191 TRACE("(%p, %d, %p, %d, %p, %p, %p)\n",
192 pVerifyPara, dwSignerIndex, pbSignedBlob, cbSignedBlob,
193 pbDecoded, pcbDecoded, ppSignerCert);
196 *ppSignerCert = NULL;
198 pVerifyPara->cbSize != sizeof(CRYPT_VERIFY_MESSAGE_PARA) ||
199 GET_CMSG_ENCODING_TYPE(pVerifyPara->dwMsgAndCertEncodingType) !=
204 SetLastError(E_INVALIDARG);
208 msg = CryptMsgOpenToDecode(pVerifyPara->dwMsgAndCertEncodingType, 0, 0,
209 pVerifyPara->hCryptProv, NULL, NULL);
212 ret = CryptMsgUpdate(msg, pbSignedBlob, cbSignedBlob, TRUE);
213 if (ret && pcbDecoded)
214 ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, pbDecoded,
218 CERT_INFO *certInfo = CRYPT_GetSignerCertInfoFromMsg(msg,
224 HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MSG,
225 pVerifyPara->dwMsgAndCertEncodingType,
226 pVerifyPara->hCryptProv, 0, msg);
230 PCCERT_CONTEXT cert = CRYPT_GetSignerCertificate(
231 msg, pVerifyPara, certInfo, store);
235 ret = CryptMsgControl(msg, 0,
236 CMSG_CTRL_VERIFY_SIGNATURE, cert->pCertInfo);
237 if (ret && ppSignerCert)
238 *ppSignerCert = cert;
240 CertFreeCertificateContext(cert);
242 CertCloseStore(store, 0);
245 CryptMemFree(certInfo);
249 if(!ret && pcbDecoded)
251 TRACE("returning %d\n", ret);
255 BOOL WINAPI CryptHashMessage(PCRYPT_HASH_MESSAGE_PARA pHashPara,
256 BOOL fDetachedHash, DWORD cToBeHashed, const BYTE *rgpbToBeHashed[],
257 DWORD rgcbToBeHashed[], BYTE *pbHashedBlob, DWORD *pcbHashedBlob,
258 BYTE *pbComputedHash, DWORD *pcbComputedHash)
263 CMSG_HASHED_ENCODE_INFO info;
265 TRACE("(%p, %d, %d, %p, %p, %p, %p, %p, %p)\n", pHashPara, fDetachedHash,
266 cToBeHashed, rgpbToBeHashed, rgcbToBeHashed, pbHashedBlob, pcbHashedBlob,
267 pbComputedHash, pcbComputedHash);
269 if (pHashPara->cbSize != sizeof(CRYPT_HASH_MESSAGE_PARA))
271 SetLastError(E_INVALIDARG);
274 /* Native seems to ignore any encoding type other than the expected
275 * PKCS_7_ASN_ENCODING
277 if (GET_CMSG_ENCODING_TYPE(pHashPara->dwMsgEncodingType) !=
280 /* Native also seems to do nothing if the output parameter isn't given */
284 flags = fDetachedHash ? CMSG_DETACHED_FLAG : 0;
285 memset(&info, 0, sizeof(info));
286 info.cbSize = sizeof(info);
287 info.hCryptProv = pHashPara->hCryptProv;
288 memcpy(&info.HashAlgorithm, &pHashPara->HashAlgorithm,
289 sizeof(info.HashAlgorithm));
290 info.pvHashAuxInfo = pHashPara->pvHashAuxInfo;
291 msg = CryptMsgOpenToEncode(pHashPara->dwMsgEncodingType, flags, CMSG_HASHED,
295 for (i = 0, ret = TRUE; ret && i < cToBeHashed; i++)
296 ret = CryptMsgUpdate(msg, rgpbToBeHashed[i], rgcbToBeHashed[i],
297 i == cToBeHashed - 1 ? TRUE : FALSE);
300 ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, pbHashedBlob,
302 if (ret && pcbComputedHash)
303 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0,
304 pbComputedHash, pcbComputedHash);
311 BOOL WINAPI CryptVerifyDetachedMessageHash(PCRYPT_HASH_MESSAGE_PARA pHashPara,
312 BYTE *pbDetachedHashBlob, DWORD cbDetachedHashBlob, DWORD cToBeHashed,
313 const BYTE *rgpbToBeHashed[], DWORD rgcbToBeHashed[], BYTE *pbComputedHash,
314 DWORD *pcbComputedHash)
319 TRACE("(%p, %p, %d, %d, %p, %p, %p, %p)\n", pHashPara, pbDetachedHashBlob,
320 cbDetachedHashBlob, cToBeHashed, rgpbToBeHashed, rgcbToBeHashed,
321 pbComputedHash, pcbComputedHash);
323 if (pHashPara->cbSize != sizeof(CRYPT_HASH_MESSAGE_PARA))
325 SetLastError(E_INVALIDARG);
328 if (GET_CMSG_ENCODING_TYPE(pHashPara->dwMsgEncodingType) !=
331 SetLastError(E_INVALIDARG);
334 msg = CryptMsgOpenToDecode(pHashPara->dwMsgEncodingType, CMSG_DETACHED_FLAG,
335 0, pHashPara->hCryptProv, NULL, NULL);
340 ret = CryptMsgUpdate(msg, pbDetachedHashBlob, cbDetachedHashBlob, TRUE);
345 for (i = 0; ret && i < cToBeHashed; i++)
347 ret = CryptMsgUpdate(msg, rgpbToBeHashed[i],
348 rgcbToBeHashed[i], i == cToBeHashed - 1 ? TRUE : FALSE);
352 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
356 ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_HASH, NULL);
357 if (ret && pcbComputedHash)
358 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0,
359 pbComputedHash, pcbComputedHash);
366 BOOL WINAPI CryptVerifyMessageHash(PCRYPT_HASH_MESSAGE_PARA pHashPara,
367 BYTE *pbHashedBlob, DWORD cbHashedBlob, BYTE *pbToBeHashed,
368 DWORD *pcbToBeHashed, BYTE *pbComputedHash, DWORD *pcbComputedHash)
373 TRACE("(%p, %p, %d, %p, %p, %p, %p)\n", pHashPara, pbHashedBlob,
374 cbHashedBlob, pbToBeHashed, pcbToBeHashed, pbComputedHash,
377 if (pHashPara->cbSize != sizeof(CRYPT_HASH_MESSAGE_PARA))
379 SetLastError(E_INVALIDARG);
382 if (GET_CMSG_ENCODING_TYPE(pHashPara->dwMsgEncodingType) !=
385 SetLastError(E_INVALIDARG);
388 msg = CryptMsgOpenToDecode(pHashPara->dwMsgEncodingType, 0, 0,
389 pHashPara->hCryptProv, NULL, NULL);
392 ret = CryptMsgUpdate(msg, pbHashedBlob, cbHashedBlob, TRUE);
395 ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_HASH, NULL);
396 if (ret && pcbToBeHashed)
397 ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0,
398 pbToBeHashed, pcbToBeHashed);
399 if (ret && pcbComputedHash)
400 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0,
401 pbComputedHash, pcbComputedHash);