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; }
static PWINECRYPT_CERTSTORE CRYPT_PKCSOpenStore(HCRYPTPROV hCryptProv, DWORD dwFlags, const void *pvPara) { HCRYPTMSG msg; PWINECRYPT_CERTSTORE store = NULL; const CRYPT_DATA_BLOB *data = pvPara; BOOL ret; DWORD msgOpenFlags = dwFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG ? 0 : CMSG_CRYPT_RELEASE_CONTEXT_FLAG; TRACE("(%ld, %08x, %p)\n", hCryptProv, dwFlags, pvPara); msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, msgOpenFlags, CMSG_SIGNED, hCryptProv, NULL, NULL); ret = CryptMsgUpdate(msg, data->pbData, data->cbData, TRUE); if (!ret) { CryptMsgClose(msg); msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, msgOpenFlags, 0, hCryptProv, NULL, NULL); ret = CryptMsgUpdate(msg, data->pbData, data->cbData, TRUE); if (ret) { DWORD type, size = sizeof(type); /* Only signed messages are allowed, check type */ ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, &type, &size); if (ret && type != CMSG_SIGNED) { SetLastError(CRYPT_E_INVALID_MSG_TYPE); ret = FALSE; } } } if (ret) store = CRYPT_MsgOpenStore(0, dwFlags, msg); CryptMsgClose(msg); TRACE("returning %p\n", store); return store; }
/* Assumes data->u.pPDSip has been loaded, and data->u.pPDSip->pSip allocated. * Calls data->u.pPDSip->pSip->pfGet to construct data->hMsg. */ static BOOL SOFTPUB_GetMessageFromFile(CRYPT_PROVIDER_DATA *data, HANDLE file, LPCWSTR filePath) { BOOL ret; LPBYTE buf = NULL; DWORD size = 0; data->u.pPDSip->psSipSubjectInfo = data->psPfns->pfnAlloc(sizeof(SIP_SUBJECTINFO)); if (!data->u.pPDSip->psSipSubjectInfo) { SetLastError(ERROR_OUTOFMEMORY); return FALSE; } data->u.pPDSip->psSipSubjectInfo->cbSize = sizeof(SIP_SUBJECTINFO); data->u.pPDSip->psSipSubjectInfo->pgSubjectType = &data->u.pPDSip->gSubject; data->u.pPDSip->psSipSubjectInfo->hFile = file; data->u.pPDSip->psSipSubjectInfo->pwsFileName = filePath; data->u.pPDSip->psSipSubjectInfo->hProv = data->hProv; ret = data->u.pPDSip->pSip->pfGet(data->u.pPDSip->psSipSubjectInfo, &data->dwEncoding, 0, &size, 0); if (!ret) { SetLastError(TRUST_E_NOSIGNATURE); return FALSE; } buf = data->psPfns->pfnAlloc(size); if (!buf) { SetLastError(ERROR_OUTOFMEMORY); return FALSE; } ret = data->u.pPDSip->pSip->pfGet(data->u.pPDSip->psSipSubjectInfo, &data->dwEncoding, 0, &size, buf); if (ret) { data->hMsg = CryptMsgOpenToDecode(data->dwEncoding, 0, 0, data->hProv, NULL, NULL); if (data->hMsg) ret = CryptMsgUpdate(data->hMsg, buf, size, TRUE); } data->psPfns->pfnFree(buf); TRACE("returning %d\n", ret); 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; }
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; }
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) { CryptMemFree(ctl); ctl = NULL; LocalFree(ctlInfo); CryptMemFree(content); CryptMsgClose(msg); } return ctl; }
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; }
/*********************************************************************** * 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 (!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; }
/*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; }
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 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; }
/* 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); } }