Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584/* * Copyright 2007 Juan Lang * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
#include <stdarg.h>#include "windef.h"#include "winbase.h"#include "wincrypt.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(crypt);
HCERTSTORE WINAPI CryptGetMessageCertificates(DWORD dwMsgAndCertEncodingType, HCRYPTPROV_LEGACY hCryptProv, DWORD dwFlags, const BYTE* pbSignedBlob, DWORD cbSignedBlob){ CRYPT_DATA_BLOB blob = { cbSignedBlob, (LPBYTE)pbSignedBlob };
TRACE("(%08x, %ld, %d08x %p, %d)\n", dwMsgAndCertEncodingType, hCryptProv, dwFlags, pbSignedBlob, cbSignedBlob);
return CertOpenStore(CERT_STORE_PROV_PKCS7, dwMsgAndCertEncodingType, hCryptProv, dwFlags, &blob);}
LONG WINAPI CryptGetMessageSignerCount(DWORD dwMsgEncodingType, const BYTE *pbSignedBlob, DWORD cbSignedBlob){ HCRYPTMSG msg; LONG count = -1;
TRACE("(%08x, %p, %d)\n", dwMsgEncodingType, pbSignedBlob, cbSignedBlob);
msg = CryptMsgOpenToDecode(dwMsgEncodingType, 0, 0, 0, NULL, NULL); if (msg) { if (CryptMsgUpdate(msg, pbSignedBlob, cbSignedBlob, TRUE)) { DWORD size = sizeof(count);
CryptMsgGetParam(msg, CMSG_SIGNER_COUNT_PARAM, 0, &count, &size); } CryptMsgClose(msg); } return count;}
static CERT_INFO *CRYPT_GetSignerCertInfoFromMsg(HCRYPTMSG msg, DWORD dwSignerIndex){ CERT_INFO *certInfo = NULL; DWORD size;
if (CryptMsgGetParam(msg, CMSG_SIGNER_CERT_INFO_PARAM, dwSignerIndex, NULL, &size)) { certInfo = CryptMemAlloc(size); if (certInfo) { if (!CryptMsgGetParam(msg, CMSG_SIGNER_CERT_INFO_PARAM, dwSignerIndex, certInfo, &size)) { CryptMemFree(certInfo); certInfo = NULL; } } } else SetLastError(CRYPT_E_UNEXPECTED_MSG_TYPE); return certInfo;}
static PCCERT_CONTEXT WINAPI CRYPT_DefaultGetSignerCertificate(void *pvGetArg, DWORD dwCertEncodingType, PCERT_INFO pSignerId, HCERTSTORE hMsgCertStore){ return CertFindCertificateInStore(hMsgCertStore, dwCertEncodingType, 0, CERT_FIND_SUBJECT_CERT, pSignerId, NULL);}
static inline PCCERT_CONTEXT CRYPT_GetSignerCertificate(HCRYPTMSG msg, PCRYPT_VERIFY_MESSAGE_PARA pVerifyPara, PCERT_INFO certInfo, HCERTSTORE store){ PFN_CRYPT_GET_SIGNER_CERTIFICATE getCert;
if (pVerifyPara->pfnGetSignerCertificate) getCert = pVerifyPara->pfnGetSignerCertificate; else getCert = CRYPT_DefaultGetSignerCertificate; return getCert(pVerifyPara->pvGetArg, pVerifyPara->dwMsgAndCertEncodingType, certInfo, store);}
BOOL WINAPI CryptVerifyDetachedMessageSignature( PCRYPT_VERIFY_MESSAGE_PARA pVerifyPara, DWORD dwSignerIndex, const BYTE *pbDetachedSignBlob, DWORD cbDetachedSignBlob, DWORD cToBeSigned, const BYTE *rgpbToBeSigned[], DWORD rgcbToBeSigned[], PCCERT_CONTEXT *ppSignerCert){ BOOL ret = FALSE; HCRYPTMSG msg;
TRACE("(%p, %d, %p, %d, %d, %p, %p, %p)\n", pVerifyPara, dwSignerIndex, pbDetachedSignBlob, cbDetachedSignBlob, cToBeSigned, rgpbToBeSigned, rgcbToBeSigned, ppSignerCert);
if (ppSignerCert) *ppSignerCert = NULL; if (!pVerifyPara || pVerifyPara->cbSize != sizeof(CRYPT_VERIFY_MESSAGE_PARA) || GET_CMSG_ENCODING_TYPE(pVerifyPara->dwMsgAndCertEncodingType) != PKCS_7_ASN_ENCODING) { SetLastError(E_INVALIDARG); return FALSE; }
msg = CryptMsgOpenToDecode(pVerifyPara->dwMsgAndCertEncodingType, CMSG_DETACHED_FLAG, 0, pVerifyPara->hCryptProv, NULL, NULL); if (msg) { ret = CryptMsgUpdate(msg, pbDetachedSignBlob, cbDetachedSignBlob, TRUE); if (ret) { DWORD i;
for (i = 0; ret && i < cToBeSigned; i++) ret = CryptMsgUpdate(msg, rgpbToBeSigned[i], rgcbToBeSigned[i], i == cToBeSigned - 1); } if (ret) { CERT_INFO *certInfo = CRYPT_GetSignerCertInfoFromMsg(msg, dwSignerIndex);
ret = FALSE; if (certInfo) { HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MSG, pVerifyPara->dwMsgAndCertEncodingType, pVerifyPara->hCryptProv, 0, msg);
if (store) { PCCERT_CONTEXT cert = CRYPT_GetSignerCertificate( msg, pVerifyPara, certInfo, store);
if (cert) { ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_SIGNATURE, cert->pCertInfo); if (ret && ppSignerCert) *ppSignerCert = cert; else CertFreeCertificateContext(cert); } else SetLastError(CRYPT_E_NOT_FOUND); CertCloseStore(store, 0); } CryptMemFree(certInfo); } } CryptMsgClose(msg); } TRACE("returning %d\n", ret); return ret;}
BOOL WINAPI CryptVerifyMessageSignature(PCRYPT_VERIFY_MESSAGE_PARA pVerifyPara, DWORD dwSignerIndex, const BYTE* pbSignedBlob, DWORD cbSignedBlob, BYTE* pbDecoded, DWORD* pcbDecoded, PCCERT_CONTEXT* ppSignerCert){ BOOL ret = FALSE; HCRYPTMSG msg;
TRACE("(%p, %d, %p, %d, %p, %p, %p)\n", pVerifyPara, dwSignerIndex, pbSignedBlob, cbSignedBlob, pbDecoded, pcbDecoded, ppSignerCert);
if (ppSignerCert) *ppSignerCert = NULL; if (!pVerifyPara || pVerifyPara->cbSize != sizeof(CRYPT_VERIFY_MESSAGE_PARA) || GET_CMSG_ENCODING_TYPE(pVerifyPara->dwMsgAndCertEncodingType) != PKCS_7_ASN_ENCODING) { if(pcbDecoded) *pcbDecoded = 0; SetLastError(E_INVALIDARG); return FALSE; }
msg = CryptMsgOpenToDecode(pVerifyPara->dwMsgAndCertEncodingType, 0, 0, pVerifyPara->hCryptProv, NULL, NULL); if (msg) { ret = CryptMsgUpdate(msg, pbSignedBlob, cbSignedBlob, TRUE); if (ret && pcbDecoded) ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, pbDecoded, pcbDecoded); if (ret) { CERT_INFO *certInfo = CRYPT_GetSignerCertInfoFromMsg(msg, dwSignerIndex);
ret = FALSE; if (certInfo) { HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MSG, pVerifyPara->dwMsgAndCertEncodingType, pVerifyPara->hCryptProv, 0, msg);
if (store) { PCCERT_CONTEXT cert = CRYPT_GetSignerCertificate( msg, pVerifyPara, certInfo, store);
if (cert) { ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_SIGNATURE, cert->pCertInfo); if (ret && ppSignerCert) *ppSignerCert = cert; else CertFreeCertificateContext(cert); } CertCloseStore(store, 0); } } CryptMemFree(certInfo); } CryptMsgClose(msg); } if(!ret && pcbDecoded) *pcbDecoded = 0; TRACE("returning %d\n", ret); return ret;}
BOOL WINAPI CryptHashMessage(PCRYPT_HASH_MESSAGE_PARA pHashPara, BOOL fDetachedHash, DWORD cToBeHashed, const BYTE *rgpbToBeHashed[], DWORD rgcbToBeHashed[], BYTE *pbHashedBlob, DWORD *pcbHashedBlob, BYTE *pbComputedHash, DWORD *pcbComputedHash){ DWORD i, flags; BOOL ret = FALSE; HCRYPTMSG msg; CMSG_HASHED_ENCODE_INFO info;
TRACE("(%p, %d, %d, %p, %p, %p, %p, %p, %p)\n", pHashPara, fDetachedHash, cToBeHashed, rgpbToBeHashed, rgcbToBeHashed, pbHashedBlob, pcbHashedBlob, pbComputedHash, pcbComputedHash);
if (pHashPara->cbSize != sizeof(CRYPT_HASH_MESSAGE_PARA)) { SetLastError(E_INVALIDARG); return FALSE; } /* Native seems to ignore any encoding type other than the expected * PKCS_7_ASN_ENCODING */ if (GET_CMSG_ENCODING_TYPE(pHashPara->dwMsgEncodingType) != PKCS_7_ASN_ENCODING) return TRUE; /* Native also seems to do nothing if the output parameter isn't given */ if (!pcbHashedBlob) return TRUE;
flags = fDetachedHash ? CMSG_DETACHED_FLAG : 0; memset(&info, 0, sizeof(info)); info.cbSize = sizeof(info); info.hCryptProv = pHashPara->hCryptProv; info.HashAlgorithm = pHashPara->HashAlgorithm; info.pvHashAuxInfo = pHashPara->pvHashAuxInfo; msg = CryptMsgOpenToEncode(pHashPara->dwMsgEncodingType, flags, CMSG_HASHED, &info, NULL, NULL); if (msg) { for (i = 0, ret = TRUE; ret && i < cToBeHashed; i++) ret = CryptMsgUpdate(msg, rgpbToBeHashed[i], rgcbToBeHashed[i], i == cToBeHashed - 1); if (ret) { ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, pbHashedBlob, pcbHashedBlob); if (ret && pcbComputedHash) ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0, pbComputedHash, pcbComputedHash); } CryptMsgClose(msg); } return ret;}
BOOL WINAPI CryptVerifyDetachedMessageHash(PCRYPT_HASH_MESSAGE_PARA pHashPara, BYTE *pbDetachedHashBlob, DWORD cbDetachedHashBlob, DWORD cToBeHashed, const BYTE *rgpbToBeHashed[], DWORD rgcbToBeHashed[], BYTE *pbComputedHash, DWORD *pcbComputedHash){ HCRYPTMSG msg; BOOL ret = FALSE;
TRACE("(%p, %p, %d, %d, %p, %p, %p, %p)\n", pHashPara, pbDetachedHashBlob, cbDetachedHashBlob, cToBeHashed, rgpbToBeHashed, rgcbToBeHashed, pbComputedHash, pcbComputedHash);
if (pHashPara->cbSize != sizeof(CRYPT_HASH_MESSAGE_PARA)) { SetLastError(E_INVALIDARG); return FALSE; } if (GET_CMSG_ENCODING_TYPE(pHashPara->dwMsgEncodingType) != PKCS_7_ASN_ENCODING) { SetLastError(E_INVALIDARG); return FALSE; } msg = CryptMsgOpenToDecode(pHashPara->dwMsgEncodingType, CMSG_DETACHED_FLAG, 0, pHashPara->hCryptProv, NULL, NULL); if (msg) { DWORD i;
ret = CryptMsgUpdate(msg, pbDetachedHashBlob, cbDetachedHashBlob, TRUE); if (ret) { if (cToBeHashed) { for (i = 0; ret && i < cToBeHashed; i++) { ret = CryptMsgUpdate(msg, rgpbToBeHashed[i], rgcbToBeHashed[i], i == cToBeHashed - 1); } } else ret = CryptMsgUpdate(msg, NULL, 0, TRUE); } if (ret) { ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_HASH, NULL); if (ret && pcbComputedHash) ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0, pbComputedHash, pcbComputedHash); } CryptMsgClose(msg); } return ret;}
BOOL WINAPI CryptVerifyMessageHash(PCRYPT_HASH_MESSAGE_PARA pHashPara, BYTE *pbHashedBlob, DWORD cbHashedBlob, BYTE *pbToBeHashed, DWORD *pcbToBeHashed, BYTE *pbComputedHash, DWORD *pcbComputedHash){ HCRYPTMSG msg; BOOL ret = FALSE;
TRACE("(%p, %p, %d, %p, %p, %p, %p)\n", pHashPara, pbHashedBlob, cbHashedBlob, pbToBeHashed, pcbToBeHashed, pbComputedHash, pcbComputedHash);
if (pHashPara->cbSize != sizeof(CRYPT_HASH_MESSAGE_PARA)) { SetLastError(E_INVALIDARG); return FALSE; } if (GET_CMSG_ENCODING_TYPE(pHashPara->dwMsgEncodingType) != PKCS_7_ASN_ENCODING) { SetLastError(E_INVALIDARG); return FALSE; } msg = CryptMsgOpenToDecode(pHashPara->dwMsgEncodingType, 0, 0, pHashPara->hCryptProv, NULL, NULL); if (msg) { ret = CryptMsgUpdate(msg, pbHashedBlob, cbHashedBlob, TRUE); if (ret) { ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_HASH, NULL); if (ret && pcbToBeHashed) ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, pbToBeHashed, pcbToBeHashed); if (ret && pcbComputedHash) ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0, pbComputedHash, pcbComputedHash); } CryptMsgClose(msg); } return ret;}
BOOL WINAPI CryptSignMessage(PCRYPT_SIGN_MESSAGE_PARA pSignPara, BOOL fDetachedSignature, DWORD cToBeSigned, const BYTE *rgpbToBeSigned[], DWORD rgcbToBeSigned[], BYTE *pbSignedBlob, DWORD *pcbSignedBlob){ HCRYPTPROV hCryptProv; BOOL ret, freeProv = FALSE; DWORD i, keySpec; PCERT_BLOB certBlob = NULL; PCRL_BLOB crlBlob = NULL; CMSG_SIGNED_ENCODE_INFO signInfo; CMSG_SIGNER_ENCODE_INFO signer; HCRYPTMSG msg = 0;
TRACE("(%p, %d, %d, %p, %p, %p, %p)\n", pSignPara, fDetachedSignature, cToBeSigned, rgpbToBeSigned, rgcbToBeSigned, pbSignedBlob, pcbSignedBlob);
if (pSignPara->cbSize != sizeof(CRYPT_SIGN_MESSAGE_PARA) || GET_CMSG_ENCODING_TYPE(pSignPara->dwMsgEncodingType) != PKCS_7_ASN_ENCODING) { *pcbSignedBlob = 0; SetLastError(E_INVALIDARG); return FALSE; } if (!pSignPara->pSigningCert) return TRUE;
ret = CryptAcquireCertificatePrivateKey(pSignPara->pSigningCert, CRYPT_ACQUIRE_CACHE_FLAG, NULL, &hCryptProv, &keySpec, &freeProv); if (!ret) return FALSE;
memset(&signer, 0, sizeof(signer)); signer.cbSize = sizeof(signer); signer.pCertInfo = pSignPara->pSigningCert->pCertInfo; signer.hCryptProv = hCryptProv; signer.dwKeySpec = keySpec; signer.HashAlgorithm = pSignPara->HashAlgorithm; signer.pvHashAuxInfo = pSignPara->pvHashAuxInfo; signer.cAuthAttr = pSignPara->cAuthAttr; signer.rgAuthAttr = pSignPara->rgAuthAttr; signer.cUnauthAttr = pSignPara->cUnauthAttr; signer.rgUnauthAttr = pSignPara->rgUnauthAttr;
memset(&signInfo, 0, sizeof(signInfo)); signInfo.cbSize = sizeof(signInfo); signInfo.cSigners = 1; signInfo.rgSigners = &signer;
if (pSignPara->cMsgCert) { certBlob = CryptMemAlloc(sizeof(CERT_BLOB) * pSignPara->cMsgCert); if (certBlob) { for (i = 0; i < pSignPara->cMsgCert; ++i) { certBlob[i].cbData = pSignPara->rgpMsgCert[i]->cbCertEncoded; certBlob[i].pbData = pSignPara->rgpMsgCert[i]->pbCertEncoded; } signInfo.cCertEncoded = pSignPara->cMsgCert; signInfo.rgCertEncoded = certBlob; } else ret = FALSE; } if (pSignPara->cMsgCrl) { crlBlob = CryptMemAlloc(sizeof(CRL_BLOB) * pSignPara->cMsgCrl); if (crlBlob) { for (i = 0; i < pSignPara->cMsgCrl; ++i) { crlBlob[i].cbData = pSignPara->rgpMsgCrl[i]->cbCrlEncoded; crlBlob[i].pbData = pSignPara->rgpMsgCrl[i]->pbCrlEncoded; } signInfo.cCrlEncoded = pSignPara->cMsgCrl; signInfo.rgCrlEncoded = crlBlob; } else ret = FALSE; } if (pSignPara->dwFlags || pSignPara->dwInnerContentType) FIXME("unimplemented feature\n");
if (ret) msg = CryptMsgOpenToEncode(pSignPara->dwMsgEncodingType, fDetachedSignature ? CMSG_DETACHED_FLAG : 0, CMSG_SIGNED, &signInfo, NULL, NULL); if (msg) { if (cToBeSigned) { for (i = 0; ret && i < cToBeSigned; ++i) { ret = CryptMsgUpdate(msg, rgpbToBeSigned[i], rgcbToBeSigned[i], i == cToBeSigned - 1); } } else ret = CryptMsgUpdate(msg, NULL, 0, TRUE); if (ret) ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, pbSignedBlob, pcbSignedBlob); CryptMsgClose(msg); } else ret = FALSE;
CryptMemFree(crlBlob); CryptMemFree(certBlob); if (freeProv) CryptReleaseContext(hCryptProv, 0); return ret;}
BOOL WINAPI CryptEncryptMessage(PCRYPT_ENCRYPT_MESSAGE_PARA pEncryptPara, DWORD cRecipientCert, PCCERT_CONTEXT rgpRecipientCert[], const BYTE *pbToBeEncrypted, DWORD cbToBeEncrypted, BYTE *pbEncryptedBlob, DWORD *pcbEncryptedBlob){ BOOL ret = TRUE; DWORD i; PCERT_INFO *certInfo = NULL; CMSG_ENVELOPED_ENCODE_INFO envelopedInfo; HCRYPTMSG msg = 0;
TRACE("(%p, %d, %p, %p, %d, %p, %p)\n", pEncryptPara, cRecipientCert, rgpRecipientCert, pbToBeEncrypted, cbToBeEncrypted, pbEncryptedBlob, pcbEncryptedBlob);
if (pEncryptPara->cbSize != sizeof(CRYPT_ENCRYPT_MESSAGE_PARA) || GET_CMSG_ENCODING_TYPE(pEncryptPara->dwMsgEncodingType) != PKCS_7_ASN_ENCODING) { *pcbEncryptedBlob = 0; SetLastError(E_INVALIDARG); return FALSE; }
memset(&envelopedInfo, 0, sizeof(envelopedInfo)); envelopedInfo.cbSize = sizeof(envelopedInfo); envelopedInfo.hCryptProv = pEncryptPara->hCryptProv; envelopedInfo.ContentEncryptionAlgorithm = pEncryptPara->ContentEncryptionAlgorithm; envelopedInfo.pvEncryptionAuxInfo = pEncryptPara->pvEncryptionAuxInfo;
if (cRecipientCert) { certInfo = CryptMemAlloc(sizeof(PCERT_INFO) * cRecipientCert); if (certInfo) { for (i = 0; i < cRecipientCert; ++i) certInfo[i] = rgpRecipientCert[i]->pCertInfo; envelopedInfo.cRecipients = cRecipientCert; envelopedInfo.rgpRecipientCert = certInfo; } else ret = FALSE; }
if (ret) msg = CryptMsgOpenToEncode(pEncryptPara->dwMsgEncodingType, 0, CMSG_ENVELOPED, &envelopedInfo, NULL, NULL); if (msg) { ret = CryptMsgUpdate(msg, pbToBeEncrypted, cbToBeEncrypted, TRUE); if (ret) ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, pbEncryptedBlob, pcbEncryptedBlob); CryptMsgClose(msg); } else ret = FALSE;
CryptMemFree(certInfo); if (!ret) *pcbEncryptedBlob = 0; return ret;}