/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Microsoft Windows, Copyright (C) Microsoft Corporation, 2000 - 2001. File: MsgHlpr.cpp Content: Helper functions for messaging. History: 11-15-99 dsie created ------------------------------------------------------------------------------*/ #include "StdAfx.h" #include "CAPICOM.h" #include "MsgHlpr.h" //////////////////////////////////////////////////////////////////////////////// // // Exported functions. // /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Function : GetMsgParam Synopsis : Allocate memory and retrieve requested message parameter using CryptGetMsgParam() API. Parameter: HCRYPTMSG hMsg - Message handler. DWORD dwMsgType - Message param type to retrieve. DWORD dwIndex - Index (should be 0 most of the time). void ** ppvData - Pointer to receive buffer. DWORD * pcbData - Size of buffer. Remark : ------------------------------------------------------------------------------*/ HRESULT GetMsgParam (HCRYPTMSG hMsg, DWORD dwMsgType, DWORD dwIndex, void ** ppvData, DWORD * pcbData) { HRESULT hr = S_OK; DWORD cbData = 0; void * pvData = NULL; DebugTrace("Entering GetMsgParam().\n"); // // Sanity check. // ATLASSERT(ppvData); ATLASSERT(pcbData); // // Determine data buffer size. // if (!::CryptMsgGetParam(hMsg, dwMsgType, dwIndex, NULL, &cbData)) { hr = HRESULT_FROM_WIN32(::GetLastError()); DebugTrace("Error [%#x]: CryptMsgGetParam() failed.\n", hr); goto ErrorExit; } // // Allocate memory for buffer. // if (!(pvData = (void *) ::CoTaskMemAlloc(cbData))) { hr = E_OUTOFMEMORY; DebugTrace("Error: out of memory.\n"); goto ErrorExit; } // // Now get the data. // if (!::CryptMsgGetParam(hMsg, dwMsgType, dwIndex, pvData, &cbData)) { hr = HRESULT_FROM_WIN32(::GetLastError()); DebugTrace("Error [%#x]: CryptMsgGetParam() failed.\n", hr); goto ErrorExit; } // // Return msg param to caller. // *ppvData = pvData; *pcbData = cbData; CommonExit: DebugTrace("Leaving GetMsgParam().\n"); return hr; ErrorExit: // // Sanity check. // ATLASSERT(FAILED(hr)); // // Free resources. // if (pvData) { ::CoTaskMemFree(pvData); } goto CommonExit; } /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Function : FindSignerCertInMessage Synopsis : Find the signer's cert in the bag of certs of the message for the specified signer. Parameter: HCRYPTMSG hMsg - Message handle. CERT_NAME_BLOB * pIssuerNameBlob - Pointer to issuer' name blob of signer's cert. CRYPT_INTEGERT_BLOB * pSerialNumberBlob - Pointer to serial number blob of signer's cert. PCERT_CONTEXT * ppCertContext - Pointer to PCERT_CONTEXT to receive the found cert, or NULL to only know the result. Remark : ------------------------------------------------------------------------------*/ HRESULT FindSignerCertInMessage (HCRYPTMSG hMsg, CERT_NAME_BLOB * pIssuerNameBlob, CRYPT_INTEGER_BLOB * pSerialNumberBlob, PCERT_CONTEXT * ppCertContext) { HRESULT hr = S_OK; DWORD dwCertCount = 0; DWORD cbCertCount = sizeof(dwCertCount); DebugTrace("Entering FindSignerCertInMessage().\n"); // // Sanity check. // ATLASSERT(NULL != hMsg); ATLASSERT(NULL != pIssuerNameBlob); ATLASSERT(NULL != pSerialNumberBlob); ATLASSERT(0 < pIssuerNameBlob->cbData); ATLASSERT(NULL != pIssuerNameBlob->pbData); ATLASSERT(0 < pSerialNumberBlob->cbData); ATLASSERT(NULL != pSerialNumberBlob->pbData); // // Get count of certs in message. // if (!::CryptMsgGetParam(hMsg, CMSG_CERT_COUNT_PARAM, 0, &dwCertCount, &cbCertCount)) { hr = HRESULT_FROM_WIN32(::GetLastError()); DebugTrace("Error [%#x]: CryptMsgGetParam() failed.\n", hr); return hr; } // // See if the signer's cert is in the bag of certs. // while (dwCertCount--) { PCCERT_CONTEXT pCertContext = NULL; CRYPT_DATA_BLOB EncodedCertBlob = {0, NULL}; // // Get a cert from the bag of certs. // hr = ::GetMsgParam(hMsg, CMSG_CERT_PARAM, dwCertCount, (void **) &EncodedCertBlob.pbData, &EncodedCertBlob.cbData); if (FAILED(hr)) { DebugTrace("Error [%#x]: GetMsgParam() failed.\n", hr); return hr; } // // Create a context for the cert. // pCertContext = ::CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, (const BYTE *) EncodedCertBlob.pbData, EncodedCertBlob.cbData); // // Free encoded cert blob memory before checking result. // ::CoTaskMemFree((LPVOID) EncodedCertBlob.pbData); if (NULL == pCertContext) { hr = HRESULT_FROM_WIN32(::GetLastError()); DebugTrace("Error [%#x]: CertCreateCertificateContext() failed.\n", hr); return hr; } // // Compare. // if (::CertCompareCertificateName(CAPICOM_ASN_ENCODING, pIssuerNameBlob, &pCertContext->pCertInfo->Issuer) && ::CertCompareIntegerBlob(pSerialNumberBlob, &pCertContext->pCertInfo->SerialNumber)) { if (NULL != ppCertContext) { *ppCertContext = (PCERT_CONTEXT) pCertContext; } else { ::CertFreeCertificateContext(pCertContext); } return S_OK; } else { // // No, keep looking. // ::CertFreeCertificateContext(pCertContext); } } // // If we get here, that means we never found the cert. // return CAPICOM_E_SIGNER_NOT_FOUND; }