| /** |
| * 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 |
| * |
| * xtest := basic test application to run through a series of tests of |
| * the XSEC library. |
| * |
| * Author(s): Berin Lautenbach |
| * |
| * $Id$ |
| * |
| */ |
| |
| #include <xsec/framework/XSECDefs.hpp> |
| |
| #include <cassert> |
| |
| #include <memory.h> |
| #include <iostream> |
| #include <stdlib.h> |
| |
| #include <xercesc/util/PlatformUtils.hpp> |
| #include <xercesc/util/XMLUniDefs.hpp> |
| #include <xercesc/util/XMLString.hpp> |
| #include <xercesc/parsers/XercesDOMParser.hpp> |
| #include <xercesc/framework/XMLFormatter.hpp> |
| #include <xercesc/framework/StdOutFormatTarget.hpp> |
| #include <xercesc/framework/MemBufFormatTarget.hpp> |
| #include <xercesc/framework/MemBufInputSource.hpp> |
| |
| #include <xercesc/dom/DOM.hpp> |
| #include <xercesc/util/XMLException.hpp> |
| #include <xercesc/util/Janitor.hpp> |
| |
| #include <xsec/transformers/TXFMOutputFile.hpp> |
| #include <xsec/dsig/DSIGTransformXPath.hpp> |
| #include <xsec/dsig/DSIGTransformXPathFilter.hpp> |
| #include <xsec/dsig/DSIGTransformC14n.hpp> |
| #include <xsec/dsig/DSIGObject.hpp> |
| |
| // XALAN |
| |
| #ifdef XSEC_HAVE_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 |
| |
| // XSEC |
| |
| #include <xsec/canon/XSECC14n20010315.hpp> |
| #include <xsec/dsig/DSIGReference.hpp> |
| #include <xsec/dsig/DSIGSignature.hpp> |
| #include <xsec/dsig/DSIGKeyInfoX509.hpp> |
| #include <xsec/dsig/DSIGKeyInfoName.hpp> |
| #include <xsec/dsig/DSIGKeyInfoPGPData.hpp> |
| #include <xsec/dsig/DSIGKeyInfoSPKIData.hpp> |
| #include <xsec/dsig/DSIGKeyInfoMgmtData.hpp> |
| #include <xsec/enc/XSECCryptoException.hpp> |
| #include <xsec/enc/XSECCryptoSymmetricKey.hpp> |
| #include <xsec/framework/XSECError.hpp> |
| #include <xsec/framework/XSECProvider.hpp> |
| #include <xsec/xenc/XENCCipher.hpp> |
| #include <xsec/xenc/XENCEncryptedData.hpp> |
| #include <xsec/xenc/XENCEncryptedKey.hpp> |
| #include <xsec/xenc/XENCEncryptionMethod.hpp> |
| #include <xsec/utils/XSECNameSpaceExpander.hpp> |
| #include <xsec/utils/XSECBinTXFMInputStream.hpp> |
| #include <xsec/utils/XSECPlatformUtils.hpp> |
| |
| #include "../../utils/XSECDOMUtils.hpp" |
| |
| #if defined (XSEC_HAVE_OPENSSL) |
| # include <xsec/enc/OpenSSL/OpenSSLCryptoKeyHMAC.hpp> |
| # include <xsec/enc/OpenSSL/OpenSSLCryptoKeyRSA.hpp> |
| # include <xsec/enc/OpenSSL/OpenSSLCryptoKeyEC.hpp> |
| # include <openssl/rand.h> |
| # include <openssl/evp.h> |
| # include <openssl/pem.h> |
| #endif |
| #if defined (XSEC_HAVE_WINCAPI) |
| # include <xsec/enc/WinCAPI/WinCAPICryptoKeyHMAC.hpp> |
| # include <xsec/enc/WinCAPI/WinCAPICryptoKeyRSA.hpp> |
| # include <xsec/enc/WinCAPI/WinCAPICryptoProvider.hpp> |
| #endif |
| #if defined (XSEC_HAVE_NSS) |
| # include <xsec/enc/NSS/NSSCryptoKeyHMAC.hpp> |
| # include <xsec/enc/NSS/NSSCryptoKeyRSA.hpp> |
| # include <xsec/enc/NSS/NSSCryptoProvider.hpp> |
| #endif |
| |
| using std::ostream; |
| using std::cout; |
| using std::cerr; |
| using std::endl; |
| using std::flush; |
| |
| |
| /* |
| * Because of all the characters, it's easiest to inject entire Xerces namespace |
| * into global |
| */ |
| |
| XERCES_CPP_NAMESPACE_USE |
| |
| // -------------------------------------------------------------------------------- |
| // Global variables |
| // -------------------------------------------------------------------------------- |
| |
| bool g_printDocs = false; |
| bool g_useWinCAPI = false; |
| bool g_useNSS = false; |
| bool g_haveAES = true; |
| bool g_testGCM = true; |
| |
| |
| // -------------------------------------------------------------------------------- |
| // Known "Good" Values |
| // -------------------------------------------------------------------------------- |
| |
| unsigned char createdDocRefs [9][20] = { |
| { 0x51, 0x3c, 0xb5, 0xdf, 0xb9, 0x1e, 0x9d, 0xaf, 0xd4, 0x4a, |
| 0x95, 0x79, 0xf1, 0xd6, 0x54, 0xe, 0xb0, 0xb0, 0x29, 0xe3, }, |
| { 0x51, 0x3c, 0xb5, 0xdf, 0xb9, 0x1e, 0x9d, 0xaf, 0xd4, 0x4a, |
| 0x95, 0x79, 0xf1, 0xd6, 0x54, 0xe, 0xb0, 0xb0, 0x29, 0xe3, }, |
| { 0x52, 0x74, 0xc3, 0xe4, 0xc5, 0xf7, 0x20, 0xb0, 0xd9, 0x52, |
| 0xdb, 0xb3, 0xee, 0x46, 0x66, 0x8f, 0xe1, 0xb6, 0x30, 0x9d, }, |
| { 0x5a, 0x14, 0x9c, 0x5a, 0x40, 0x34, 0x51, 0x4f, 0xef, 0x1d, |
| 0x85, 0x44, 0xc7, 0x2a, 0xd3, 0xd2, 0x2, 0xed, 0x67, 0xb4, }, |
| { 0x88, 0xd1, 0x65, 0xed, 0x2a, 0xe7, 0xc0, 0xbd, 0xea, 0x3e, |
| 0xe6, 0xf3, 0xd4, 0x8c, 0xf7, 0xdd, 0xc8, 0x85, 0xa9, 0x6d, }, |
| { 0x52, 0x74, 0xc3, 0xe4, 0xc5, 0xf7, 0x20, 0xb0, 0xd9, 0x52, |
| 0xdb, 0xb3, 0xee, 0x46, 0x66, 0x8f, 0xe1, 0xb6, 0x30, 0x9d, }, |
| { 0x52, 0x74, 0xc3, 0xe4, 0xc5, 0xf7, 0x20, 0xb0, 0xd9, 0x52, |
| 0xdb, 0xb3, 0xee, 0x46, 0x66, 0x8f, 0xe1, 0xb6, 0x30, 0x9d, }, |
| { 0x69, 0xBA, 0xF1, 0x53, 0x7D, 0x81, 0x78, 0xCA, 0xCA, 0x60, |
| 0x3B, 0x2F, 0x55, 0x9C, 0x8E, 0x5F, 0xEB, 0x35, 0x38, 0x25, }, |
| { 0x51, 0x3c, 0xb5, 0xdf, 0xb9, 0x1e, 0x9d, 0xaf, 0xd4, 0x4a, |
| 0x95, 0x79, 0xf1, 0xd6, 0x54, 0xe, 0xb0, 0xb0, 0x29, 0xe3, } |
| |
| }; |
| |
| unsigned char longShaRefs [4][64] = { |
| |
| { 0x7f, 0xa4, 0xab, 0xe8, 0x07, 0x06, 0x35, 0xf3, 0xa3, 0x56, |
| 0xe8, 0x64, 0x2d, 0xc4, 0x7c, 0x8c, 0x1e, 0x48, 0x74, 0xf0, |
| 0x48, 0x63, 0x1b, 0xea, 0x57, 0xec, 0x96, 0xa6, }, |
| { 0x75, 0xec, 0xba, 0x51, 0xda, 0xb7, 0x42, 0x16, 0x34, 0x2d, |
| 0xd7, 0x4e, 0x6a, 0x33, 0xb6, 0xb3, 0xe3, 0x2d, 0x28, 0xf6, |
| 0x7b, 0x87, 0x21, 0xfd, 0xd2, 0x2e, 0x50, 0xb9, 0x55, 0x81, |
| 0x23, 0x06, }, |
| { 0x99, 0x25, 0x92, 0xa3, 0xa9, 0x44, 0x12, 0x4d, 0xa1, 0x86, |
| 0x3f, 0x81, 0xd3, 0xa7, 0x37, 0x61, 0xff, 0x86, 0x9f, 0x02, |
| 0x16, 0x48, 0x16, 0xa0, 0xec, 0x7c, 0xd5, 0x33, 0x30, 0xeb, |
| 0xb2, 0x9f, 0x93, 0xb9, 0x4a, 0x32, 0x20, 0x2e, 0x8a, 0xfd, |
| 0xa6, 0x6e, 0x67, 0x1d, 0x96, 0xcd, 0xf1, 0xcb, }, |
| { 0xf8, 0xf5, 0xf3, 0xb6, 0xab, 0x7c, 0x25, 0x52, 0x06, 0x23, |
| 0x2c, 0x9f, 0x4e, 0x25, 0x0f, 0x16, 0x58, 0xf3, 0xc6, 0xdc, |
| 0xb4, 0x85, 0x04, 0x3d, 0x9f, 0xee, 0x7d, 0x5d, 0x73, 0x86, |
| 0xe3, 0xd4, 0x3a, 0xe0, 0xd5, 0x8a, 0xec, 0x7f, 0xd4, 0x63, |
| 0x4f, 0x9a, 0xcf, 0xfa, 0x15, 0xdb, 0x0f, 0xe5, 0x09, 0x6b, |
| 0xf1, 0xa1, 0x36, 0x05, 0x42, 0x69, 0x49, 0xc3, 0x9e, 0x8c, |
| 0x99, 0xa6, 0x75, 0xae, }, |
| }; |
| |
| // -------------------------------------------------------------------------------- |
| // Some test data |
| // -------------------------------------------------------------------------------- |
| |
| // "CN=<Test,>,O=XSEC " |
| |
| XMLCh s_tstDName[] = { |
| |
| chLatin_C, |
| chLatin_N, |
| chEqual, |
| chOpenAngle, |
| chLatin_T, |
| chLatin_e, |
| chLatin_s, |
| chLatin_t, |
| chComma, |
| chCloseAngle, |
| chComma, |
| chLatin_O, |
| chEqual, |
| chLatin_X, |
| chLatin_S, |
| chLatin_E, |
| chLatin_C, |
| chSpace, |
| chSpace, |
| chNull |
| |
| }; |
| |
| XMLCh s_tstKeyName[] = { |
| |
| chLatin_F, chLatin_r, chLatin_e, chLatin_d, chSingleQuote, |
| chLatin_s, chSpace, chLatin_n, chLatin_a, chLatin_m, |
| chLatin_e, chNull |
| }; |
| |
| XMLCh s_tstPGPKeyID[] = { |
| |
| chLatin_D, chLatin_u, chLatin_m, chLatin_m, chLatin_y, chSpace, |
| chLatin_P, chLatin_G, chLatin_P, chSpace, |
| chLatin_I, chLatin_D, chNull |
| }; |
| |
| XMLCh s_tstPGPKeyPacket[] = { |
| |
| chLatin_D, chLatin_u, chLatin_m, chLatin_m, chLatin_y, chSpace, |
| chLatin_P, chLatin_G, chLatin_P, chSpace, |
| chLatin_P, chLatin_a, chLatin_c, chLatin_k, chLatin_e, chLatin_t, chNull |
| }; |
| |
| XMLCh s_tstSexp1[] = { |
| |
| chLatin_D, chLatin_u, chLatin_m, chLatin_m, chLatin_y, chSpace, |
| chLatin_S, chLatin_e, chLatin_x, chLatin_p, chDigit_1, chNull |
| }; |
| |
| XMLCh s_tstSexp2[] = { |
| |
| chLatin_D, chLatin_u, chLatin_m, chLatin_m, chLatin_y, chSpace, |
| chLatin_S, chLatin_e, chLatin_x, chLatin_p, chDigit_2, chNull |
| }; |
| |
| XMLCh s_tstMgmtData[] = { |
| |
| chLatin_D, chLatin_u, chLatin_m, chLatin_m, chLatin_y, chSpace, |
| chLatin_M, chLatin_g, chLatin_m, chLatin_t, chSpace, |
| chLatin_D, chLatin_a, chLatin_t, chLatin_a, chNull |
| |
| }; |
| |
| XMLCh s_tstCarriedKeyName[] = { |
| |
| chLatin_D, chLatin_u, chLatin_m, chLatin_m, chLatin_y, chSpace, |
| chLatin_C, chLatin_a, chLatin_r, chLatin_r, chLatin_y, chNull |
| |
| }; |
| |
| XMLCh s_tstRecipient[] = { |
| |
| chLatin_D, chLatin_u, chLatin_m, chLatin_m, chLatin_y, chSpace, |
| chLatin_R, chLatin_e, chLatin_c, chLatin_i, chLatin_p, |
| chLatin_i, chLatin_e, chLatin_n, chLatin_t, chNull |
| |
| }; |
| |
| XMLCh s_tstEncoding[] = { |
| chLatin_B, chLatin_a, chLatin_s, chLatin_e, chDigit_6, chDigit_4, chNull |
| }; |
| |
| XMLCh s_tstMimeType[] = { |
| chLatin_i, chLatin_m, chLatin_a, chLatin_g, chLatin_e, |
| chForwardSlash, chLatin_p, chLatin_n, chLatin_g, chNull |
| }; |
| |
| unsigned char s_tstOAEPparams[] = "12345678"; |
| |
| unsigned char s_tstBase64EncodedString[] = "YmNkZWZnaGlqa2xtbm9wcRrPXjQ1hvhDFT+EdesMAPE4F6vlT+y0HPXe0+nAGLQ8"; |
| char s_tstDecryptedString[] = "A test encrypted secret"; |
| |
| // -------------------------------------------------------------------------------- |
| // Some test keys |
| // -------------------------------------------------------------------------------- |
| |
| // A PKCS8 PEM encoded PrivateKey structure (not Encrypted) |
| |
| char s_tstRSAPrivateKey[] = "\n\ |
| -----BEGIN RSA PRIVATE KEY-----\n\ |
| MIICXAIBAAKBgQDQj3pktZckAzwshRnfvLhz3daNU6xpAzoHo3qjCftxDwH1RynP\n\ |
| A5eycJVkV8mwH2C1PFktpjtQTZ2CvPjuKmUV5zEvmYzuIo6SWYaVZN/PJjzsEZMa\n\ |
| VA+U8GhfX1YF/rsuFzXCi8r6FVd3LN//pXHEwoDGdJUdlpdVEuX1iFKlNQIDAQAB\n\ |
| AoGAYQ7Uc7e6Xa0PvNw4XVHzOSC870pISxqQT+u5b9R+anAEhkQW5dsTJpyUOX1N\n\ |
| RCRmGhG6oq7gnY9xRN1yr0uVfJNtc9/HnzJL7L1jeJC8Ub+zbEBvNuPDL2P21ArW\n\ |
| tcXRycUlfRCRBLop7rfOYPXsjtboAGnQY/6hK4rOF4XGrQUCQQD3Euj+0mZqRRZ4\n\ |
| M1yN2wVP0mKOMg2i/HZXaNeVd9X/wyBgK6b7BxHf6onf/mIBWnJnRBlvdCrSdhuT\n\ |
| lPKEoSgvAkEA2BhfWwQihqD4qJcV65nfosjzOZG41rHX69nIqHI7Ejx5ZgeQByH9\n\ |
| Ym96yXoSpZj9ZlFsJYNogTBBnUBjs+jL2wJAFjpVS9eR7y2X/+hfA0QZDj1XMIPA\n\ |
| RlGANAzymDfXwNLFLuG+fAb+zK5FCSnRl12TvUabIzPIRnbptDVKPDRjcQJBALn8\n\ |
| 0CVv+59P8HR6BR3QRBDBT8Xey+3NB4Aw42lHV9wsPHg6ThY1hPYx6MZ70IzCjmZ/\n\ |
| 8cqfvVRjijWj86wm0z0CQFKfRfBRraOZqfmOiAB4+ILhbJwKBBO6avX9TPgMYkyN\n\ |
| mWKCxS+9fPiy1iI+G+B9xkw2gJ9i8P81t7fsOvdTDFA=\n\ |
| -----END RSA PRIVATE KEY-----"; |
| |
| char s_tstECPrivateKey[] = "\n\ |
| -----BEGIN PRIVATE KEY-----\n\ |
| MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDAGJjEIHP3P1fDZV9lG\n\ |
| lVfblOulUksJ+QdX9SeOswKIiQ9Oc5l6NTswN2bm+IRhaouhZANiAARrJ/UeKETr\n\ |
| cFdFSM9sjB31PDIB6IdjtwyzMUIAJHlqoQ6IJo3887jvgUZyevY0+CUoS0N3L+9W\n\ |
| mPgOiq9TRw6O5mrjSk1rmCx+2o2bnk+tWEysp7AWswUgNGgVkhumq9A=\n\ |
| -----END PRIVATE KEY-----"; |
| |
| static char s_keyStr[] = "abcdefghijklmnopqrstuvwxyzabcdef"; |
| |
| |
| // -------------------------------------------------------------------------------- |
| // Find a node |
| // -------------------------------------------------------------------------------- |
| |
| DOMNode * findNode(DOMNode * n, XMLCh * name) { |
| |
| if (XMLString::compareString(name, n->getNodeName()) == 0) |
| return n; |
| |
| DOMNode * c = n->getFirstChild(); |
| |
| while (c != NULL) { |
| |
| if (c->getNodeType() == DOMNode::ELEMENT_NODE) { |
| |
| DOMNode * s = findNode(c, name); |
| if (s != NULL) |
| return s; |
| |
| } |
| |
| c = c->getNextSibling(); |
| |
| } |
| |
| return NULL; |
| |
| } |
| |
| // -------------------------------------------------------------------------------- |
| // Create a key |
| // -------------------------------------------------------------------------------- |
| |
| XSECCryptoKeyHMAC * createHMACKey(const unsigned char * str) { |
| |
| // Create the HMAC key |
| XSECCryptoKeyHMAC * hmacKey = NULL; |
| |
| #if defined(XSEC_HAVE_WINCAPI) |
| |
| if (g_useWinCAPI == true) { |
| hmacKey = new WinCAPICryptoKeyHMAC(0); |
| } |
| #endif |
| |
| # if defined (XSEC_HAVE_NSS) |
| if (g_useNSS == true) { |
| hmacKey = new NSSCryptoKeyHMAC(); |
| } |
| #endif |
| |
| #if defined (XSEC_HAVE_OPENSSL) |
| if (hmacKey == NULL) |
| hmacKey = new OpenSSLCryptoKeyHMAC(); |
| #endif |
| |
| hmacKey->setKey((unsigned char *) str, (unsigned int) strlen((char *)str)); |
| |
| return hmacKey; |
| |
| } |
| |
| // -------------------------------------------------------------------------------- |
| // Utility function for outputting hex data |
| // -------------------------------------------------------------------------------- |
| |
| void outputHex(unsigned char * buf, int len) { |
| |
| cout << std::hex; |
| for (int i = 0; i < len; ++i) { |
| cout << "0x" << (unsigned int) buf[i] << ", "; |
| } |
| cout << std::ios::dec << endl; |
| |
| } |
| |
| // -------------------------------------------------------------------------------- |
| // Create a basic document |
| // -------------------------------------------------------------------------------- |
| |
| DOMDocument * createTestDoc(DOMImplementation * impl) { |
| |
| DOMDocument *doc = impl->createDocument( |
| 0, // root element namespace URI. |
| MAKE_UNICODE_STRING("ADoc"), // root element name |
| NULL);// DOMDocumentType()); // document type object (DTD). |
| |
| DOMElement *rootElem = doc->getDocumentElement(); |
| rootElem->setAttributeNS(DSIGConstants::s_unicodeStrURIXMLNS, |
| MAKE_UNICODE_STRING("xmlns:foo"), MAKE_UNICODE_STRING("http://www.foo.org")); |
| |
| DOMElement * prodElem = doc->createElement(MAKE_UNICODE_STRING("product")); |
| rootElem->appendChild(prodElem); |
| |
| DOMText * prodDataVal = doc->createTextNode(MAKE_UNICODE_STRING("XMLSecurityC")); |
| prodElem->appendChild(prodDataVal); |
| |
| DOMElement *catElem = doc->createElement(MAKE_UNICODE_STRING("category")); |
| rootElem->appendChild(catElem); |
| catElem->setAttributeNS(NULL,MAKE_UNICODE_STRING("idea"), MAKE_UNICODE_STRING("great")); |
| |
| DOMText *catDataVal = doc->createTextNode(MAKE_UNICODE_STRING("XML Security Tools")); |
| catElem->appendChild(catDataVal); |
| |
| return doc; |
| |
| } |
| // -------------------------------------------------------------------------------- |
| // Output a document if so required |
| // -------------------------------------------------------------------------------- |
| |
| void outputDoc(DOMImplementation * impl, DOMDocument * doc) { |
| |
| if (g_printDocs == false) |
| return; |
| |
| XMLFormatTarget *formatTarget = new StdOutFormatTarget(); |
| |
| // DOM L3 version as per Xerces 3.0 API |
| DOMLSSerializer *theSerializer = ((DOMImplementationLS*)impl)->createLSSerializer(); |
| |
| // 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); |
| |
| cerr << endl; |
| |
| theSerializer->write(doc, theOutput); |
| |
| cout << endl; |
| |
| cerr << endl; |
| |
| delete theSerializer; |
| delete formatTarget; |
| |
| } |
| |
| // -------------------------------------------------------------------------------- |
| // Unit test helper functions |
| // -------------------------------------------------------------------------------- |
| |
| bool reValidateSig(DOMImplementation *impl, DOMDocument * inDoc, XSECCryptoKey *k) { |
| |
| // Take a signature in DOM, serialise and re-validate |
| |
| try { |
| |
| MemBufFormatTarget *formatTarget = new MemBufFormatTarget(); |
| |
| DOMLSSerializer *theSerializer = ((DOMImplementationLS*)impl)->createLSSerializer(); |
| |
| // 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(inDoc,theOutput); |
| |
| // Copy to a new buffer |
| XMLSize_t len = formatTarget->getLen(); |
| char * mbuf = new char [len + 1]; |
| memcpy(mbuf, formatTarget->getRawBuffer(), len); |
| mbuf[len] = '\0'; |
| |
| delete theSerializer; |
| delete formatTarget; |
| |
| /* |
| * Re-parse |
| */ |
| |
| XercesDOMParser parser; |
| |
| parser.setDoNamespaces(true); |
| parser.setCreateEntityReferenceNodes(true); |
| |
| MemBufInputSource* memIS = new MemBufInputSource ((const XMLByte*) mbuf, |
| len, "XSECMem"); |
| |
| parser.parse(*memIS); |
| DOMDocument * doc = parser.adoptDocument(); |
| |
| |
| delete(memIS); |
| delete[] mbuf; |
| |
| /* |
| * Validate signature |
| */ |
| |
| XSECProvider prov; |
| DSIGSignature * sig = prov.newSignatureFromDOM(doc); |
| sig->load(); |
| sig->setSigningKey(k); |
| |
| bool ret = sig->verify(); |
| |
| doc->release(); |
| |
| return ret; |
| |
| } |
| |
| catch (const XSECException &e) |
| { |
| cerr << "An error occurred during signature processing\n Message: "; |
| char * ce = XMLString::transcode(e.getMsg()); |
| cerr << ce << endl; |
| delete ce; |
| exit(1); |
| |
| } |
| catch (const XSECCryptoException &e) |
| { |
| cerr << "A cryptographic error occurred during signature processing\n Message: " |
| << e.getMsg() << endl; |
| exit(1); |
| } |
| |
| } |
| // -------------------------------------------------------------------------------- |
| // Unit tests for signature |
| // -------------------------------------------------------------------------------- |
| |
| |
| void unitTestEnvelopingSignature(DOMImplementation * impl) { |
| |
| // This tests an enveloping signature as the root node |
| |
| cerr << "Creating enveloping signature ... "; |
| |
| try { |
| |
| // Create a document |
| |
| DOMDocument * doc = impl->createDocument(); |
| |
| // Create the signature |
| |
| XSECProvider prov; |
| DSIGSignature *sig; |
| DOMElement *sigNode; |
| |
| sig = prov.newSignature(); |
| sig->setDSIGNSPrefix(MAKE_UNICODE_STRING("ds")); |
| sig->setPrettyPrint(true); |
| |
| sigNode = sig->createBlankSignature(doc, |
| DSIGConstants::s_unicodeStrURIC14N_COM, |
| DSIGConstants::s_unicodeStrURIHMAC_SHA1); |
| |
| doc->appendChild(sigNode); |
| |
| // Add an object |
| DSIGObject * obj = sig->appendObject(); |
| obj->setId(MAKE_UNICODE_STRING("ObjectId")); |
| |
| // Create a text node |
| DOMText * txt= doc->createTextNode(MAKE_UNICODE_STRING("A test string")); |
| obj->appendChild(txt); |
| |
| // Add a Reference |
| sig->createReference(MAKE_UNICODE_STRING("#ObjectId"), |
| DSIGConstants::s_unicodeStrURISHA1); |
| |
| // Get a key |
| cerr << "signing ... "; |
| |
| sig->setSigningKey(createHMACKey((unsigned char *) "secret")); |
| sig->sign(); |
| |
| cerr << "validating ... "; |
| if (!sig->verify()) { |
| cerr << "bad verify!" << endl; |
| exit(1); |
| } |
| |
| cerr << "OK ... serialise and re-verify ... "; |
| if (!reValidateSig(impl, doc, createHMACKey((unsigned char *) "secret"))) { |
| |
| cerr << "bad verify!" << endl; |
| exit(1); |
| |
| } |
| |
| cerr << "OK ... "; |
| |
| // Now set to bad |
| txt->setNodeValue(MAKE_UNICODE_STRING("A bad string")); |
| |
| cerr << "verify bad data ... "; |
| if (sig->verify()) { |
| |
| cerr << "bad - should have failed!" << endl; |
| exit(1); |
| |
| } |
| |
| cerr << "OK (verify false) ... serialise and re-verify ... "; |
| if (reValidateSig(impl, doc, createHMACKey((unsigned char *) "secret"))) { |
| |
| cerr << "bad - should have failed" << endl; |
| exit(1); |
| |
| } |
| |
| cerr << "OK" << endl; |
| // Reset to OK |
| txt->setNodeValue(MAKE_UNICODE_STRING("A test string")); |
| outputDoc(impl, doc); |
| doc->release(); |
| |
| |
| } |
| |
| catch (const XSECException &e) |
| { |
| cerr << "An error occurred during signature processing\n Message: "; |
| char * ce = XMLString::transcode(e.getMsg()); |
| cerr << ce << endl; |
| delete ce; |
| exit(1); |
| |
| } |
| catch (const XSECCryptoException &e) |
| { |
| cerr << "A cryptographic error occurred during signature processing\n Message: " |
| << e.getMsg() << endl; |
| exit(1); |
| } |
| |
| |
| } |
| |
| void unitTestBase64NodeSignature(DOMImplementation * impl) { |
| |
| // This tests a normal signature with a reference to a Base64 element |
| |
| cerr << "Creating a base64 Element reference ... "; |
| |
| try { |
| |
| // Create a document |
| |
| DOMDocument * doc = impl->createDocument(); |
| |
| // Create the signature |
| |
| XSECProvider prov; |
| DSIGSignature *sig; |
| DOMElement *sigNode; |
| |
| sig = prov.newSignature(); |
| sig->setDSIGNSPrefix(MAKE_UNICODE_STRING("ds")); |
| sig->setPrettyPrint(true); |
| sigNode = sig->createBlankSignature(doc, |
| DSIGConstants::s_unicodeStrURIC14N_COM, |
| DSIGConstants::s_unicodeStrURIHMAC_SHA1); |
| |
| doc->appendChild(sigNode); |
| |
| // Add an object |
| DSIGObject * obj = sig->appendObject(); |
| obj->setId(MAKE_UNICODE_STRING("ObjectId")); |
| |
| // Create a text node |
| DOMText * txt= doc->createTextNode(MAKE_UNICODE_STRING("QSB0ZXN0IHN0cmluZw==")); |
| obj->appendChild(txt); |
| |
| // Add a Reference |
| DSIGReference * ref = sig->createReference(MAKE_UNICODE_STRING("#ObjectId"), |
| DSIGConstants::s_unicodeStrURISHA1); |
| // Add a Base64 transform |
| ref->appendBase64Transform(); |
| |
| // Get a key |
| cerr << "signing ... "; |
| |
| sig->setSigningKey(createHMACKey((unsigned char *) "secret")); |
| sig->sign(); |
| |
| cerr << "validating ... "; |
| if (!sig->verify()) { |
| cerr << "bad verify!" << endl; |
| exit(1); |
| } |
| |
| cerr << "OK ... serialise and re-verify ... "; |
| if (!reValidateSig(impl, doc, createHMACKey((unsigned char *) "secret"))) { |
| |
| cerr << "bad verify!" << endl; |
| exit(1); |
| |
| } |
| |
| cerr << "OK ... "; |
| |
| // Now set to bad |
| txt->setNodeValue(MAKE_UNICODE_STRING("QSAybmQgdGVzdCBzdHJpbmc=")); |
| |
| cerr << "verify bad data ... "; |
| if (sig->verify()) { |
| |
| cerr << "bad - should have failed!" << endl; |
| exit(1); |
| |
| } |
| |
| cerr << "OK (verify false) ... serialise and re-verify ... "; |
| if (reValidateSig(impl, doc, createHMACKey((unsigned char *) "secret"))) { |
| |
| cerr << "bad - should have failed" << endl; |
| exit(1); |
| |
| } |
| |
| cerr << "OK" << endl; |
| // Reset to OK |
| txt->setNodeValue(MAKE_UNICODE_STRING("QSB0ZXN0IHN0cmluZw==")); |
| outputDoc(impl, doc); |
| doc->release(); |
| |
| |
| } |
| |
| catch (const XSECException &e) |
| { |
| cerr << "An error occurred during signature processing\n Message: "; |
| char * ce = XMLString::transcode(e.getMsg()); |
| cerr << ce << endl; |
| delete ce; |
| exit(1); |
| |
| } |
| catch (const XSECCryptoException &e) |
| { |
| cerr << "A cryptographic error occurred during signature processing\n Message: " |
| << e.getMsg() << endl; |
| exit(1); |
| } |
| |
| |
| } |
| |
| |
| void unitTestLongSHA(DOMImplementation * impl) { |
| |
| // This tests an enveloping signature as the root node, using SHA224/256/384/512 |
| |
| cerr << "Creating long SHA references using HMAC... "; |
| |
| try { |
| |
| // Create a document |
| |
| DOMDocument * doc = impl->createDocument(); |
| |
| // Create the signature |
| |
| XSECProvider prov; |
| DSIGSignature *sig; |
| DOMElement *sigNode; |
| DSIGReference *ref[4]; |
| |
| sig = prov.newSignature(); |
| sig->setDSIGNSPrefix(MAKE_UNICODE_STRING("ds")); |
| sig->setPrettyPrint(true); |
| |
| sigNode = sig->createBlankSignature(doc, |
| DSIGConstants::s_unicodeStrURIEXC_C14N_COM, |
| DSIGConstants::s_unicodeStrURIHMAC_SHA512); |
| |
| doc->appendChild(sigNode); |
| |
| // Add an object |
| DSIGObject * obj = sig->appendObject(); |
| obj->setId(MAKE_UNICODE_STRING("ObjectId")); |
| |
| // Create a text node |
| DOMText * txt= doc->createTextNode(MAKE_UNICODE_STRING("A test string")); |
| obj->appendChild(txt); |
| |
| // Add a Reference |
| if (XSECPlatformUtils::g_cryptoProvider->algorithmSupported(XSECCryptoHash::HASH_SHA224)) { |
| cerr << "224 ... "; |
| ref[0] = sig->createReference(MAKE_UNICODE_STRING("#ObjectId"), |
| DSIGConstants::s_unicodeStrURISHA224); |
| } |
| else { |
| ref[0] = NULL; |
| } |
| |
| if (XSECPlatformUtils::g_cryptoProvider->algorithmSupported(XSECCryptoHash::HASH_SHA256)) { |
| cerr << "256 ... "; |
| ref[1] = sig->createReference(MAKE_UNICODE_STRING("#ObjectId"), |
| DSIGConstants::s_unicodeStrURISHA256); |
| } |
| else { |
| ref[1] = NULL; |
| } |
| |
| if (XSECPlatformUtils::g_cryptoProvider->algorithmSupported(XSECCryptoHash::HASH_SHA384)) { |
| cerr << "384 ... "; |
| ref[2] = sig->createReference(MAKE_UNICODE_STRING("#ObjectId"), |
| DSIGConstants::s_unicodeStrURISHA384); |
| } |
| else { |
| ref[2] = NULL; |
| } |
| |
| if (XSECPlatformUtils::g_cryptoProvider->algorithmSupported(XSECCryptoHash::HASH_SHA512)) { |
| cerr << "512 ... "; |
| ref[3] = sig->createReference(MAKE_UNICODE_STRING("#ObjectId"), |
| DSIGConstants::s_unicodeStrURISHA512); |
| } |
| else { |
| ref[3] = NULL; |
| } |
| |
| // Get a key |
| cerr << "signing ... "; |
| |
| sig->setSigningKey(createHMACKey((unsigned char *) "secret")); |
| sig->sign(); |
| |
| cerr << "validating ... "; |
| if (!sig->verify()) { |
| cerr << "bad verify!" << endl; |
| exit(1); |
| } |
| |
| cerr << "OK ... serialise and re-verify ... "; |
| if (!reValidateSig(impl, doc, createHMACKey((unsigned char *) "secret"))) { |
| |
| cerr << "bad verify!" << endl; |
| exit(1); |
| |
| } |
| |
| cerr << "OK ... "; |
| |
| // Now set to bad |
| txt->setNodeValue(MAKE_UNICODE_STRING("A bad string")); |
| |
| cerr << "verify bad data ... "; |
| if (sig->verify()) { |
| |
| cerr << "bad - should have failed!" << endl; |
| exit(1); |
| |
| } |
| |
| cerr << "OK (verify false) ... serialize and re-verify ... "; |
| if (reValidateSig(impl, doc, createHMACKey((unsigned char *) "secret"))) { |
| |
| cerr << "bad - should have failed" << endl; |
| exit(1); |
| |
| } |
| |
| cerr << "OK" << endl; |
| // Reset to OK |
| txt->setNodeValue(MAKE_UNICODE_STRING("A test string")); |
| |
| // Now check the references |
| cerr << " Checking reference values against known good" << endl; |
| |
| unsigned char buf[128]; |
| int len; |
| |
| const char * shastrings[] = { |
| "SHA224", |
| "SHA256", |
| "SHA384", |
| "SHA512" |
| }; |
| |
| /* |
| * Validate the reference hash values from known good |
| */ |
| |
| int i; |
| for (i = 0; i < 4; ++i) { |
| if (ref[i] == NULL) { |
| continue; |
| } |
| |
| cerr << " Calculating hash for reference " << shastrings[i] << " ... "; |
| |
| len = (int) ref[i]->calculateHash(buf, 128); |
| |
| cerr << " Done\n Checking -> "; |
| |
| if (len < 20) { |
| cerr << "Bad (Length = " << len << ")" << endl; |
| exit (1); |
| } |
| |
| for (int j = 0; j < len; ++j) { |
| |
| if (buf[j] != longShaRefs[i][j]) { |
| cerr << "Bad at location " << j << endl; |
| for (j = 0; j < len; ++j) { |
| fprintf(stderr, "0x%02x, ", buf[j]); |
| } |
| exit (1); |
| } |
| |
| } |
| cerr << "Good.\n"; |
| |
| } |
| |
| outputDoc(impl, doc); |
| doc->release(); |
| |
| |
| } |
| |
| catch (const XSECException &e) |
| { |
| cerr << "An error occurred during signature processing\n Message: "; |
| char * ce = XMLString::transcode(e.getMsg()); |
| cerr << ce << endl; |
| delete ce; |
| exit(1); |
| |
| } |
| catch (const XSECCryptoException &e) |
| { |
| cerr << "A cryptographic error occurred during signature processing\n Message: " |
| << e.getMsg() << endl; |
| exit(1); |
| } |
| |
| } |
| |
| void unitTestSig(DOMImplementation * impl, XSECCryptoKey * k, const XMLCh * AlgURI) { |
| |
| // Given a specific RSA/EC key and particular algorithm URI, sign and validate a document |
| |
| try { |
| |
| // Create a document |
| |
| DOMDocument * doc = impl->createDocument(); |
| |
| // Create the signature |
| |
| XSECProvider prov; |
| DSIGSignature *sig; |
| DOMElement *sigNode; |
| |
| sig = prov.newSignature(); |
| sig->setDSIGNSPrefix(MAKE_UNICODE_STRING("ds")); |
| sig->setPrettyPrint(true); |
| |
| sigNode = sig->createBlankSignature(doc, |
| DSIGConstants::s_unicodeStrURIC14N_COM, |
| AlgURI); |
| |
| doc->appendChild(sigNode); |
| |
| // Add an object |
| DSIGObject * obj = sig->appendObject(); |
| obj->setId(MAKE_UNICODE_STRING("ObjectId")); |
| |
| // Create a text node |
| DOMText * txt= doc->createTextNode(MAKE_UNICODE_STRING("A test string")); |
| obj->appendChild(txt); |
| |
| // Get a key |
| cerr << "signing ... "; |
| |
| sig->setSigningKey(k->clone()); |
| sig->sign(); |
| |
| cerr << "OK ... "; |
| |
| cerr << "validating ... "; |
| if (!sig->verify()) { |
| cerr << "bad verify!" << endl; |
| exit(1); |
| } |
| |
| cerr << "OK ... serialise and re-verify ... "; |
| if (!reValidateSig(impl, doc, k)) { |
| |
| cerr << "bad verify!" << endl; |
| exit(1); |
| |
| } |
| |
| cerr << "OK"; |
| |
| cerr << "\n"; |
| |
| outputDoc(impl, doc); |
| doc->release(); |
| |
| |
| } |
| |
| catch (const XSECException &e) |
| { |
| cerr << "An error occurred during signature processing\n Message: "; |
| char * ce = XMLString::transcode(e.getMsg()); |
| cerr << ce << endl; |
| delete ce; |
| exit(1); |
| |
| } |
| catch (const XSECCryptoException &e) |
| { |
| cerr << "A cryptographic error occurred during signature processing\n Message: " |
| << e.getMsg() << endl; |
| exit(1); |
| } |
| |
| } |
| |
| |
| void unitTestRSA(DOMImplementation * impl) { |
| |
| /* First we load some keys to use! */ |
| |
| XSECCryptoKeyRSA * rsaKey; |
| |
| #if defined (XSEC_HAVE_OPENSSL) |
| if (!g_useWinCAPI && !g_useNSS) { |
| // Load the key |
| BIO * bioMem = BIO_new(BIO_s_mem()); |
| BIO_puts(bioMem, s_tstRSAPrivateKey); |
| EVP_PKEY * pk = PEM_read_bio_PrivateKey(bioMem, NULL, NULL, NULL); |
| |
| rsaKey = new OpenSSLCryptoKeyRSA(pk); |
| |
| BIO_free(bioMem); |
| EVP_PKEY_free(pk); |
| } |
| #endif |
| |
| #if defined (XSEC_HAVE_WINCAPI) |
| if (g_useWinCAPI) { |
| |
| // Use the internal key |
| WinCAPICryptoProvider *cp = (WinCAPICryptoProvider *) (XSECPlatformUtils::g_cryptoProvider); |
| HCRYPTPROV p = cp->getApacheKeyStore(); |
| |
| rsaKey = new WinCAPICryptoKeyRSA(p, AT_KEYEXCHANGE, true); |
| } |
| |
| #endif |
| |
| #if defined (XSEC_HAVE_NSS) |
| if (g_useNSS) { |
| // Heavily based on Mozilla example code |
| SECKEYPrivateKey *prvKey = 0; |
| SECKEYPublicKey *pubKey = 0; |
| PK11SlotInfo *slot = 0; |
| PK11RSAGenParams rsaParams; |
| |
| // Use a bog standard key size |
| rsaParams.keySizeInBits = 1024; |
| rsaParams.pe = 65537; |
| |
| // We need somewhere to temporarily store a generated key |
| slot = PK11_GetInternalKeySlot(); |
| if (!slot) { |
| cerr << "Error generating key - can't get NSS slot\n"; |
| exit (1); |
| } |
| |
| // Do the generate |
| prvKey = PK11_GenerateKeyPair(slot, CKM_RSA_PKCS_KEY_PAIR_GEN, &rsaParams, |
| &pubKey, PR_FALSE, PR_TRUE, 0); |
| |
| if (!prvKey) { |
| if (slot) |
| PK11_FreeSlot(slot); |
| cerr << "Error generating key within NSS\n"; |
| exit (1); |
| } |
| |
| // Now use the key! |
| rsaKey = new NSSCryptoKeyRSA(pubKey, prvKey); |
| |
| } |
| #endif |
| |
| cerr << "Unit testing RSA-SHA1 signature ... "; |
| unitTestSig(impl, (XSECCryptoKeyRSA *) rsaKey->clone(), DSIGConstants::s_unicodeStrURIRSA_SHA1); |
| |
| if (XSECPlatformUtils::g_cryptoProvider->algorithmSupported(XSECCryptoHash::HASH_SHA224)) { |
| cerr << "Unit testing RSA-SHA224 signature ... "; |
| unitTestSig(impl, (XSECCryptoKeyRSA *)rsaKey->clone(), DSIGConstants::s_unicodeStrURIRSA_SHA224); |
| } |
| |
| if (XSECPlatformUtils::g_cryptoProvider->algorithmSupported(XSECCryptoHash::HASH_SHA256)) { |
| cerr << "Unit testing RSA-SHA256 signature ... "; |
| unitTestSig(impl, (XSECCryptoKeyRSA *)rsaKey->clone(), DSIGConstants::s_unicodeStrURIRSA_SHA256); |
| } |
| |
| if (XSECPlatformUtils::g_cryptoProvider->algorithmSupported(XSECCryptoHash::HASH_SHA384)) { |
| cerr << "Unit testing RSA-SHA384 signature ... "; |
| unitTestSig(impl, (XSECCryptoKeyRSA *)rsaKey->clone(), DSIGConstants::s_unicodeStrURIRSA_SHA384); |
| } |
| |
| if (XSECPlatformUtils::g_cryptoProvider->algorithmSupported(XSECCryptoHash::HASH_SHA512)) { |
| cerr << "Unit testing RSA-SHA512 signature ... "; |
| unitTestSig(impl, (XSECCryptoKeyRSA *) rsaKey->clone(), DSIGConstants::s_unicodeStrURIRSA_SHA512); |
| } |
| |
| cerr << "Unit testing RSA-MD5 signature ... "; |
| unitTestSig(impl, rsaKey, DSIGConstants::s_unicodeStrURIRSA_MD5); |
| } |
| |
| void unitTestEC(DOMImplementation * impl) { |
| #if defined (XSEC_HAVE_OPENSSL) && defined (XSEC_OPENSSL_HAVE_EC) |
| |
| /* First we load some keys to use! */ |
| |
| XSECCryptoKeyEC * ecKey; |
| |
| // Load the key |
| BIO * bioMem = BIO_new(BIO_s_mem()); |
| BIO_puts(bioMem, s_tstECPrivateKey); |
| EVP_PKEY * pk = PEM_read_bio_PrivateKey(bioMem, NULL, NULL, NULL); |
| |
| ecKey = new OpenSSLCryptoKeyEC(pk); |
| |
| BIO_free(bioMem); |
| EVP_PKEY_free(pk); |
| |
| cerr << "Unit testing ECDSA-SHA1 signature ... "; |
| unitTestSig(impl, (XSECCryptoKeyEC *) ecKey->clone(), DSIGConstants::s_unicodeStrURIECDSA_SHA1); |
| |
| if (XSECPlatformUtils::g_cryptoProvider->algorithmSupported(XSECCryptoHash::HASH_SHA224)) { |
| cerr << "Unit testing ECDSA-SHA224 signature ... "; |
| unitTestSig(impl, (XSECCryptoKeyEC *)ecKey->clone(), DSIGConstants::s_unicodeStrURIECDSA_SHA224); |
| } |
| |
| if (XSECPlatformUtils::g_cryptoProvider->algorithmSupported(XSECCryptoHash::HASH_SHA256)) { |
| cerr << "Unit testing ECDSA-SHA256 signature ... "; |
| unitTestSig(impl, (XSECCryptoKeyEC *)ecKey->clone(), DSIGConstants::s_unicodeStrURIECDSA_SHA256); |
| } |
| |
| if (XSECPlatformUtils::g_cryptoProvider->algorithmSupported(XSECCryptoHash::HASH_SHA384)) { |
| cerr << "Unit testing ECDSA-SHA384 signature ... "; |
| unitTestSig(impl, (XSECCryptoKeyEC *)ecKey->clone(), DSIGConstants::s_unicodeStrURIECDSA_SHA384); |
| } |
| |
| if (XSECPlatformUtils::g_cryptoProvider->algorithmSupported(XSECCryptoHash::HASH_SHA512)) { |
| cerr << "Unit testing ECDSA-SHA512 signature ... "; |
| } |
| unitTestSig(impl, (XSECCryptoKeyEC *) ecKey->clone(), DSIGConstants::s_unicodeStrURIECDSA_SHA512); |
| #endif |
| } |
| |
| void unitTestSignature(DOMImplementation * impl) { |
| |
| // Test an enveloping signature |
| unitTestEnvelopingSignature(impl); |
| #ifdef XSEC_HAVE_XALAN |
| unitTestBase64NodeSignature(impl); |
| #else |
| cerr << "Skipping base64 node test (Requires XPath)" << endl; |
| #endif |
| |
| // Test "long" sha hashes |
| if (XSECPlatformUtils::g_cryptoProvider->algorithmSupported(XSECCryptoHash::HASH_SHA512)) |
| unitTestLongSHA(impl); |
| else |
| cerr << "Skipping long SHA hash tests as SHA512 not supported by crypto provider" << endl; |
| |
| // Test RSA Signatures |
| unitTestRSA(impl); |
| |
| // Test EC Signatures |
| unitTestEC(impl); |
| } |
| |
| // -------------------------------------------------------------------------------- |
| // Basic tests of signature function |
| // -------------------------------------------------------------------------------- |
| |
| void testSignature(DOMImplementation *impl) { |
| |
| cerr << "Creating a known doc and signing (HMAC-SHA1)" << endl; |
| |
| // Create a document |
| |
| DOMDocument * doc = createTestDoc(impl); |
| |
| // Check signature functions |
| |
| XSECProvider prov; |
| DSIGSignature *sig; |
| DSIGReference *ref[10]; |
| DOMElement *sigNode; |
| int refCount; |
| |
| try { |
| |
| /* |
| * Now we have a document, create a signature for it. |
| */ |
| |
| sig = prov.newSignature(); |
| sig->setDSIGNSPrefix(MAKE_UNICODE_STRING("ds")); |
| sig->setPrettyPrint(true); |
| |
| sigNode = sig->createBlankSignature(doc, |
| DSIGConstants::s_unicodeStrURIC14N_COM, |
| DSIGConstants::s_unicodeStrURIHMAC_SHA1); |
| DOMElement * rootElem = doc->getDocumentElement(); |
| DOMNode * prodElem = rootElem->getFirstChild(); |
| |
| rootElem->appendChild(doc->createTextNode(DSIGConstants::s_unicodeStrNL)); |
| rootElem->insertBefore(doc->createComment(MAKE_UNICODE_STRING(" a comment ")), prodElem); |
| rootElem->appendChild(sigNode); |
| rootElem->insertBefore(doc->createTextNode(DSIGConstants::s_unicodeStrNL), prodElem); |
| |
| /* |
| * Add some test references |
| */ |
| |
| ref[0] = sig->createReference(MAKE_UNICODE_STRING(""), |
| DSIGConstants::s_unicodeStrURISHA1); |
| ref[0]->appendEnvelopedSignatureTransform(); |
| |
| ref[1] = sig->createReference(MAKE_UNICODE_STRING("#xpointer(/)"), |
| DSIGConstants::s_unicodeStrURISHA1); |
| ref[1]->appendEnvelopedSignatureTransform(); |
| ref[1]->appendCanonicalizationTransform(DSIGConstants::s_unicodeStrURIC14N_NOC); |
| |
| ref[2] = sig->createReference(MAKE_UNICODE_STRING("#xpointer(/)"), |
| DSIGConstants::s_unicodeStrURISHA1); |
| ref[2]->appendEnvelopedSignatureTransform(); |
| ref[2]->appendCanonicalizationTransform(DSIGConstants::s_unicodeStrURIC14N_COM); |
| |
| ref[3] = sig->createReference(MAKE_UNICODE_STRING("#xpointer(/)"), |
| DSIGConstants::s_unicodeStrURISHA1); |
| ref[3]->appendEnvelopedSignatureTransform(); |
| ref[3]->appendCanonicalizationTransform(DSIGConstants::s_unicodeStrURIEXC_C14N_NOC); |
| |
| ref[4] = sig->createReference(MAKE_UNICODE_STRING("#xpointer(/)"), |
| DSIGConstants::s_unicodeStrURISHA1); |
| ref[4]->appendEnvelopedSignatureTransform(); |
| ref[4]->appendCanonicalizationTransform(DSIGConstants::s_unicodeStrURIEXC_C14N_COM); |
| |
| ref[5] = sig->createReference(MAKE_UNICODE_STRING("#xpointer(/)"), |
| DSIGConstants::s_unicodeStrURISHA1); |
| ref[5]->appendEnvelopedSignatureTransform(); |
| DSIGTransformC14n * ce = ref[5]->appendCanonicalizationTransform( |
| DSIGConstants::s_unicodeStrURIEXC_C14N_COM); |
| ce->addInclusiveNamespace("foo"); |
| |
| sig->setECNSPrefix(MAKE_UNICODE_STRING("ec")); |
| ref[6] = sig->createReference(MAKE_UNICODE_STRING("#xpointer(/)"), |
| DSIGConstants::s_unicodeStrURISHA1); |
| ref[6]->appendEnvelopedSignatureTransform(); |
| ce = ref[6]->appendCanonicalizationTransform( |
| DSIGConstants::s_unicodeStrURIEXC_C14N_COM); |
| ce->addInclusiveNamespace("foo"); |
| |
| #ifndef XSEC_HAVE_XALAN |
| |
| cerr << "WARNING : No testing of XPath being performed as Xalan not present" << endl; |
| refCount = 7; |
| |
| #else |
| /* |
| * Create some XPath/XPathFilter references |
| */ |
| |
| |
| ref[7] = sig->createReference(MAKE_UNICODE_STRING(""), |
| DSIGConstants::s_unicodeStrURISHA1); |
| sig->setXPFNSPrefix(MAKE_UNICODE_STRING("xpf")); |
| DSIGTransformXPathFilter * xpf = ref[7]->appendXPathFilterTransform(); |
| xpf->appendFilter(DSIGXPathFilterExpr::FILTER_INTERSECT, MAKE_UNICODE_STRING("//ADoc/category")); |
| |
| ref[8] = sig->createReference(MAKE_UNICODE_STRING(""), |
| DSIGConstants::s_unicodeStrURISHA1); |
| /* ref[5]->appendXPathTransform("ancestor-or-self::dsig:Signature", |
| "xmlns:dsig=http://www.w3.org/2000/09/xmldsig#"); */ |
| |
| DSIGTransformXPath * x = ref[8]->appendXPathTransform("count(ancestor-or-self::dsig:Signature | \ |
| here()/ancestor::dsig:Signature[1]) > \ |
| count(ancestor-or-self::dsig:Signature)"); |
| x->setNamespace("dsig", "http://www.w3.org/2000/09/xmldsig#"); |
| |
| refCount = 9; |
| |
| #endif |
| |
| /* |
| * Sign the document, using an HMAC algorithm and the key "secret" |
| */ |
| |
| |
| sig->appendKeyName(MAKE_UNICODE_STRING("The secret key is \"secret\"")); |
| |
| // Append a test DNames |
| |
| DSIGKeyInfoX509 * x509 = sig->appendX509Data(); |
| x509->setX509SubjectName(s_tstDName); |
| |
| // Append a test PGPData element |
| sig->appendPGPData(s_tstPGPKeyID, s_tstPGPKeyPacket); |
| |
| // Append an SPKIData element |
| DSIGKeyInfoSPKIData * spki = sig->appendSPKIData(s_tstSexp1); |
| spki->appendSexp(s_tstSexp2); |
| |
| // Append a MgmtData element |
| sig->appendMgmtData(s_tstMgmtData); |
| |
| sig->setSigningKey(createHMACKey((unsigned char *) "secret")); |
| sig->sign(); |
| |
| // Output the document post signature if necessary |
| outputDoc(impl, doc); |
| |
| cerr << endl << "Doc signed OK - Checking values against Known Good" << endl; |
| |
| unsigned char buf[128]; |
| XMLSize_t len; |
| |
| /* |
| * Validate the reference hash values from known good |
| */ |
| |
| int i; |
| for (i = 0; i < refCount; ++i) { |
| |
| cerr << "Calculating hash for reference " << i << " ... "; |
| |
| len = (int) ref[i]->calculateHash(buf, 128); |
| |
| cerr << " Done\nChecking -> "; |
| |
| if (len != 20) { |
| cerr << "Bad (Length = " << len << ")" << endl; |
| exit (1); |
| } |
| |
| for (int j = 0; j < 20; ++j) { |
| |
| if (buf[j] != createdDocRefs[i][j]) { |
| cerr << "Bad at location " << j << endl; |
| exit (1); |
| } |
| |
| } |
| cerr << "Good.\n"; |
| |
| } |
| |
| /* |
| * Verify the signature check works |
| */ |
| |
| cerr << "Running \"verifySignatureOnly()\" on calculated signature ... "; |
| if (sig->verifySignatureOnly()) { |
| cerr << "OK" << endl; |
| } |
| else { |
| cerr << "Failed" << endl; |
| char * e = XMLString::transcode(sig->getErrMsgs()); |
| cout << e << endl; |
| XSEC_RELEASE_XMLCH(e); |
| exit(1); |
| } |
| |
| /* |
| * Change the document and ensure the signature fails. |
| */ |
| |
| cerr << "Setting incorrect key in Signature object" << endl; |
| sig->setSigningKey(createHMACKey((unsigned char *) "badsecret")); |
| |
| cerr << "Running \"verifySignatureOnly()\" on calculated signature ... "; |
| if (!sig->verifySignatureOnly()) { |
| cerr << "OK (Signature bad)" << endl; |
| } |
| else { |
| cerr << "Failed (signature OK but should be bad)" << endl; |
| exit(1); |
| } |
| |
| // Don't need the signature now the DOM structure is in place |
| prov.releaseSignature(sig); |
| |
| /* |
| * Now serialise the document to memory so we can re-parse and check from scratch |
| */ |
| |
| cerr << "Serialising the document to a memory buffer ... "; |
| |
| MemBufFormatTarget *formatTarget = new MemBufFormatTarget(); |
| |
| DOMLSSerializer *theSerializer = ((DOMImplementationLS*)impl)->createLSSerializer(); |
| |
| // 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); |
| |
| // Copy to a new buffer |
| len = formatTarget->getLen(); |
| char * mbuf = new char [len + 1]; |
| memcpy(mbuf, formatTarget->getRawBuffer(), len); |
| mbuf[len] = '\0'; |
| #if 0 |
| cout << mbuf << endl; |
| #endif |
| delete theSerializer; |
| delete formatTarget; |
| |
| cerr << "done\nParsing memory buffer back to DOM ... "; |
| |
| // Also release the document so that we can re-load from scratch |
| |
| doc->release(); |
| |
| /* |
| * Re-parse |
| */ |
| |
| XercesDOMParser parser; |
| |
| parser.setDoNamespaces(true); |
| parser.setCreateEntityReferenceNodes(true); |
| |
| MemBufInputSource* memIS = new MemBufInputSource ((const XMLByte*) mbuf, |
| len, "XSECMem"); |
| |
| parser.parse(*memIS); |
| doc = parser.adoptDocument(); |
| |
| |
| delete(memIS); |
| delete[] mbuf; |
| |
| cerr << "done\nValidating signature ..."; |
| |
| /* |
| * Validate signature |
| */ |
| |
| sig = prov.newSignatureFromDOM(doc); |
| sig->load(); |
| sig->setSigningKey(createHMACKey((unsigned char *) "secret")); |
| |
| if (sig->verify()) { |
| cerr << "OK" << endl; |
| } |
| else { |
| cerr << "Failed\n" << endl; |
| char * e = XMLString::transcode(sig->getErrMsgs()); |
| cerr << e << endl; |
| XSEC_RELEASE_XMLCH(e); |
| exit(1); |
| } |
| |
| /* |
| * Ensure DNames are read back in and decoded properly |
| */ |
| |
| DSIGKeyInfoList * kil = sig->getKeyInfoList(); |
| int nki = (int) kil->getSize(); |
| |
| cerr << "Checking Distinguished name is decoded correctly ... "; |
| for (i = 0; i < nki; ++i) { |
| |
| if (kil->item(i)->getKeyInfoType() == DSIGKeyInfo::KEYINFO_X509) { |
| |
| if (strEquals(s_tstDName, ((DSIGKeyInfoX509 *) kil->item(i))->getX509SubjectName())) { |
| cerr << "yes" << endl; |
| } |
| else { |
| cerr << "decoded incorrectly" << endl;; |
| exit (1); |
| } |
| } |
| if (kil->item(i)->getKeyInfoType() == DSIGKeyInfo::KEYINFO_PGPDATA) { |
| |
| cerr << "Validating PGPData read back OK ... "; |
| |
| DSIGKeyInfoPGPData * p = (DSIGKeyInfoPGPData *)kil->item(i); |
| |
| if (!(strEquals(p->getKeyID(), s_tstPGPKeyID) && |
| strEquals(p->getKeyPacket(), s_tstPGPKeyPacket))) { |
| |
| cerr << "no!"; |
| exit(1); |
| } |
| |
| cerr << "yes\n"; |
| } |
| if (kil->item(i)->getKeyInfoType() == DSIGKeyInfo::KEYINFO_SPKIDATA) { |
| |
| cerr << "Validating SPKIData read back OK ... "; |
| |
| DSIGKeyInfoSPKIData * s = (DSIGKeyInfoSPKIData *)kil->item(i); |
| |
| if (s->getSexpSize() != 2) { |
| cerr << "no - expected two S-expressions"; |
| exit(1); |
| } |
| |
| if (!(strEquals(s->getSexp(0), s_tstSexp1) && |
| strEquals(s->getSexp(1), s_tstSexp2))) { |
| |
| cerr << "no!"; |
| exit(1); |
| } |
| |
| cerr << "yes\n"; |
| } |
| if (kil->item(i)->getKeyInfoType() == DSIGKeyInfo::KEYINFO_MGMTDATA) { |
| |
| cerr << "Validating MgmtData read back OK ... "; |
| |
| DSIGKeyInfoMgmtData * m = (DSIGKeyInfoMgmtData *)kil->item(i); |
| |
| if (!strEquals(m->getData(), s_tstMgmtData)) { |
| |
| cerr << "no!"; |
| exit(1); |
| } |
| |
| cerr << "yes\n"; |
| } |
| } |
| } |
| |
| catch (const XSECException &e) |
| { |
| cerr << "An error occurred during signature processing\n Message: "; |
| char * ce = XMLString::transcode(e.getMsg()); |
| cerr << ce << endl; |
| delete ce; |
| exit(1); |
| |
| } |
| catch (const XSECCryptoException &e) |
| { |
| cerr << "A cryptographic error occurred during signature processing\n Message: " |
| << e.getMsg() << endl; |
| exit(1); |
| } |
| |
| // Output the document post signature if necessary |
| outputDoc(impl, doc); |
| |
| doc->release(); |
| |
| } |
| |
| // -------------------------------------------------------------------------------- |
| // Unit tests for test encrypt/Decrypt |
| // -------------------------------------------------------------------------------- |
| |
| void unitTestCipherReference(DOMImplementation * impl) { |
| |
| DOMDocument *doc = impl->createDocument( |
| 0, // root element namespace URI. |
| MAKE_UNICODE_STRING("ADoc"), // root element name |
| NULL);// DOMDocumentType()); // document type object (DTD). |
| |
| DOMElement *rootElem = doc->getDocumentElement(); |
| |
| // Use key k to wrap a test key, decrypt it and make sure it is still OK |
| XSECProvider prov; |
| XENCCipher * cipher; |
| |
| try { |
| |
| cipher = prov.newCipher(doc); |
| |
| cerr << "Creating CipherReference ... "; |
| |
| XENCEncryptedData * xenc = |
| cipher->createEncryptedData(XENCCipherData::REFERENCE_TYPE, DSIGConstants::s_unicodeStrURIAES128_CBC, MAKE_UNICODE_STRING("#CipherText")); |
| |
| rootElem->appendChild(xenc->getElement()); |
| |
| // Now create the data that is referenced |
| DOMElement * cipherVal = doc->createElement(MAKE_UNICODE_STRING("MyCipherValue")); |
| rootElem->appendChild(cipherVal); |
| cipherVal->setAttributeNS(NULL, MAKE_UNICODE_STRING("Id"), MAKE_UNICODE_STRING("CipherText")); |
| cipherVal->setIdAttributeNS(NULL, MAKE_UNICODE_STRING("Id"), true); |
| |
| cipherVal->appendChild(doc->createTextNode(MAKE_UNICODE_STRING((char *) s_tstBase64EncodedString))); |
| |
| // Now add the transforms necessary to decrypt |
| XENCCipherReference *cref = xenc->getCipherData()->getCipherReference(); |
| |
| if (cref == NULL) { |
| cerr << "Failed - no CipherReference object" << endl; |
| exit(1); |
| } |
| |
| cerr << "done ... appending XPath and Base64 transforms ... "; |
| |
| //cref->appendXPathTransform("self::text()[parent::rep:CipherValue[@Id="example1"]]"); |
| cref->appendXPathTransform("self::text()[parent::MyCipherValue[@Id=\"CipherText\"]]"); |
| cref->appendBase64Transform(); |
| |
| cerr << "done ... decrypting ... "; |
| |
| // Create a key |
| XSECCryptoSymmetricKey * ks = |
| XSECPlatformUtils::g_cryptoProvider->keySymmetric(XSECCryptoSymmetricKey::KEY_AES_128); |
| ks->setKey((unsigned char *) s_keyStr, 16); |
| |
| cipher->setKey(ks); |
| |
| // Now try to decrypt |
| DOMNode * n = findXENCNode(doc, "EncryptedData"); |
| |
| XSECBinTXFMInputStream *is = cipher->decryptToBinInputStream((DOMElement *) n); |
| Janitor<XSECBinTXFMInputStream> j_is(is); |
| |
| XMLByte buf[1024]; |
| |
| cerr << "done ... comparing to known good ... "; |
| |
| XMLSize_t bytesRead = is->readBytes(buf, 1024); |
| buf[bytesRead] = '\0'; |
| if (strcmp((char *) buf, s_tstDecryptedString) == 0) { |
| cerr << "OK" << endl; |
| } |
| else { |
| cerr << "failed - bad compare of decrypted data" << endl; |
| } |
| |
| } |
| |
| catch (const XSECException &e) |
| { |
| cerr << "failed\n"; |
| cerr << "An error occurred during signature processing\n Message: "; |
| char * ce = XMLString::transcode(e.getMsg()); |
| cerr << ce << endl; |
| delete ce; |
| exit(1); |
| |
| } |
| catch (const XSECCryptoException &e) |
| { |
| cerr << "failed\n"; |
| cerr << "A cryptographic error occurred during signature processing\n Message: " |
| << e.getMsg() << endl; |
| exit(1); |
| } |
| |
| outputDoc(impl, doc); |
| doc->release(); |
| |
| } |
| |
| |
| void unitTestElementContentEncrypt(DOMImplementation *impl, XSECCryptoKey * key, const XMLCh* algorithm, bool doElementContent) { |
| |
| if (doElementContent) |
| cerr << "Encrypting Element Content ... "; |
| else |
| cerr << "Encrypting Element ... "; |
| |
| // Create a document |
| |
| DOMDocument * doc = createTestDoc(impl); |
| DOMNode * categoryNode = findNode(doc, MAKE_UNICODE_STRING("category")); |
| if (categoryNode == NULL) { |
| |
| cerr << "Error finding category node for encryption test" << endl; |
| exit(1); |
| |
| } |
| |
| // Create and execute cipher |
| |
| XSECProvider prov; |
| XENCCipher * cipher; |
| |
| try { |
| |
| /* |
| * Now we have a document, find the data node. |
| */ |
| |
| cipher = prov.newCipher(doc); |
| cipher->setXENCNSPrefix(MAKE_UNICODE_STRING("xenc")); |
| cipher->setPrettyPrint(true); |
| |
| // Set a key |
| |
| cipher->setKey(key->clone()); |
| |
| // Now encrypt! |
| if (doElementContent) |
| cipher->encryptElementContent(doc->getDocumentElement(), algorithm); |
| else |
| cipher->encryptElement((DOMElement *) categoryNode, algorithm); |
| |
| cerr << "done ... check encrypted ... "; |
| |
| DOMNode * t = findNode(doc, MAKE_UNICODE_STRING("category")); |
| if (t != NULL) { |
| |
| cerr << "no - a category child still exists" << endl; |
| exit(1); |
| |
| } |
| else |
| cerr << "yes" << endl; |
| |
| outputDoc(impl, doc); |
| |
| if (doElementContent) |
| cerr << "Decrypting Element content ... "; |
| else |
| cerr << "Decrypting Element ... "; |
| |
| // OK - Now we try to decrypt |
| // Find the EncryptedData node |
| DOMNode * n = findXENCNode(doc, "EncryptedData"); |
| |
| XENCCipher * cipher2 = prov.newCipher(doc); |
| |
| cipher2->setKey(key); |
| |
| cipher2->decryptElement(static_cast<DOMElement *>(n)); |
| |
| cerr << "done ... check decrypt ... "; |
| t = findNode(doc, MAKE_UNICODE_STRING("category")); |
| |
| if (t == NULL) { |
| |
| cerr << " failed - category did not decrypt properly" << endl; |
| exit(1); |
| |
| } |
| else |
| cerr << "OK" << endl; |
| |
| outputDoc(impl, doc); |
| |
| } |
| catch (const XSECException &e) |
| { |
| cerr << "An error occurred during encryption processing\n Message: "; |
| char * ce = XMLString::transcode(e.getMsg()); |
| cerr << ce << endl; |
| delete ce; |
| exit(1); |
| |
| } |
| catch (const XSECCryptoException &e) |
| { |
| cerr << "A cryptographic error occurred during encryption processing\n Message: " |
| << e.getMsg() << endl; |
| exit(1); |
| } |
| |
| doc->release(); |
| |
| } |
| |
| void unitTestSmallElement(DOMImplementation *impl) { |
| |
| cerr << "Encrypt small input... "; |
| |
| // Create a document |
| |
| DOMDocument * doc = createTestDoc(impl); |
| DOMElement * productNode = (DOMElement *) findNode(doc, MAKE_UNICODE_STRING("product")); |
| if (productNode == NULL) { |
| |
| cerr << "Error finding product node for small input encryption test" << endl; |
| exit(1); |
| |
| } |
| |
| // Shrink the input text |
| DOMNode * textNode = productNode->getFirstChild(); |
| textNode->setNodeValue(MAKE_UNICODE_STRING("sm")); |
| |
| // Create and execute cipher |
| |
| XSECProvider prov; |
| XENCCipher * cipher; |
| |
| try { |
| |
| /* |
| * Now we have a document, find the data node. |
| */ |
| |
| cipher = prov.newCipher(doc); |
| cipher->setXENCNSPrefix(MAKE_UNICODE_STRING("xenc")); |
| cipher->setPrettyPrint(true); |
| |
| // Set a key |
| XSECCryptoSymmetricKey * ks = |
| XSECPlatformUtils::g_cryptoProvider->keySymmetric(XSECCryptoSymmetricKey::KEY_3DES_192); |
| ks->setKey((unsigned char *) s_keyStr, 24); |
| |
| cipher->setKey(ks->clone()); |
| |
| // Now encrypt! |
| cipher->encryptElementContent(productNode, DSIGConstants::s_unicodeStrURI3DES_CBC); |
| |
| cerr << "done ... check encrypted ... "; |
| |
| DOMNode * t = findNode(doc, MAKE_UNICODE_STRING("product")); |
| t = findFirstChildOfType(t, DOMNode::TEXT_NODE); |
| while (t != NULL && ! strEquals(t->getNodeValue(), "sm")) |
| t = findNextChildOfType(t, DOMNode::TEXT_NODE); |
| |
| if (t != NULL) { |
| |
| cerr << "no - text child still exists" << endl; |
| exit(1); |
| |
| } |
| else |
| cerr << "yes" << endl; |
| |
| outputDoc(impl, doc); |
| |
| cerr << "Decrypting Element content ... "; |
| |
| // OK - Now we try to decrypt |
| // Find the EncryptedData node |
| DOMNode * n = findXENCNode(doc, "EncryptedData"); |
| |
| XENCCipher * cipher2 = prov.newCipher(doc); |
| |
| cipher2->setKey(ks); |
| |
| cipher2->decryptElement(static_cast<DOMElement *>(n)); |
| |
| cerr << "done ... check decrypt ... "; |
| t = findNode(doc, MAKE_UNICODE_STRING("product")); |
| t = findFirstChildOfType(t, DOMNode::TEXT_NODE); |
| if (t == NULL || !strEquals(t->getNodeValue(), "sm")) { |
| |
| cerr << " failed - small text did not decrypt properly" << endl; |
| exit(1); |
| |
| } |
| else |
| cerr << "OK" << endl; |
| |
| outputDoc(impl, doc); |
| |
| } |
| catch (const XSECException &e) |
| { |
| cerr << "An error occurred during encryption processing\n Message: "; |
| char * ce = XMLString::transcode(e.getMsg()); |
| cerr << ce << endl; |
| delete ce; |
| exit(1); |
| |
| } |
| catch (const XSECCryptoException &e) |
| { |
| cerr << "A cryptographic error occurred during encryption processing\n Message: " |
| << e.getMsg() << endl; |
| exit(1); |
| } |
| |
| doc->release(); |
| |
| } |
| |
| |
| void unitTestKeyEncrypt( |
| DOMImplementation* impl, |
| XSECCryptoKey* k, |
| const XMLCh* algorithm, |
| const XMLCh* mgf=NULL, |
| unsigned char* oaepParams=NULL, |
| unsigned int oaepParamsLen=0 |
| ) { |
| |
| // Create a document that we will embed the encrypted key in |
| DOMDocument *doc = impl->createDocument( |
| 0, // root element namespace URI. |
| MAKE_UNICODE_STRING("ADoc"), // root element name |
| NULL);// DOMDocumentType()); // document type object (DTD). |
| |
| DOMElement *rootElem = doc->getDocumentElement(); |
| |
| // Use key k to wrap a test key, decrypt it and make sure it is still OK |
| XSECProvider prov; |
| XENCCipher * cipher; |
| |
| try { |
| |
| // Encrypt a dummy key |
| |
| cerr << "encrypt ... "; |
| |
| static unsigned char toEncryptStr[] = "A test key to use for da"; |
| |
| cipher = prov.newCipher(doc); |
| cipher->setXENCNSPrefix(MAKE_UNICODE_STRING("xenc")); |
| cipher->setPrettyPrint(true); |
| |
| // Set a key |
| |
| cipher->setKEK(k); |
| |
| XENCEncryptedKey * encryptedKey; |
| encryptedKey = cipher->encryptKey( |
| toEncryptStr, (unsigned int) strlen((char *) toEncryptStr), algorithm, mgf, oaepParams, oaepParamsLen |
| ); |
| Janitor<XENCEncryptedKey> j_encryptedKey(encryptedKey); |
| |
| rootElem->appendChild(encryptedKey->getElement()); |
| |
| // Decrypt |
| cerr << "decrypt ... "; |
| |
| XMLByte decBuf[64]; |
| cipher->decryptKey(encryptedKey, decBuf, 64); |
| |
| // Check |
| cerr << "comparing ... "; |
| if (memcmp(decBuf, toEncryptStr, strlen((char *) toEncryptStr)) == 0) { |
| cerr << "OK ... "; |
| } |
| else { |
| cerr << "different = failed!" << endl; |
| exit(2); |
| } |
| |
| cerr << "decrypt from DOM ... "; |
| // Decrypt from DOM |
| DOMNode * keyNode = findXENCNode(doc, "EncryptedKey"); |
| if (keyNode == NULL) { |
| cerr << "no key - failed!" << endl; |
| exit(2); |
| } |
| memset(decBuf, 0, 64); |
| cipher->decryptKey((DOMElement *) keyNode, decBuf, 64); |
| |
| cerr << "comparing ... "; |
| if (memcmp(decBuf, toEncryptStr, strlen((char *) toEncryptStr)) == 0) { |
| cerr << "OK" << endl; |
| } |
| else { |
| cerr << "different = failed!" << endl; |
| exit(2); |
| } |
| |
| } |
| |
| catch (const XSECException &e) |
| { |
| cerr << "failed\n"; |
| cerr << "An error occurred during signature processing\n Message: "; |
| char * ce = XMLString::transcode(e.getMsg()); |
| cerr << ce << endl; |
| delete ce; |
| exit(1); |
| |
| } |
| catch (const XSECCryptoException &e) |
| { |
| cerr << "failed\n"; |
| cerr << "A cryptographic error occurred during signature processing\n Message: " |
| << e.getMsg() << endl; |
| exit(1); |
| } |
| |
| outputDoc(impl, doc); |
| doc->release(); |
| |
| } |
| |
| |
| |
| void unitTestEncrypt(DOMImplementation *impl) { |
| |
| try { |
| // Key wraps |
| cerr << "RSA key wrap... "; |
| |
| #if defined (XSEC_HAVE_OPENSSL) |
| if (!g_useWinCAPI && !g_useNSS) { |
| // Load the key |
| BIO * bioMem = BIO_new(BIO_s_mem()); |
| BIO_puts(bioMem, s_tstRSAPrivateKey); |
| EVP_PKEY * pk = PEM_read_bio_PrivateKey(bioMem, NULL, NULL, NULL); |
| |
| OpenSSLCryptoKeyRSA * k = new OpenSSLCryptoKeyRSA(pk); |
| |
| unitTestKeyEncrypt(impl, k, DSIGConstants::s_unicodeStrURIRSA_1_5); |
| |
| cerr << "RSA OAEP key wrap... "; |
| k = new OpenSSLCryptoKeyRSA(pk); |
| unitTestKeyEncrypt(impl, k, DSIGConstants::s_unicodeStrURIRSA_OAEP_MGFP1, DSIGConstants::s_unicodeStrURIMGF1_SHA1); |
| |
| cerr << "RSA OAEP key wrap + params... "; |
| k = new OpenSSLCryptoKeyRSA(pk); |
| unitTestKeyEncrypt(impl, k, DSIGConstants::s_unicodeStrURIRSA_OAEP_MGFP1, DSIGConstants::s_unicodeStrURIMGF1_SHA1, |
| s_tstOAEPparams, (unsigned int) strlen((char *) s_tstOAEPparams)); |
| |
| cerr << "RSA OAEP 1.1 key wrap... "; |
| k = new OpenSSLCryptoKeyRSA(pk); |
| unitTestKeyEncrypt(impl, k, DSIGConstants::s_unicodeStrURIRSA_OAEP, DSIGConstants::s_unicodeStrURIMGF1_SHA1); |
| |
| if (XSECPlatformUtils::g_cryptoProvider->algorithmSupported(XSECCryptoHash::HASH_SHA224)) { |
| cerr << "RSA OAEP 1.1 key wrap with MGF1+SHA224... "; |
| k = new OpenSSLCryptoKeyRSA(pk); |
| unitTestKeyEncrypt(impl, k, DSIGConstants::s_unicodeStrURIRSA_OAEP, DSIGConstants::s_unicodeStrURIMGF1_SHA224); |
| } |
| |
| if (XSECPlatformUtils::g_cryptoProvider->algorithmSupported(XSECCryptoHash::HASH_SHA256)) { |
| cerr << "RSA OAEP 1.1 key wrap with MGF1+SHA256... "; |
| k = new OpenSSLCryptoKeyRSA(pk); |
| unitTestKeyEncrypt(impl, k, DSIGConstants::s_unicodeStrURIRSA_OAEP, DSIGConstants::s_unicodeStrURIMGF1_SHA256); |
| } |
| |
| if (XSECPlatformUtils::g_cryptoProvider->algorithmSupported(XSECCryptoHash::HASH_SHA384)) { |
| cerr << "RSA OAEP 1.1 key wrap with MGF1+SHA384... "; |
| k = new OpenSSLCryptoKeyRSA(pk); |
| unitTestKeyEncrypt(impl, k, DSIGConstants::s_unicodeStrURIRSA_OAEP, DSIGConstants::s_unicodeStrURIMGF1_SHA384); |
| } |
| |
| if (XSECPlatformUtils::g_cryptoProvider->algorithmSupported(XSECCryptoHash::HASH_SHA512)) { |
| cerr << "RSA OAEP 1.1 key wrap with MGF1+SHA512... "; |
| k = new OpenSSLCryptoKeyRSA(pk); |
| unitTestKeyEncrypt(impl, k, DSIGConstants::s_unicodeStrURIRSA_OAEP, DSIGConstants::s_unicodeStrURIMGF1_SHA512); |
| } |
| |
| BIO_free(bioMem); |
| EVP_PKEY_free(pk); |
| } |
| #endif |
| |
| #if defined (XSEC_HAVE_WINCAPI) |
| if (g_useWinCAPI) { |
| |
| // Use the internal key |
| WinCAPICryptoProvider *cp = (WinCAPICryptoProvider *) (XSECPlatformUtils::g_cryptoProvider); |
| HCRYPTPROV p = cp->getApacheKeyStore(); |
| |
| WinCAPICryptoKeyRSA * rsaKey = new WinCAPICryptoKeyRSA(p, AT_KEYEXCHANGE, true); |
| unitTestKeyEncrypt(impl, rsaKey, DSIGConstants::s_unicodeStrURIRSA_1_5); |
| |
| cerr << "RSA OAEP key wrap... "; |
| rsaKey = new WinCAPICryptoKeyRSA(p, AT_KEYEXCHANGE, true); |
| unitTestKeyEncrypt(impl, rsaKey, DSIGConstants::s_unicodeStrURIRSA_OAEP_MGFP1); |
| |
| cerr << "RSA OAEP 1.1 key wrap... "; |
| rsaKey = new WinCAPICryptoKeyRSA(p, AT_KEYEXCHANGE, true); |
| unitTestKeyEncrypt(impl, rsaKey, DSIGConstants::s_unicodeStrURIRSA_OAEP); |
| } |
| |
| #endif |
| |
| #if defined (XSEC_HAVE_NSS) |
| if (g_useNSS) { |
| // Heavily based on Mozilla example code |
| SECKEYPrivateKey *prvKey = 0; |
| SECKEYPublicKey *pubKey = 0; |
| PK11SlotInfo *slot = 0; |
| PK11RSAGenParams rsaParams; |
| |
| // Use a bog standard key size |
| rsaParams.keySizeInBits = 1024; |
| rsaParams.pe = 65537; |
| |
| // We need somewhere to temporarily store a generated key |
| slot = PK11_GetInternalKeySlot(); |
| if (!slot) { |
| cerr << "Error generating key - can't get NSS slot\n"; |
| exit (1); |
| } |
| |
| // Do the generate |
| prvKey = PK11_GenerateKeyPair(slot, CKM_RSA_PKCS_KEY_PAIR_GEN, &rsaParams, |
| &pubKey, PR_FALSE, PR_TRUE, 0); |
| |
| if (!prvKey) { |
| if (slot) |
| PK11_FreeSlot(slot); |
| cerr << "Error generating key within NSS\n"; |
| exit (1); |
| } |
| |
| // Now use the key! |
| NSSCryptoKeyRSA * rsaKey = new NSSCryptoKeyRSA(pubKey, prvKey); |
| unitTestKeyEncrypt(impl, rsaKey, DSIGConstants::s_unicodeStrURIRSA_1_5); |
| |
| if (slot) |
| // Actual keys will be deleted by the provider |
| PK11_FreeSlot(slot); |
| |
| cerr << "RSA OAEP key wrap skipped - not yet supported in NSS crypto provider\n"; |
| |
| } |
| #endif |
| |
| XSECCryptoSymmetricKey * ks; |
| |
| if (g_haveAES) { |
| cerr << "AES 128 key wrap... "; |
| |
| ks = XSECPlatformUtils::g_cryptoProvider->keySymmetric(XSECCryptoSymmetricKey::KEY_AES_128); |
| ks->setKey((unsigned char *) s_keyStr, 16); |
| |
| unitTestKeyEncrypt(impl, ks, DSIGConstants::s_unicodeStrURIKW_AES128); |
| |
| cerr << "AES 192 key wrap... "; |
| |
| ks = XSECPlatformUtils::g_cryptoProvider->keySymmetric(XSECCryptoSymmetricKey::KEY_AES_192); |
| ks->setKey((unsigned char *) s_keyStr, 24); |
| |
| unitTestKeyEncrypt(impl, ks, DSIGConstants::s_unicodeStrURIKW_AES192); |
| |
| cerr << "AES 256 key wrap... "; |
| |
| ks = XSECPlatformUtils::g_cryptoProvider->keySymmetric(XSECCryptoSymmetricKey::KEY_AES_256); |
| ks->setKey((unsigned char *) s_keyStr, 32); |
| |
| unitTestKeyEncrypt(impl, ks, DSIGConstants::s_unicodeStrURIKW_AES256); |
| } |
| |
| else |
| cerr << "Skipped AES key wrap tests" << endl; |
| |
| cerr << "Triple DES key wrap... "; |
| |
| ks = XSECPlatformUtils::g_cryptoProvider->keySymmetric(XSECCryptoSymmetricKey::KEY_3DES_192); |
| ks->setKey((unsigned char *) s_keyStr, 24); |
| |
| unitTestKeyEncrypt(impl, ks, DSIGConstants::s_unicodeStrURIKW_3DES); |
| |
| // Now do Element encrypts |
| |
| if (g_haveAES) { |
| // 128 AES |
| ks = XSECPlatformUtils::g_cryptoProvider->keySymmetric(XSECCryptoSymmetricKey::KEY_AES_128); |
| ks->setKey((unsigned char *) s_keyStr, 16); |
| |
| cerr << "Unit testing AES 128 bit CBC encryption" << endl; |
| unitTestElementContentEncrypt(impl, ks->clone(), DSIGConstants::s_unicodeStrURIAES128_CBC, false); |
| unitTestElementContentEncrypt(impl, ks, DSIGConstants::s_unicodeStrURIAES128_CBC, true); |
| |
| //192 AES |
| ks = XSECPlatformUtils::g_cryptoProvider->keySymmetric(XSECCryptoSymmetricKey::KEY_AES_192); |
| ks->setKey((unsigned char *) s_keyStr, 24); |
| |
| cerr << "Unit testing AES 192 bit CBC encryption" << endl; |
| unitTestElementContentEncrypt(impl, ks->clone(), DSIGConstants::s_unicodeStrURIAES192_CBC, false); |
| unitTestElementContentEncrypt(impl, ks, DSIGConstants::s_unicodeStrURIAES192_CBC, true); |
| |
| // 256 AES |
| ks = XSECPlatformUtils::g_cryptoProvider->keySymmetric(XSECCryptoSymmetricKey::KEY_AES_256); |
| ks->setKey((unsigned char *) s_keyStr, 32); |
| |
| cerr << "Unit testing AES 256 bit CBC encryption" << endl; |
| unitTestElementContentEncrypt(impl, ks->clone(), DSIGConstants::s_unicodeStrURIAES256_CBC, false); |
| unitTestElementContentEncrypt(impl, ks, DSIGConstants::s_unicodeStrURIAES256_CBC, true); |
| |
| if (g_testGCM) { |
| // 128 AES-GCM |
| ks = XSECPlatformUtils::g_cryptoProvider->keySymmetric(XSECCryptoSymmetricKey::KEY_AES_128); |
| ks->setKey((unsigned char *)s_keyStr, 16); |
| |
| cerr << "Unit testing AES 128 bit GCM encryption" << endl; |
| unitTestElementContentEncrypt(impl, ks->clone(), DSIGConstants::s_unicodeStrURIAES128_GCM, false); |
| unitTestElementContentEncrypt(impl, ks, DSIGConstants::s_unicodeStrURIAES128_GCM, true); |
| |
| //192 AES-GCM |
| ks = XSECPlatformUtils::g_cryptoProvider->keySymmetric(XSECCryptoSymmetricKey::KEY_AES_192); |
| ks->setKey((unsigned char *)s_keyStr, 24); |
| |
| cerr << "Unit testing AES 192 bit GCM encryption" << endl; |
| unitTestElementContentEncrypt(impl, ks->clone(), DSIGConstants::s_unicodeStrURIAES192_GCM, false); |
| unitTestElementContentEncrypt(impl, ks, DSIGConstants::s_unicodeStrURIAES192_GCM, true); |
| |
| // 256 AES-GCM |
| ks = XSECPlatformUtils::g_cryptoProvider->keySymmetric(XSECCryptoSymmetricKey::KEY_AES_256); |
| ks->setKey((unsigned char *)s_keyStr, 32); |
| |
| cerr << "Unit testing AES 256 bit GCM encryption" << endl; |
| unitTestElementContentEncrypt(impl, ks->clone(), DSIGConstants::s_unicodeStrURIAES256_GCM, false); |
| unitTestElementContentEncrypt(impl, ks, DSIGConstants::s_unicodeStrURIAES256_GCM, true); |
| } |
| else { |
| cerr << "Skipped AES-GCM Element tests" << endl; |
| } |
| } |
| |
| else { |
| cerr << "Skipped AES Element tests" << endl; |
| } |
| |
| // 192 3DES |
| ks = XSECPlatformUtils::g_cryptoProvider->keySymmetric(XSECCryptoSymmetricKey::KEY_3DES_192); |
| ks->setKey((unsigned char *) s_keyStr, 24); |
| |
| cerr << "Unit testing 3DES CBC encryption" << endl; |
| unitTestElementContentEncrypt(impl, ks->clone(), DSIGConstants::s_unicodeStrURI3DES_CBC, false); |
| unitTestElementContentEncrypt(impl, ks, DSIGConstants::s_unicodeStrURI3DES_CBC, true); |
| #ifdef XSEC_HAVE_XALAN |
| if (g_haveAES) { |
| cerr << "Unit testing CipherReference creation and decryption" << endl; |
| unitTestCipherReference(impl); |
| } |
| else { |
| cerr << "Skipped Cipher Reference Test (uses AES)" << endl; |
| } |
| #else |
| cerr << "Skipped Cipher Reference Test (requires XPath)" << endl; |
| #endif |
| cerr << "Misc. encryption tests" << endl; |
| unitTestSmallElement(impl); |
| } |
| catch (const XSECCryptoException &e) |
| { |
| cerr << "failed\n"; |
| cerr << "A cryptographic error occurred during encryption unit tests\n Message: " |
| << e.getMsg() << endl; |
| exit(1); |
| } |
| |
| } |
| // -------------------------------------------------------------------------------- |
| // Test encrypt/Decrypt |
| // -------------------------------------------------------------------------------- |
| |
| void testEncrypt(DOMImplementation *impl) { |
| |
| cerr << "Creating a known doc encrypting a portion of it" << endl; |
| |
| // Create a document |
| |
| DOMDocument * doc = createTestDoc(impl); |
| DOMNode * categoryNode = findNode(doc, MAKE_UNICODE_STRING("category")); |
| if (categoryNode == NULL) { |
| |
| cerr << "Error finding category node for encryption test" << endl; |
| exit(1); |
| |
| } |
| |
| // Check signature functions |
| |
| XSECProvider prov; |
| XENCCipher * cipher; |
| |
| try { |
| |
| /* |
| * Now we have a document, find the data node. |
| */ |
| |
| // Generate a key |
| unsigned char randomBuffer[256]; |
| |
| if (XSECPlatformUtils::g_cryptoProvider->getRandom(randomBuffer, 256) != 256) { |
| |
| cerr << "Unable to obtain enough random bytes from Crypto Provider" << endl; |
| exit(1); |
| |
| } |
| |
| cipher = prov.newCipher(doc); |
| cipher->setXENCNSPrefix(MAKE_UNICODE_STRING("xenc")); |
| cipher->setPrettyPrint(true); |
| |
| // Set a key |
| |
| XSECCryptoSymmetricKey * k = |
| XSECPlatformUtils::g_cryptoProvider->keySymmetric(XSECCryptoSymmetricKey::KEY_3DES_192); |
| k->setKey((unsigned char *) randomBuffer, 24); |
| cipher->setKey(k); |
| |
| // Now encrypt! |
| cerr << "Performing 3DES encryption on <category> element ... "; |
| cipher->encryptElement((DOMElement *) categoryNode, DSIGConstants::s_unicodeStrURI3DES_CBC); |
| |
| // Add a KeyInfo |
| cerr << "done\nAppending a <KeyName> ... "; |
| XENCEncryptedData * encryptedData = cipher->getEncryptedData(); |
| encryptedData->appendKeyName(s_tstKeyName); |
| cerr << "done\nAdding Encoding and MimeType ... "; |
| |
| // Add MimeType and Encoding |
| encryptedData->setEncoding(s_tstEncoding); |
| encryptedData->setMimeType(s_tstMimeType); |
| |
| // Set a KeySize |
| cerr << "done\nSetting <KeySize> ... "; |
| encryptedData->getEncryptionMethod()->setKeySize(192); |
| |
| cerr << "done\nSearching for <category> ... "; |
| |
| DOMNode * t = findNode(doc, MAKE_UNICODE_STRING("category")); |
| if (t != NULL) { |
| |
| cerr << "found!\nError - category is not encrypted" << endl; |
| exit(1); |
| |
| } |
| else |
| cerr << "not found (OK - now encrypted)" << endl; |
| |
| // Now try to encrypt the Key |
| |
| cerr << "Encrypting symmetric key ... " << endl; |
| |
| XSECCryptoSymmetricKey * kek; |
| if (g_haveAES) { |
| |
| kek = XSECPlatformUtils::g_cryptoProvider->keySymmetric(XSECCryptoSymmetricKey::KEY_AES_128); |
| kek->setKey((unsigned char *) s_keyStr, 16); |
| } |
| else { |
| kek = XSECPlatformUtils::g_cryptoProvider->keySymmetric(XSECCryptoSymmetricKey::KEY_3DES_192); |
| kek->setKey((unsigned char *) s_keyStr, 24); |
| |
| } |
| |
| cipher->setKEK(kek); |
| |
| XENCEncryptedKey * encryptedKey; |
| if (g_haveAES) |
| encryptedKey = cipher->encryptKey(randomBuffer, 24, DSIGConstants::s_unicodeStrURIKW_AES128); |
| else |
| encryptedKey = cipher->encryptKey(randomBuffer, 24, DSIGConstants::s_unicodeStrURIKW_3DES); |
| cerr << "done!" << endl; |
| |
| cerr << "Adding CarriedKeyName and Recipient to encryptedKey ... " << endl; |
| encryptedKey->setCarriedKeyName(s_tstCarriedKeyName); |
| encryptedKey->setRecipient(s_tstRecipient); |
| cerr << "done!" << endl; |
| |
| encryptedData->appendEncryptedKey(encryptedKey); |
| |
| outputDoc(impl, doc); |
| |
| // OK - Now we try to decrypt |
| // Find the EncryptedData node |
| DOMNode * n = findXENCNode(doc, "EncryptedData"); |
| |
| XENCCipher * cipher2 = prov.newCipher(doc); |
| |
| XSECCryptoSymmetricKey * k2; |
| |
| if (g_haveAES) { |
| k2 = XSECPlatformUtils::g_cryptoProvider->keySymmetric(XSECCryptoSymmetricKey::KEY_AES_128); |
| k2->setKey((unsigned char *) s_keyStr, 16); |
| } |
| |
| else { |
| k2 = XSECPlatformUtils::g_cryptoProvider->keySymmetric(XSECCryptoSymmetricKey::KEY_3DES_192); |
| k2->setKey((unsigned char *) s_keyStr, 24); |
| } |
| |
| cipher2->setKEK(k2); |
| |
| cerr << "Decrypting ... "; |
| cipher2->decryptElement(static_cast<DOMElement *>(n)); |
| cerr << "done" << endl; |
| |
| cerr << "Checking for <category> element ... "; |
| |
| t = findNode(doc, MAKE_UNICODE_STRING("category")); |
| |
| if (t == NULL) { |
| |
| cerr << " not found!\nError - category did not decrypt properly" << endl; |
| exit(1); |
| |
| } |
| else |
| cerr << "found" << endl; |
| |
| cerr << "Checking <KeyName> element is set correctly ... "; |
| |
| encryptedData = cipher2->getEncryptedData(); |
| |
| if (encryptedData == NULL) { |
| cerr << "no - cannot access EncryptedData element" << endl; |
| exit(1); |
| } |
| |
| DSIGKeyInfoList * kil = encryptedData->getKeyInfoList(); |
| int nki = (int) kil->getSize(); |
| bool foundNameOK = false; |
| |
| int i; |
| for (i = 0; i < nki; ++i) { |
| |
| if (kil->item(i)->getKeyInfoType() == DSIGKeyInfo::KEYINFO_NAME) { |
| |
| DSIGKeyInfoName *n = (DSIGKeyInfoName *) (kil->item(i)); |
| if (!strEquals(n->getKeyName(), s_tstKeyName)) { |
| |
| cerr << "no!" << endl; |
| exit (1); |
| } |
| foundNameOK = true; |
| break; |
| } |
| |
| } |
| |
| if (foundNameOK == false) { |
| cerr << "no!" << endl; |
| exit(1); |
| } |
| else |
| cerr << "yes." << endl; |
| |
| cerr << "Checking CarriedKeyName and Recipient values ... "; |
| bool foundCCN = false; |
| bool foundRecipient = false; |
| |
| for (i = 0; i < nki; ++i) { |
| |
| if (kil->item(i)->getKeyInfoType() == DSIGKeyInfo::KEYINFO_ENCRYPTEDKEY) { |
| |
| XENCEncryptedKey * xek = (XENCEncryptedKey*)(kil->item(i)); |
| |
| if (strEquals(xek->getCarriedKeyName(), s_tstCarriedKeyName)) { |
| |
| foundCCN = true; |
| } |
| |
| if (strEquals(xek->getRecipient(), s_tstRecipient)) { |
| |
| foundRecipient = true; |
| } |
| } |
| } |
| |
| if (foundCCN == false || foundRecipient == false) { |
| cerr << "no!" << endl; |
| exit(1); |
| } |
| else { |
| cerr << "OK" << endl; |
| } |
| |
| cerr << "Checking MimeType and Encoding ... "; |
| if (encryptedData->getMimeType() == NULL || !strEquals(encryptedData->getMimeType(), s_tstMimeType)) { |
| cerr << "Bad MimeType" << endl; |
| exit(1); |
| } |
| if (encryptedData->getEncoding() == NULL || !strEquals(encryptedData->getEncoding(), s_tstEncoding)) { |
| cerr << "Bad Encoding" << endl; |
| exit(1); |
| } |
| |
| cerr << "OK" << endl; |
| |
| cerr << "Checking KeySize in EncryptionMethod ... "; |
| if (encryptedData->getEncryptionMethod() == NULL || encryptedData->getEncryptionMethod()->getKeySize() != 192) { |
| cerr << "Bad KeySize" << endl; |
| exit(1); |
| } |
| |
| cerr << "OK" << endl; |
| |
| } |
| catch (const XSECException &e) |
| { |
| cerr << "An error occurred during signature processing\n Message: "; |
| char * ce = XMLString::transcode(e.getMsg()); |
| cerr << ce << endl; |
| delete ce; |
| exit(1); |
| |
| } |
| catch (const XSECCryptoException &e) |
| { |
| cerr << "A cryptographic error occurred during signature processing\n Message: " |
| << e.getMsg() << endl; |
| exit(1); |
| } |
| |
| outputDoc(impl, doc); |
| doc->release(); |
| |
| } |
| |
| // -------------------------------------------------------------------------------- |
| // Print usage instructions |
| // -------------------------------------------------------------------------------- |
| |
| void printUsage(void) { |
| |
| cerr << "\nUsage: xtest [options]\n\n"; |
| cerr << " Where options are :\n\n"; |
| cerr << " --help/-h\n"; |
| cerr << " This help message\n\n"; |
| #if defined (XSEC_HAVE_WINCAPI) && defined (XSEC_HAVE_OPENSSL) |
| cerr << " --wincapi/-w\n"; |
| cerr << " Use Windows Crypto API for crypto functionality\n\n"; |
| #endif |
| #if defined (XSEC_HAVE_NSS) |
| cerr << " --nss/-n\n"; |
| cerr << " Use NSS Crypto API for crypto functionality\n\n"; |
| #endif |
| cerr << " --print-docs/-p\n"; |
| cerr << " Print the test documents\n\n"; |
| cerr << " --signature-only/-s\n"; |
| cerr << " Only run basic signature test\n\n"; |
| cerr << " --signature-unit-only/-t\n"; |
| cerr << " Only run signature unit tests\n\n"; |
| cerr << " --encryption-only/-e\n"; |
| cerr << " Only run basic encryption test\n\n"; |
| cerr << " --encryption-unit-only/-u\n"; |
| cerr << " Only run encryption unit tests\n\n"; |
| cerr << " --no-gcm\n"; |
| cerr << " Exclude AES-GCM tests\n\n"; |
| } |
| // -------------------------------------------------------------------------------- |
| // Main |
| // -------------------------------------------------------------------------------- |
| |
| int main(int argc, char **argv) { |
| |
| /* We output a version number to overcome a "feature" in Microsoft's memory |
| leak detection */ |
| |
| cerr << "DSIG Info - Using Apache XML-Security-C Library v" << |
| XSEC_VERSION_MAJOR << |
| "." << XSEC_VERSION_MEDIUM << "." << XSEC_VERSION_MINOR << |
| " (" << _XSEC_VERSION_FULL << ")\n"; |
| |
| // Check parameters |
| bool doEncryptionTest = true; |
| bool doEncryptionUnitTests = true; |
| bool doSignatureTest = true; |
| bool doSignatureUnitTests = true; |
| |
| // Testing for which Crypto API to use by default - only really useful on windows |
| #if !defined(XSEC_HAVE_OPENSSL) |
| #if defined(XSEC_HAVE_WINCAPI) |
| g_useWinCAPI = true; |
| #endif |
| #endif |
| |
| int paramCount = 1; |
| |
| while (paramCount < argc) { |
| |
| if (_stricmp(argv[paramCount], "--help") == 0 || _stricmp(argv[paramCount], "-h") == 0) { |
| printUsage(); |
| exit(0); |
| } |
| else if (_stricmp(argv[paramCount], "--print-docs") == 0 || _stricmp(argv[paramCount], "-p") == 0) { |
| g_printDocs = true; |
| paramCount++; |
| } |
| #if defined(XSEC_HAVE_WINCAPI) && defined(XSEC_HAVE_OPENSSL) |
| else if (_stricmp(argv[paramCount], "--wincapi") == 0 || _stricmp(argv[paramCount], "-w") == 0) { |
| g_useWinCAPI = true; |
| paramCount++; |
| } |
| #endif |
| #if defined(XSEC_HAVE_NSS) |
| else if (_stricmp(argv[paramCount], "--nss") == 0 || _stricmp(argv[paramCount], "-n") == 0) { |
| g_useNSS = true; |
| paramCount++; |
| } |
| #endif |
| |
| else if (_stricmp(argv[paramCount], "--signature-only") == 0 || _stricmp(argv[paramCount], "-s") == 0) { |
| doEncryptionTest = false; |
| doEncryptionUnitTests = false; |
| doSignatureUnitTests = false; |
| paramCount++; |
| } |
| else if (_stricmp(argv[paramCount], "--encryption-only") == 0 || _stricmp(argv[paramCount], "-e") == 0) { |
| doSignatureTest = false; |
| doEncryptionUnitTests = false; |
| doSignatureUnitTests = false; |
| paramCount++; |
| } |
| else if (_stricmp(argv[paramCount], "--encryption-unit-only") == 0 || _stricmp(argv[paramCount], "-u") == 0) { |
| doEncryptionTest = false; |
| doSignatureTest = false; |
| doSignatureUnitTests = false; |
| paramCount++; |
| } |
| else if (_stricmp(argv[paramCount], "--signature-unit-only") == 0 || _stricmp(argv[paramCount], "-t") == 0) { |
| doEncryptionTest = false; |
| doSignatureTest = false; |
| doEncryptionUnitTests = false; |
| paramCount++; |
| } |
| else if (_stricmp(argv[paramCount], "--no-gcm") == 0) { |
| g_testGCM = false; |
| paramCount++; |
| } |
| /* else if (stricmp(argv[paramCount], "--xkms-only") == 0 || stricmp(argv[paramCount], "-x") == 0) { |
| doEncryptionTest = false; |
| doSignatureTest = false; |
| doEncryptionUnitTests = false; |
| doSignatureUnitTests = false; |
| paramCount++; |
| }*/ |
| else { |
| printUsage(); |
| return 2; |
| } |
| } |
| |
| |
| #if defined (_DEBUG) && defined (_MSC_VER) && defined (_XSEC_DO_MEMDEBUG) |
| |
| // 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 |
| |
| // First initialise the XML system |
| |
| try { |
| |
| XMLPlatformUtils::Initialize(); |
| #ifdef XSEC_HAVE_XALAN |
| XPathEvaluator::initialize(); |
| XalanTransformer::initialize(); |
| #endif |
| XSECPlatformUtils::Initialise(); |
| |
| #if defined (XSEC_HAVE_OPENSSL) && defined (XSEC_HAVE_WINCAPI) |
| if (g_useWinCAPI) { |
| // Setup for Windows Crypt API |
| WinCAPICryptoProvider * cp; |
| // First set windows as the crypto provider |
| cp = new WinCAPICryptoProvider(); |
| XSECPlatformUtils::SetCryptoProvider(cp); |
| } |
| #endif |
| #if defined (XSEC_HAVE_NSS) |
| if (g_useNSS) { |
| // Setup for NSS Crypt API |
| NSSCryptoProvider * cp; |
| // First set windows as the crypto provider |
| cp = new NSSCryptoProvider(); |
| XSECPlatformUtils::SetCryptoProvider(cp); |
| } |
| #endif |
| |
| |
| } |
| catch (const XMLException &e) { |
| |
| cerr << "Error during initialisation of Xerces" << endl; |
| cerr << "Error Message = : " |
| << e.getMessage() << endl; |
| |
| } |
| |
| { |
| |
| // Set up for tests |
| |
| g_haveAES = XSECPlatformUtils::g_cryptoProvider->algorithmSupported(XSECCryptoSymmetricKey::KEY_AES_128); |
| |
| // Setup for building documents |
| |
| XMLCh tempStr[100]; |
| XMLString::transcode("Core", tempStr, 99); |
| DOMImplementation *impl = DOMImplementationRegistry::getDOMImplementation(tempStr); |
| |
| // Output some info |
| char * provName = XMLString::transcode(XSECPlatformUtils::g_cryptoProvider->getProviderName()); |
| cerr << "Crypto Provider string : " << provName << endl; |
| XSEC_RELEASE_XMLCH(provName); |
| |
| // Test signature functions |
| if (doSignatureTest) { |
| cerr << endl << "===================================="; |
| cerr << endl << "Testing Signature Function"; |
| cerr << endl << "===================================="; |
| cerr << endl << endl; |
| |
| testSignature(impl); |
| } |
| |
| // Test signature functions |
| if (doSignatureUnitTests) { |
| cerr << endl << "===================================="; |
| cerr << endl << "Performing Signature Unit Tests"; |
| cerr << endl << "===================================="; |
| cerr << endl << endl; |
| |
| unitTestSignature(impl); |
| } |
| |
| // Test encrypt function |
| if (doEncryptionTest) { |
| cerr << endl << "===================================="; |
| cerr << endl << "Testing Encryption Function"; |
| cerr << endl << "===================================="; |
| cerr << endl << endl; |
| |
| testEncrypt(impl); |
| } |
| |
| // Running Encryption Unit test |
| if (doEncryptionUnitTests) { |
| cerr << endl << "===================================="; |
| cerr << endl << "Performing Encryption Unit Tests"; |
| cerr << endl << "===================================="; |
| cerr << endl << endl; |
| |
| unitTestEncrypt(impl); |
| } |
| cerr << endl << "All tests passed" << endl; |
| |
| } |
| |
| XSECPlatformUtils::Terminate(); |
| #ifdef XSEC_HAVE_XALAN |
| XalanTransformer::terminate(); |
| XPathEvaluator::terminate(); |
| #endif |
| XMLPlatformUtils::Terminate(); |
| |
| #if defined (_DEBUG) && defined (_MSC_VER) && defined (_XSEC_DO_MEMDEBUG) |
| |
| _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 0; |
| |
| } |