/*********************************************************************** * CryptCATOpen (WINTRUST.@) */ HANDLE WINAPI CryptCATOpen(LPWSTR pwszFileName, DWORD fdwOpenFlags, HCRYPTPROV hProv, DWORD dwPublicVersion, DWORD dwEncodingType) { HANDLE file, hmsg; BYTE *buffer = NULL; DWORD size, flags = OPEN_EXISTING; struct cryptcat *cc; TRACE("%s, %x, %lx, %x, %x\n", debugstr_w(pwszFileName), fdwOpenFlags, hProv, dwPublicVersion, dwEncodingType); if (!pwszFileName) { SetLastError(ERROR_INVALID_PARAMETER); return INVALID_HANDLE_VALUE; } if (!dwPublicVersion) dwPublicVersion = 0x00000100; if (!dwEncodingType) dwEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING; if (fdwOpenFlags & CRYPTCAT_OPEN_ALWAYS) flags |= OPEN_ALWAYS; if (fdwOpenFlags & CRYPTCAT_OPEN_CREATENEW) flags |= CREATE_NEW; file = CreateFileW(pwszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, flags, 0, NULL); if (file == INVALID_HANDLE_VALUE) return INVALID_HANDLE_VALUE; size = GetFileSize(file, NULL); if (!(buffer = HeapAlloc(GetProcessHeap(), 0, size))) { CloseHandle(file); SetLastError(ERROR_OUTOFMEMORY); return INVALID_HANDLE_VALUE; } if (!(hmsg = CryptMsgOpenToDecode(dwEncodingType, 0, 0, hProv, NULL, NULL))) { CloseHandle(file); HeapFree(GetProcessHeap(), 0, buffer); return INVALID_HANDLE_VALUE; } if (!ReadFile(file, buffer, size, &size, NULL) || !CryptMsgUpdate(hmsg, buffer, size, TRUE)) { CloseHandle(file); HeapFree(GetProcessHeap(), 0, buffer); CryptMsgClose(hmsg); return INVALID_HANDLE_VALUE; } HeapFree(GetProcessHeap(), 0, buffer); CloseHandle(file); size = sizeof(DWORD); if (!(cc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*cc)))) { CryptMsgClose(hmsg); SetLastError(ERROR_OUTOFMEMORY); return INVALID_HANDLE_VALUE; } cc->msg = hmsg; cc->encoding = dwEncodingType; if (CryptMsgGetParam(hmsg, CMSG_ATTR_CERT_COUNT_PARAM, 0, &cc->attr_count, &size)) { DWORD i, sum = 0; BYTE *p; for (i = 0; i < cc->attr_count; i++) { if (!CryptMsgGetParam(hmsg, CMSG_ATTR_CERT_PARAM, i, NULL, &size)) { CryptMsgClose(hmsg); return INVALID_HANDLE_VALUE; } sum += size; } if (!(cc->attr = HeapAlloc(GetProcessHeap(), 0, sizeof(*cc->attr) * cc->attr_count + sum))) { CryptMsgClose(hmsg); SetLastError(ERROR_OUTOFMEMORY); return INVALID_HANDLE_VALUE; } p = (BYTE *)(cc->attr + cc->attr_count); for (i = 0; i < cc->attr_count; i++) { if (!CryptMsgGetParam(hmsg, CMSG_ATTR_CERT_PARAM, i, NULL, &size)) { CryptMsgClose(hmsg); HeapFree(GetProcessHeap(), 0, cc->attr); return INVALID_HANDLE_VALUE; } if (!CryptMsgGetParam(hmsg, CMSG_ATTR_CERT_PARAM, i, p, &size)) { CryptMsgClose(hmsg); HeapFree(GetProcessHeap(), 0, cc->attr); return INVALID_HANDLE_VALUE; } p += size; } cc->inner = decode_inner_content(hmsg, dwEncodingType, &cc->inner_len); if (!cc->inner || !CryptSIPRetrieveSubjectGuid(pwszFileName, NULL, &cc->subject)) { CryptMsgClose(hmsg); HeapFree(GetProcessHeap(), 0, cc->attr); HeapFree(GetProcessHeap(), 0, cc->inner); HeapFree(GetProcessHeap(), 0, cc); return INVALID_HANDLE_VALUE; } cc->magic = CRYPTCAT_MAGIC; return cc; } return INVALID_HANDLE_VALUE; }
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; }
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; }
PCCTL_CONTEXT WINAPI CertCreateCTLContext(DWORD dwMsgAndCertEncodingType, const BYTE *pbCtlEncoded, DWORD cbCtlEncoded) { PCTL_CONTEXT ctl = NULL; HCRYPTMSG msg; BOOL ret; BYTE *content = NULL; DWORD contentSize = 0, size; PCTL_INFO ctlInfo = NULL; TRACE("(%08x, %p, %d)\n", dwMsgAndCertEncodingType, pbCtlEncoded, cbCtlEncoded); if (GET_CERT_ENCODING_TYPE(dwMsgAndCertEncodingType) != X509_ASN_ENCODING) { SetLastError(E_INVALIDARG); return NULL; } if (!pbCtlEncoded || !cbCtlEncoded) { SetLastError(ERROR_INVALID_DATA); return NULL; } msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, 0, 0, 0, NULL, NULL); if (!msg) return NULL; ret = CryptMsgUpdate(msg, pbCtlEncoded, cbCtlEncoded, TRUE); if (!ret) { SetLastError(ERROR_INVALID_DATA); goto end; } /* Check that it's really a CTL */ ret = CryptMsgGetParam(msg, CMSG_INNER_CONTENT_TYPE_PARAM, 0, NULL, &size); if (ret) { char *innerContent = CryptMemAlloc(size); if (innerContent) { ret = CryptMsgGetParam(msg, CMSG_INNER_CONTENT_TYPE_PARAM, 0, innerContent, &size); if (ret) { if (strcmp(innerContent, szOID_CTL)) { SetLastError(ERROR_INVALID_DATA); ret = FALSE; } } CryptMemFree(innerContent); } else { SetLastError(ERROR_OUTOFMEMORY); ret = FALSE; } } if (!ret) goto end; ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, NULL, &contentSize); if (!ret) goto end; content = CryptMemAlloc(contentSize); if (content) { ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, content, &contentSize); if (ret) { ret = CryptDecodeObjectEx(dwMsgAndCertEncodingType, PKCS_CTL, content, contentSize, CRYPT_DECODE_ALLOC_FLAG, NULL, &ctlInfo, &size); if (ret) { ctl = Context_CreateDataContext(sizeof(CTL_CONTEXT)); if (ctl) { BYTE *data = CryptMemAlloc(cbCtlEncoded); if (data) { memcpy(data, pbCtlEncoded, cbCtlEncoded); ctl->dwMsgAndCertEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING; ctl->pbCtlEncoded = data; ctl->cbCtlEncoded = cbCtlEncoded; ctl->pCtlInfo = ctlInfo; ctl->hCertStore = NULL; ctl->hCryptMsg = msg; ctl->pbCtlContext = content; ctl->cbCtlContext = contentSize; } else { SetLastError(ERROR_OUTOFMEMORY); ret = FALSE; } } else { SetLastError(ERROR_OUTOFMEMORY); ret = FALSE; } } } } else { SetLastError(ERROR_OUTOFMEMORY); ret = FALSE; } end: if (!ret) { CertFreeCTLContext(ctl); ctl = NULL; LocalFree(ctlInfo); CryptMemFree(content); CryptMsgClose(msg); } return ctl; }
LPTSTR CPublisherHelp::GetSigningName(const WCHAR* szFileName){ HCERTSTORE hStore = NULL; HCRYPTMSG hMsg = NULL; PCCERT_CONTEXT pCertContext = NULL; BOOL fResult; DWORD dwEncoding, dwContentType, dwFormatType; PCMSG_SIGNER_INFO pSignerInfo = NULL; PCMSG_SIGNER_INFO pCounterSignerInfo = NULL; DWORD dwSignerInfo; CERT_INFO CertInfo; SPROG_PUBLISHERINFO ProgPubInfo; ZeroMemory(&ProgPubInfo, sizeof(ProgPubInfo)); __try{ fResult = CryptQueryObject(CERT_QUERY_OBJECT_FILE, szFileName, CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED, CERT_QUERY_FORMAT_FLAG_BINARY, 0, &dwEncoding, &dwContentType, &dwFormatType, &hStore, &hMsg, NULL); if (!fResult) { return NULL; } // Get signer information size. fResult = CryptMsgGetParam(hMsg, CMSG_SIGNER_INFO_PARAM, 0, NULL, &dwSignerInfo); if (!fResult) { return NULL; } pSignerInfo = (PCMSG_SIGNER_INFO)LocalAlloc(LPTR, dwSignerInfo); if (!pSignerInfo) { return NULL; } // Get Signer Information. fResult = CryptMsgGetParam(hMsg, CMSG_SIGNER_INFO_PARAM, 0, (PVOID)pSignerInfo, &dwSignerInfo); if (!fResult) { return NULL; } // Get program name and publisher information from // signer info structure. if (GetProgAndPublisherInfo(pSignerInfo, &ProgPubInfo)) { } else{ return NULL; } // Search for the signer certificate in the temporary // certificate store. CertInfo.Issuer = pSignerInfo->Issuer; CertInfo.SerialNumber = pSignerInfo->SerialNumber; pCertContext = CertFindCertificateInStore(hStore, ENCODING, 0, CERT_FIND_SUBJECT_CERT, (PVOID)&CertInfo, NULL); if (!pCertContext) { return NULL; } // Print Signer certificate information. LPTSTR szName = NULL; DWORD dwData; // Get Subject name size. if (!(dwData = CertGetNameString(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, NULL, 0))) { return NULL; } // Allocate memory for subject name. szName = (LPTSTR)LocalAlloc(LPTR, dwData * sizeof(TCHAR)); if (!szName) { return NULL; } // Get subject name. if (!(CertGetNameString(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, szName, dwData))) { return NULL; } // Print Subject Name. return szName; } __finally { if (ProgPubInfo.lpszProgramName != NULL) LocalFree(ProgPubInfo.lpszProgramName); if (ProgPubInfo.lpszPublisherLink != NULL) LocalFree(ProgPubInfo.lpszPublisherLink); if (ProgPubInfo.lpszMoreInfoLink != NULL) LocalFree(ProgPubInfo.lpszMoreInfoLink); if (pSignerInfo != NULL) LocalFree(pSignerInfo); if (pCounterSignerInfo != NULL) LocalFree(pCounterSignerInfo); if (pCertContext != NULL) CertFreeCertificateContext(pCertContext); if (hStore != NULL) CertCloseStore(hStore, 0); if (hMsg != NULL) CryptMsgClose(hMsg); } return NULL; }
/*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; }
PyCRYPTMSG::~PyCRYPTMSG(void) { if (hcryptmsg!=NULL) CryptMsgClose(hcryptmsg); Py_XDECREF(this->obcryptmsg); }
/** * Checks to see if a file stored at filePath matches the specified info. * * @param filePath The PE file path to check * @param infoToMatch The acceptable information to match * @return ERROR_SUCCESS if successful, ERROR_NOT_FOUND if the info * does not match, or the last error otherwise. */ DWORD CheckCertificateForPEFile(LPCWSTR filePath, CertificateCheckInfo &infoToMatch) { HCERTSTORE certStore = nullptr; HCRYPTMSG cryptMsg = nullptr; PCCERT_CONTEXT certContext = nullptr; PCMSG_SIGNER_INFO signerInfo = nullptr; DWORD lastError = ERROR_SUCCESS; // Get the HCERTSTORE and HCRYPTMSG from the signed file. DWORD encoding, contentType, formatType; BOOL result = CryptQueryObject(CERT_QUERY_OBJECT_FILE, filePath, CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED, CERT_QUERY_CONTENT_FLAG_ALL, 0, &encoding, &contentType, &formatType, &certStore, &cryptMsg, nullptr); if (!result) { lastError = GetLastError(); LOG_WARN(("CryptQueryObject failed. (%d)", lastError)); goto cleanup; } // Pass in nullptr to get the needed signer information size. DWORD signerInfoSize; result = CryptMsgGetParam(cryptMsg, CMSG_SIGNER_INFO_PARAM, 0, nullptr, &signerInfoSize); if (!result) { lastError = GetLastError(); LOG_WARN(("CryptMsgGetParam failed. (%d)", lastError)); goto cleanup; } // Allocate the needed size for the signer information. signerInfo = (PCMSG_SIGNER_INFO)LocalAlloc(LPTR, signerInfoSize); if (!signerInfo) { lastError = GetLastError(); LOG_WARN(("Unable to allocate memory for Signer Info. (%d)", lastError)); goto cleanup; } // Get the signer information (PCMSG_SIGNER_INFO). // In particular we want the issuer and serial number. result = CryptMsgGetParam(cryptMsg, CMSG_SIGNER_INFO_PARAM, 0, (PVOID)signerInfo, &signerInfoSize); if (!result) { lastError = GetLastError(); LOG_WARN(("CryptMsgGetParam failed. (%d)", lastError)); goto cleanup; } // Search for the signer certificate in the certificate store. CERT_INFO certInfo; certInfo.Issuer = signerInfo->Issuer; certInfo.SerialNumber = signerInfo->SerialNumber; certContext = CertFindCertificateInStore(certStore, ENCODING, 0, CERT_FIND_SUBJECT_CERT, (PVOID)&certInfo, nullptr); if (!certContext) { lastError = GetLastError(); LOG_WARN(("CertFindCertificateInStore failed. (%d)", lastError)); goto cleanup; } if (!DoCertificateAttributesMatch(certContext, infoToMatch)) { lastError = ERROR_NOT_FOUND; LOG_WARN(("Certificate did not match issuer or name. (%d)", lastError)); goto cleanup; } cleanup: if (signerInfo) { LocalFree(signerInfo); } if (certContext) { CertFreeCertificateContext(certContext); } if (certStore) { CertCloseStore(certStore, 0); } if (cryptMsg) { CryptMsgClose(cryptMsg); } return lastError; }
/* Used to decode non-embedded messages */ static BOOL CRYPT_QueryMessageObject(DWORD dwObjectType, const void *pvObject, DWORD dwExpectedContentTypeFlags, DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType, HCERTSTORE *phCertStore, HCRYPTMSG *phMsg) { CERT_BLOB fileBlob; const CERT_BLOB *blob; BOOL ret; HCRYPTMSG msg = NULL; DWORD encodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING; switch (dwObjectType) { case CERT_QUERY_OBJECT_FILE: /* This isn't an embedded PKCS7 message, so just read the file * directly */ ret = CRYPT_ReadBlobFromFile((LPCWSTR)pvObject, &fileBlob); blob = &fileBlob; break; case CERT_QUERY_OBJECT_BLOB: blob = (const CERT_BLOB *)pvObject; ret = TRUE; break; default: SetLastError(E_INVALIDARG); /* FIXME: is this the correct error? */ ret = FALSE; } if (!ret) return FALSE; ret = FALSE; /* Try it first as a PKCS content info */ if ((dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED) || (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED)) { msg = CryptMsgOpenToDecode(encodingType, 0, 0, 0, NULL, NULL); if (msg) { ret = CryptMsgUpdate(msg, blob->pbData, blob->cbData, TRUE); if (ret) { DWORD type, len = sizeof(type); ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, &type, &len); if (ret) { if ((dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED)) { if (type != CMSG_SIGNED) { SetLastError(ERROR_INVALID_DATA); ret = FALSE; } else if (pdwContentType) *pdwContentType = CERT_QUERY_CONTENT_PKCS7_SIGNED; } else if ((dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED)) { if (type != CMSG_DATA) { SetLastError(ERROR_INVALID_DATA); ret = FALSE; } else if (pdwContentType) *pdwContentType = CERT_QUERY_CONTENT_PKCS7_UNSIGNED; } } } if (!ret) { CryptMsgClose(msg); msg = NULL; } } } /* Failing that, try explicitly typed messages */ if (!ret && (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED)) { msg = CryptMsgOpenToDecode(encodingType, 0, CMSG_SIGNED, 0, NULL, NULL); if (msg) { ret = CryptMsgUpdate(msg, blob->pbData, blob->cbData, TRUE); if (!ret) { CryptMsgClose(msg); msg = NULL; } } if (msg && pdwContentType) *pdwContentType = CERT_QUERY_CONTENT_PKCS7_SIGNED; } if (!ret && (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED)) { msg = CryptMsgOpenToDecode(encodingType, 0, CMSG_DATA, 0, NULL, NULL); if (msg) { ret = CryptMsgUpdate(msg, blob->pbData, blob->cbData, TRUE); if (!ret) { CryptMsgClose(msg); msg = NULL; } } if (msg && pdwContentType) *pdwContentType = CERT_QUERY_CONTENT_PKCS7_UNSIGNED; } if (pdwMsgAndCertEncodingType) *pdwMsgAndCertEncodingType = encodingType; if (msg) { if (phMsg) *phMsg = msg; if (phCertStore) *phCertStore = CertOpenStore(CERT_STORE_PROV_MSG, encodingType, 0, 0, msg); } if (blob == &fileBlob) CryptMemFree(blob->pbData); TRACE("returning %d\n", ret); return ret; }
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); } }