| /** |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| /* |
| * XSEC |
| * |
| * cipher := Tool to handle basic encryption/decryption of XML documents |
| * |
| * Author(s): Berin Lautenbach |
| * |
| * $Id$ |
| * |
| */ |
| |
| // XSEC |
| |
| #include <xsec/utils/XSECPlatformUtils.hpp> |
| #include <xsec/framework/XSECProvider.hpp> |
| #include <xsec/framework/XSECException.hpp> |
| #include <xsec/enc/XSECCryptoException.hpp> |
| #include <xsec/enc/XSECCryptoUtils.hpp> |
| #include <xsec/enc/OpenSSL/OpenSSLCryptoSymmetricKey.hpp> |
| #include <xsec/utils/XSECBinTXFMInputStream.hpp> |
| #include <xsec/xenc/XENCEncryptedData.hpp> |
| #include <xsec/xenc/XENCEncryptedKey.hpp> |
| |
| #include "XencInteropResolver.hpp" |
| |
| #include "../../utils/XSECDOMUtils.hpp" |
| |
| // General |
| |
| #include <memory.h> |
| #include <string.h> |
| #include <iostream> |
| #include <fstream> |
| #include <stdlib.h> |
| |
| #if defined(HAVE_UNISTD_H) |
| # include <unistd.h> |
| #else |
| # if defined(HAVE_DIRECT_H) |
| # include <direct.h> |
| # endif |
| #endif |
| |
| #if defined (_DEBUG) && defined (_MSC_VER) |
| #include <crtdbg.h> |
| #endif |
| |
| |
| #include <xercesc/util/PlatformUtils.hpp> |
| #include <xercesc/util/XMLString.hpp> |
| |
| #include <xercesc/dom/DOM.hpp> |
| #include <xercesc/parsers/XercesDOMParser.hpp> |
| #include <xercesc/util/XMLException.hpp> |
| #include <xercesc/util/XMLUri.hpp> |
| #include <xercesc/util/XMLUni.hpp> |
| #include <xercesc/util/Janitor.hpp> |
| #include <xercesc/util/BinFileInputStream.hpp> |
| #include <xercesc/framework/XMLFormatter.hpp> |
| #include <xercesc/framework/StdOutFormatTarget.hpp> |
| #include <xercesc/framework/LocalFileFormatTarget.hpp> |
| |
| XERCES_CPP_NAMESPACE_USE |
| |
| using std::cerr; |
| using std::cout; |
| using std::endl; |
| using std::ostream; |
| |
| #ifdef XSEC_HAVE_XALAN |
| |
| // XALAN |
| |
| #include <xalanc/XPath/XPathEvaluator.hpp> |
| #include <xalanc/XalanTransformer/XalanTransformer.hpp> |
| |
| // If this isn't defined, we're on Xalan 1.12+ and require modern C++ |
| #ifndef XALAN_USING_XALAN |
| # define XALAN_USING_XALAN(NAME) using xalanc :: NAME; |
| #endif |
| |
| XALAN_USING_XALAN(XPathEvaluator) |
| XALAN_USING_XALAN(XalanTransformer) |
| |
| #endif |
| |
| #if defined (XSEC_HAVE_OPENSSL) |
| // OpenSSL |
| |
| # include <xsec/enc/OpenSSL/OpenSSLCryptoKeyHMAC.hpp> |
| # include <xsec/enc/OpenSSL/OpenSSLCryptoKeyRSA.hpp> |
| # include <openssl/err.h> |
| # include <openssl/bio.h> |
| # include <openssl/evp.h> |
| # include <openssl/pem.h> |
| |
| #endif |
| |
| #if defined (XSEC_HAVE_WINCAPI) |
| |
| # include <xsec/enc/WinCAPI/WinCAPICryptoProvider.hpp> |
| # include <xsec/enc/WinCAPI/WinCAPICryptoSymmetricKey.hpp> |
| # include <xsec/enc/WinCAPI/WinCAPICryptoKeyHMAC.hpp> |
| |
| #endif |
| |
| #if defined (XSEC_HAVE_NSS) |
| |
| # include <xsec/enc/NSS/NSSCryptoProvider.hpp> |
| # include <xsec/enc/NSS/NSSCryptoSymmetricKey.hpp> |
| # include <xsec/enc/NSS/NSSCryptoKeyHMAC.hpp> |
| |
| #endif |
| |
| #include <time.h> |
| |
| #ifndef XSEC_HAVE_XALAN |
| |
| std::ostream& operator<< (std::ostream& target, const XMLCh * s) |
| { |
| char *p = XMLString::transcode(s); |
| target << p; |
| XSEC_RELEASE_XMLCH(p); |
| return target; |
| } |
| |
| #endif |
| |
| // ---------------------------------------------------------------------------- |
| // Checksig |
| // ---------------------------------------------------------------------------- |
| |
| |
| void printUsage(void) { |
| |
| cerr << "\nUsage: cipher [options] <input file name>\n\n"; |
| cerr << " Where options are :\n\n"; |
| cerr << " --decrypt/-d\n"; |
| cerr << " Operate in decrypt mode (default) - outputs the decrypted octet stream\n"; |
| cerr << " Reads in the input file as an XML file, searches for an EncryptedData node\n"; |
| cerr << " and decrypts the content\n"; |
| cerr << " --decrypt-element/-de\n"; |
| cerr << " Operate in decrypt and XML mode.\n"; |
| cerr << " This will output the original XML document with the first encrypted\n"; |
| cerr << " element decrypted.\n"; |
| cerr << " --encrypt-file/-ef\n"; |
| cerr << " Encrypt the contents of the input file as raw data and create an\n"; |
| cerr << " XML Encrypted Data outpu\n"; |
| cerr << " --encrypt-xml/-ex\n"; |
| cerr << " Parse the input file and encrypt the doc element down, storing the\n"; |
| cerr << " output as a XML Encrypted Data\n"; |
| cerr << " --key/-k [kek] <KEY_TYPE> [options]\n"; |
| cerr << " Set the key to use.\n"; |
| cerr << " If the first parameter is \"kek\", the key arguments will be used\n"; |
| cerr << " as a Key EncryptionKey\n"; |
| cerr << " KEY_TYPE defines what the key is. Can be one of :\n"; |
| cerr << " X509, RSA, AES128, AES192, AES256, AES128-GCM, AES192-GCM, AES256-GCM or 3DES\n"; |
| cerr << " options are :\n"; |
| cerr << " <filename> - for X509 PEM files (must be an RSA KEK certificate\n"; |
| cerr << " <filename> <password> - for RSA private key files (MUST be a KEK)\n"; |
| cerr << " <key-string> - For a string to use as the key for AES or DES keys\n"; |
| #ifdef XSEC_XKMS_ENABLED |
| cerr << " --xkms/-x\n"; |
| cerr << " The key that follows on the command line is to be interpreted as\n"; |
| cerr << " an XKMS RSAKeyPair encryption key\n"; |
| #endif |
| cerr << " --interop/-i\n"; |
| cerr << " Use the interop resolver for Baltimore interop examples\n"; |
| cerr << " --out-file/-o\n"; |
| cerr << " Output the result to the indicated file (rather than stdout)\n"; |
| #ifdef XSEC_HAVE_WINCAPI |
| cerr << " --wincapi/-w\n"; |
| cerr << " Force use of Windows Crypto API\n"; |
| #endif |
| #ifdef XSEC_HAVE_NSS |
| cerr << " --nss/-n\n"; |
| cerr << " Force use of NSS Crypto API\n"; |
| #endif |
| |
| cerr << "\n Exits with codes :\n"; |
| cerr << " 0 = Decrypt/Encrypt OK\n"; |
| cerr << " 1 = Decrypt/Encrypt failed\n"; |
| cerr << " 2 = Processing error\n"; |
| |
| } |
| |
| int evaluate(int argc, char ** argv) { |
| |
| char * filename = NULL; |
| char * outfile = NULL; |
| unsigned char * keyStr = NULL; |
| bool doDecrypt = true; |
| bool errorsOccured = false; |
| bool doDecryptElement = false; |
| bool useInteropResolver = false; |
| bool encryptFileAsData = false; |
| bool parseXMLInput = true; |
| bool doXMLOutput = false; |
| #ifdef XSEC_XKMS_ENABLED |
| bool isXKMSKey = false; |
| #endif |
| XSECCryptoKey * kek = NULL; |
| XSECCryptoKey * key = NULL; |
| int keyLen = 0; |
| const XMLCh* kekAlg = NULL; |
| const XMLCh* keyAlg = NULL; |
| DOMDocument *doc; |
| unsigned char keyBuf[24]; |
| XMLFormatTarget *formatTarget ; |
| |
| #if defined(_WIN32) && defined (XSEC_HAVE_WINCAPI) |
| HCRYPTPROV win32DSSCSP = 0; // Crypto Providers |
| HCRYPTPROV win32RSACSP = 0; |
| |
| CryptAcquireContext(&win32DSSCSP, NULL, NULL, PROV_DSS, CRYPT_VERIFYCONTEXT); |
| CryptAcquireContext(&win32RSACSP, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); |
| |
| #endif |
| |
| if (argc < 2) { |
| |
| printUsage(); |
| return 2; |
| } |
| |
| // Run through parameters |
| int paramCount = 1; |
| |
| while (paramCount < argc - 1) { |
| |
| if (_stricmp(argv[paramCount], "--decrypt-element") == 0 || _stricmp(argv[paramCount], "-de") == 0) { |
| paramCount++; |
| doDecrypt = true; |
| doDecryptElement = true; |
| doXMLOutput = true; |
| parseXMLInput = true; |
| } |
| else if (_stricmp(argv[paramCount], "--interop") == 0 || _stricmp(argv[paramCount], "-i") == 0) { |
| // Use the interop key resolver |
| useInteropResolver = true; |
| paramCount++; |
| } |
| else if (_stricmp(argv[paramCount], "--encrypt-file") == 0 || _stricmp(argv[paramCount], "-ef") == 0) { |
| // Use this file as the input |
| doDecrypt = false; |
| encryptFileAsData = true; |
| doXMLOutput = true; |
| parseXMLInput = false; |
| paramCount++; |
| } |
| else if (_stricmp(argv[paramCount], "--encrypt-xml") == 0 || _stricmp(argv[paramCount], "-ex") == 0) { |
| // Us this file as an XML input file |
| doDecrypt = false; |
| encryptFileAsData = false; |
| doXMLOutput = true; |
| parseXMLInput = true; |
| paramCount++; |
| } |
| else if (_stricmp(argv[paramCount], "--out-file") == 0 || _stricmp(argv[paramCount], "-o") == 0) { |
| if (paramCount +2 >= argc) { |
| printUsage(); |
| return 1; |
| } |
| paramCount++; |
| outfile = argv[paramCount]; |
| paramCount++; |
| } |
| #ifdef XSEC_XKMS_ENABLED |
| else if (_stricmp(argv[paramCount], "--xkms") == 0 || _stricmp(argv[paramCount], "-x") == 0) { |
| paramCount++; |
| isXKMSKey = true; |
| } |
| #endif |
| #ifdef XSEC_HAVE_WINCAPI |
| else if (_stricmp(argv[paramCount], "--wincapi") == 0 || _stricmp(argv[paramCount], "-w") == 0) { |
| // Use the interop key resolver |
| WinCAPICryptoProvider * cp = new WinCAPICryptoProvider(); |
| XSECPlatformUtils::SetCryptoProvider(cp); |
| paramCount++; |
| } |
| #endif |
| #ifdef XSEC_HAVE_NSS |
| else if (_stricmp(argv[paramCount], "--nss") == 0 || _stricmp(argv[paramCount], "-n") == 0) { |
| // NSS Crypto Provider |
| NSSCryptoProvider * cp = new NSSCryptoProvider(); |
| XSECPlatformUtils::SetCryptoProvider(cp); |
| paramCount++; |
| } |
| #endif |
| else if (_stricmp(argv[paramCount], "--key") == 0 || _stricmp(argv[paramCount], "-k") == 0) { |
| |
| // Have a key! |
| paramCount++; |
| bool isKEK = false; |
| XSECCryptoSymmetricKey::SymmetricKeyType loadKeyAs = |
| XSECCryptoSymmetricKey::KEY_NONE; |
| |
| if (_stricmp(argv[paramCount], "kek") == 0) { |
| isKEK = true; |
| paramCount++; |
| if (paramCount >= argc) { |
| printUsage(); |
| return 2; |
| } |
| } |
| |
| if (_stricmp(argv[paramCount], "3DES") == 0 || |
| _stricmp(argv[paramCount], "AES128") == 0 || |
| _stricmp(argv[paramCount], "AES192") == 0 || |
| _stricmp(argv[paramCount], "AES256") == 0 || |
| _stricmp(argv[paramCount], "AES128-GCM") == 0 || |
| _stricmp(argv[paramCount], "AES192-GCM") == 0 || |
| _stricmp(argv[paramCount], "AES256-GCM") == 0) { |
| |
| if (paramCount +2 >= argc) { |
| printUsage(); |
| return 2; |
| } |
| |
| switch(argv[paramCount][4]) { |
| case '\0' : |
| keyLen = 24; |
| loadKeyAs = XSECCryptoSymmetricKey::KEY_3DES_192; |
| keyAlg = DSIGConstants::s_unicodeStrURI3DES_CBC; |
| break; |
| case '2' : |
| keyLen = 16; |
| loadKeyAs = XSECCryptoSymmetricKey::KEY_AES_128; |
| if (isKEK) { |
| kekAlg = DSIGConstants::s_unicodeStrURIKW_AES128; |
| } |
| else if (strlen(argv[paramCount]) == 6) { |
| keyAlg = DSIGConstants::s_unicodeStrURIAES128_CBC; |
| } |
| else { |
| keyAlg = DSIGConstants::s_unicodeStrURIAES128_GCM; |
| } |
| break; |
| case '9' : |
| keyLen = 24; |
| loadKeyAs = XSECCryptoSymmetricKey::KEY_AES_192; |
| if (isKEK) { |
| kekAlg = DSIGConstants::s_unicodeStrURIKW_AES192; |
| } |
| else if (strlen(argv[paramCount]) == 6) { |
| keyAlg = DSIGConstants::s_unicodeStrURIAES192_CBC; |
| } |
| else { |
| keyAlg = DSIGConstants::s_unicodeStrURIAES192_GCM; |
| } |
| break; |
| case '5' : |
| keyLen = 32; |
| loadKeyAs = XSECCryptoSymmetricKey::KEY_AES_256; |
| if (isKEK) { |
| kekAlg = DSIGConstants::s_unicodeStrURIKW_AES256; |
| } |
| else if (strlen(argv[paramCount]) == 6) { |
| keyAlg = DSIGConstants::s_unicodeStrURIAES256_CBC; |
| } |
| else { |
| keyAlg = DSIGConstants::s_unicodeStrURIAES256_GCM; |
| } |
| break; |
| } |
| |
| paramCount++; |
| unsigned char keyStr[64]; |
| if (strlen(argv[paramCount]) > 64) { |
| cerr << "Key string too long\n"; |
| return 2; |
| } |
| XSECCryptoSymmetricKey * sk = |
| XSECPlatformUtils::g_cryptoProvider->keySymmetric(loadKeyAs); |
| |
| #ifdef XSEC_XKMS_ENABLED |
| if (isXKMSKey) { |
| unsigned char kbuf[XSEC_MAX_HASH_SIZE]; |
| CalculateXKMSKEK((unsigned char *) argv[paramCount], (int) strlen(argv[paramCount]), kbuf, XSEC_MAX_HASH_SIZE); |
| sk->setKey(kbuf, keyLen); |
| } |
| else { |
| #endif |
| memset(keyStr, 0, 64); |
| strcpy((char *) keyStr, argv[paramCount]); |
| sk->setKey(keyStr, keyLen); |
| #ifdef XSEC_XKMS_ENABLED |
| } |
| #endif |
| paramCount++; |
| if (isKEK) |
| kek = sk; |
| else |
| key = sk; |
| } |
| |
| |
| #ifdef XSEC_HAVE_OPENSSL |
| |
| else if (_stricmp(argv[paramCount], "RSA") == 0) { |
| // RSA private key file |
| |
| if (paramCount + 3 >= argc) { |
| |
| printUsage(); |
| return 2; |
| |
| } |
| |
| if (!isKEK) { |
| cerr << "RSA private keys may only be KEKs\n"; |
| return 2; |
| } |
| |
| BIO * bioKey; |
| if ((bioKey = BIO_new(BIO_s_file())) == NULL) { |
| |
| cerr << "Error opening private key file\n\n"; |
| return 1; |
| |
| } |
| |
| if (BIO_read_filename(bioKey, argv[paramCount + 1]) <= 0) { |
| |
| cerr << "Error opening private key file\n\n"; |
| return 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"; |
| return 1; |
| |
| } |
| |
| kek = new OpenSSLCryptoKeyRSA(pkey); |
| kekAlg = DSIGConstants::s_unicodeStrURIRSA_OAEP_MGFP1; |
| EVP_PKEY_free(pkey); |
| BIO_free(bioKey); |
| paramCount += 3; |
| } |
| |
| else if (_stricmp(argv[paramCount], "X509") == 0) { |
| |
| // X509 cert used to load an encrypting key |
| |
| if (paramCount + 2 >= argc) { |
| |
| printUsage(); |
| exit (1); |
| |
| } |
| |
| if (!isKEK) { |
| cerr << "X509 private keys may only be KEKs\n"; |
| return 2; |
| } |
| |
| // Load the encrypting key |
| // 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) { |
| |
| BIO * bio_err; |
| |
| if ((bio_err=BIO_new(BIO_s_file())) != NULL) |
| BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT); |
| |
| cerr << "Error loading certificate key\n\n"; |
| ERR_print_errors(bio_err); |
| BIO_free(bio_err); |
| exit (1); |
| |
| } |
| |
| // Now load the key |
| EVP_PKEY *pkey; |
| |
| pkey = X509_get_pubkey(x); |
| #ifdef XSEC_OPENSSL_HAVE_EVP_PKEY_ID |
| if (pkey == NULL || EVP_PKEY_id(pkey) != EVP_PKEY_RSA) |
| #else |
| if (pkey == NULL || pkey->type != EVP_PKEY_RSA) |
| #endif |
| { |
| cerr << "Error extracting RSA key from certificate" << endl; |
| } |
| |
| kek = new OpenSSLCryptoKeyRSA(pkey); |
| kekAlg = DSIGConstants::s_unicodeStrURIRSA_OAEP_MGFP1; |
| |
| // Clean up |
| |
| EVP_PKEY_free (pkey); |
| X509_free(x); |
| BIO_free(bioX509); |
| |
| paramCount += 2; |
| |
| } /* argv[1] = "--x509cert" */ |
| #endif /* XSEC_HAVE_OPENSSL */ |
| else { |
| printUsage(); |
| return 2; |
| } |
| } |
| |
| else { |
| cerr << "Unknown option: " << argv[paramCount] << endl; |
| printUsage(); |
| return 2; |
| } |
| } |
| |
| if (paramCount >= argc) { |
| printUsage(); |
| return 2; |
| } |
| |
| if (outfile != NULL) { |
| formatTarget = new LocalFileFormatTarget(outfile); |
| } |
| else { |
| formatTarget = new StdOutFormatTarget(); |
| } |
| |
| filename = argv[paramCount]; |
| |
| if (parseXMLInput) { |
| |
| XercesDOMParser * parser = new XercesDOMParser; |
| Janitor<XercesDOMParser> j_parser(parser); |
| |
| parser->setDoNamespaces(true); |
| parser->setCreateEntityReferenceNodes(true); |
| |
| // Now parse out file |
| |
| XMLSize_t errorCount = 0; |
| try |
| { |
| parser->parse(filename); |
| 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; |
| return (2); |
| |
| } |
| |
| /* |
| |
| Now that we have the parsed file, get the DOM document and start looking at it |
| |
| */ |
| |
| doc = parser->adoptDocument(); |
| } |
| |
| else { |
| // Create an empty document |
| XMLCh tempStr[100]; |
| XMLString::transcode("Core", tempStr, 99); |
| DOMImplementation *impl = DOMImplementationRegistry::getDOMImplementation(tempStr); |
| doc = impl->createDocument( |
| 0, // root element namespace URI. |
| MAKE_UNICODE_STRING("ADoc"), // root element name |
| NULL);// DOMDocumentType()); // document type object (DTD). |
| } |
| |
| |
| XSECProvider prov; |
| XENCCipher * cipher = prov.newCipher(doc); |
| |
| if (kek != NULL) |
| cipher->setKEK(kek); |
| if (key != NULL) |
| cipher->setKey(key); |
| |
| try { |
| |
| if (doDecrypt) { |
| |
| if (useInteropResolver == true) { |
| |
| // Map out base path of the file |
| #ifdef 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'; |
| |
| XMLCh * uriT = XMLString::transcode(baseURI); |
| #ifdef XSEC_HAVE_GETCWD_DYN |
| free(path); |
| free(baseURI); |
| #endif |
| |
| XencInteropResolver ires(doc, &(uriT[8])); |
| XSEC_RELEASE_XMLCH(uriT); |
| cipher->setKeyInfoResolver(&ires); |
| |
| } |
| // Find the EncryptedData node |
| DOMNode * n = findXENCNode(doc, "EncryptedData"); |
| |
| if (doDecryptElement) { |
| while (n != NULL) { |
| |
| // decrypt |
| cipher->decryptElement(static_cast<DOMElement *>(n)); |
| |
| // Find the next EncryptedData node |
| n = findXENCNode(doc, "EncryptedData"); |
| } |
| |
| } |
| else { |
| XSECBinTXFMInputStream * bis = cipher->decryptToBinInputStream(static_cast<DOMElement *>(n)); |
| Janitor<XSECBinTXFMInputStream> j_bis(bis); |
| |
| XMLByte buf[1024]; |
| XMLSize_t read = bis->readBytes(buf, 1023); |
| while (read > 0) { |
| formatTarget->writeChars(buf, read, NULL); |
| read = bis->readBytes(buf, 1023); |
| } |
| } |
| } |
| else { |
| |
| XENCEncryptedData *xenc = NULL; |
| // Encrypting |
| if (kek != NULL && key == NULL) { |
| XSECPlatformUtils::g_cryptoProvider->getRandom(keyBuf, 24); |
| XSECCryptoSymmetricKey * k = |
| XSECPlatformUtils::g_cryptoProvider->keySymmetric(XSECCryptoSymmetricKey::KEY_3DES_192); |
| k->setKey(keyBuf, 24); |
| cipher->setKey(k); |
| keyAlg = DSIGConstants::s_unicodeStrURI3DES_CBC; |
| keyStr = keyBuf; |
| keyLen = 24; |
| } |
| |
| if (encryptFileAsData) { |
| |
| // Create a BinInputStream |
| BinFileInputStream * is = new BinFileInputStream(filename, XMLPlatformUtils::fgMemoryManager); |
| xenc = cipher->encryptBinInputStream(is, keyAlg); |
| |
| // Replace the document element |
| DOMElement * elt = doc->getDocumentElement(); |
| doc->replaceChild(xenc->getElement(), elt); |
| elt->release(); |
| } |
| else { |
| // Document encryption |
| cipher->encryptElement(doc->getDocumentElement(), keyAlg); |
| } |
| |
| // Do we encrypt a created key? |
| if (kek != NULL && xenc != NULL) { |
| XENCEncryptedKey *xkey = cipher->encryptKey(keyStr, keyLen, kekAlg); |
| // Add to the EncryptedData |
| xenc->appendEncryptedKey(xkey); |
| } |
| } |
| |
| if (doXMLOutput) { |
| // Output the result |
| |
| XMLCh core[] = { |
| XERCES_CPP_NAMESPACE_QUALIFIER chLatin_C, |
| XERCES_CPP_NAMESPACE_QUALIFIER chLatin_o, |
| XERCES_CPP_NAMESPACE_QUALIFIER chLatin_r, |
| XERCES_CPP_NAMESPACE_QUALIFIER chLatin_e, |
| XERCES_CPP_NAMESPACE_QUALIFIER chNull |
| }; |
| |
| DOMImplementation *impl = DOMImplementationRegistry::getDOMImplementation(core); |
| |
| DOMLSSerializer *theSerializer = ((DOMImplementationLS*)impl)->createLSSerializer(); |
| Janitor<DOMLSSerializer> j_theSerializer(theSerializer); |
| |
| // Get the config so we can set up pretty printing |
| DOMConfiguration *dc = theSerializer->getDomConfig(); |
| dc->setParameter(XMLUni::fgDOMWRTFormatPrettyPrint, false); |
| |
| // Now create an output object to format to UTF-8 |
| DOMLSOutput *theOutput = ((DOMImplementationLS*)impl)->createLSOutput(); |
| Janitor<DOMLSOutput> j_theOutput(theOutput); |
| |
| theOutput->setEncoding(MAKE_UNICODE_STRING("UTF-8")); |
| theOutput->setByteStream(formatTarget); |
| |
| theSerializer->write(doc, theOutput); |
| |
| cout << endl; |
| |
| } |
| } |
| |
| catch (const XSECException &e) { |
| char * msg = XMLString::transcode(e.getMsg()); |
| cerr << "An error occurred during encryption/decryption operation\n Message: " |
| << msg << endl; |
| XSEC_RELEASE_XMLCH(msg); |
| errorsOccured = true; |
| if (formatTarget != NULL) |
| delete formatTarget; |
| doc->release(); |
| return 2; |
| } |
| catch (const XSECCryptoException &e) { |
| cerr << "An error occurred during encryption/decryption operation\n Message: " |
| << e.getMsg() << endl; |
| errorsOccured = true; |
| if (formatTarget != NULL) |
| delete formatTarget; |
| doc->release(); |
| |
| #ifdef XSEC_HAVE_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); |
| |
| ERR_print_errors(bio_err); |
| #endif |
| return 2; |
| } |
| |
| if (formatTarget != NULL) |
| delete formatTarget; |
| |
| doc->release(); |
| return 0; |
| } |
| |
| |
| int main(int argc, char **argv) { |
| |
| int retResult; |
| |
| #if defined (_DEBUG) && defined (_MSC_VER) |
| |
| // Do some memory debugging under Visual C++ |
| |
| _CrtMemState s1, s2, s3; |
| |
| // At this point we are about to start really using XSEC, so |
| // Take a "before" checkpoing |
| |
| _CrtMemCheckpoint( &s1 ); |
| |
| #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; |
| |
| } |
| |
| retResult = evaluate(argc, argv); |
| |
| XSECPlatformUtils::Terminate(); |
| #ifdef XSEC_HAVE_XALAN |
| XalanTransformer::terminate(); |
| XPathEvaluator::terminate(); |
| #endif |
| XMLPlatformUtils::Terminate(); |
| |
| #if defined (_DEBUG) && defined (_MSC_VER) |
| |
| _CrtMemCheckpoint( &s2 ); |
| |
| if ( _CrtMemDifference( &s3, &s1, &s2 ) && ( |
| s3.lCounts[0] > 0 || |
| s3.lCounts[1] > 1 || |
| // s3.lCounts[2] > 2 || We don't worry about C Runtime |
| s3.lCounts[3] > 0 || |
| s3.lCounts[4] > 0)) { |
| |
| // Note that there is generally 1 Normal and 1 CRT block |
| // still taken. 1 is from Xalan and 1 from stdio |
| |
| // Send all reports to STDOUT |
| _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE ); |
| _CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDOUT ); |
| _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE ); |
| _CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDOUT ); |
| _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE ); |
| _CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDOUT ); |
| |
| // Dumpy memory stats |
| |
| _CrtMemDumpAllObjectsSince( &s3 ); |
| _CrtMemDumpStatistics( &s3 ); |
| } |
| |
| // Now turn off memory leak checking and end as there are some |
| // Globals that are allocated that get seen as leaks (Xalan?) |
| |
| int dbgFlag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); |
| dbgFlag &= ~(_CRTDBG_LEAK_CHECK_DF); |
| _CrtSetDbgFlag( dbgFlag ); |
| |
| #endif |
| |
| return retResult; |
| } |