| /* | |
| * 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; | |
| } |