Exemple #1
0
static BOOL WINTRUST_VerifySigner(CRYPT_PROVIDER_DATA *data, DWORD signerIdx)
{
    BOOL ret;
    CERT_INFO *certInfo = WINTRUST_GetSignerCertInfo(data, signerIdx);

    if (certInfo)
    {
        PCCERT_CONTEXT subject = CertGetSubjectCertificateFromStore(
         data->pahStores[0], data->dwEncoding, certInfo);

        if (subject)
        {
            CMSG_CTRL_VERIFY_SIGNATURE_EX_PARA para = { sizeof(para), 0,
             signerIdx, CMSG_VERIFY_SIGNER_CERT, (LPVOID)subject };

            ret = CryptMsgControl(data->hMsg, 0, CMSG_CTRL_VERIFY_SIGNATURE_EX,
             &para);
            if (!ret)
                SetLastError(TRUST_E_CERT_SIGNATURE);
            else
                data->psPfns->pfnAddCert2Chain(data, signerIdx, FALSE, 0,
                 subject);
            CertFreeCertificateContext(subject);
        }
        else
        {
            SetLastError(TRUST_E_NO_SIGNER_CERT);
            ret = FALSE;
        }
        data->psPfns->pfnFree(certInfo);
    }
    else
        ret = FALSE;
    return ret;
}
Exemple #2
0
static DWORD WINTRUST_VerifySigner(CRYPT_PROVIDER_DATA *data, DWORD signerIdx)
{
    DWORD err;
    CERT_INFO *certInfo = WINTRUST_GetSignerCertInfo(data, signerIdx);

    if (certInfo)
    {
        PCCERT_CONTEXT subject = CertGetSubjectCertificateFromStore(
         data->pahStores[0], data->dwEncoding, certInfo);

        if (subject)
        {
            CMSG_CTRL_VERIFY_SIGNATURE_EX_PARA para = { sizeof(para), 0,
             signerIdx, CMSG_VERIFY_SIGNER_CERT, (LPVOID)subject };

            if (!CryptMsgControl(data->hMsg, 0, CMSG_CTRL_VERIFY_SIGNATURE_EX,
             &para))
                err = TRUST_E_CERT_SIGNATURE;
            else
            {
                data->psPfns->pfnAddCert2Chain(data, signerIdx, FALSE, 0,
                 subject);
                err = ERROR_SUCCESS;
            }
            CertFreeCertificateContext(subject);
        }
        else
            err = TRUST_E_NO_SIGNER_CERT;
        data->psPfns->pfnFree(certInfo);
    }
    else
        err = GetLastError();
    return err;
}
Exemple #3
0
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;
}
Exemple #4
0
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;
}
DWORD do_low_verify (const char *infile, const char *outfile)
{
    HCRYPTPROV hCryptProv = 0;               // CSP handle
    PCCERT_CONTEXT pUserCert = NULL;		// User certificate to be used
    DWORD ret = 1;
    FILE *tbs = NULL;
    BYTE *mem_tbs = NULL;
    DWORD mem_len = 0;
    FILE *signature = NULL;
    BYTE *mem_signature = NULL;
    DWORD signature_len = 0;
	HCRYPTMSG hMsg = 0;
	
    DWORD cbDecoded;
    BYTE *pbDecoded;
    DWORD cbSignerCertInfo;
    PCERT_INFO pSignerCertInfo;
    PCCERT_CONTEXT pSignerCertContext;
    PCERT_INFO pSignerCertificateInfo;
    HCERTSTORE hStoreHandle = NULL;
	
    if (! infile) {
		fprintf (stderr, "No input file was specified\n");
		goto err;
    }
	
	
    tbs = fopen (infile, "rb");
    if (!tbs) {
		fprintf (stderr, "Cannot open input file\n");
		goto err;
    }
	
    mem_len = 0;
    while (!feof(tbs)) {
		int r = 0;
		BYTE tmp[1024];
		r = fread (tmp, 1, 1024, tbs);
		mem_tbs = (BYTE *)realloc (mem_tbs, mem_len+r);
		memcpy (&mem_tbs[mem_len], tmp, r);
		mem_len += r;
    }
    fclose (tbs);
    tbs = NULL;
	
	
    if (signature) {
		signature_len = 0;
		while (!feof(signature)) {
			int r = 0;
			BYTE tmp[1024];
			r = fread (tmp, 1, 1024, signature);
			mem_signature = (BYTE *)realloc (mem_signature , signature_len+r);
			memcpy (&mem_signature [signature_len], tmp, r);
			signature_len += r;
		}
		fclose (signature);
		signature = NULL;
    }
	
    //--------------------------------------------------------------------
    // Open a message for decoding.
    
    hMsg = CryptMsgOpenToDecode(
								TYPE_DER,      // Encoding type.
								0,                     // Flags.
								0,                     // Use the default message type.
								hCryptProv,            // Cryptographic provider.
								NULL,                  // Recipient information.
								NULL);                 // Stream information.
    if (hMsg) 
		printf("The message to decode is open. \n");
    else{
    	fprintf (stderr, "OpenToDecode failed");
		ret = CSP_GetLastError();
		goto err;
	}
    //--------------------------------------------------------------------
    // Update the message with an encoded blob.
    // Both pbEncodedBlob, the encoded data, 
    // and cbEnclodeBlob, the length of the encoded data,
    // must be available. 
    
	
    if (CryptMsgUpdate(
					   hMsg,                 // Handle to the message
					   mem_tbs,        // Pointer to the encoded blob
					   mem_len,        // Size of the encoded blob
					   TRUE)){               // Last call) 
		printf("The encoded blob has been added to the message. \n");
	}
    else { 
		
		fprintf (stderr, "Decode MsgUpdate failed");
		ret = CSP_GetLastError();
		goto err;
    }
    //--------------------------------------------------------------------
    // Get the size of the content.
    
    ret = CryptMsgGetParam(
						   hMsg,                  // Handle to the message
						   CMSG_CONTENT_PARAM,    // Parameter type
						   0,                     // Index
						   NULL,                  // Address for returned info
						   &cbDecoded);           // Size of the returned info
    if (ret)
		printf("The message parameter (CMSG_CONTENT_PARAM) has been acquired. Message size: %d\n", cbDecoded);
    else{
		fprintf (stderr, "Decode CMSG_CONTENT_PARAM failed");
		ret = CSP_GetLastError();
		goto err;
	}
    //--------------------------------------------------------------------
    // Allocate memory.
    
    pbDecoded = (BYTE *) malloc(cbDecoded);
    if (!pbDecoded){
		
		fprintf (stderr, "Decode memory allocation failed");
		ret = CSP_GetLastError();
		goto err;
	}
    //--------------------------------------------------------------------
    // Get a pointer to the content.
    
    ret = CryptMsgGetParam(
						   hMsg,                 // Handle to the message
						   CMSG_CONTENT_PARAM,   // Parameter type
						   0,                    // Index
						   pbDecoded,            // Address for returned 
						   &cbDecoded);          // Size of the returned        
    if (ret)
		printf("The message param (CMSG_CONTENT_PARAM) updated. Length is %lu.\n",(unsigned long)cbDecoded);
    else{
		
		fprintf (stderr, "Decode CMSG_CONTENT_PARAM #2 failed");
		ret = CSP_GetLastError();
		goto err;
	}
    //--------------------------------------------------------------------
    // Verify the signature.
    // First, get the signer CERT_INFO from the message.
    
    //--------------------------------------------------------------------
    // Get the size of memory required.
	
    if (! pUserCert) { 
		ret = CryptMsgGetParam(
							   hMsg,                         // Handle to the message
							   CMSG_SIGNER_CERT_INFO_PARAM,  // Parameter type
							   0,                            // Index
							   NULL,                        // Address for returned 
							   &cbSignerCertInfo);          // Size of the returned 
		if (ret)
			printf("Try to get user cert. OK. Length %d.\n",cbSignerCertInfo);
		else {
			printf("No user certificate found in message.\n");
		}
    }
	
    if (pUserCert) {
		hStoreHandle = CertOpenStore(CERT_STORE_PROV_MEMORY, TYPE_DER, 0, CERT_STORE_CREATE_NEW_FLAG,NULL);
		if (!hStoreHandle){
			printf("Cannot create temporary store in memory.");
		    return CSP_GetLastError();
		}
		if (pUserCert) {
			ret = CertAddCertificateContextToStore(hStoreHandle, pUserCert, CERT_STORE_ADD_ALWAYS, NULL);
			pSignerCertInfo = pUserCert->pCertInfo;
		}
		else
			ret = 0;
		if (!ret){
			printf("Cannot add user certificate to store.");
			return CSP_GetLastError();
		}
    }
    
    //--------------------------------------------------------------------
    // Allocate memory.
    
    if (!pUserCert) {
		pSignerCertInfo = (PCERT_INFO) malloc(cbSignerCertInfo);
		if (!pSignerCertInfo){
			printf("Verify memory allocation failed");
			return CSP_GetLastError();
		}
    }
    
    //--------------------------------------------------------------------
    // Get the message certificate information (CERT_INFO
    // structure).
    
    if (! pUserCert) {
		ret = CryptMsgGetParam(
							   hMsg,                         // Handle to the message
							   CMSG_SIGNER_CERT_INFO_PARAM,  // Parameter type
							   0,                            // Index
							   pSignerCertInfo,              // Address for returned 
							   &cbSignerCertInfo);           // Size of the returned 
	    if (ret) 
			printf("The signer info has been returned. \n");
	    else{
			printf("Verify SIGNER_CERT_INFO #2 failed");
			return CSP_GetLastError();
		}
    }
    //--------------------------------------------------------------------
    // Open a certificate store in memory using CERT_STORE_PROV_MSG,
    // which initializes it with the certificates from the message.
    
    if (! hStoreHandle) {
		hStoreHandle = CertOpenStore(
									 CERT_STORE_PROV_MSG,        // Store provider type 
									 TYPE_DER,		    // Encoding type
									 hCryptProv,                 // Cryptographic provider
									 0,                          // Flags
									 hMsg);                      // Handle to the message
		if (hStoreHandle)
			printf("The message certificate store be used for verifying\n");
    }
	
    if (! hStoreHandle) {
	    printf("Cannot open certificate store form message\n");
		return CSP_GetLastError();
    }
    //--------------------------------------------------------------------
    // Find the signer's certificate in the store.
    
    if(pSignerCertContext = CertGetSubjectCertificateFromStore(
															   hStoreHandle,       // Handle to store
															   TYPE_DER,   // Encoding type
															   pSignerCertInfo))   // Pointer to retrieved CERT_CONTEXT
    {
		DWORD errCode=0;
		DWORD err;
		printf("A signer certificate has been retrieved. \n");
		err=VerifyCertificate(pSignerCertContext,&errCode);
		if (err)
		{
			printf("Subject cert verification failed: err=%x\n",err);
			return err;
		}
		if (errCode)
		{
			printf("Subject cert BAD: errCode=%x\n",errCode);
			return errCode;
		}
	}
    else
    {
		printf("Verify GetSubjectCert failed");
		return CSP_GetLastError();
    }
    //--------------------------------------------------------------------
    // Use the CERT_INFO from the signer certificate to verify
    // the signature.

    
    pSignerCertificateInfo = pSignerCertContext->pCertInfo;
    if(CryptMsgControl(
					   hMsg,                       // Handle to the message
					   0,                          // Flags
					   CMSG_CTRL_VERIFY_SIGNATURE, // Control type
					   pSignerCertificateInfo))    // Pointer to the CERT_INFO
    {
		printf("\nSignature was VERIFIED.\n");
    }
    else
    {
		printf("\nThe signature was NOT VEIFIED.\n");
    }
    if(hStoreHandle)
		CertCloseStore(hStoreHandle, CERT_CLOSE_STORE_FORCE_FLAG);
	
	ret = 0;
err:
    return ret;
	
}
Exemple #6
0
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;
}
Exemple #7
0
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;
}
Exemple #8
0
void DecodeMessage(PCRYPT_DATA_BLOB pEncodedBlob,
                   LPWSTR pwszSignerName)
{
    //---------------------------------------------------------------
    //    Buffer to hold the name of the subject of a certificate.

    wchar_t pszNameString[MAX_NAME];

    //---------------------------------------------------------------
    //  The following variables are used only in the decoding phase.

    HCRYPTMSG hMsg;
    HCERTSTORE hStoreHandle;           // certificate store handle
    DWORD cbData = sizeof(DWORD);
    DWORD cbDecoded;
    BYTE *pbDecoded;
    DWORD cbSignerCertInfo;
    PCERT_INFO pSignerCertInfo;
    PCCERT_CONTEXT pSignerCertContext;

    /*---------------------------------------------------------------
        The following code decodes the message and verifies the 
        message signature.  This code would normally be in a 
        stand-alone program that would read the signed and encoded 
        message and its length from a file from an email message, 
        or from some other source.
    ---------------------------------------------------------------*/

    //---------------------------------------------------------------
    //  Open a message for decoding.

    if(hMsg = CryptMsgOpenToDecode(
        MY_ENCODING_TYPE,      // encoding type
        0,                     // flags
        0,                     // use the default message type
                               // the message type is 
                               // listed in the message header
        NULL,                  // cryptographic provider 
                               // use NULL for the default provider
        NULL,                  // recipient information
        NULL))                 // stream information
    {
        printf("The message to decode is open. \n");
    }
    else
    {
        MyHandleError("OpenToDecode failed");
    }
    //---------------------------------------------------------------
    //  Update the message with an encoded BLOB.

    if(CryptMsgUpdate(
        hMsg,                 // handle to the message
        pEncodedBlob->pbData, // pointer to the encoded BLOB
        pEncodedBlob->cbData, // size of the encoded BLOB
        TRUE))                // last call
    {
        printf("The encoded BLOB has been added to the message. \n");
    }
    else
    {
        MyHandleError("Decode MsgUpdate failed");
    }

    //---------------------------------------------------------------
    //  Get the number of bytes needed for a buffer
    //  to hold the decoded message.

    if(CryptMsgGetParam(
        hMsg,                  // handle to the message
        CMSG_CONTENT_PARAM,    // parameter type
        0,                     // index
        NULL,                  
        &cbDecoded))           // size of the returned information
    {
        printf("The message parameter has been acquired. \n");
    }
    else
    {
        MyHandleError("Decode CMSG_CONTENT_PARAM failed.");
    }
    //---------------------------------------------------------------
    // Allocate memory.

    if(!(pbDecoded = (BYTE *) malloc(cbDecoded)))
    {
        MyHandleError("Decode memory allocation failed.");
    }

    //---------------------------------------------------------------
    // Copy the content to the buffer.

    if(CryptMsgGetParam(
        hMsg,                 // handle to the message
        CMSG_CONTENT_PARAM,   // parameter type
        0,                    // index
        pbDecoded,            // address for returned information
        &cbDecoded))          // size of the returned information
    {
        printf("The decoded message is =>\n%s\n\n",
            (LPSTR)pbDecoded);
    }
    else
    {
        MyHandleError("Decode CMSG_CONTENT_PARAM #2 failed");
    }

    //---------------------------------------------------------------
    // Verify the signature.
    // First, get the signer CERT_INFO from the message.

    //---------------------------------------------------------------
    // Get the size of memory required for the certificate.

    if(CryptMsgGetParam(
        hMsg,                         // handle to the message
        CMSG_SIGNER_CERT_INFO_PARAM,  // parameter type
        0,                            // index
        NULL,   
        &cbSignerCertInfo))           // size of the returned 
                                      // information
    {
        printf("%d bytes needed for the buffer.\n", 
            cbSignerCertInfo);
    }
    else
    {
        MyHandleError("Verify SIGNER_CERT_INFO #1 failed.");
    }

    //---------------------------------------------------------------
    // Allocate memory.

    if(!(pSignerCertInfo = (PCERT_INFO) malloc(cbSignerCertInfo)))
    {
        MyHandleError("Verify memory allocation failed.");
    }

    //---------------------------------------------------------------
    // Get the message certificate information (CERT_INFO
    // structure).

    if(!(CryptMsgGetParam(
        hMsg,                         // handle to the message
        CMSG_SIGNER_CERT_INFO_PARAM,  // parameter type
        0,                            // index
        pSignerCertInfo,              // address for returned 
                                      // information
        &cbSignerCertInfo)))          // size of the returned 
                                      // information
    {
        MyHandleError("Verify SIGNER_CERT_INFO #2 failed");
    }

    //---------------------------------------------------------------
    // Open a certificate store in memory using CERT_STORE_PROV_MSG,
    // which initializes it with the certificates from the message.

    if(hStoreHandle = CertOpenStore(
        CERT_STORE_PROV_MSG,         // store provider type 
        MY_ENCODING_TYPE,            // encoding type
        NULL,                        // cryptographic provider
                                     // use NULL for the default
        0,                           // flags
        hMsg))                       // handle to the message
    {
        printf("The certificate store to be used for message " \
            "verification has been opened.\n");
    }
    else  
    {
        MyHandleError("Verify open store failed");
    }

    //---------------------------------------------------------------
    // Find the signer's certificate in the store.

    if(pSignerCertContext = CertGetSubjectCertificateFromStore(
        hStoreHandle,       // handle to the store
        MY_ENCODING_TYPE,   // encoding type
        pSignerCertInfo))   // pointer to retrieved CERT_CONTEXT
    {
        if(CertGetNameString(
            pSignerCertContext,
            CERT_NAME_SIMPLE_DISPLAY_TYPE,
            0,
            NULL,
            pszNameString,
            MAX_NAME) > 1)
        {
            wprintf(L"The message signer is  %s \n",pszNameString);
        }
        else
        {
            MyHandleError("Getting the signer's name failed.\n");
        }
    }
    else
    {
        MyHandleError("Verify GetSubjectCert failed");
    }

    //---------------------------------------------------------------
    // Use the CERT_INFO from the signer certificate to verify
    // the signature.

    if(CryptMsgControl(
        hMsg,
        0,
        CMSG_CTRL_VERIFY_SIGNATURE,
        pSignerCertContext->pCertInfo))
    {
        printf("Verify signature succeeded. \n");


    }
    else
    {
        printf("The signature was not verified. \n");
		DWORD const errcode = GetLastError();
		std::wcerr << format_sys_message<TCHAR>(errcode) << TEXT("\n"); 

        ReportFailure();
    }
    //---------------------------------------------------------------
    // Clean up.
    if(pEncodedBlob->pbData)
    {
        free(pEncodedBlob->pbData);
        pEncodedBlob->pbData = NULL;
    }
    if(pbDecoded)
    {
        free(pbDecoded);
    }
    if(pSignerCertInfo)
    {
        free(pSignerCertInfo);
    }
    if(pSignerCertContext)
    {
        CertFreeCertificateContext(pSignerCertContext); 
    }
    if(hStoreHandle)
    {
        CertCloseStore(hStoreHandle, CERT_CLOSE_STORE_FORCE_FLAG);
    }
    if(hMsg)
    {
        CryptMsgClose(hMsg);
    }
}