in xsec/tools/templatesign/templatesign.cpp [553:1342]
int main(int argc, char **argv) {
XSECCryptoKey * key = NULL;
DSIGKeyInfoX509 * keyInfoX509 = NULL;
const char * x509SubjectName = NULL;
#if defined (XSEC_HAVE_OPENSSL)
OpenSSLCryptoX509 * certs[128];
#endif
int certCount = 0;
int paramCount;
bool clearKeyInfo = false;
#if defined(XSEC_HAVE_WINCAPI)
HCRYPTPROV win32DSSCSP = 0; // Crypto Provider
HCRYPTPROV win32RSACSP = 0; // Crypto Provider
bool winDssKeyInfo = false;
bool winRsaKeyInfo = false;
WinCAPICryptoKeyDSA * winKeyDSA = NULL;
WinCAPICryptoKeyRSA * winKeyRSA = NULL;
#endif
// Initialise the XML system
try {
XMLPlatformUtils::Initialize();
#ifdef XSEC_HAVE_XALAN
XPathEvaluator::initialize();
XalanTransformer::initialize();
#endif
XSECPlatformUtils::Initialise();
}
catch (const XMLException &e) {
cerr << "Error during initialisation of Xerces" << endl;
cerr << "Error Message = : "
<< e.getMessage() << endl;
}
#if defined (XSEC_HAVE_OPENSSL)
// Initialize OpenSSL
ERR_load_crypto_strings();
BIO * bio_err;
if ((bio_err=BIO_new(BIO_s_file())) != NULL)
BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
#endif
if (argc < 2) {
printUsage();
exit (1);
}
paramCount = 1;
while (paramCount < argc - 1) {
// Run through all parameters
if (_stricmp(argv[paramCount], "--x509subjectname") == 0 || _stricmp(argv[paramCount], "-s") == 0) {
if (paramCount +2 >= argc) {
printUsage();
exit(1);
}
// Get the subject name
x509SubjectName = argv[paramCount + 1];
paramCount += 2;
}
#if defined (XSEC_HAVE_OPENSSL)
else if (_stricmp(argv[paramCount], "--dsakey") == 0 || _stricmp(argv[paramCount], "-d") == 0
|| _stricmp(argv[paramCount], "--rsakey") == 0 || _stricmp(argv[paramCount], "-r") == 0
# if defined(XSEC_OPENSSL_HAVE_EC)
|| _stricmp(argv[paramCount], "--eckey") == 0 || _stricmp(argv[paramCount], "-e") == 0
# endif
) {
// OpenSSL Key
if (paramCount + 3 >= argc) {
printUsage();
exit (1);
}
if (key != 0) {
cerr << "\nError loading private key - another key already loaded\n\n";
printUsage();
exit(1);
}
// Load the signing key
// For now just read a particular file
BIO * bioKey;
if ((bioKey = BIO_new(BIO_s_file())) == NULL) {
cerr << "Error opening private key file\n\n";
exit (1);
}
if (BIO_read_filename(bioKey, argv[paramCount + 1]) <= 0) {
cerr << "Error opening private key file\n\n";
exit (1);
}
EVP_PKEY * pkey;
pkey = PEM_read_bio_PrivateKey(bioKey,NULL,NULL,argv[paramCount + 2]);
if (pkey == NULL) {
cerr << "Error loading private key\n\n";
ERR_print_errors(bio_err);
exit (1);
}
if (_stricmp(argv[paramCount], "--dsakey") == 0 || _stricmp(argv[paramCount], "-d") == 0) {
// Check type is correct
if (EVP_PKEY_id(pkey) != EVP_PKEY_DSA) {
cerr << "DSA Key requested, but OpenSSL loaded something else\n";
exit (1);
}
// Create the XSEC OpenSSL interface
key = new OpenSSLCryptoKeyDSA(pkey);
}
#if defined(XSEC_OPENSSL_HAVE_EC)
else if (_stricmp(argv[paramCount], "--eckey") == 0 || _stricmp(argv[paramCount], "-e") == 0) {
// Check type is correct
if (EVP_PKEY_id(pkey) != EVP_PKEY_EC) {
cerr << "EC Key requested, but OpenSSL loaded something else\n";
exit (1);
}
// Create the XSEC OpenSSL interface
key = new OpenSSLCryptoKeyEC(pkey);
}
#endif
else {
if (EVP_PKEY_id(pkey) != EVP_PKEY_RSA) {
cerr << "RSA Key requested, but OpenSSL loaded something else\n";
exit (1);
}
key = new OpenSSLCryptoKeyRSA(pkey);
}
EVP_PKEY_free(pkey);
BIO_free(bioKey);
paramCount += 3;
} /* argv[1] = "dsa/rsa/ec" */
else if (_stricmp(argv[paramCount], "--x509cert") == 0 || _stricmp(argv[paramCount], "-x") == 0) {
// X509Data keyInfo
if (paramCount + 2 >= argc) {
printUsage();
exit (1);
}
// Load the cert.
// For now just read a particular file
BIO * bioX509;
if ((bioX509 = BIO_new(BIO_s_file())) == NULL) {
cerr << "Error opening file\n\n";
exit (1);
}
if (BIO_read_filename(bioX509, argv[paramCount + 1]) <= 0) {
cerr << "Error opening X509 Certificate " << argv[paramCount + 1] << "\n\n";
exit (1);
}
X509 * x
;
x = PEM_read_bio_X509_AUX(bioX509,NULL,NULL,NULL);
if (x == NULL) {
cerr << "Error loading certificate\n\n";
ERR_print_errors(bio_err);
exit (1);
}
// Create the XSEC OpenSSL interface - used only to translate to Base64
certs[certCount++] = new OpenSSLCryptoX509(x);
X509_free(x);
BIO_free(bioX509);
paramCount += 2;
} /* argv[1] = "--x509cert" */
else
#endif
if (_stricmp(argv[paramCount], "--hmackey") == 0 || _stricmp(argv[paramCount], "-h") == 0) {
XSECCryptoKeyHMAC* hmacKey = XSECPlatformUtils::g_cryptoProvider->keyHMAC();
hmacKey->setKey((unsigned char *) argv[paramCount + 1], (unsigned int) strlen(argv[paramCount + 1]));
key = hmacKey;
paramCount += 2;
}
else if (_stricmp(argv[paramCount], "--clearkeys") == 0 || _stricmp(argv[paramCount], "-c") == 0) {
clearKeyInfo = true;
paramCount += 1;
}
#if defined (XSEC_HAVE_WINCAPI)
else if (_stricmp(argv[paramCount], "--windss") == 0 || _stricmp(argv[paramCount], "-wd") == 0) {
WinCAPICryptoProvider * cp;
// First set windows as the crypto provider
cp = new WinCAPICryptoProvider();
XSECPlatformUtils::SetCryptoProvider(cp);
// Now set the key
if (!CryptAcquireContext(&win32DSSCSP,
NULL,
NULL,
PROV_DSS,
0)) {
cerr << "Error acquiring Crypto context - Attempting to generate new key pair" << endl;
// Attempt to gen a new keyset
if (!CryptAcquireContext(&win32DSSCSP,
NULL,
NULL,
PROV_DSS,
CRYPT_NEWKEYSET)) {
cerr << "Error acquiring DSS Crypto Service Provider with new keyset" << endl;
return 2;
}
else {
HCRYPTKEY k;
if (!CryptGenKey(win32DSSCSP, AT_SIGNATURE, CRYPT_EXPORTABLE, &k)) {
cerr << "Error generating DSS keyset" << endl;
return 2;
}
CryptDestroyKey(k);
}
}
winKeyDSA = new WinCAPICryptoKeyDSA(win32DSSCSP, AT_SIGNATURE, true);
key = winKeyDSA;
paramCount++;
}
else if (_stricmp(argv[paramCount], "--winrsa") == 0 || _stricmp(argv[paramCount], "-wr") == 0) {
WinCAPICryptoProvider * cp;
cp = new WinCAPICryptoProvider();
XSECPlatformUtils::SetCryptoProvider(cp);
if (!CryptAcquireContext(&win32RSACSP,
NULL,
NULL,
PROV_RSA_FULL,
0)) {
cerr << "Error acquiring Crypto context - Attempting to generate new RSA key pair" << endl;
// Attempt to gen a new keyset
if (!CryptAcquireContext(&win32RSACSP,
NULL,
NULL,
PROV_RSA_FULL,
CRYPT_NEWKEYSET)) {
cerr << "Error acquiring RSA Crypto Service Provider with new keyset" << endl;
return 2;
}
else {
HCRYPTKEY k;
if (!CryptGenKey(win32RSACSP, AT_SIGNATURE, CRYPT_EXPORTABLE, &k)) {
cerr << "Error generating RSA keyset" << endl;
return 2;
}
CryptDestroyKey(k);
}
}
winKeyRSA = new WinCAPICryptoKeyRSA(win32RSACSP, AT_SIGNATURE, true);
key = winKeyRSA;
paramCount++;
}
else if (_stricmp(argv[paramCount], "--winhmac") == 0 || _stricmp(argv[paramCount], "-wh") == 0) {
WinCAPICryptoProvider * cp;
// Obtain default PROV_RSA, with default user key container
// Note we open in VERIFYCONTEXT as we do not require a assymetric key pair
if (!CryptAcquireContext(&win32RSACSP,
NULL,
NULL,
PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT)) {
cerr << "Error acquiring RSA Crypto Service Provider" << endl;
return 2;
}
cp = new WinCAPICryptoProvider();
XSECPlatformUtils::SetCryptoProvider(cp);
paramCount++;
HCRYPTKEY k;
HCRYPTHASH h;
BOOL fResult = CryptCreateHash(
win32RSACSP,
CALG_SHA,
0,
0,
&h);
if (fResult == 0) {
cerr << "Error creating hash to create windows hmac key from password" << endl;
return 2;
}
fResult = CryptHashData(
h,
(unsigned char *) argv[paramCount],
(DWORD) strlen(argv[paramCount]),
0);
if (fResult == 0) {
cerr << "Error hashing password to create windows hmac key" << endl;
return 2;
}
// Now create a key
fResult = CryptDeriveKey(
win32RSACSP,
CALG_RC2,
h,
CRYPT_EXPORTABLE,
&k);
if (fResult == 0) {
cerr << "Error deriving key from hash value" << endl;
return 2;
}
// Wrap in a WinCAPI object
WinCAPICryptoKeyHMAC * hk;
hk = new WinCAPICryptoKeyHMAC(win32RSACSP);
hk->setWinKey(k);
key = hk;
CryptDestroyHash(h);
paramCount++;
}
else if (_stricmp(argv[paramCount], "--windsskeyinfo") == 0 || _stricmp(argv[paramCount], "-wdi") == 0) {
winDssKeyInfo = true;
paramCount++;
}
else if (_stricmp(argv[paramCount], "--winrsakeyinfo") == 0 || _stricmp(argv[paramCount], "-wri") == 0) {
winRsaKeyInfo = true;
paramCount++;
}
// Need to find a better way to check this
// If CryptAcquireCertificatePrivateKey is not defined in the included
// version of wincapi.h, CRYPT_ACQUIRE_CACHE_FLAG will not be set
#if defined (CRYPT_ACQUIRE_CACHE_FLAG)
// Code provided by Milan Tomic
//Please note that this example below use CryptAcquireCertificatePrivateKey() function
//which is not declared in wincrypt.h that ships with VC++ 6. If you would like to run
//this example you'll need to replace your old wincrypt.h and crypt32.lib with new versions.
//This example below is compatible with Windows 98/IE 5 and above OS/IE versions.
else if (_stricmp(argv[paramCount], "--wincer") == 0 || _stricmp(argv[paramCount], "-wc") == 0) {
WinCAPICryptoProvider * cp;
PCCERT_CONTEXT pSignerCert = NULL;
DWORD dwKeySpec;
HCERTSTORE hStoreHandle;
#define MY_ENCODING_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
// Obtain default PROV_DSS with default user key container
if (!CryptAcquireContext(&win32DSSCSP,
NULL,
NULL,
PROV_DSS,
0)) {
cerr << "Error acquiring DSS Crypto Service Provider" << endl;
return 2;
}//*/
// Open 'Personal' certificate store
if (!(hStoreHandle = CertOpenStore(CERT_STORE_PROV_SYSTEM,
0,
NULL,
CERT_SYSTEM_STORE_CURRENT_USER,
L"MY"))) {
cerr << "Error opening 'Personal' store." << endl;
return 2;
}
// Find desired cerificate
if (!(pSignerCert = CertFindCertificateInStore(hStoreHandle,
MY_ENCODING_TYPE,
0,
CERT_FIND_SUBJECT_STR_A,
argv[paramCount+1],
NULL))) {
cerr << "Can't find '" << argv[paramCount+1] << "' certificate in 'Personal' store." << endl;
return 2;
}
// Now get certificate's private key
if (!CryptAcquireCertificatePrivateKey(pSignerCert,
0,
NULL,
&win32RSACSP,
&dwKeySpec,
NULL)) {
cerr << "Can't acquire private key of '" << argv[paramCount+1] << "' certificate." << endl;
exit(1);
}
cp = new WinCAPICryptoProvider();
XSECPlatformUtils::SetCryptoProvider(cp);
HCRYPTKEY k;
BOOL fResult = CryptGetUserKey(
win32RSACSP,
dwKeySpec,
&k);
if (!fResult || k == 0) {
cerr << "Error obtaining default user (AT_SIGNATURE or AT_KEYEXCHANGE) key from windows RSA provider.\n";
exit(1);
};
winKeyRSA = new WinCAPICryptoKeyRSA(win32RSACSP, k);
key = winKeyRSA;
paramCount += 2;
CertFreeCertificateContext(pSignerCert);
CertCloseStore(hStoreHandle, 0);
}
#endif /* CRYPT_ACQUIRE_CACHE_FLAG */
#endif /* XSEC_HAVE_WINCAPI */
else {
printUsage();
exit(1);
}
}
// Create and set up the parser
XercesDOMParser * parser = new XercesDOMParser;
parser->setDoNamespaces(true);
parser->setCreateEntityReferenceNodes(true);
// Now parse out file
bool errorsOccured = false;
XMLSize_t errorCount = 0;
try
{
parser->parse(argv[argc - 1]);
errorCount = parser->getErrorCount();
if (errorCount > 0)
errorsOccured = true;
}
catch (const XMLException& e)
{
cerr << "An error occurred during parsing\n Message: "
<< e.getMessage() << endl;
errorsOccured = true;
}
catch (const DOMException& e)
{
cerr << "A DOM error occurred during parsing\n DOMException code: "
<< e.code << endl;
errorsOccured = true;
}
if (errorsOccured) {
cout << "Errors during parse" << endl;
exit (1);
}
/*
Now that we have the parsed file, get the DOM document and start looking at it
*/
DOMNode *doc; // The document that we parsed
doc = parser->getDocument();
DOMDocument *theDOM = parser->getDocument();
// Find the signature node
DOMNode *sigNode = findDSIGNode(doc, "Signature");
// Create the signature checker
if (sigNode == 0) {
cerr << "Could not find <Signature> node in " << argv[argc-1] << endl;
exit(1);
}
XSECProvider * prov = new XSECProvider;
DSIGSignature * sig = prov->newSignatureFromDOM(theDOM, sigNode);
// Map out base path of the file
char * filename=argv[argc-1];
#if XSEC_HAVE_GETCWD_DYN
char *path = getcwd(NULL, 0);
char *baseURI = (char*)malloc(strlen(path) + 8 + 1 + strlen(filename) + 1);
#else
char path[PATH_MAX];
char baseURI[(PATH_MAX * 2) + 10];
getcwd(path, PATH_MAX);
#endif
strcpy(baseURI, "file:///");
// Ugly and nasty but quick
if (filename[0] != '\\' && filename[0] != '/' && filename[1] != ':') {
strcat(baseURI, path);
strcat(baseURI, "/");
} else if (path[1] == ':') {
path[2] = '\0';
strcat(baseURI, path);
}
strcat(baseURI, filename);
// Find any ':' and "\" characters
int lastSlash = 0;
for (unsigned int i = 8; i < strlen(baseURI); ++i) {
if (baseURI[i] == '\\') {
lastSlash = i;
baseURI[i] = '/';
}
else if (baseURI[i] == '/')
lastSlash = i;
}
// The last "\\" must prefix the filename
baseURI[lastSlash + 1] = '\0';
sig->getURIResolver()->setBaseURI(MAKE_UNICODE_STRING(baseURI));
#if XSEC_HAVE_GETCWD_DYN
free(path);
free(baseURI);
#endif
try {
sig->load();
if (clearKeyInfo == true)
sig->clearKeyInfo();
if (key != NULL)
sig->setSigningKey(key);
sig->sign();
// Add any KeyInfo elements
#if defined(XSEC_HAVE_WINCAPI)
if (winDssKeyInfo == true && winKeyDSA != NULL) {
char pBuf[1024];
char qBuf[1024];
char gBuf[1024];
char yBuf[1024];
unsigned int i;
i = winKeyDSA->getPBase64BigNums((char *) pBuf, 1024);
pBuf[i] = '\0';
i = winKeyDSA->getQBase64BigNums((char *) qBuf, 1024);
qBuf[i] = '\0';
i = winKeyDSA->getGBase64BigNums((char *) gBuf, 1024);
gBuf[i] = '\0';
i = winKeyDSA->getYBase64BigNums((char *) yBuf, 1024);
yBuf[i] = '\0';
sig->clearKeyInfo();
sig->appendDSAKeyValue(
MAKE_UNICODE_STRING(pBuf),
MAKE_UNICODE_STRING(qBuf),
MAKE_UNICODE_STRING(gBuf),
MAKE_UNICODE_STRING(yBuf));
}
if (winRsaKeyInfo == true && winKeyRSA != NULL) {
char eBuf[1024];
char mBuf[1024];
unsigned int i;
i = winKeyRSA->getExponentBase64BigNums((char *) eBuf, 1024);
eBuf[i] = '\0';
i = winKeyRSA->getModulusBase64BigNums((char *) mBuf, 1024);
mBuf[i] = '\0';
sig->clearKeyInfo();
sig->appendRSAKeyValue(
MAKE_UNICODE_STRING(mBuf),
MAKE_UNICODE_STRING(eBuf));
}
#endif
#if defined (XSEC_HAVE_OPENSSL)
if (certCount > 0) {
int i;
// Have some certificates - see if there is already an X509 list
DSIGKeyInfoList * kiList = sig->getKeyInfoList();
int kiSize = (int) kiList->getSize();
for (i = 0; i < kiSize; ++i) {
if (kiList->item(i)->getKeyInfoType() == DSIGKeyInfo::KEYINFO_X509) {
keyInfoX509 = (DSIGKeyInfoX509 *) kiList->item(i);
break;
}
}
if (keyInfoX509 == 0) {
// Not found - need to create
keyInfoX509 = sig->appendX509Data();
}
for (i = 0; i < certCount; ++i) {
keyInfoX509->appendX509Certificate(certs[i]->getDEREncodingSB().sbStrToXMLCh());
}
} /* certCount > 0 */
#endif
if (x509SubjectName != NULL) {
int i;
// Have some certificates - see if there is already an X509 list
DSIGKeyInfoList * kiList = sig->getKeyInfoList();
int kiSize = (int) kiList->getSize();
for (i = 0; i < kiSize; ++i) {
if (kiList->item(i)->getKeyInfoType() == DSIGKeyInfo::KEYINFO_X509) {
keyInfoX509 = (DSIGKeyInfoX509 *) kiList->item(i);
break;
}
}
if (keyInfoX509 == 0) {
// Not found - need to create
keyInfoX509 = sig->appendX509Data();
}
keyInfoX509->setX509SubjectName(MAKE_UNICODE_STRING(x509SubjectName));
} /* certCount > 0 */
}
catch (const XSECException &e) {
char * m = XMLString::transcode(e.getMsg());
cerr << "An error occurred during signing operation\n Message: "
<< m << endl;
XSEC_RELEASE_XMLCH(m);
errorsOccured = true;
exit (1);
}
catch (const XSECCryptoException &e) {
cerr << "A cryptographic error occurred during signature operation\n Message: "
<< e.getMsg() << endl;
errorsOccured = true;
exit(1);
}
catch (const NetAccessorException&) {
cerr << "A network error occurred during signing operation\n" << endl;
errorsOccured = true;
exit(1);
}
// Print out the result
DOMPrintFormatTarget* formatTarget = new DOMPrintFormatTarget();
const XMLCh* encNameStr = XMLString::transcode("UTF-8");
DOMNode *aNode = doc->getFirstChild();
if (aNode->getNodeType() == DOMNode::ENTITY_NODE)
{
const XMLCh* aStr = ((DOMEntity *)aNode)->getInputEncoding();
if (!strEquals(aStr, ""))
{
encNameStr = aStr;
}
}
XMLSize_t lent = XMLString::stringLen(encNameStr);
gEncodingName = new XMLCh[lent + 1];
XMLString::copyNString(gEncodingName, encNameStr, lent);
gEncodingName[lent] = 0;
gFormatter = new XMLFormatter("UTF-8", 0, formatTarget,
XMLFormatter::NoEscapes, gUnRepFlags);
cout << doc;
delete [] gEncodingName;
XMLCh * toRelease = (XMLCh *) encNameStr;
XSEC_RELEASE_XMLCH(toRelease);
delete gFormatter;
delete formatTarget;
#if defined (_WIN32) && defined (XSEC_HAVE_WINCAPI)
if (win32DSSCSP != 0)
CryptReleaseContext(win32DSSCSP,0);
if (win32RSACSP != 0)
CryptReleaseContext(win32RSACSP,0);
#endif
prov->releaseSignature(sig);
delete parser;
delete prov;
XSECPlatformUtils::Terminate();
#ifdef XSEC_HAVE_XALAN
XalanTransformer::terminate();
XPathEvaluator::terminate();
#endif
XMLPlatformUtils::Terminate();
return 0;
}