TSFISample.cpp
//
tsfisample.cpp : sample application focused on the interfaces that comprise
// the TSFI.
//
#include "stdafx.h"
//Global
variables
const char*
g_banner =
"********************************************************************************";
/**
g_mediator
contains the mediator/colleague set that will be used by
all commands
that require PKI support.
*/
IPKIFMediator* g_mediator = NULL;
/**
g_settings
contains user-specified path settings.
*/
CPKIFPathSettingsPtr
g_settings;
/**
g_path contains
the path object used for iterative calls to BuildPath and
ValidatePath and
g_pathResults contains the associated results.
*/
CPKIFCertificatePathPtr
g_path;
CPKIFPathValidationResultsPtr
g_results;
typedef pair<string,
Commands> CommandMap;
int _tmain(int argc, _TCHAR* argv[])
{
//Prepare a map containing command
strings and enumerated values
g_map.insert(CommandMap(string("0"), CMD_QUIT));
g_map.insert(CommandMap(string("1"),
CMD_NEW_DEFAULT_MEDIATOR));
g_map.insert(CommandMap(string("2"),
CMD_NEW_MEDIATOR_WITH_OCSP));
g_map.insert(CommandMap(string("3"), CMD_ADD_LDAP));
g_map.insert(CommandMap(string("4"),
CMD_SPECIFY_DEFAULT_SETTINGS));
g_map.insert(CommandMap(string("5"),
CMD_USE_DEFAULT_SETTINGS));
g_map.insert(CommandMap(string("6"),
CMD_BUILD_PATH));
g_map.insert(CommandMap(string("7"), CMD_VAL_PATH));
g_map.insert(CommandMap(string("8"),
CMD_BUILD_AND_VAL_PATH));
g_map.insert(CommandMap(string("9"), CMD_GEN_SIG));
g_map.insert(CommandMap(string("10"), CMD_VER_SIG));
g_map.insert(CommandMap(string("11"), CMD_ENC_MSG));
g_map.insert(CommandMap(string("12"), CMS_DEC_MSG));
//in g_mediator. Operators are free to replace this via a call
to
//Cmd_NewDefaultMediator or
Cmd_NewMediatorWithOCSP and to alter it
//via a call to Cmd_AddLDAP.
Cmd_NewDefaultMediator();
{
//Show the menu, then...
DisplayMainMenu();
//Handle the command and
determine if there's more to do
} while(ProcessCommand());
cout << "Goodbye!" << endl;
return 0;
}
//***************************************************************************
// UTILITY
FUNCTIONS
//***************************************************************************
/**
DisplayMainMenu
permits the user to perform the tasks defined in the
Commands
enumeration.
*/
void DisplayMainMenu()
{
cout << g_banner << endl;
cout << "Select from the following commands. Enter 0 to quit." << endl << endl;
cout << "Environment definition commands:"
<< endl;
cout << "\t1 - Create default mediator/colleague
set" << endl
<< "\t2 - Create default mediator/colleage set
with a trusted OCSP responder" << endl
<< "\t3 - Add an LDAP directory to previously
created mediator/colleague set" << endl
<< "\t4 - Specify path processing
settings" << endl
<< "\t5 - Use default path processing
settings" << endl << endl;
cout << "Certification path processing
commands:" << endl;
cout << "\t6 - Build a certification path"
<< endl
<< "\t7 - Validate a certification path (must
follow \"Build a certification path\")" << endl
<< "\t8 - Build and validate a certification
path" << endl << endl;
cout << "Signature processing commands:"
<< endl;
cout << "\t9 - Generate a signed message"
<< endl
<< "\t10 - Verify a signed message"
<< endl << endl;
cout << "PKI encryption processing commands:"
<< endl;
cout << "\t11 - Generate an encrypted message"
<< endl
<< "\t12 - Decrypt an encrypted message"
<< endl;
cout << g_banner << endl;
}
void CleanGlobals()
{
//Free the mediator, there is
one. all other globals are smart
pointers
//that will be cleaned up
automatically
if(g_mediator)
FreeDefaultMediator(g_mediator);
g_mediator = NULL;
}
void Pause()
{
system("pause");
}
bool ProcessCommand()
{
try
{
bool bQuit = false;
char buf[50];
cin >> buf;
int cmd = -1;
map <string, Commands> :: const_iterator cm =
g_map.find(string(buf));
if(cm != g_map.end())
cmd = cm->second;
switch(cmd)
{
case CMD_QUIT:
bQuit = true;
Cmd_Quit();
break;
case
CMD_NEW_DEFAULT_MEDIATOR:
Cmd_NewDefaultMediator();
break;
case
CMD_NEW_MEDIATOR_WITH_OCSP:
Cmd_NewMediatorWithOCSP();
break;
case CMD_ADD_LDAP:
Cmd_AddLDAP();
break;
case
CMD_SPECIFY_DEFAULT_SETTINGS:
Cmd_SpecifyDefaultSettings();
break;
case
CMD_USE_DEFAULT_SETTINGS:
Cmd_UseDefaultSettings();
break;
case CMD_BUILD_PATH:
Cmd_BuildPath();
break;
case CMD_VAL_PATH:
Cmd_ValidatePath();
break;
case
CMD_BUILD_AND_VAL_PATH:
Cmd_BuildAndValidatePath();
break;
case CMD_GEN_SIG:
Cmd_GenerateSignature();
break;
case CMD_VER_SIG:
Cmd_VerifySignature();
break;
case CMD_ENC_MSG:
Cmd_EncryptMessage();
break;
case CMS_DEC_MSG:
Cmd_DecryptMessage();
break;
default:
cout << "ERROR: Unrecognized
command" << endl;
}
if(!bQuit)
Pause();
return !bQuit;
}
catch(CPKIFException& pe)
{
CPKIFStringPtr details = pe.print();
cout << details->c_str() << endl;
Pause();
}
catch(std::exception& se)
{
cout << "Unexpected std::exception"
<< endl;
Pause();
}
catch(...)
{
cout << "Unexpected exception." <<
endl;
Pause();
}
return true;
}
bool SolicitBool(const char* prompt)
{
do
{
cout << prompt << "(y or n)?: ";
char buf;
cin >> buf;
if('y' == buf || 'Y' ==
buf)
return true;
else if('n' == buf || 'N' == buf)
return false;
else
cout << "ERROR: You entered an invalid
character." << endl;
}
while(1);
}
bool SolicitInteger(const char* prompt)
{
do
{
cout << prompt << ": ";
char buf[25];
cin >> buf;
return (atoi(buf));
}
while(1);
}
CPKIFTimePtr
GetTimeOfInterest()
{
if(SolicitBool("Verify
paths relative to a time other than the current system time"))
{
do
{
cout << "Enter the validation time of
interest as GeneralizedTime string (e.g., 20050305124955X): ";
char buf[100];
cin >> buf;
try
{
CPKIFTimePtr time(new
CPKIFTime(buf));
return time;
}
catch(CPKIFException&
e)
{
cout << "ERROR: invalid time value
entered" << endl;
}
}
while(1);
}
else
{
CPKIFTimePtr time;
return time;
}
}
void
GetPolicyOIDs(vector<CPKIFPolicyInformationPtr>& oids)
{
bool addAnother = false;
char oidBuf[100];
cout << "Enter OIDs corresponding to certificate
policies in the initial policy set." << endl;
do
{
memset(oidBuf, 0, 100);
cout << "Enter an OID value corresponding to a
certificate policy using dot notation (e.g., 2.5.29.37.0): " <<
endl;
cin >> oidBuf;
try
{
CPKIFOIDPtr oid(new
CPKIFOID(new string(oidBuf)));
CPKIFPolicyInformationPtr policy(new CPKIFPolicyInformation(oid));
oids.push_back(policy);
addAnother = SolicitBool("Would you like to
add another policy");
}
catch(CPKIFException&
e)
{
cout << "ERROR: invalid OID
entered" << endl;
}
}while(addAnother);
}
CPKIFPathSettingsPtr
GetPathSettingsFromUser()
{
CPKIFPathSettingsPtr settings(new
CPKIFPathSettings());
//builder-focused setting
settings->SetUseValidatorFilterWhenBuilding(SolicitBool
("Should basic validation checks be performed during
path building"));
//revocation-related settings
settings->SetCheckRevocationStatus(SolicitBool
("Should revocation status be checked during path
validation"));
if(settings->GetCheckRevocationStatus())
{
settings->SetRequireFreshRevocationData(SolicitBool
("Should fresh revocation data, i.e.
nextUpdate < TOI, be required"));
if(SolicitBool("Should recent revocation data, i.e.
thisUpdate > threshold, be required"))
{
settings->SetRequireSufficientlyRecent(true);
settings->SetSufficientlyRecent(SolicitInteger
("Enter the maximum age of acceptable
revocation status information (in seconds)"));
}
else
{
settings->SetRequireSufficientlyRecent(false);
}
}
else
{
//these don't matter since we
aren't checking revocation status,
//but set to false anyway
settings->SetRequireFreshRevocationData(false);
settings->SetRequireSufficientlyRecent(false);
}
//time of interest for validation
CPKIFTimePtr time = GetTimeOfInterest();
if(time != (CPKIFTime*)NULL)
{
settings->SetValidationTime(time);
}
settings->SetInitialExplicitPolicyIndicator(SolicitBool
("Should the initial explicit policy indicator be
set to true"));
settings->SetInitialInhibitAnyPolicyIndicator(SolicitBool
("Should the initial inhibit any policy indicator be
set to true"));
settings->SetInitialPolicyMappingInhibitIndicator(SolicitBool
("Should the initial policy mapping inhibit
indicator be set to true"));
if(SolicitBool("Would you
like to specify policies for the initial policy set"))
{
vector<CPKIFPolicyInformationPtr> oids;
GetPolicyOIDs(oids);
CPKIFPolicyInformationListPtr list(new CPKIFPolicyInformationList);
vector<CPKIFPolicyInformationPtr>::iterator pos;
vector<CPKIFPolicyInformationPtr>::iterator end =
oids.end();
for(pos = oids.begin();
pos != end; ++pos)
list->push_back((*pos));
settings->SetInitialPolicySet(list);
}
return settings;
}
long filesize(FILE *stream)
{
long curpos, length;
curpos = ftell(stream);
fseek(stream, 0L, SEEK_END);
length = ftell(stream);
fseek(stream, curpos, SEEK_SET);
return length;
}
bool WriteToFile(const char* prompt, const unsigned char* pBuf, int
nLenOfBuf)
{
do
{
cout << prompt << ": ";
char buf[MAX_PATH];
cin >> buf;
FILE* f = fopen(buf, "wb+");
if(!f)
{
cout << "ERROR: failed to open the
specified file for writing" << endl;
}
else
{
size_t bytesRead = fwrite(pBuf, 1, nLenOfBuf, f);
fclose(f);
cout << "Wrote " << bytesRead
<< " bytes to " << buf << endl;
return true;
}
}while(1);
return false;
}
bool SolicitFile(const char* prompt, unsigned char**
ppBuf, int* pLenOfBuf)
{
do
{
cout << prompt << ": ";
char buf[MAX_PATH];
cin >> buf;
FILE* f = fopen(buf, "rb");
if(!f)
{
cout << "ERROR: failed to open the
specified file for reading" << endl;
}
else
{
*pLenOfBuf = filesize(f);
*ppBuf = new unsigned char[*pLenOfBuf];
size_t bytesRead = fread(*ppBuf, 1, *pLenOfBuf, f);
fclose(f);
cout << "Read " << bytesRead
<< " bytes from " << buf << endl;
return true;
}
}while(1);
//give up (never gets here)
return false;
}
CPKIFCertificatePtr
GetCertificate(const char*
prompt)
{
unsigned char* pTargetCertBuf = NULL;
int nTargetCertLen = 0;
if(!SolicitFile(prompt,
&pTargetCertBuf, &nTargetCertLen))
{
cout << "ERROR: Failed to read target
certificate from specified file." << endl;
CPKIFCertificatePtr targetCert;
return targetCert;
}
CPKIFCertificatePtr targetCert(new
CPKIFCertificate);
targetCert->Decode(pTargetCertBuf, nTargetCertLen);
//clean up buffer returned from
SolicitFile. A copy has been made by
targetCert.
delete[] pTargetCertBuf;
pTargetCertBuf = NULL;
return targetCert;
}
//***************************************************************************
// COMMAND
FUNCTIONS
//***************************************************************************
/**
Cmd_Quit is
called when the user selects the Quit option from the main
menu.
This function
must clean up any memory stored in global variables.
*/
void Cmd_Quit()
{
CleanGlobals();
}
/**
Cmd_NewDefaultMediator
is called when the user selects the "Create default mediator/colleague
set"
option from the
main menu.
*/
void Cmd_NewDefaultMediator()
{
CleanGlobals();
g_mediator = MakeDefaultMediator();
}
/**
Cmd_NewMediatorWithOCSP
is called when the user selects the "Create default
mediator/colleague
set with a trusted OCSP responder" option from the main menu.
This function
permits the user create a mediator/colleague set in which the first
revocation status
source is a trusted responder.
*/
void Cmd_NewMediatorWithOCSP()
{
CleanGlobals();
char host[MAX_PATH];
cout << "Enter the IP address or DNS name of the
OCSP responder: " << endl;
cin >> host;
int port;
cout << "Enter the port number of the OCSP
responder: " << endl;
cin >> port;
CPKIFOCSPChecker* ocsp = new
CPKIFOCSPChecker();
ocsp->SetHost((const char*)host);
ocsp->Set_Port(port);
g_mediator = MakeDefaultMediator(false,
ocsp);
}
/**
Cmd_AddLDAP is
called when the user selects the "Add an LDAP directory to previously
created
mediator/colleague set" option from the main menu.
This function
permits the user to add an LDAP-accessible directory to the mediator/colleague
collection stored
in g_mediator.
*/
void Cmd_AddLDAP()
{
char host[MAX_PATH];
cout << "Enter the IP address or DNS name of the
LDAP directory: " << endl;
cin >> host;
int port;
cout << "Enter the port number of the LDAP
directory: " << endl;
cin >> port;
CPKIFLDAPRepository* ldap = new
CPKIFLDAPRepository();
ldap->SetHost((const char*)host);
ldap->Set_Port(port);
CPKIFCacheMediator2* pCache =
g_mediator->GetMediator<CPKIFCacheMediator2>();
pCache->AddColleague(ldap);
}
Cmd_SpecifyDefaultSettings
is called when the user selects the "Specify path
processing
settings" option from the main menu.
This function
must permit the user to specify a the various properties of CPKIFPathSettings.
*/
void
Cmd_SpecifyDefaultSettings()
{
g_settings = GetPathSettingsFromUser();
}
/**
Cmd_UseDefaultSettings
is called when the user selects the "Use default path processing
settings" option from the main menu.
This function
must permit the user to specify a the various properties of CPKIFPathSettings.
*/
void Cmd_UseDefaultSettings()
{
CPKIFPathSettingsPtr ps(new
CPKIFPathSettings);
g_settings = ps;
}
/**
Cmd_BuildPath is
called when the user selects the "Build a certification path" option
from the main menu.
This function
must permit the user to specify a target certificate, and optionally
path settings,
then attempt to build a path using the global mediator.
*/
void Cmd_BuildPath()
{
bool bReset = false;
if(g_path !=
(CPKIFCertificatePath*)NULL)
{
bReset = SolicitBool
("Reset state variables and begin a new path
building operation");
}
if(bReset || g_path ==
(CPKIFCertificatePath*)NULL)
{
CPKIFCertificatePtr targetCert = GetCertificate(
"Enter the full path and file name of the
target certificate");
if(targetCert ==
(CPKIFCertificate*)NULL)
return;
//Reset the global variables
used by BuildPath and ValidatePath
CPKIFCertificatePathPtr path(new
CPKIFCertificatePath);
g_path = path;
CPKIFPathValidationResultsPtr results(new CPKIFPathValidationResults);
g_results = results;
g_path->SetTarget(targetCert);
if(g_settings !=
(CPKIFPathSettings*)NULL)
g_path->SetPathSettings(g_settings);
}
if(iPB->BuildPath(*g_path))
cout << "Found a certification path. Details below..." << endl;
else
cout << "Failed to find a certification
path. Details below..." <<
endl;
CPKIFPathLogger logPath;
logPath.LogPath(*g_path, "TSFI Sample application",
&cout);
}
/**
Cmd_ValidatePath
is called when the user selects the "Validate a certification path"
option from the main menu.
This function
attempts to validate the path returned by the previous call to Build Path.
*/
void Cmd_ValidatePath()
{
if(g_path == (CPKIFCertificatePath*)NULL)
{
cout << "ERROR: no path is available. You must build a path before \
validating a path." << endl;
return;
}
IPKIFPathValidate* iPV =
g_mediator->GetMediator<IPKIFPathValidate>();
bool isSig = false, isEnc= false;
isSig = SolicitBool("Is the target certificate intended
for signature verification purposes");
isEnc = SolicitBool("Is the target certificate intended
for encryption purposes");
CPKIFFuncStoragePtr keyUsageProcessor(new
CPKIFFuncStorage(NULL));
if(isSig)
keyUsageProcessor->addFunc(keyUsageChecker_Signature);
if(isEnc)
keyUsageProcessor->addFunc(keyUsageChecker_Encryption);
iPV->ValidatePath(*g_path, *g_results, keyUsageProcessor);
CPKIFPathLogger logPath;
logPath.LogValidationResults(*g_results, *g_path, "TSFI
Sample application", &cout);
}
/**
Cmd_BuildAndValidatePath
is called when the user selects the "Build and validate a certification
path" option from the main menu.
This function
must permit the user to specify a target certificate, and optionally
path
settings. It then attempts to build a
path and validate a path using the global mediator.
*/
void Cmd_BuildAndValidatePath()
{
CPKIFCertificatePtr targetCert = GetCertificate(
"Enter the full path and file name of the target
certificate");
CPKIFCertificatePath path;
path.SetTarget(targetCert);
if(g_settings !=
(CPKIFPathSettings*)NULL)
path.SetPathSettings(g_settings);
CPKIFPathValidationResults pvr;
IPKIFPathBuildAndValidate* iPBAV = g_mediator->GetMediator<IPKIFPathBuildAndValidate>();
if(iPBAV)
iPBAV->BuildAndValidatePath(path, pvr);
CPKIFPathLogger logPath;
logPath.LogValidationResults(pvr, path, "TSFI Sample
application", &cout);
}
/**
Cmd_GenerateSignature
is called when the user selects the "Generate a signed message"
option from the main menu.
This function
must permit the user to specify content to sign, signer credential and file
name to which the signed
message will be written.
*/
void Cmd_GenerateSignature()
{
unsigned char* pDataToSign = NULL;
int nDataToSignLen = 0;
if(!SolicitFile(
"Enter the full path and file name of the file
containing the data to sign", &pDataToSign, &nDataToSignLen))
{
cout << "ERROR: Failed to read data to sign
from specified file." << endl;
return;
}
CPKIFBufferPtr contentBuffer(new
CPKIFBuffer(pDataToSign, nDataToSignLen));
delete[] pDataToSign;
pDataToSign = NULL;
CPKIFSignedData sd;
IPKIFCryptoKeyIDOperations* iKIDO = g_mediator->GetMediator<IPKIFCryptoKeyIDOperations>();
CPKIFCredentialList creds;
std::bitset<9> ku = DigitalSignature | NonRepudiation;
iKIDO->GetKeyList(creds, &ku);
bool addAnother = false;
do
{
cout << "The following " <<
creds.size() <<
" credentials are available for signature
generation purposes" << endl;
CPKIFCredentialList::iterator pos = creds.begin();
CPKIFCredentialList::iterator end = creds.end();
for(int slot = 0; pos != end; ++pos)
{
cout << slot++ << ": Name - "
<< (*pos)->Name() <<
"
ID: " << (*pos)->ID() << endl;
}
int selection = -1;
do
{
cout << "Enter the number corresponding
to the credential with which you \
would like to sign: ";
cin >> selection;
if(selection >
creds.size())
cout << "ERROR: invalid
selection" << endl;
else
{
CPKIFSignerInfoPtr si(new CPKIFSignerInfo);
si->SetCredential(creds[selection]);
sd.AddSignerInfo(si);
if(SolicitBool("Include
signer's certificate in message"))
sd.AddCertificate(creds[selection]->GetCertificate());
break;
}
}while(1);
addAnother = SolicitBool("Would you like to add
another signer");
}while(addAnother);
sd.AddMediator(g_mediator);
CPKIFEncapsulatedContentInfoPtr ecip(new
CPKIFEncapsulatedContentInfo);
ecip->SetContent(contentBuffer);
sd.SetEncapsulatedContent(ecip);
CPKIFBufferPtr encodedSD = sd.Encode();
CPKIFContentInfo ci;
ci.SetContentType(g_signedData);
ci.SetContent(encodedSD);
CPKIFBufferPtr signedMessage = ci.Encode();
WriteToFile("Enter the full path and filename of the
location to receive the signed message",
signedMessage->GetBuffer(),
signedMessage->GetLength());
}
/**
Cmd_VerifySignature
is called when the user selects the "Verify a signed message" option
from the main menu.
This function
must permit the user to specify content to verify and file name to which the
message content
will be written.
*/
void Cmd_VerifySignature()
{
unsigned char* pDataToVerify = NULL;
int nDataToVerifyLen = 0;
if(!SolicitFile("Enter the
full path and file name of the file containing the signed message \
to verify", &pDataToVerify,
&nDataToVerifyLen))
{
cout << "ERROR: Failed to read data to verify
from specified file." << endl;
return;
}
CPKIFContentInfo ci;
ci.Decode(pDataToVerify, nDataToVerifyLen);
delete[] pDataToVerify;
pDataToVerify = NULL;
if(*g_signedData !=
*ci.GetContentType())
{
cout << "ERROR: file does not contain a signed
message";
return;
}
CPKIFSignedData sd;
sd.AddMediator(g_mediator);
sd.Decode(ci.GetContent());
CPKIFSignerInfos sis;
sd.GetSignerInfos(sis);
do
{
cout << "The following " <<
sis.size() << " signers are available for signature \
verification purposes" << endl;
CPKIFSignerInfos::iterator pos = sis.begin();
CPKIFSignerInfos::iterator end = sis.end();
for(int slot = 0; pos != end; ++pos)
{
switch((*pos)->GetSignerIdentifierChoice())
{
case
CPKIFSignerInfo::ISSUERANDSERIAL:
{
CPKIFIssuerAndSerialNumberPtr iasn =
(*pos)->GetIssuerAndSerialNumber();
cout << slot++ << ":
Issuer - "
<< iasn->GetName()->string()
<< " Serial - "
<<
iasn->GetSerialNumber() << endl;
break;
}
case
CPKIFSignerInfo::SKID:
{
CPKIFBufferPtr skid =
(*pos)->GetSKID();
char*
asciiSKID = new char[(skid->GetLength()
* 2)+1];
btoa((const
char*)skid->GetBuffer(),
asciiSKID, skid->GetLength());
cout << slot++ << ":
" << asciiSKID << endl;
}
break;
default:
cout << "Unrecognized signer
identifier type" << endl;
}
}
int selection = -1;
do
{
cout << "Enter the number corresponding
to the signer whose signature you \
would like to verify: ";
cin >> selection;
if(selection >
sis.size())
cout << "ERROR: invalid
selection" << endl;
else
{
CMSVerificationStatus status = NOT_VERIFIED;
sd.Verify(selection, status);
cout << "Verification status =
";
switch(status)
{
case
REV_STATUS_INVALID:
cout <<
"REV_STATUS_INVALID" << endl;
break;
case
CERT_PATH_INVALID:
cout <<
"CERT_PATH_INVALID" << endl;
break;
case
CMS_SIGNATURE_INVALID:
cout <<
"CMS_SIGNATURE_INVALID" << endl;
break;
case
NOT_VERIFIED:
cout << "NOT_VERIFIED"
<< endl;
break;
case
CMS_SIGNATURE_VERIFIED:
cout <<
"CMS_SIGNATURE_VERIFIED" << endl;
break;
case
CERT_PATH_VERIFIED:
cout <<
"CERT_PATH_VERIFIED" << endl;
break;
case
REV_STATUS_VERIFIED:
cout <<
"REV_STATUS_VERIFIED" << endl;
break;
default:
cout << "UNRECOGNIZED
STATUS" << endl;
}
CPKIFPathValidationResultsPtr pvr =
sd.GetValidationResults();
CPKIFCertificatePathPtr path = sd.GetPath();
CPKIFPathLogger log;
log.LogValidationResults(*pvr, *path,
"TSFI Sample Application",
&cout);
break;
}
}while(1);
verifyAnother = SolicitBool("Would you like to
verify another signer");
}while(verifyAnother);
}
/**
Cmd_EncryptMessage
is called when the user selects the "Generate an encrypted message"
option from the main menu.
This function
must permit the user to specify content to encrypt and one or more recipients.
*/
void Cmd_EncryptMessage()
{
unsigned char* pDataToEncrypt = NULL;
int nDataToEncryptLen = 0;
if(!SolicitFile(
"Enter the full path and file name of the file
containing the data to encrypt",
&pDataToEncrypt, &nDataToEncryptLen))
{
cout << "ERROR: Failed to read data to sign
from specified file." << endl;
return;
}
CPKIFBufferPtr contentBuffer(new
CPKIFBuffer(pDataToEncrypt, nDataToEncryptLen));
delete[] pDataToEncrypt;
pDataToEncrypt = NULL;
CPKIFEnvelopedData ed;
ed.AddMediator(g_mediator);
bool addAnother = false;
do
{
bool checkStatus =
SolicitBool(
"Would you like to perform path validation for
the recipient's certificate");
CPKIFCertificatePtr cert = GetCertificate(
"Enter the full path and file name of a
recipient's DER encoded certificate");
if(cert ==
(CPKIFCertificate*)NULL)
{
cout << "ERROR: failed to obtain
recipient's certificate from specified file"
<< endl;
}
else
{
CPKIFCertificatePathPtr path;
CPKIFPathValidationResultsPtr pvr;
try
{
CMSPathValidationStatus minStatus =
PVS_REV_STATUS_VERIFIED;
if(!checkStatus)
minStatus = PVS_NOT_VALIDATED;
ed.AddRecipient(cert, path, pvr, minStatus);
cout << "Recipient added to
message" << endl;
}
catch(CPKIFException&
e)
{
if(MSG_INVALID_RECIP
!= e.GetErrorCode())
throw
e;
cout << "Recipient not added to
message" << endl;
CPKIFStringPtr details = e.print();
cout << details->c_str() <<
endl;
}
if(pvr !=
(CPKIFPathValidationResults*)NULL &&
path != (CPKIFCertificatePath*)NULL)
{
CPKIFPathLogger log;
log.LogValidationResults(*pvr, *path,
"TSFI Sample Application",
&cout);
}
}
addAnother = SolicitBool("Would you like to add
another recipient");
}while(addAnother);
CPKIFEncryptedContentInfoPtr ecip(new
CPKIFEncryptedContentInfo);
ecip->SetContent(contentBuffer);
ed.SetDataToEncrypt(ecip);
CPKIFBufferPtr encodedED = ed.Encode();
CPKIFContentInfo ci;
ci.SetContentType(g_envelopedData);
ci.SetContent(encodedED);
CPKIFBufferPtr encryptedMessage = ci.Encode();
WriteToFile("Enter the full path and filename of the
location to receive the \
encrypted message",
encryptedMessage->GetBuffer(), encryptedMessage->GetLength());
}
/**
Cmd_DecryptMessage
is called when the user selects the "Decrypt an encrypted message"
option from the main menu.
This function
must permit the user to specify content to decrypt. It could
be extended to
permit specification of the credential to use to perform the decryption.
*/
void Cmd_DecryptMessage()
{
unsigned char* pDataToDecrypt = NULL;
int nDataToDecryptLen = 0;
if(!SolicitFile("Enter the
full path and file name of the file containing the data to \
decrypt", &pDataToDecrypt,
&nDataToDecryptLen))
{
cout << "ERROR: Failed to read data to decrypt
from specified file." << endl;
return;
}
CPKIFContentInfo ci;
ci.Decode(pDataToDecrypt, nDataToDecryptLen);
delete[] pDataToDecrypt;
pDataToDecrypt = NULL;
if(*g_envelopedData !=
*ci.GetContentType())
{
cout << "ERROR: file does not contain an
encrypted message";
return;
}
CPKIFEnvelopedData ed;
ed.Decode(ci.GetContent());
ed.AddMediator(g_mediator);
CPKIFCredentialPtr dummy;
CPKIFBufferPtr decryptedMessage = ed.Decrypt(dummy);
WriteToFile("Enter the full path and filename of the
location to receive the encrypted \
message",
decryptedMessage->GetBuffer(), decryptedMessage->GetLength());
}