1 /**
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
20 /*
21 * XSEC
22 *
23 * cipher := Tool to handle basic encryption/decryption of XML documents
24 *
25 * Author(s): Berin Lautenbach
26 *
27 * $Id: cipher.cpp 1894293 2021-10-15 14:14:50Z scantor $
28 *
29 */
30
31 // XSEC
32
33 #include <xsec/utils/XSECPlatformUtils.hpp>
34 #include <xsec/framework/XSECProvider.hpp>
35 #include <xsec/framework/XSECException.hpp>
36 #include <xsec/enc/XSECCryptoException.hpp>
37 #include <xsec/enc/XSECCryptoUtils.hpp>
38 #include <xsec/enc/OpenSSL/OpenSSLCryptoSymmetricKey.hpp>
39 #include <xsec/utils/XSECBinTXFMInputStream.hpp>
40 #include <xsec/xenc/XENCEncryptedData.hpp>
41 #include <xsec/xenc/XENCEncryptedKey.hpp>
42
43 #include "XencInteropResolver.hpp"
44
45 #include "../../utils/XSECDOMUtils.hpp"
46
47 // General
48
49 #include <memory.h>
50 #include <string.h>
51 #include <iostream>
52 #include <fstream>
53 #include <stdlib.h>
54
55 #if defined(HAVE_UNISTD_H)
56 # include <unistd.h>
57 #else
58 # if defined(HAVE_DIRECT_H)
59 # include <direct.h>
60 # endif
61 #endif
62
63 #if defined (_DEBUG) && defined (_MSC_VER)
64 #include <crtdbg.h>
65 #endif
66
67
68 #include <xercesc/util/PlatformUtils.hpp>
69 #include <xercesc/util/XMLString.hpp>
70
71 #include <xercesc/dom/DOM.hpp>
72 #include <xercesc/parsers/XercesDOMParser.hpp>
73 #include <xercesc/util/XMLException.hpp>
74 #include <xercesc/util/XMLUri.hpp>
75 #include <xercesc/util/XMLUni.hpp>
76 #include <xercesc/util/Janitor.hpp>
77 #include <xercesc/util/BinFileInputStream.hpp>
78 #include <xercesc/framework/XMLFormatter.hpp>
79 #include <xercesc/framework/StdOutFormatTarget.hpp>
80 #include <xercesc/framework/LocalFileFormatTarget.hpp>
81
82 XERCES_CPP_NAMESPACE_USE
83
84 using std::cerr;
85 using std::cout;
86 using std::endl;
87 using std::ostream;
88
89 #ifdef XSEC_HAVE_XALAN
90
91 // XALAN
92
93 #include <xalanc/XPath/XPathEvaluator.hpp>
94 #include <xalanc/XalanTransformer/XalanTransformer.hpp>
95
96 // If this isn't defined, we're on Xalan 1.12+ and require modern C++
97 #ifndef XALAN_USING_XALAN
98 # define XALAN_USING_XALAN(NAME) using xalanc :: NAME;
99 #endif
100
101 XALAN_USING_XALAN(XPathEvaluator)
102 XALAN_USING_XALAN(XalanTransformer)
103
104 #endif
105
106 #if defined (XSEC_HAVE_OPENSSL)
107 // OpenSSL
108
109 # include <xsec/enc/OpenSSL/OpenSSLCryptoKeyHMAC.hpp>
110 # include <xsec/enc/OpenSSL/OpenSSLCryptoKeyRSA.hpp>
111 # include <openssl/err.h>
112 # include <openssl/bio.h>
113 # include <openssl/evp.h>
114 # include <openssl/pem.h>
115
116 #endif
117
118 #if defined (XSEC_HAVE_WINCAPI)
119
120 # include <xsec/enc/WinCAPI/WinCAPICryptoProvider.hpp>
121 # include <xsec/enc/WinCAPI/WinCAPICryptoSymmetricKey.hpp>
122 # include <xsec/enc/WinCAPI/WinCAPICryptoKeyHMAC.hpp>
123
124 #endif
125
126 #if defined (XSEC_HAVE_NSS)
127
128 # include <xsec/enc/NSS/NSSCryptoProvider.hpp>
129 # include <xsec/enc/NSS/NSSCryptoSymmetricKey.hpp>
130 # include <xsec/enc/NSS/NSSCryptoKeyHMAC.hpp>
131
132 #endif
133
134 #include <time.h>
135
136 #ifndef XSEC_HAVE_XALAN
137
138 std::ostream& operator<< (std::ostream& target, const XMLCh * s)
139 {
140 char *p = XMLString::transcode(s);
141 target << p;
142 XSEC_RELEASE_XMLCH(p);
143 return target;
144 }
145
146 #endif
147
148 // ----------------------------------------------------------------------------
149 // Checksig
150 // ----------------------------------------------------------------------------
151
152
printUsage(void)153 void printUsage(void) {
154
155 cerr << "\nUsage: cipher [options] <input file name>\n\n";
156 cerr << " Where options are :\n\n";
157 cerr << " --decrypt/-d\n";
158 cerr << " Operate in decrypt mode (default) - outputs the decrypted octet stream\n";
159 cerr << " Reads in the input file as an XML file, searches for an EncryptedData node\n";
160 cerr << " and decrypts the content\n";
161 cerr << " --decrypt-element/-de\n";
162 cerr << " Operate in decrypt and XML mode.\n";
163 cerr << " This will output the original XML document with the first encrypted\n";
164 cerr << " element decrypted.\n";
165 cerr << " --encrypt-file/-ef\n";
166 cerr << " Encrypt the contents of the input file as raw data and create an\n";
167 cerr << " XML Encrypted Data outpu\n";
168 cerr << " --encrypt-xml/-ex\n";
169 cerr << " Parse the input file and encrypt the doc element down, storing the\n";
170 cerr << " output as a XML Encrypted Data\n";
171 cerr << " --key/-k [kek] <KEY_TYPE> [options]\n";
172 cerr << " Set the key to use.\n";
173 cerr << " If the first parameter is \"kek\", the key arguments will be used\n";
174 cerr << " as a Key EncryptionKey\n";
175 cerr << " KEY_TYPE defines what the key is. Can be one of :\n";
176 cerr << " X509, RSA, AES128, AES192, AES256, AES128-GCM, AES192-GCM, AES256-GCM or 3DES\n";
177 cerr << " options are :\n";
178 cerr << " <filename> - for X509 PEM files (must be an RSA KEK certificate\n";
179 cerr << " <filename> <password> - for RSA private key files (MUST be a KEK)\n";
180 cerr << " <key-string> - For a string to use as the key for AES or DES keys\n";
181 #ifdef XSEC_XKMS_ENABLED
182 cerr << " --xkms/-x\n";
183 cerr << " The key that follows on the command line is to be interpreted as\n";
184 cerr << " an XKMS RSAKeyPair encryption key\n";
185 #endif
186 cerr << " --interop/-i\n";
187 cerr << " Use the interop resolver for Baltimore interop examples\n";
188 cerr << " --out-file/-o\n";
189 cerr << " Output the result to the indicated file (rather than stdout)\n";
190 #ifdef XSEC_HAVE_WINCAPI
191 cerr << " --wincapi/-w\n";
192 cerr << " Force use of Windows Crypto API\n";
193 #endif
194 #ifdef XSEC_HAVE_NSS
195 cerr << " --nss/-n\n";
196 cerr << " Force use of NSS Crypto API\n";
197 #endif
198
199 cerr << "\n Exits with codes :\n";
200 cerr << " 0 = Decrypt/Encrypt OK\n";
201 cerr << " 1 = Decrypt/Encrypt failed\n";
202 cerr << " 2 = Processing error\n";
203
204 }
205
evaluate(int argc,char ** argv)206 int evaluate(int argc, char ** argv) {
207
208 char * filename = NULL;
209 char * outfile = NULL;
210 unsigned char * keyStr = NULL;
211 bool doDecrypt = true;
212 bool errorsOccured = false;
213 bool doDecryptElement = false;
214 bool useInteropResolver = false;
215 bool encryptFileAsData = false;
216 bool parseXMLInput = true;
217 bool doXMLOutput = false;
218 #ifdef XSEC_XKMS_ENABLED
219 bool isXKMSKey = false;
220 #endif
221 XSECCryptoKey * kek = NULL;
222 XSECCryptoKey * key = NULL;
223 int keyLen = 0;
224 const XMLCh* kekAlg = NULL;
225 const XMLCh* keyAlg = NULL;
226 DOMDocument *doc;
227 unsigned char keyBuf[24];
228 XMLFormatTarget *formatTarget ;
229
230 #if defined(_WIN32) && defined (XSEC_HAVE_WINCAPI)
231 HCRYPTPROV win32DSSCSP = 0; // Crypto Providers
232 HCRYPTPROV win32RSACSP = 0;
233
234 CryptAcquireContext(&win32DSSCSP, NULL, NULL, PROV_DSS, CRYPT_VERIFYCONTEXT);
235 CryptAcquireContext(&win32RSACSP, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
236
237 #endif
238
239 if (argc < 2) {
240
241 printUsage();
242 return 2;
243 }
244
245 // Run through parameters
246 int paramCount = 1;
247
248 while (paramCount < argc - 1) {
249
250 if (_stricmp(argv[paramCount], "--decrypt-element") == 0 || _stricmp(argv[paramCount], "-de") == 0) {
251 paramCount++;
252 doDecrypt = true;
253 doDecryptElement = true;
254 doXMLOutput = true;
255 parseXMLInput = true;
256 }
257 else if (_stricmp(argv[paramCount], "--interop") == 0 || _stricmp(argv[paramCount], "-i") == 0) {
258 // Use the interop key resolver
259 useInteropResolver = true;
260 paramCount++;
261 }
262 else if (_stricmp(argv[paramCount], "--encrypt-file") == 0 || _stricmp(argv[paramCount], "-ef") == 0) {
263 // Use this file as the input
264 doDecrypt = false;
265 encryptFileAsData = true;
266 doXMLOutput = true;
267 parseXMLInput = false;
268 paramCount++;
269 }
270 else if (_stricmp(argv[paramCount], "--encrypt-xml") == 0 || _stricmp(argv[paramCount], "-ex") == 0) {
271 // Us this file as an XML input file
272 doDecrypt = false;
273 encryptFileAsData = false;
274 doXMLOutput = true;
275 parseXMLInput = true;
276 paramCount++;
277 }
278 else if (_stricmp(argv[paramCount], "--out-file") == 0 || _stricmp(argv[paramCount], "-o") == 0) {
279 if (paramCount +2 >= argc) {
280 printUsage();
281 return 1;
282 }
283 paramCount++;
284 outfile = argv[paramCount];
285 paramCount++;
286 }
287 #ifdef XSEC_XKMS_ENABLED
288 else if (_stricmp(argv[paramCount], "--xkms") == 0 || _stricmp(argv[paramCount], "-x") == 0) {
289 paramCount++;
290 isXKMSKey = true;
291 }
292 #endif
293 #ifdef XSEC_HAVE_WINCAPI
294 else if (_stricmp(argv[paramCount], "--wincapi") == 0 || _stricmp(argv[paramCount], "-w") == 0) {
295 // Use the interop key resolver
296 WinCAPICryptoProvider * cp = new WinCAPICryptoProvider();
297 XSECPlatformUtils::SetCryptoProvider(cp);
298 paramCount++;
299 }
300 #endif
301 #ifdef XSEC_HAVE_NSS
302 else if (_stricmp(argv[paramCount], "--nss") == 0 || _stricmp(argv[paramCount], "-n") == 0) {
303 // NSS Crypto Provider
304 NSSCryptoProvider * cp = new NSSCryptoProvider();
305 XSECPlatformUtils::SetCryptoProvider(cp);
306 paramCount++;
307 }
308 #endif
309 else if (_stricmp(argv[paramCount], "--key") == 0 || _stricmp(argv[paramCount], "-k") == 0) {
310
311 // Have a key!
312 paramCount++;
313 bool isKEK = false;
314 XSECCryptoSymmetricKey::SymmetricKeyType loadKeyAs =
315 XSECCryptoSymmetricKey::KEY_NONE;
316
317 if (_stricmp(argv[paramCount], "kek") == 0) {
318 isKEK = true;
319 paramCount++;
320 if (paramCount >= argc) {
321 printUsage();
322 return 2;
323 }
324 }
325
326 if (_stricmp(argv[paramCount], "3DES") == 0 ||
327 _stricmp(argv[paramCount], "AES128") == 0 ||
328 _stricmp(argv[paramCount], "AES192") == 0 ||
329 _stricmp(argv[paramCount], "AES256") == 0 ||
330 _stricmp(argv[paramCount], "AES128-GCM") == 0 ||
331 _stricmp(argv[paramCount], "AES192-GCM") == 0 ||
332 _stricmp(argv[paramCount], "AES256-GCM") == 0) {
333
334 if (paramCount +2 >= argc) {
335 printUsage();
336 return 2;
337 }
338
339 switch(argv[paramCount][4]) {
340 case '\0' :
341 keyLen = 24;
342 loadKeyAs = XSECCryptoSymmetricKey::KEY_3DES_192;
343 keyAlg = DSIGConstants::s_unicodeStrURI3DES_CBC;
344 break;
345 case '2' :
346 keyLen = 16;
347 loadKeyAs = XSECCryptoSymmetricKey::KEY_AES_128;
348 if (isKEK) {
349 kekAlg = DSIGConstants::s_unicodeStrURIKW_AES128;
350 }
351 else if (strlen(argv[paramCount]) == 6) {
352 keyAlg = DSIGConstants::s_unicodeStrURIAES128_CBC;
353 }
354 else {
355 keyAlg = DSIGConstants::s_unicodeStrURIAES128_GCM;
356 }
357 break;
358 case '9' :
359 keyLen = 24;
360 loadKeyAs = XSECCryptoSymmetricKey::KEY_AES_192;
361 if (isKEK) {
362 kekAlg = DSIGConstants::s_unicodeStrURIKW_AES192;
363 }
364 else if (strlen(argv[paramCount]) == 6) {
365 keyAlg = DSIGConstants::s_unicodeStrURIAES192_CBC;
366 }
367 else {
368 keyAlg = DSIGConstants::s_unicodeStrURIAES192_GCM;
369 }
370 break;
371 case '5' :
372 keyLen = 32;
373 loadKeyAs = XSECCryptoSymmetricKey::KEY_AES_256;
374 if (isKEK) {
375 kekAlg = DSIGConstants::s_unicodeStrURIKW_AES256;
376 }
377 else if (strlen(argv[paramCount]) == 6) {
378 keyAlg = DSIGConstants::s_unicodeStrURIAES256_CBC;
379 }
380 else {
381 keyAlg = DSIGConstants::s_unicodeStrURIAES256_GCM;
382 }
383 break;
384 }
385
386 paramCount++;
387 unsigned char keyStr[64];
388 if (strlen(argv[paramCount]) > 64) {
389 cerr << "Key string too long\n";
390 return 2;
391 }
392 XSECCryptoSymmetricKey * sk =
393 XSECPlatformUtils::g_cryptoProvider->keySymmetric(loadKeyAs);
394
395 #ifdef XSEC_XKMS_ENABLED
396 if (isXKMSKey) {
397 unsigned char kbuf[XSEC_MAX_HASH_SIZE];
398 CalculateXKMSKEK((unsigned char *) argv[paramCount], (int) strlen(argv[paramCount]), kbuf, XSEC_MAX_HASH_SIZE);
399 sk->setKey(kbuf, keyLen);
400 }
401 else {
402 #endif
403 memset(keyStr, 0, 64);
404 strcpy((char *) keyStr, argv[paramCount]);
405 sk->setKey(keyStr, keyLen);
406 #ifdef XSEC_XKMS_ENABLED
407 }
408 #endif
409 paramCount++;
410 if (isKEK)
411 kek = sk;
412 else
413 key = sk;
414 }
415
416
417 #ifdef XSEC_HAVE_OPENSSL
418
419 else if (_stricmp(argv[paramCount], "RSA") == 0) {
420 // RSA private key file
421
422 if (paramCount + 3 >= argc) {
423
424 printUsage();
425 return 2;
426
427 }
428
429 if (!isKEK) {
430 cerr << "RSA private keys may only be KEKs\n";
431 return 2;
432 }
433
434 BIO * bioKey;
435 if ((bioKey = BIO_new(BIO_s_file())) == NULL) {
436
437 cerr << "Error opening private key file\n\n";
438 return 1;
439
440 }
441
442 if (BIO_read_filename(bioKey, argv[paramCount + 1]) <= 0) {
443
444 cerr << "Error opening private key file\n\n";
445 return 1;
446
447 }
448
449 EVP_PKEY * pkey;
450 pkey = PEM_read_bio_PrivateKey(bioKey,NULL,NULL,argv[paramCount + 2]);
451
452 if (pkey == NULL) {
453
454 cerr << "Error loading private key\n\n";
455 return 1;
456
457 }
458
459 kek = new OpenSSLCryptoKeyRSA(pkey);
460 kekAlg = DSIGConstants::s_unicodeStrURIRSA_OAEP_MGFP1;
461 EVP_PKEY_free(pkey);
462 BIO_free(bioKey);
463 paramCount += 3;
464 }
465
466 else if (_stricmp(argv[paramCount], "X509") == 0) {
467
468 // X509 cert used to load an encrypting key
469
470 if (paramCount + 2 >= argc) {
471
472 printUsage();
473 exit (1);
474
475 }
476
477 if (!isKEK) {
478 cerr << "X509 private keys may only be KEKs\n";
479 return 2;
480 }
481
482 // Load the encrypting key
483 // For now just read a particular file
484
485 BIO * bioX509;
486
487 if ((bioX509 = BIO_new(BIO_s_file())) == NULL) {
488
489 cerr << "Error opening file\n\n";
490 exit (1);
491
492 }
493
494 if (BIO_read_filename(bioX509, argv[paramCount + 1]) <= 0) {
495
496 cerr << "Error opening X509 Certificate " << argv[paramCount + 1] << "\n\n";
497 exit (1);
498
499 }
500
501 X509 * x
502 ;
503 x = PEM_read_bio_X509_AUX(bioX509,NULL,NULL,NULL);
504
505 if (x == NULL) {
506
507 BIO * bio_err;
508
509 if ((bio_err=BIO_new(BIO_s_file())) != NULL)
510 BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
511
512 cerr << "Error loading certificate key\n\n";
513 ERR_print_errors(bio_err);
514 BIO_free(bio_err);
515 exit (1);
516
517 }
518
519 // Now load the key
520 EVP_PKEY *pkey;
521
522 pkey = X509_get_pubkey(x);
523 #ifdef XSEC_OPENSSL_HAVE_EVP_PKEY_ID
524 if (pkey == NULL || EVP_PKEY_id(pkey) != EVP_PKEY_RSA)
525 #else
526 if (pkey == NULL || pkey->type != EVP_PKEY_RSA)
527 #endif
528 {
529 cerr << "Error extracting RSA key from certificate" << endl;
530 }
531
532 kek = new OpenSSLCryptoKeyRSA(pkey);
533 kekAlg = DSIGConstants::s_unicodeStrURIRSA_OAEP_MGFP1;
534
535 // Clean up
536
537 EVP_PKEY_free (pkey);
538 X509_free(x);
539 BIO_free(bioX509);
540
541 paramCount += 2;
542
543 } /* argv[1] = "--x509cert" */
544 #endif /* XSEC_HAVE_OPENSSL */
545 else {
546 printUsage();
547 return 2;
548 }
549 }
550
551 else {
552 cerr << "Unknown option: " << argv[paramCount] << endl;
553 printUsage();
554 return 2;
555 }
556 }
557
558 if (paramCount >= argc) {
559 printUsage();
560 return 2;
561 }
562
563 if (outfile != NULL) {
564 formatTarget = new LocalFileFormatTarget(outfile);
565 }
566 else {
567 formatTarget = new StdOutFormatTarget();
568 }
569
570 filename = argv[paramCount];
571
572 if (parseXMLInput) {
573
574 XercesDOMParser * parser = new XercesDOMParser;
575 Janitor<XercesDOMParser> j_parser(parser);
576
577 parser->setDoNamespaces(true);
578 parser->setCreateEntityReferenceNodes(true);
579
580 // Now parse out file
581
582 XMLSize_t errorCount = 0;
583 try
584 {
585 parser->parse(filename);
586 errorCount = parser->getErrorCount();
587 if (errorCount > 0)
588 errorsOccured = true;
589 }
590
591 catch (const XMLException& e)
592 {
593 cerr << "An error occurred during parsing\n Message: "
594 << e.getMessage() << endl;
595 errorsOccured = true;
596 }
597
598
599 catch (const DOMException& e)
600 {
601 cerr << "A DOM error occurred during parsing\n DOMException code: "
602 << e.code << endl;
603 errorsOccured = true;
604 }
605
606 if (errorsOccured) {
607
608 cout << "Errors during parse" << endl;
609 return (2);
610
611 }
612
613 /*
614
615 Now that we have the parsed file, get the DOM document and start looking at it
616
617 */
618
619 doc = parser->adoptDocument();
620 }
621
622 else {
623 // Create an empty document
624 XMLCh tempStr[100];
625 XMLString::transcode("Core", tempStr, 99);
626 DOMImplementation *impl = DOMImplementationRegistry::getDOMImplementation(tempStr);
627 doc = impl->createDocument(
628 0, // root element namespace URI.
629 MAKE_UNICODE_STRING("ADoc"), // root element name
630 NULL);// DOMDocumentType()); // document type object (DTD).
631 }
632
633
634 XSECProvider prov;
635 XENCCipher * cipher = prov.newCipher(doc);
636
637 if (kek != NULL)
638 cipher->setKEK(kek);
639 if (key != NULL)
640 cipher->setKey(key);
641
642 try {
643
644 if (doDecrypt) {
645
646 if (useInteropResolver == true) {
647
648 // Map out base path of the file
649 #ifdef XSEC_HAVE_GETCWD_DYN
650 char *path = getcwd(NULL, 0);
651 char *baseURI = (char*)malloc(strlen(path) + 8 + 1 + strlen(filename) + 1);
652 #else
653 char path[PATH_MAX];
654 char baseURI[(PATH_MAX * 2) + 10];
655 getcwd(path, PATH_MAX);
656 #endif
657 strcpy(baseURI, "file:///");
658
659 // Ugly and nasty but quick
660 if (filename[0] != '\\' && filename[0] != '/' && filename[1] != ':') {
661 strcat(baseURI, path);
662 strcat(baseURI, "/");
663 } else if (path[1] == ':') {
664 path[2] = '\0';
665 strcat(baseURI, path);
666 }
667
668 strcat(baseURI, filename);
669
670 // Find any ':' and "\" characters
671 int lastSlash = 0;
672 for (unsigned int i = 8; i < strlen(baseURI); ++i) {
673 if (baseURI[i] == '\\') {
674 lastSlash = i;
675 baseURI[i] = '/';
676 }
677 else if (baseURI[i] == '/')
678 lastSlash = i;
679 }
680
681 // The last "\\" must prefix the filename
682 baseURI[lastSlash + 1] = '\0';
683
684 XMLCh * uriT = XMLString::transcode(baseURI);
685 #ifdef XSEC_HAVE_GETCWD_DYN
686 free(path);
687 free(baseURI);
688 #endif
689
690 XencInteropResolver ires(doc, &(uriT[8]));
691 XSEC_RELEASE_XMLCH(uriT);
692 cipher->setKeyInfoResolver(&ires);
693
694 }
695 // Find the EncryptedData node
696 DOMNode * n = findXENCNode(doc, "EncryptedData");
697
698 if (doDecryptElement) {
699 while (n != NULL) {
700
701 // decrypt
702 cipher->decryptElement(static_cast<DOMElement *>(n));
703
704 // Find the next EncryptedData node
705 n = findXENCNode(doc, "EncryptedData");
706 }
707
708 }
709 else {
710 XSECBinTXFMInputStream * bis = cipher->decryptToBinInputStream(static_cast<DOMElement *>(n));
711 Janitor<XSECBinTXFMInputStream> j_bis(bis);
712
713 XMLByte buf[1024];
714 XMLSize_t read = bis->readBytes(buf, 1023);
715 while (read > 0) {
716 formatTarget->writeChars(buf, read, NULL);
717 read = bis->readBytes(buf, 1023);
718 }
719 }
720 }
721 else {
722
723 XENCEncryptedData *xenc = NULL;
724 // Encrypting
725 if (kek != NULL && key == NULL) {
726 XSECPlatformUtils::g_cryptoProvider->getRandom(keyBuf, 24);
727 XSECCryptoSymmetricKey * k =
728 XSECPlatformUtils::g_cryptoProvider->keySymmetric(XSECCryptoSymmetricKey::KEY_3DES_192);
729 k->setKey(keyBuf, 24);
730 cipher->setKey(k);
731 keyAlg = DSIGConstants::s_unicodeStrURI3DES_CBC;
732 keyStr = keyBuf;
733 keyLen = 24;
734 }
735
736 if (encryptFileAsData) {
737
738 // Create a BinInputStream
739 BinFileInputStream * is = new BinFileInputStream(filename, XMLPlatformUtils::fgMemoryManager);
740 xenc = cipher->encryptBinInputStream(is, keyAlg);
741
742 // Replace the document element
743 DOMElement * elt = doc->getDocumentElement();
744 doc->replaceChild(xenc->getElement(), elt);
745 elt->release();
746 }
747 else {
748 // Document encryption
749 cipher->encryptElement(doc->getDocumentElement(), keyAlg);
750 }
751
752 // Do we encrypt a created key?
753 if (kek != NULL && xenc != NULL) {
754 XENCEncryptedKey *xkey = cipher->encryptKey(keyStr, keyLen, kekAlg);
755 // Add to the EncryptedData
756 xenc->appendEncryptedKey(xkey);
757 }
758 }
759
760 if (doXMLOutput) {
761 // Output the result
762
763 XMLCh core[] = {
764 XERCES_CPP_NAMESPACE_QUALIFIER chLatin_C,
765 XERCES_CPP_NAMESPACE_QUALIFIER chLatin_o,
766 XERCES_CPP_NAMESPACE_QUALIFIER chLatin_r,
767 XERCES_CPP_NAMESPACE_QUALIFIER chLatin_e,
768 XERCES_CPP_NAMESPACE_QUALIFIER chNull
769 };
770
771 DOMImplementation *impl = DOMImplementationRegistry::getDOMImplementation(core);
772
773 DOMLSSerializer *theSerializer = ((DOMImplementationLS*)impl)->createLSSerializer();
774 Janitor<DOMLSSerializer> j_theSerializer(theSerializer);
775
776 // Get the config so we can set up pretty printing
777 DOMConfiguration *dc = theSerializer->getDomConfig();
778 dc->setParameter(XMLUni::fgDOMWRTFormatPrettyPrint, false);
779
780 // Now create an output object to format to UTF-8
781 DOMLSOutput *theOutput = ((DOMImplementationLS*)impl)->createLSOutput();
782 Janitor<DOMLSOutput> j_theOutput(theOutput);
783
784 theOutput->setEncoding(MAKE_UNICODE_STRING("UTF-8"));
785 theOutput->setByteStream(formatTarget);
786
787 theSerializer->write(doc, theOutput);
788
789 cout << endl;
790
791 }
792 }
793
794 catch (const XSECException &e) {
795 char * msg = XMLString::transcode(e.getMsg());
796 cerr << "An error occurred during encryption/decryption operation\n Message: "
797 << msg << endl;
798 XSEC_RELEASE_XMLCH(msg);
799 errorsOccured = true;
800 if (formatTarget != NULL)
801 delete formatTarget;
802 doc->release();
803 return 2;
804 }
805 catch (const XSECCryptoException &e) {
806 cerr << "An error occurred during encryption/decryption operation\n Message: "
807 << e.getMsg() << endl;
808 errorsOccured = true;
809 if (formatTarget != NULL)
810 delete formatTarget;
811 doc->release();
812
813 #ifdef XSEC_HAVE_OPENSSL
814 ERR_load_crypto_strings();
815 BIO * bio_err;
816 if ((bio_err=BIO_new(BIO_s_file())) != NULL)
817 BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
818
819 ERR_print_errors(bio_err);
820 #endif
821 return 2;
822 }
823
824 if (formatTarget != NULL)
825 delete formatTarget;
826
827 doc->release();
828 return 0;
829 }
830
831
main(int argc,char ** argv)832 int main(int argc, char **argv) {
833
834 int retResult;
835
836 #if defined (_DEBUG) && defined (_MSC_VER)
837
838 // Do some memory debugging under Visual C++
839
840 _CrtMemState s1, s2, s3;
841
842 // At this point we are about to start really using XSEC, so
843 // Take a "before" checkpoing
844
845 _CrtMemCheckpoint( &s1 );
846
847 #endif
848
849 // Initialise the XML system
850
851 try {
852
853 XMLPlatformUtils::Initialize();
854 #ifdef XSEC_HAVE_XALAN
855 XPathEvaluator::initialize();
856 XalanTransformer::initialize();
857 #endif
858 XSECPlatformUtils::Initialise();
859
860 }
861 catch (const XMLException &e) {
862
863 cerr << "Error during initialisation of Xerces" << endl;
864 cerr << "Error Message = : "
865 << e.getMessage() << endl;
866
867 }
868
869 retResult = evaluate(argc, argv);
870
871 XSECPlatformUtils::Terminate();
872 #ifdef XSEC_HAVE_XALAN
873 XalanTransformer::terminate();
874 XPathEvaluator::terminate();
875 #endif
876 XMLPlatformUtils::Terminate();
877
878 #if defined (_DEBUG) && defined (_MSC_VER)
879
880 _CrtMemCheckpoint( &s2 );
881
882 if ( _CrtMemDifference( &s3, &s1, &s2 ) && (
883 s3.lCounts[0] > 0 ||
884 s3.lCounts[1] > 1 ||
885 // s3.lCounts[2] > 2 || We don't worry about C Runtime
886 s3.lCounts[3] > 0 ||
887 s3.lCounts[4] > 0)) {
888
889 // Note that there is generally 1 Normal and 1 CRT block
890 // still taken. 1 is from Xalan and 1 from stdio
891
892 // Send all reports to STDOUT
893 _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE );
894 _CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDOUT );
895 _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE );
896 _CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDOUT );
897 _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE );
898 _CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDOUT );
899
900 // Dumpy memory stats
901
902 _CrtMemDumpAllObjectsSince( &s3 );
903 _CrtMemDumpStatistics( &s3 );
904 }
905
906 // Now turn off memory leak checking and end as there are some
907 // Globals that are allocated that get seen as leaks (Xalan?)
908
909 int dbgFlag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
910 dbgFlag &= ~(_CRTDBG_LEAK_CHECK_DF);
911 _CrtSetDbgFlag( dbgFlag );
912
913 #endif
914
915 return retResult;
916 }
917