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, ¶)) 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; }
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, ¶); 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; }
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; }
/*cert obj must be freed*/ static int extractSigningCertificate(const KSI_PKISignature *signature, PCCERT_CONTEXT *cert) { int res = KSI_UNKNOWN_ERROR; KSI_CTX *ctx = NULL; HCERTSTORE certStore = NULL; DWORD signerCount = 0; PCERT_INFO pSignerCertInfo = NULL; HCRYPTMSG signaturMSG = NULL; PCCERT_CONTEXT signing_cert = NULL; BYTE *dataRecieved = NULL; char buf[1024]; DWORD dataLen = 0; if (signature == NULL || cert == NULL){ res = KSI_INVALID_ARGUMENT; goto cleanup; } ctx = signature->ctx; KSI_ERR_clearErrors(ctx); /*Get Signature certificates as a certificate store*/ certStore = CryptGetMessageCertificates(PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, (HCRYPTPROV_LEGACY)NULL, 0, signature->pkcs7.pbData, signature->pkcs7.cbData); if (certStore == NULL){ KSI_LOG_debug(signature->ctx, "%s", getMSError(GetLastError(), buf, sizeof(buf))); KSI_pushError(ctx, res = KSI_INVALID_FORMAT, "Unable to get signatures PKI certificates."); goto cleanup; } /*Counting signing certificates*/ signerCount = CryptGetMessageSignerCount(PKCS_7_ASN_ENCODING, signature->pkcs7.pbData, signature->pkcs7.cbData); if (signerCount == -1){ KSI_LOG_debug(signature->ctx, "%s", getMSError(GetLastError(), buf, sizeof(buf))); KSI_pushError(ctx, res = KSI_INVALID_FORMAT, "Unable to count PKI signatures certificates."); goto cleanup; } /*Is there exactly 1 signing cert?*/ if (signerCount != 1){ KSI_pushError(ctx, res = KSI_INVALID_FORMAT, "PKI signature certificate count is not 1."); goto cleanup; } /*Open signature for decoding*/ signaturMSG = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0,0, NULL, NULL); if (signaturMSG == NULL){ DWORD error = GetLastError(); const char *errmsg = getMSError(GetLastError(), buf, sizeof(buf)); KSI_LOG_debug(signature->ctx, "%s", errmsg); if (error == E_INVALIDARG) KSI_pushError(ctx, res = KSI_INVALID_FORMAT, errmsg); else if (error == E_OUTOFMEMORY) KSI_pushError(ctx, res = KSI_OUT_OF_MEMORY, NULL); else KSI_pushError(ctx, res = KSI_UNKNOWN_ERROR, errmsg); goto cleanup; } if (!CryptMsgUpdate(signaturMSG, signature->pkcs7.pbData, signature->pkcs7.cbData, TRUE)){ DWORD error = GetLastError(); const char *errmsg = getMSError(GetLastError(), buf, sizeof(buf)); KSI_LOG_debug(signature->ctx, "%s", errmsg); if (error == E_OUTOFMEMORY) KSI_pushError(ctx, res = KSI_OUT_OF_MEMORY, NULL); else if (error == CRYPT_E_UNEXPECTED_ENCODING) KSI_pushError(ctx, res = KSI_INVALID_FORMAT, "The PKI signature is not encoded as PKCS7."); else if (error == CRYPT_E_MSG_ERROR) KSI_pushError(ctx, res = KSI_CRYPTO_FAILURE, errmsg); else KSI_pushError(ctx, res = KSI_UNKNOWN_ERROR, errmsg); goto cleanup; } /*Get signatures signing cert id*/ if (!CryptMsgGetParam (signaturMSG, CMSG_SIGNER_CERT_INFO_PARAM, 0, NULL, &dataLen)){ DWORD error = GetLastError(); const char *errmsg = getMSError(GetLastError(), buf, sizeof(buf)); KSI_LOG_debug(signature->ctx, "%s", errmsg); if (error == CRYPT_E_ATTRIBUTES_MISSING) KSI_pushError(ctx, res = KSI_INVALID_FORMAT, "The PKI signature does not contain signing certificate id."); else KSI_pushError(ctx, res = KSI_INVALID_FORMAT, errmsg); goto cleanup; } dataRecieved = KSI_malloc(dataLen); if (dataRecieved == NULL){ KSI_pushError(ctx, res = KSI_OUT_OF_MEMORY, NULL); goto cleanup; } if (!CryptMsgGetParam (signaturMSG, CMSG_SIGNER_CERT_INFO_PARAM, 0, dataRecieved, &dataLen)){ KSI_LOG_debug(signature->ctx, "%s", getMSError(GetLastError(), buf, sizeof(buf))); KSI_pushError(ctx, res = KSI_INVALID_FORMAT, "Unable to get PKI signatures signing certificate id."); goto cleanup; } pSignerCertInfo = (PCERT_INFO)dataRecieved; /*Get signing cert*/ signing_cert = CertGetSubjectCertificateFromStore(certStore, X509_ASN_ENCODING, pSignerCertInfo); if (signing_cert == NULL){ KSI_LOG_debug(signature->ctx, "%s", getMSError(GetLastError(), buf, sizeof(buf))); KSI_pushError(ctx, res = KSI_CRYPTO_FAILURE, "Unable to get PKI signatures signer certificate."); goto cleanup; } /*The copy of the object is NOT created. Just its reference value is incremented*/ signing_cert = CertDuplicateCertificateContext(signing_cert); *cert = signing_cert; signing_cert = NULL; res = KSI_OK; cleanup: if (signing_cert) CertFreeCertificateContext(signing_cert); if (certStore) CertCloseStore(certStore, CERT_CLOSE_STORE_CHECK_FLAG); if (signaturMSG) CryptMsgClose(signaturMSG); KSI_free(dataRecieved); return res; }
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); } }