You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
817 lines
25 KiB
817 lines
25 KiB
//+-------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
//
|
|
// Copyright (C) Microsoft Corporation, 1995 - 1999
|
|
//
|
|
// File: fencrypt.cpp
|
|
//
|
|
// Contents: File encryption tool. Encrypts a file looking in the MY
|
|
// system certificate store for the specifed subject common name
|
|
// with exchange private keys.
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
#include <windows.h>
|
|
#include <assert.h>
|
|
#include "wincrypt.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <memory.h>
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Helper function to make MBCS from Unicode string
|
|
//--------------------------------------------------------------------------
|
|
BOOL WINAPI MkMBStr(PBYTE pbBuff, DWORD cbBuff, LPCWSTR wsz, char ** pszMB) {
|
|
|
|
DWORD cbConverted;
|
|
|
|
assert(pszMB != NULL);
|
|
*pszMB = NULL;
|
|
if(wsz == NULL)
|
|
return(TRUE);
|
|
|
|
// how long is the mb string
|
|
cbConverted = WideCharToMultiByte( 0,
|
|
0,
|
|
wsz,
|
|
-1,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
NULL);
|
|
|
|
// get a buffer long enough
|
|
if(pbBuff != NULL && cbConverted < cbBuff)
|
|
*pszMB = (char *) pbBuff;
|
|
else
|
|
*pszMB = (char *) malloc(cbConverted);
|
|
|
|
|
|
if(*pszMB == NULL) {
|
|
SetLastError(ERROR_OUTOFMEMORY);
|
|
return(FALSE);
|
|
}
|
|
|
|
// now convert to MB
|
|
WideCharToMultiByte(0,
|
|
0,
|
|
wsz,
|
|
-1,
|
|
*pszMB,
|
|
cbConverted,
|
|
NULL,
|
|
NULL);
|
|
return(TRUE);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Frees string allocated by the above function
|
|
//--------------------------------------------------------------------------
|
|
void WINAPI FreeMBStr(PBYTE pbBuff, char * szMB) {
|
|
|
|
if((szMB != NULL) && (pbBuff != (PBYTE)szMB))
|
|
free(szMB);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Win95 only supports CryptAcquireContextA. This function converts the
|
|
// unicode parameters to multibyte.
|
|
//--------------------------------------------------------------------------
|
|
BOOL WINAPI CryptAcquireContextU(
|
|
HCRYPTPROV *phProv,
|
|
LPCWSTR lpContainer,
|
|
LPCWSTR lpProvider,
|
|
DWORD dwProvType,
|
|
DWORD dwFlags) {
|
|
|
|
BYTE rgb1[_MAX_PATH];
|
|
BYTE rgb2[_MAX_PATH];
|
|
char * szContainer = NULL;
|
|
char * szProvider = NULL;
|
|
LONG err;
|
|
|
|
err = FALSE;
|
|
if(
|
|
MkMBStr(rgb1, _MAX_PATH, lpContainer, &szContainer) &&
|
|
MkMBStr(rgb2, _MAX_PATH, lpProvider, &szProvider) )
|
|
err = CryptAcquireContextA (
|
|
phProv,
|
|
szContainer,
|
|
szProvider,
|
|
dwProvType,
|
|
dwFlags
|
|
);
|
|
|
|
FreeMBStr(rgb1, szContainer);
|
|
FreeMBStr(rgb2, szProvider);
|
|
|
|
return(err);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Helper function to allocated the output buffer
|
|
// and call CryptDecodeObject.
|
|
//--------------------------------------------------------------------------
|
|
BOOL
|
|
WINAPI
|
|
MDecodeObject(
|
|
IN DWORD dwEncodingType,
|
|
IN LPCSTR lpszStructureType,
|
|
IN const PBYTE pbEncoded,
|
|
IN DWORD cbEncoded,
|
|
OUT PVOID * ppvoid
|
|
)
|
|
{
|
|
DWORD cb = 0;
|
|
|
|
assert(ppvoid != NULL);
|
|
*ppvoid = NULL;
|
|
|
|
// get the size
|
|
if(!CryptDecodeObject(
|
|
dwEncodingType,
|
|
lpszStructureType,
|
|
pbEncoded,
|
|
cbEncoded,
|
|
0, // dwFlags
|
|
NULL,
|
|
&cb
|
|
))
|
|
return(FALSE);
|
|
|
|
// allocate the buffer
|
|
if( (*ppvoid = malloc(cb)) == NULL )
|
|
{
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
return(FALSE);
|
|
}
|
|
|
|
// Decode the data
|
|
if(!CryptDecodeObject(
|
|
dwEncodingType,
|
|
lpszStructureType,
|
|
pbEncoded,
|
|
cbEncoded,
|
|
0, // dwFlags
|
|
*ppvoid,
|
|
&cb
|
|
))
|
|
{
|
|
|
|
free(*ppvoid);
|
|
*ppvoid = NULL;
|
|
return(FALSE);
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Helper function to allocated the output buffer
|
|
// and call CertRDNValueToStr.
|
|
//--------------------------------------------------------------------------
|
|
DWORD
|
|
WINAPI
|
|
MCertRDNValueToStr(
|
|
IN DWORD dwValueType,
|
|
IN PCERT_RDN_VALUE_BLOB pValue,
|
|
OUT OPTIONAL LPSTR * ppsz
|
|
)
|
|
{
|
|
|
|
DWORD cb = 0;
|
|
|
|
assert(ppsz != NULL);
|
|
*ppsz = NULL;
|
|
|
|
// get the size
|
|
cb = CertRDNValueToStrA(
|
|
dwValueType,
|
|
pValue,
|
|
NULL,
|
|
0);
|
|
|
|
// allocate the buffer
|
|
if( (*ppsz = (LPSTR) malloc(cb)) == NULL )
|
|
{
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
return(0);
|
|
}
|
|
|
|
// now convert the CERT_RDN Value to an
|
|
// ascii string based on the specified
|
|
// ASN value type.
|
|
// This shouldn't fail.
|
|
return(CertRDNValueToStrA(
|
|
dwValueType,
|
|
pValue,
|
|
*ppsz,
|
|
cb));
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Helper function to get and allocate the exported public key info
|
|
//--------------------------------------------------------------------------
|
|
BOOL
|
|
WINAPI
|
|
MCryptExportPublicKeyInfo(
|
|
HCRYPTPROV hProv,
|
|
DWORD dwKeySpec,
|
|
PCERT_PUBLIC_KEY_INFO *ppPubKeyInfo
|
|
)
|
|
{
|
|
DWORD cbPubKeyInfo;
|
|
assert(ppPubKeyInfo != NULL);
|
|
*ppPubKeyInfo = NULL;
|
|
|
|
|
|
// get the size
|
|
if(!CryptExportPublicKeyInfo(
|
|
hProv,
|
|
dwKeySpec,
|
|
X509_ASN_ENCODING,
|
|
NULL, // pPubKeyInfo
|
|
&cbPubKeyInfo
|
|
)
|
|
)
|
|
return(FALSE);
|
|
|
|
// allocate the buffer
|
|
if( (*ppPubKeyInfo = (PCERT_PUBLIC_KEY_INFO) malloc(cbPubKeyInfo)) == NULL )
|
|
{
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
return(FALSE);
|
|
}
|
|
|
|
if(!CryptExportPublicKeyInfo(
|
|
hProv,
|
|
dwKeySpec,
|
|
X509_ASN_ENCODING,
|
|
*ppPubKeyInfo,
|
|
&cbPubKeyInfo
|
|
)
|
|
)
|
|
{
|
|
free(*ppPubKeyInfo);
|
|
*ppPubKeyInfo = NULL;
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
//+-------------------------------------------------------------------------
|
|
// Helper function to allocated the output buffer
|
|
// and call CertGetCertificateContextProperty.
|
|
//--------------------------------------------------------------------------
|
|
BOOL
|
|
WINAPI
|
|
MCertGetCertificateContextProperty(
|
|
IN PCCERT_CONTEXT pCertContext,
|
|
IN DWORD dwPropId,
|
|
OUT void ** ppvData
|
|
)
|
|
{
|
|
|
|
DWORD cb = 0;
|
|
|
|
assert(ppvData != NULL);
|
|
*ppvData = NULL;
|
|
|
|
// get the size
|
|
if( !CertGetCertificateContextProperty(
|
|
pCertContext,
|
|
dwPropId,
|
|
NULL,
|
|
&cb))
|
|
return(FALSE);
|
|
|
|
// allocate the buffer
|
|
if( (*ppvData = malloc(cb)) == NULL )
|
|
{
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
return(FALSE);
|
|
}
|
|
|
|
// Get the property out of the cert
|
|
if( !CertGetCertificateContextProperty(
|
|
pCertContext,
|
|
dwPropId,
|
|
*ppvData,
|
|
&cb))
|
|
{
|
|
|
|
free(*ppvData);
|
|
*ppvData = NULL;
|
|
return(FALSE);
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Helper function to allocated the output buffer
|
|
// and call CryptEncryptMessage.
|
|
//--------------------------------------------------------------------------
|
|
BOOL
|
|
WINAPI
|
|
MCryptEncryptMessage(
|
|
IN PCRYPT_ENCRYPT_MESSAGE_PARA pEncryptPara,
|
|
IN DWORD cRecipientCert,
|
|
IN PCCERT_CONTEXT rgpRecipientCert[],
|
|
IN const BYTE *pbToBeEncrypted,
|
|
IN DWORD cbToBeEncrypted,
|
|
OUT BYTE **ppbEncryptedBlob,
|
|
OUT DWORD *pcbEncryptedBlob
|
|
)
|
|
{
|
|
|
|
assert(ppbEncryptedBlob != NULL);
|
|
*ppbEncryptedBlob = NULL;
|
|
|
|
assert(pcbEncryptedBlob != NULL);
|
|
*pcbEncryptedBlob = 0;
|
|
|
|
// get the size
|
|
if(!CryptEncryptMessage(
|
|
pEncryptPara,
|
|
cRecipientCert,
|
|
rgpRecipientCert,
|
|
pbToBeEncrypted,
|
|
cbToBeEncrypted,
|
|
NULL,
|
|
pcbEncryptedBlob
|
|
))
|
|
return(FALSE);
|
|
|
|
// allocate the buffer
|
|
if( (*ppbEncryptedBlob = (BYTE *) malloc(*pcbEncryptedBlob)) == NULL )
|
|
{
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
return(FALSE);
|
|
}
|
|
|
|
// encrypt the data
|
|
if(!CryptEncryptMessage(
|
|
pEncryptPara,
|
|
cRecipientCert,
|
|
rgpRecipientCert,
|
|
pbToBeEncrypted,
|
|
cbToBeEncrypted,
|
|
*ppbEncryptedBlob,
|
|
pcbEncryptedBlob))
|
|
{
|
|
free(*ppbEncryptedBlob);
|
|
*ppbEncryptedBlob = NULL;
|
|
*pcbEncryptedBlob = 0;
|
|
return(FALSE);
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Display FEncrypt usage.
|
|
//--------------------------------------------------------------------------
|
|
void
|
|
Usage(void)
|
|
{
|
|
printf("Usage: FEncrypt [options] <SubjectName> <ClearTextFileName> <EncryptedFileName>\n");
|
|
printf("Options are:\n");
|
|
printf(" -RC2 - RC2 encryption\n");
|
|
printf(" -RC4 - RC4 encryption\n");
|
|
printf(" -SP3 - SP3 compatible encryption\n");
|
|
printf(" -FIX - Fix by loading sp3crmsg.dll\n");
|
|
exit(1);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Generalized error routine
|
|
//--------------------------------------------------------------------------
|
|
#define PRINTERROR(psz, err) _PrintError((psz), (err), __LINE__)
|
|
void
|
|
_PrintError(char *pszMsg, DWORD err, DWORD line)
|
|
{
|
|
printf("%s failed on line %u: %u(%x)\n", pszMsg, line, err, err);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Grovels the cert store looking for a cert with the specified
|
|
// subject common name. Then checks to see that there are private
|
|
// and public exchange keys.
|
|
//--------------------------------------------------------------------------
|
|
PCCERT_CONTEXT GetSubjectCertFromStore(
|
|
HCERTSTORE hMyStore,
|
|
const char * szSubjectName,
|
|
HCRYPTPROV * phProv
|
|
)
|
|
{
|
|
|
|
DWORD i, j;
|
|
PCCERT_CONTEXT pCertContext = NULL;
|
|
PCCERT_CONTEXT pCertContextLast = NULL;
|
|
PCERT_NAME_INFO pNameInfo = NULL;
|
|
LPSTR sz = NULL;
|
|
PCRYPT_KEY_PROV_INFO pProvInfo = NULL;
|
|
HCRYPTPROV hProv = NULL;
|
|
PCERT_PUBLIC_KEY_INFO pPubKeyInfo = NULL;
|
|
|
|
assert(hMyStore != NULL);
|
|
assert(phProv != NULL);
|
|
*phProv = NULL;
|
|
|
|
// Enum all certs looking for the requested common
|
|
// subject name that has private keys (so we know we can decrypt)
|
|
while( hProv == NULL &&
|
|
(pCertContext = CertEnumCertificatesInStore(
|
|
hMyStore,
|
|
pCertContextLast)) != NULL)
|
|
{
|
|
|
|
// decode the subject name into RDNs
|
|
if(MDecodeObject(X509_ASN_ENCODING, X509_NAME,
|
|
pCertContext->pCertInfo->Subject.pbData,
|
|
pCertContext->pCertInfo->Subject.cbData,
|
|
(void **) &pNameInfo)
|
|
)
|
|
{
|
|
|
|
// loop thru looking for an CERT_RDN and COMMON Name that works
|
|
for(i=0; i<pNameInfo->cRDN && hProv == NULL; i++)
|
|
{
|
|
for(j=0; j<pNameInfo->rgRDN[i].cRDNAttr && hProv == NULL; j++)
|
|
{
|
|
|
|
// check to see if this is the common name
|
|
if( !strcmp(pNameInfo->rgRDN[i].rgRDNAttr[j].pszObjId,
|
|
szOID_COMMON_NAME) )
|
|
{
|
|
|
|
// convert the string to something I can read
|
|
MCertRDNValueToStr(
|
|
pNameInfo->rgRDN[i].rgRDNAttr[j].dwValueType,
|
|
&pNameInfo->rgRDN[i].rgRDNAttr[j].Value,
|
|
&sz);
|
|
|
|
// see if this is a viable certificate to use
|
|
if( sz == NULL ||
|
|
|
|
// see if it is the common name we are looking for
|
|
_stricmp(sz, szSubjectName) ||
|
|
|
|
// see if there are associated private keys
|
|
// to ensure we can decrypt the data later
|
|
!MCertGetCertificateContextProperty(
|
|
pCertContext,
|
|
CERT_KEY_PROV_INFO_PROP_ID,
|
|
(void **) &pProvInfo) ||
|
|
|
|
// Make sure it is an exchange key for encryption
|
|
pProvInfo->dwKeySpec != AT_KEYEXCHANGE ||
|
|
|
|
// see if the keys are really there
|
|
!CryptAcquireContextU(
|
|
&hProv,
|
|
pProvInfo->pwszContainerName,
|
|
pProvInfo->pwszProvName,
|
|
pProvInfo->dwProvType,
|
|
pProvInfo->dwFlags &
|
|
~CERT_SET_KEY_CONTEXT_PROP_ID)
|
|
)
|
|
{
|
|
|
|
// On an error we didn't find a valid
|
|
// key provider. Unfortunately, the CSP
|
|
// may not leave the prov handle NULL
|
|
// so clear it out
|
|
hProv = NULL;
|
|
}
|
|
|
|
|
|
// Make sure the public keys in the
|
|
// CSP match the public key in the certificate
|
|
else if(
|
|
// export the public key blob
|
|
!MCryptExportPublicKeyInfo(
|
|
hProv,
|
|
pProvInfo->dwKeySpec,
|
|
&pPubKeyInfo
|
|
) ||
|
|
|
|
// see if the public keys compare with
|
|
// what is in the certificate
|
|
!CertComparePublicKeyInfo(
|
|
X509_ASN_ENCODING,
|
|
&pCertContext->pCertInfo->SubjectPublicKeyInfo,
|
|
pPubKeyInfo
|
|
)
|
|
)
|
|
// if the keys didn't compare, then we don't
|
|
// want to use this ceritificate
|
|
{
|
|
|
|
// close the hProv, we didn't find a valid cert
|
|
assert(hProv != NULL);
|
|
CryptReleaseContext(hProv, 0);
|
|
hProv = NULL;
|
|
}
|
|
|
|
// free public key info
|
|
if(pPubKeyInfo != NULL)
|
|
{
|
|
free(pPubKeyInfo);
|
|
pPubKeyInfo = NULL;
|
|
}
|
|
|
|
// clean up opened prov info
|
|
if(pProvInfo != NULL)
|
|
{
|
|
free(pProvInfo);
|
|
pProvInfo = NULL;
|
|
}
|
|
|
|
// free the space for the ascii common name
|
|
if(sz != NULL)
|
|
{
|
|
free(sz);
|
|
sz = NULL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// free the name info data
|
|
if(pNameInfo != NULL)
|
|
{
|
|
free(pNameInfo);
|
|
pNameInfo = NULL;
|
|
}
|
|
}
|
|
|
|
// go to the next certificate
|
|
pCertContextLast = pCertContext;
|
|
}
|
|
|
|
assert(pProvInfo == NULL);
|
|
assert(sz == NULL);
|
|
assert(pNameInfo == NULL);
|
|
|
|
// There is a good cert in the store, return it
|
|
if(hProv != NULL)
|
|
{
|
|
*phProv = hProv;
|
|
assert(pCertContext != NULL);
|
|
return(pCertContext);
|
|
}
|
|
|
|
return(NULL);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Main program. Open a file to encrypt,
|
|
// encrypts it and then writes the encrypted
|
|
// data to the output file.
|
|
//--------------------------------------------------------------------------
|
|
int __cdecl
|
|
main(int argc, char * argv[])
|
|
{
|
|
|
|
DWORD dwExitValue = 0;
|
|
|
|
HCERTSTORE hMyStore = NULL;
|
|
PCCERT_CONTEXT pCertContext = NULL;
|
|
HCRYPTPROV hProv = NULL;
|
|
|
|
HANDLE hFileOut = INVALID_HANDLE_VALUE;
|
|
HANDLE hFile = INVALID_HANDLE_VALUE;
|
|
DWORD cbFile = 0;
|
|
HANDLE hMap = NULL;
|
|
PBYTE pbFile = NULL;
|
|
|
|
BOOL fResult;
|
|
HMODULE hDll = NULL;
|
|
CMSG_SP3_COMPATIBLE_AUX_INFO SP3AuxInfo;
|
|
BOOL fSP3 = FALSE;
|
|
BOOL fFix = FALSE;
|
|
|
|
CRYPT_ALGORITHM_IDENTIFIER encryptAlgId = {szOID_RSA_RC4, 0};
|
|
CRYPT_ENCRYPT_MESSAGE_PARA encryptInfo;
|
|
PBYTE pbEncryptedBlob = NULL;
|
|
DWORD cbEncryptedBlob = 0;
|
|
DWORD cb = 0;
|
|
|
|
|
|
// Advance past fencrypt.exe and check for leading options
|
|
while (--argc > 0) {
|
|
if (**++argv != '-')
|
|
break;
|
|
|
|
if (0 == _stricmp(argv[0], "-RC2"))
|
|
encryptAlgId.pszObjId = szOID_RSA_RC2CBC;
|
|
else if (0 == _stricmp(argv[0], "-RC4"))
|
|
encryptAlgId.pszObjId = szOID_RSA_RC4;
|
|
else if (0 == _stricmp(argv[0], "-SP3"))
|
|
fSP3 = TRUE;
|
|
else if (0 == _stricmp(argv[0], "-FIX"))
|
|
fFix = TRUE;
|
|
else {
|
|
printf("Bad option: %s\n", argv[0]);
|
|
Usage();
|
|
}
|
|
}
|
|
|
|
|
|
// must have the parameters
|
|
if (argc != 3)
|
|
Usage();
|
|
|
|
if (fFix) {
|
|
if (NULL == (hDll = LoadLibraryA("sp3crmsg.dll")))
|
|
{
|
|
PRINTERROR("LoadLibraryA(sp3crmsg.dll)", GetLastError());
|
|
goto ErrCleanUp;
|
|
}
|
|
}
|
|
|
|
// Open the MY store
|
|
if( (hMyStore = CertOpenSystemStore(NULL, "My")) == NULL )
|
|
{
|
|
PRINTERROR("CertOpenSystemStore", GetLastError());
|
|
goto ErrCleanUp;
|
|
}
|
|
|
|
// Find a certificate in the MY store that
|
|
// matches the subject name and has private keys
|
|
if( (pCertContext = GetSubjectCertFromStore(hMyStore, argv[0], &hProv)) == NULL)
|
|
{
|
|
printf("Unable to find certificate %s with valid keys.\n", argv[0]);
|
|
goto ErrCleanUp;
|
|
}
|
|
|
|
// At this point we have a provider, Cert and a public key.
|
|
// We should be able to encrypt
|
|
|
|
// Read in the clear text file
|
|
if(
|
|
|
|
// read in the file to encrypt
|
|
(hFile = CreateFileA(
|
|
argv[1], // pointer to name of the file
|
|
GENERIC_READ, // access (read-write) mode
|
|
FILE_SHARE_READ, // share mode
|
|
NULL, // pointer to security descriptor
|
|
OPEN_EXISTING, // how to create
|
|
FILE_ATTRIBUTE_NORMAL, // file attributes
|
|
NULL // handle to file with attributes to copy
|
|
)) == INVALID_HANDLE_VALUE ||
|
|
|
|
// create a file mapping object
|
|
(hMap = CreateFileMapping(
|
|
hFile, // handle to file to map
|
|
NULL, // optional security attributes
|
|
PAGE_READONLY, // protection for mapping object
|
|
0, // high-order 32 bits of object size
|
|
0, // low-order 32 bits of object size
|
|
NULL // name of file-mapping object
|
|
)) == NULL ||
|
|
|
|
// Map the file into the address space
|
|
(pbFile = (PBYTE) MapViewOfFileEx(
|
|
hMap, // file-mapping object to map into address space
|
|
FILE_MAP_READ, // access mode
|
|
0, // high-order 32 bits of file offset
|
|
0, // low-order 32 bits of file offset
|
|
0, // number of bytes to map
|
|
NULL // suggested starting address for mapped view
|
|
)) == NULL
|
|
)
|
|
{
|
|
|
|
PRINTERROR("File Open", GetLastError());
|
|
goto ErrCleanUp;
|
|
}
|
|
|
|
// get the size of the file
|
|
if( (cbFile = GetFileSize(
|
|
hFile, // handle of file to get size of
|
|
NULL // address of high-order word for file size
|
|
)) == 0
|
|
)
|
|
{
|
|
printf("File %s has a 0 length.\n", argv[1]);
|
|
goto ErrCleanUp;
|
|
}
|
|
|
|
// at this point we have a file mapping, go ahead and encrypt the file
|
|
|
|
// Do rc4 encryption
|
|
memset(&encryptInfo, 0, sizeof(CRYPT_ENCRYPT_MESSAGE_PARA));
|
|
encryptInfo.cbSize =
|
|
sizeof(CRYPT_ENCRYPT_MESSAGE_PARA);
|
|
encryptInfo.dwMsgEncodingType = PKCS_7_ASN_ENCODING;
|
|
encryptInfo.hCryptProv = hProv;
|
|
encryptInfo.ContentEncryptionAlgorithm = encryptAlgId;
|
|
|
|
if (fSP3) {
|
|
memset(&SP3AuxInfo, 0, sizeof(CMSG_SP3_COMPATIBLE_AUX_INFO));
|
|
SP3AuxInfo.cbSize = sizeof(CMSG_SP3_COMPATIBLE_AUX_INFO);
|
|
SP3AuxInfo.dwFlags = CMSG_SP3_COMPATIBLE_ENCRYPT_FLAG;
|
|
encryptInfo.pvEncryptionAuxInfo = &SP3AuxInfo;
|
|
}
|
|
|
|
// encrypt it
|
|
fResult = MCryptEncryptMessage(
|
|
&encryptInfo,
|
|
1,
|
|
&pCertContext,
|
|
pbFile,
|
|
cbFile,
|
|
&pbEncryptedBlob,
|
|
&cbEncryptedBlob
|
|
);
|
|
if (!fResult && fSP3 && (DWORD) E_INVALIDARG == GetLastError()) {
|
|
printf(
|
|
"Non-NULL pvEncryptionAuxInfo not supported in SP3 crypt32.dll\n");
|
|
|
|
encryptInfo.pvEncryptionAuxInfo = NULL;
|
|
fResult = MCryptEncryptMessage(
|
|
&encryptInfo,
|
|
1,
|
|
&pCertContext,
|
|
pbFile,
|
|
cbFile,
|
|
&pbEncryptedBlob,
|
|
&cbEncryptedBlob
|
|
);
|
|
}
|
|
if (!fResult) {
|
|
PRINTERROR("MCryptEncryptMessage", GetLastError());
|
|
goto ErrCleanUp;
|
|
}
|
|
|
|
// write the encrypted file out
|
|
if(
|
|
|
|
// open the output file
|
|
(hFileOut = CreateFileA(
|
|
argv[2], // pointer to name of the file
|
|
GENERIC_WRITE, // access (read-write) mode
|
|
FILE_SHARE_READ, // share mode
|
|
NULL, // pointer to security descriptor
|
|
CREATE_ALWAYS, // how to create
|
|
FILE_ATTRIBUTE_NORMAL, // file attributes
|
|
NULL // handle to file with attributes to copy
|
|
)) == INVALID_HANDLE_VALUE ||
|
|
|
|
//write to the file
|
|
!WriteFile(
|
|
hFileOut, // handle to file to write to
|
|
pbEncryptedBlob, // pointer to data to write to file
|
|
cbEncryptedBlob, // number of bytes to write
|
|
&cb, // pointer to number of bytes written
|
|
NULL // pointer to structure needed for overlapped I/O
|
|
)
|
|
)
|
|
{
|
|
PRINTERROR("File Write", GetLastError());
|
|
goto ErrCleanUp;
|
|
}
|
|
|
|
|
|
CleanUp:
|
|
|
|
if(hDll)
|
|
FreeLibrary(hDll);
|
|
|
|
if(hMap != NULL)
|
|
CloseHandle(hMap);
|
|
|
|
if(hFile != INVALID_HANDLE_VALUE && hFile != NULL)
|
|
CloseHandle(hFile);
|
|
|
|
if(hFileOut != INVALID_HANDLE_VALUE && hFile != NULL)
|
|
CloseHandle(hFileOut);
|
|
|
|
if(pCertContext != NULL)
|
|
CertFreeCertificateContext(pCertContext);
|
|
|
|
if(hProv != NULL)
|
|
CryptReleaseContext(hProv, 0);
|
|
|
|
if(hMyStore != NULL)
|
|
CertCloseStore(hMyStore, 0);
|
|
|
|
if(pbEncryptedBlob != NULL)
|
|
free(pbEncryptedBlob);
|
|
|
|
return(dwExitValue);
|
|
|
|
ErrCleanUp:
|
|
dwExitValue = 1;
|
|
goto CleanUp;
|
|
}
|
|
|
|
|