BOOL WINAPI CryptHashMessage(PCRYPT_HASH_MESSAGE_PARA pHashPara, BOOL fDetachedHash, DWORD cToBeHashed, const BYTE *rgpbToBeHashed[], DWORD rgcbToBeHashed[], BYTE *pbHashedBlob, DWORD *pcbHashedBlob, BYTE *pbComputedHash, DWORD *pcbComputedHash) { DWORD i, flags; BOOL ret = FALSE; HCRYPTMSG msg; CMSG_HASHED_ENCODE_INFO info; TRACE("(%p, %d, %d, %p, %p, %p, %p, %p, %p)\n", pHashPara, fDetachedHash, cToBeHashed, rgpbToBeHashed, rgcbToBeHashed, pbHashedBlob, pcbHashedBlob, pbComputedHash, pcbComputedHash); if (pHashPara->cbSize != sizeof(CRYPT_HASH_MESSAGE_PARA)) { SetLastError(E_INVALIDARG); return FALSE; } /* Native seems to ignore any encoding type other than the expected * PKCS_7_ASN_ENCODING */ if (GET_CMSG_ENCODING_TYPE(pHashPara->dwMsgEncodingType) != PKCS_7_ASN_ENCODING) return TRUE; /* Native also seems to do nothing if the output parameter isn't given */ if (!pcbHashedBlob) return TRUE; flags = fDetachedHash ? CMSG_DETACHED_FLAG : 0; memset(&info, 0, sizeof(info)); info.cbSize = sizeof(info); info.hCryptProv = pHashPara->hCryptProv; memcpy(&info.HashAlgorithm, &pHashPara->HashAlgorithm, sizeof(info.HashAlgorithm)); info.pvHashAuxInfo = pHashPara->pvHashAuxInfo; msg = CryptMsgOpenToEncode(pHashPara->dwMsgEncodingType, flags, CMSG_HASHED, &info, NULL, NULL); if (msg) { for (i = 0, ret = TRUE; ret && i < cToBeHashed; i++) ret = CryptMsgUpdate(msg, rgpbToBeHashed[i], rgcbToBeHashed[i], i == cToBeHashed - 1 ? TRUE : FALSE); if (ret) { ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, pbHashedBlob, pcbHashedBlob); if (ret && pcbComputedHash) ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0, pbComputedHash, pcbComputedHash); } CryptMsgClose(msg); } return ret; }
DWORD do_low_sign (const char *infile, const char *outfile) { char OID[64] = szOID_CP_GOST_R3411; int include = 1; HCRYPTPROV hCryptProv = 0; // CSP handle PCCERT_CONTEXT pUserCert = NULL; // User certificate to be used DWORD keytype = 0; CSP_BOOL should_release_ctx = FALSE; DWORD ret = 1; FILE *tbs = NULL; BYTE *mem_tbs = NULL; DWORD mem_len = 0; HCRYPTMSG hMsg = 0; DWORD HashAlgSize; DWORD dwSize; CRYPT_ALGORITHM_IDENTIFIER HashAlgorithm; CMSG_SIGNER_ENCODE_INFO SignerEncodeInfo; CERT_BLOB SignerCertBlob; CERT_BLOB SignerCertBlobArray[1]; DWORD cbEncodedBlob; BYTE *pbEncodedBlob = NULL; CMSG_SIGNER_ENCODE_INFO SignerEncodeInfoArray[1]; CMSG_SIGNED_ENCODE_INFO SignedMsgEncodeInfo; CSP_BOOL bResult = FALSE; CRYPT_KEY_PROV_INFO *pProvInfo = NULL; HCERTSTORE hCertStore = 0; hCertStore = CertOpenSystemStore(0, "My"); if(!hCertStore){ ret = CSP_GetLastError(); fprintf (stderr, "CertOpenSystemStore failed."); goto err; } while( !bResult){ pUserCert= CertEnumCertificatesInStore(hCertStore, pUserCert); if(!pUserCert){ break; } bResult = CertGetCertificateContextProperty( pUserCert, CERT_KEY_PROV_INFO_PROP_ID, NULL, &dwSize); if (bResult) { free(pProvInfo); pProvInfo = (CRYPT_KEY_PROV_INFO *)malloc(dwSize); if (pProvInfo) { bResult = CertGetCertificateContextProperty( pUserCert, CERT_KEY_PROV_INFO_PROP_ID, pProvInfo, &dwSize); } } } if(!bResult){ fprintf (stderr, "No certificates with private key link."); goto err; } if (! infile) { fprintf (stderr, "No input file was specified\n"); goto err; } if (CryptAcquireCertificatePrivateKey( pUserCert, 0, //DWORD dwFlags, NULL, &hCryptProv, &keytype, // returned key type AT_SIGNATURE ! AT_KEYEXCAHGE &should_release_ctx // if FALSE DO NOT Release CTX )) { printf("A CSP has been acquired. \n"); } else { ret = CSP_GetLastError(); fprintf (stderr, "Cryptographic context could not be acquired."); 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; //-------------------------------------------------------------------- // Initialize the algorithm identifier structure. HashAlgSize = sizeof(HashAlgorithm); memset(&HashAlgorithm, 0, HashAlgSize); // Init. to zero. HashAlgorithm.pszObjId = OID; // Initialize the necessary member. //-------------------------------------------------------------------- // Initialize the CMSG_SIGNER_ENCODE_INFO structure. memset(&SignerEncodeInfo, 0, sizeof(CMSG_SIGNER_ENCODE_INFO)); SignerEncodeInfo.cbSize = sizeof(CMSG_SIGNER_ENCODE_INFO); SignerEncodeInfo.pCertInfo = pUserCert->pCertInfo; SignerEncodeInfo.hCryptProv = hCryptProv; SignerEncodeInfo.dwKeySpec = keytype; SignerEncodeInfo.HashAlgorithm = HashAlgorithm; SignerEncodeInfo.pvHashAuxInfo = NULL; //-------------------------------------------------------------------- // Create an array of one. Note: Currently, there can be only one // signer. SignerEncodeInfoArray[0] = SignerEncodeInfo; //-------------------------------------------------------------------- // Initialize the CMSG_SIGNED_ENCODE_INFO structure. SignerCertBlob.cbData = pUserCert->cbCertEncoded; SignerCertBlob.pbData = pUserCert->pbCertEncoded; //-------------------------------------------------------------------- // Initialize the array of one CertBlob. SignerCertBlobArray[0] = SignerCertBlob; memset(&SignedMsgEncodeInfo, 0, sizeof(CMSG_SIGNED_ENCODE_INFO)); SignedMsgEncodeInfo.cbSize = sizeof(CMSG_SIGNED_ENCODE_INFO); SignedMsgEncodeInfo.cSigners = 1; SignedMsgEncodeInfo.rgSigners = SignerEncodeInfoArray; SignedMsgEncodeInfo.cCertEncoded = include; if (include) SignedMsgEncodeInfo.rgCertEncoded = SignerCertBlobArray; else SignedMsgEncodeInfo.rgCertEncoded = NULL; SignedMsgEncodeInfo.rgCrlEncoded = NULL; //-------------------------------------------------------------------- // Get the size of the encoded message blob. if(cbEncodedBlob = CryptMsgCalculateEncodedLength( TYPE_DER, // Message encoding type 0, // Flags CMSG_SIGNED, // Message type &SignedMsgEncodeInfo, // Pointer to structure NULL, // Inner content object ID mem_len)) // Size of content */ { printf("The length of the data has been calculated. \n"); } else { ret = CSP_GetLastError(); fprintf (stderr, "Getting cbEncodedBlob length failed"); goto err; } //-------------------------------------------------------------------- // Allocate memory for the encoded blob. pbEncodedBlob = (BYTE *) malloc(cbEncodedBlob); if (!pbEncodedBlob){ ret = CSP_GetLastError(); fprintf (stderr, "Memory allocation failed"); goto err; } //-------------------------------------------------------------------- // Open a message to encode. if(hMsg = CryptMsgOpenToEncode( TYPE_DER, // Encoding type 0, // Flags CMSG_SIGNED, // Message type &SignedMsgEncodeInfo, // Pointer to structure NULL, // Inner content object ID NULL)) // Stream information (not used) { printf("The message to be encoded has been opened. \n"); } else { ret = CSP_GetLastError(); fprintf (stderr, "OpenToEncode failed"); goto err; } //-------------------------------------------------------------------- // Update the message with the data. if(CryptMsgUpdate( hMsg, // Handle to the message mem_tbs, // Pointer to the content mem_len, // Size of the content TRUE)) // Last call { printf("Content has been added to the encoded message. \n"); } else { ret = CSP_GetLastError(); fprintf (stderr, "MsgUpdate failed"); goto err; } //-------------------------------------------------------------------- // Get the resulting message. if(CryptMsgGetParam( hMsg, // Handle to the message CMSG_CONTENT_PARAM, // Parameter type 0, // Index pbEncodedBlob, // Pointer to the blob &cbEncodedBlob)) // Size of the blob { printf("Message encoded successfully. \n"); } else { ret = CSP_GetLastError(); fprintf (stderr, "MsgGetParam failed"); goto err; } //-------------------------------------------------------------------- // pbEncodedBlob now points to the encoded, signed content. //-------------------------------------------------------------------- if (outfile) { FILE *out = NULL; out = fopen (outfile, "wb"); if (out) { fwrite (pbEncodedBlob, cbEncodedBlob, 1, out); fclose (out); printf ("Output file (%s) has been saved\n", outfile); } else perror ("Cannot open out file\n"); } ret = 0; //-------------------------------------------------------------------- // Clean up. err: if(pbEncodedBlob) free(pbEncodedBlob); if(hMsg) CryptMsgClose(hMsg); if(hCryptProv) CryptReleaseContext(hCryptProv,0); if(hCertStore) CertCloseStore(hCertStore, 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 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; }