xsec/dsig/DSIGSignature.cpp (551 lines of code) (raw):

/** * 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 * * DSIGSignature := Class for checking and setting up signature nodes in a DSIG signature * * Author(s): Berin Lautenbach * * $Id$ * */ // XSEC Includes #include <xsec/dsig/DSIGSignature.hpp> #include <xsec/dsig/DSIGConstants.hpp> #include <xsec/dsig/DSIGKeyInfoX509.hpp> #include <xsec/dsig/DSIGObject.hpp> #include <xsec/dsig/DSIGReference.hpp> #include <xsec/dsig/DSIGTransformList.hpp> #include <xsec/dsig/DSIGKeyInfoValue.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/dsig/DSIGAlgorithmHandlerDefault.hpp> #include <xsec/enc/XSECCryptoKeyDSA.hpp> #include <xsec/enc/XSECCryptoKeyRSA.hpp> #include <xsec/enc/XSECKeyInfoResolver.hpp> #include <xsec/framework/XSECError.hpp> #include <xsec/framework/XSECAlgorithmHandler.hpp> #include <xsec/framework/XSECAlgorithmMapper.hpp> #include <xsec/framework/XSECEnv.hpp> #include <xsec/framework/XSECURIResolver.hpp> #include <xsec/transformers/TXFMDocObject.hpp> #include <xsec/transformers/TXFMOutputFile.hpp> #include <xsec/transformers/TXFMBase64.hpp> #include <xsec/transformers/TXFMC14n.hpp> #include <xsec/transformers/TXFMChain.hpp> #include <xsec/utils/XSECBinTXFMInputStream.hpp> #include <xsec/utils/XSECPlatformUtils.hpp> #include "../utils/XSECAlgorithmSupport.hpp" #include "../utils/XSECDOMUtils.hpp" // Xerces includes #include <xercesc/dom/DOMNamedNodeMap.hpp> #include <xercesc/util/Janitor.hpp> XERCES_CPP_NAMESPACE_USE // -------------------------------------------------------------------------------- // Init // -------------------------------------------------------------------------------- void DSIGSignature::Initialise() { DSIGAlgorithmHandlerDefault def; // Register default signature algorithm handlers XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURIRSA_SHA1, def); XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURIRSA_MD5, def); XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURIRSA_SHA224, def); XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURIRSA_SHA256, def); XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURIRSA_SHA384, def); XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURIRSA_SHA512, def); XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURIDSA_SHA1, def); XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURIDSA_SHA256, def); XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURIECDSA_SHA1, def); XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURIECDSA_SHA224, def); XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURIECDSA_SHA256, def); XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURIECDSA_SHA384, def); XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURIECDSA_SHA512, def); XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURIHMAC_SHA1, def); XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURIHMAC_SHA224, def); XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURIHMAC_SHA256, def); XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURIHMAC_SHA384, def); XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURIHMAC_SHA512, def); // Register default hashing algorithm handlers XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURISHA1, def); XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURISHA224, def); XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURISHA256, def); XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURISHA384, def); XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURISHA512, def); XSECPlatformUtils::registerAlgorithmHandler(DSIGConstants::s_unicodeStrURIMD5, def); } // -------------------------------------------------------------------------------- // Get the Canonicalised BYTE_STREAM of the SignedInfo // -------------------------------------------------------------------------------- XSECBinTXFMInputStream* DSIGSignature::makeBinInputStream() const { TXFMBase* txfm; // Create the starting point for the transform list XSECnew(txfm, TXFMDocObject(mp_doc)); TXFMChain* chain; XSECnew(chain, TXFMChain(txfm)); Janitor<TXFMChain> j_chain(chain); ((TXFMDocObject*) txfm)->setInput(mp_doc, mp_signedInfo->getDOMNode()); // canonicalize the SignedInfo content bool exclusive; bool comments; bool onedotone; if (XSECAlgorithmSupport::evalCanonicalizationMethod(mp_signedInfo->getCanonicalizationMethod(), exclusive, comments, onedotone)) { XSECnew(txfm, TXFMC14n(mp_doc)); chain->appendTxfm(txfm); if (comments) txfm->activateComments(); else txfm->stripComments(); if (exclusive) ((TXFMC14n*) txfm)->setExclusive(); if (onedotone) ((TXFMC14n*) txfm)->setInclusive11(); } else { throw XSECException(XSECException::SigVfyError, "Unknown CanonicalizationMethod in DSIGSignature::makeBinInputStream()"); } // Now create the InputStream XSECBinTXFMInputStream* ret = new XSECBinTXFMInputStream(chain); j_chain.release(); return ret; } // -------------------------------------------------------------------------------- // Get the list of references // -------------------------------------------------------------------------------- DSIGReferenceList* DSIGSignature::getReferenceList() { return mp_signedInfo ? mp_signedInfo->getReferenceList() : NULL; } const DSIGReferenceList* DSIGSignature::getReferenceList() const { return mp_signedInfo ? mp_signedInfo->getReferenceList() : NULL; } const XMLCh* DSIGSignature::getAlgorithmURI() const { return mp_signedInfo ? mp_signedInfo->getAlgorithmURI() : NULL; } // -------------------------------------------------------------------------------- // Set and Get Resolvers // -------------------------------------------------------------------------------- void DSIGSignature::setURIResolver(XSECURIResolver* resolver) { mp_env->setURIResolver(resolver); } XSECURIResolver* DSIGSignature::getURIResolver() const { return mp_env->getURIResolver(); } void DSIGSignature::setKeyInfoResolver(XSECKeyInfoResolver* resolver) { if (mp_KeyInfoResolver != 0) delete mp_KeyInfoResolver; mp_KeyInfoResolver = resolver->clone(); } XSECKeyInfoResolver* DSIGSignature::getKeyInfoResolver() const { return mp_KeyInfoResolver; } // -------------------------------------------------------------------------------- // Object Handling // -------------------------------------------------------------------------------- DSIGObject* DSIGSignature::appendObject() { DSIGObject* ret; XSECnew(ret, DSIGObject(mp_env)); DOMElement* elt = ret->createBlankObject(); mp_sigNode->appendChild(elt); mp_env->doPrettyPrint(mp_sigNode); m_objects.push_back(ret); return ret; } int DSIGSignature::getObjectLength() const { return (unsigned int) m_objects.size(); } DSIGObject* DSIGSignature::getObjectItem(int i) { if ( i < 0 || i >= ((int) m_objects.size())) { throw XSECException(XSECException::ObjectError, "DSIGSignature::getObjectItem - index out of range"); } return m_objects[i]; } const DSIGObject* DSIGSignature::getObjectItem(int i) const { if ( i < 0 || i >= ((int) m_objects.size())) { throw XSECException(XSECException::ObjectError, "DSIGSignature::getObjectItem - index out of range"); } return m_objects[i]; } // -------------------------------------------------------------------------------- // Signature // -------------------------------------------------------------------------------- // Constructors and Destructors DSIGSignature::DSIGSignature(DOMDocument* doc, DOMNode* sigNode) : m_loaded(false), mp_doc(doc), mp_sigNode(sigNode), mp_signedInfo(NULL), mp_signatureValueNode(NULL), m_keyInfoList(NULL), mp_KeyInfoNode(NULL), m_errStr(""), mp_signingKey(NULL), mp_KeyInfoResolver(NULL), m_interlockingReferences(false) { // Set up our formatter XSECnew(mp_formatter, XSECSafeBufferFormatter("UTF-8",XMLFormatter::NoEscapes, XMLFormatter::UnRep_CharRef)); // Set up the environment XSECnew(mp_env, XSECEnv(doc)); m_keyInfoList.setEnvironment(mp_env); } DSIGSignature::DSIGSignature() : m_loaded(false), mp_doc(NULL), mp_sigNode(NULL), mp_signedInfo(NULL), mp_signatureValueNode(NULL), m_keyInfoList(NULL), mp_KeyInfoNode(NULL), m_errStr(""), mp_signingKey(NULL), mp_KeyInfoResolver(NULL), m_interlockingReferences(false) { // Set up our formatter XSECnew(mp_formatter, XSECSafeBufferFormatter("UTF-8",XMLFormatter::NoEscapes, XMLFormatter::UnRep_CharRef)); XSECnew(mp_env, XSECEnv(NULL)); m_keyInfoList.setEnvironment(mp_env); } DSIGSignature::~DSIGSignature() { if (mp_env != NULL) delete mp_env; if (mp_signingKey != NULL) { delete mp_signingKey; mp_signingKey = NULL; } if (mp_signedInfo != NULL) { delete mp_signedInfo; mp_signedInfo = NULL; } if (mp_formatter != NULL) { delete mp_formatter; mp_formatter = NULL; } if (mp_KeyInfoResolver != NULL) { delete mp_KeyInfoResolver; mp_KeyInfoResolver = NULL; } // Delete any object items for (int i = 0; i < ((int) m_objects.size()); ++i) { delete (m_objects[i]); } } // Actions const XMLCh* DSIGSignature::getErrMsgs() const { return m_errStr.rawXMLChBuffer(); } // -------------------------------------------------------------------------------- // Pretty Printing // -------------------------------------------------------------------------------- void DSIGSignature::setPrettyPrint(bool flag) { mp_env->setPrettyPrintFlag(flag); } bool DSIGSignature::getPrettyPrint() const { return mp_env->getPrettyPrintFlag(); } // -------------------------------------------------------------------------------- // Creating signatures from blank // -------------------------------------------------------------------------------- void DSIGSignature::setDSIGNSPrefix(const XMLCh* prefix) { mp_env->setDSIGNSPrefix(prefix); } void DSIGSignature::setECNSPrefix(const XMLCh* prefix) { mp_env->setECNSPrefix(prefix); } void DSIGSignature::setXPFNSPrefix(const XMLCh* prefix) { mp_env->setXPFNSPrefix(prefix); } // get const XMLCh* DSIGSignature::getDSIGNSPrefix() const { return mp_env->getDSIGNSPrefix(); } const XMLCh* DSIGSignature::getECNSPrefix() const { return mp_env->getECNSPrefix(); } const XMLCh* DSIGSignature::getXPFNSPrefix() const { return mp_env->getXPFNSPrefix(); } DOMElement*DSIGSignature::createBlankSignature( DOMDocument* doc, const XMLCh* canonicalizationAlgorithmURI, const XMLCh* signatureAlgorithmURI) { // "New" method to create a blank signature, based on URIs. mp_doc = doc; mp_env->setParentDocument(doc); const XMLCh* prefixNS = mp_env->getDSIGNSPrefix(); safeBuffer str; makeQName(str, prefixNS, "Signature"); DOMElement*sigNode = doc->createElementNS(DSIGConstants::s_unicodeStrURIDSIG, str.rawXMLChBuffer()); if (prefixNS[0] == '\0') { str.sbTranscodeIn("xmlns"); } else { str.sbTranscodeIn("xmlns:"); str.sbXMLChCat(prefixNS); } sigNode->setAttributeNS(DSIGConstants::s_unicodeStrURIXMLNS, str.rawXMLChBuffer(), DSIGConstants::s_unicodeStrURIDSIG); mp_sigNode = sigNode; mp_env->doPrettyPrint(mp_sigNode); // Create the skeleton SignedInfo XSECnew(mp_signedInfo, DSIGSignedInfo(mp_doc, mp_formatter, mp_env)); mp_sigNode->appendChild(mp_signedInfo->createBlankSignedInfo( canonicalizationAlgorithmURI, signatureAlgorithmURI)); mp_env->doPrettyPrint(mp_sigNode); // Create a dummy signature value (dummy until signed) makeQName(str, mp_env->getDSIGNSPrefix(), "SignatureValue"); DOMElement*sigValNode = doc->createElementNS(DSIGConstants::s_unicodeStrURIDSIG, str.rawXMLChBuffer()); mp_signatureValueNode = sigValNode; mp_sigNode->appendChild(sigValNode); mp_env->doPrettyPrint(mp_sigNode); // Some text to mark this as a template only sigValNode->appendChild(doc->createTextNode(MAKE_UNICODE_STRING("Not yet signed"))); m_loaded = true; return sigNode; } // -------------------------------------------------------------------------------- // Creating References // -------------------------------------------------------------------------------- DSIGReference* DSIGSignature::createReference( const XMLCh* URI, const XMLCh* hashAlgorithmURI, const XMLCh* type) { return mp_signedInfo->createReference(URI, hashAlgorithmURI, type); } DSIGReference* DSIGSignature::removeReference(DSIGReferenceList::size_type index) { return mp_signedInfo ? mp_signedInfo->removeReference(index) : NULL; } // -------------------------------------------------------------------------------- // Manipulation of KeyInfo elements // -------------------------------------------------------------------------------- void DSIGSignature::clearKeyInfo() { if (mp_KeyInfoNode == 0) return; if (mp_sigNode->removeChild(mp_KeyInfoNode) != mp_KeyInfoNode) { throw XSECException(XSECException::ExpectedDSIGChildNotFound, "Attempted to remove KeyInfo node but it is no longer a child of <Signature>"); } mp_KeyInfoNode->release(); // No longer required mp_KeyInfoNode = NULL; // Clear out the list m_keyInfoList.empty(); } void DSIGSignature::createKeyInfoElement() { if (mp_KeyInfoNode != NULL) return; safeBuffer str; makeQName(str, mp_env->getDSIGNSPrefix(), "KeyInfo"); mp_KeyInfoNode = m_keyInfoList.createKeyInfo(); // Append the node to the end of the signature DOMNode* afterSignatureValue = mp_signatureValueNode->getNextSibling(); while (afterSignatureValue != 0 && afterSignatureValue->getNodeType() != DOMNode::ELEMENT_NODE) afterSignatureValue = afterSignatureValue->getNextSibling(); if (afterSignatureValue == 0) { mp_sigNode->appendChild(mp_KeyInfoNode); mp_env->doPrettyPrint(mp_sigNode); } else { mp_sigNode->insertBefore(mp_KeyInfoNode, afterSignatureValue); if (mp_env->getPrettyPrintFlag() == true) mp_sigNode->insertBefore(mp_doc->createTextNode(DSIGConstants::s_unicodeStrNL), afterSignatureValue); } } DSIGKeyInfoValue* DSIGSignature::appendDSAKeyValue(const XMLCh* P, const XMLCh* Q, const XMLCh* G, const XMLCh* Y) { createKeyInfoElement(); return m_keyInfoList.appendDSAKeyValue(P, Q, G, Y); } DSIGKeyInfoValue* DSIGSignature::appendRSAKeyValue(const XMLCh* modulus, const XMLCh* exponent) { createKeyInfoElement(); return m_keyInfoList.appendRSAKeyValue(modulus, exponent); } DSIGKeyInfoX509* DSIGSignature::appendX509Data() { createKeyInfoElement(); return m_keyInfoList.appendX509Data(); } DSIGKeyInfoName* DSIGSignature::appendKeyName(const XMLCh* name, bool isDName) { createKeyInfoElement(); return m_keyInfoList.appendKeyName(name, isDName); } DSIGKeyInfoPGPData* DSIGSignature::appendPGPData(const XMLCh* id, const XMLCh* packet) { createKeyInfoElement(); return m_keyInfoList.appendPGPData(id, packet); } DSIGKeyInfoSPKIData* DSIGSignature::appendSPKIData(const XMLCh* sexp) { createKeyInfoElement(); return m_keyInfoList.appendSPKIData(sexp); } DSIGKeyInfoMgmtData* DSIGSignature::appendMgmtData(const XMLCh* data) { createKeyInfoElement(); return m_keyInfoList.appendMgmtData(data); } // -------------------------------------------------------------------------------- // Working on Existing templates // -------------------------------------------------------------------------------- void DSIGSignature::load() { // Load all the information from the source document into local variables for easier // manipulation by the other functions in the class if (mp_sigNode == NULL) { // Attempt to load an empty signature element throw XSECException(XSECException::LoadEmptySignature); } if (!strEquals(getDSIGLocalName(mp_sigNode), "Signature")) { throw XSECException(XSECException::LoadNonSignature); } m_loaded = true; // Find the prefix being used so that we can later use it to manipulate the signature mp_env->setDSIGNSPrefix(mp_sigNode->getPrefix()); // Now check for SignedInfo DOMNode*tmpElt = mp_sigNode->getFirstChild(); while (tmpElt != 0 && (tmpElt->getNodeType() != DOMNode::ELEMENT_NODE)) // Skip text and comments tmpElt = tmpElt->getNextSibling(); if (tmpElt == 0 || !strEquals(getDSIGLocalName(tmpElt), "SignedInfo")) { throw XSECException(XSECException::ExpectedDSIGChildNotFound, "Expected <SignedInfo> as first child of <Signature>"); } // Have a signed info XSECnew(mp_signedInfo, DSIGSignedInfo(mp_doc, mp_formatter, tmpElt, mp_env)); mp_signedInfo->load(); // Look at Signature Value tmpElt = findNextElementChild(tmpElt); if (tmpElt == 0 || !strEquals(getDSIGLocalName(tmpElt), "SignatureValue")) { throw XSECException(XSECException::ExpectedDSIGChildNotFound, "Expected <SignatureValue> node"); } DOMNode*tmpSV = tmpElt->getFirstChild(); while (tmpSV != 0 && tmpSV->getNodeType() != DOMNode::TEXT_NODE) tmpSV = tmpSV->getNextSibling(); if (tmpSV == 0) throw XSECException(XSECException::ExpectedDSIGChildNotFound, "Expected TEXT child of <SignatureValue>"); mp_signatureValueNode = tmpElt; // The signature value is transcoded to local code page, as it is easier // to work with, and should be low ASCII in any case (Base64) m_signatureValueSB.sbTranscodeIn(tmpSV->getNodeValue()); // Now look at KeyInfo tmpElt = findNextElementChild(tmpElt); if (tmpElt != 0 && strEquals(getDSIGLocalName(tmpElt), "KeyInfo")) { // Have a keyInfo mp_KeyInfoNode = tmpElt; // In case we later want to manipulate it m_keyInfoList.loadListFromXML(tmpElt); tmpElt = findNextElementChild(tmpElt); } while (tmpElt != 0 && strEquals(getDSIGLocalName(tmpElt), "Object")) { DSIGObject* obj; XSECnew(obj, DSIGObject(mp_env, tmpElt)); obj->load(); m_objects.push_back(obj); tmpElt = findNextElementChild(tmpElt); } /* * Strictly speaking, this should remain, but it causes too many problems with non * conforming signatures if (tmpElt != 0) { throw XSECException(XSECException::ExpectedDSIGChildNotFound, "DSIGSignature::load - Unexpected (non Object) Element found at end of signature"); } */ } TXFMChain* DSIGSignature::getSignedInfoInput() const { TXFMBase* txfm; TXFMChain* chain; // First we calculate the hash. Start off by creating a starting point XSECnew(txfm, TXFMDocObject(mp_doc)); XSECnew(chain, TXFMChain(txfm)); Janitor<TXFMChain> j_chain(chain); ((TXFMDocObject*) txfm)->setInput(mp_doc, mp_signedInfo->getDOMNode()); // canonicalise the SignedInfo content bool exclusive; bool comments; bool onedotone; if (XSECAlgorithmSupport::evalCanonicalizationMethod(mp_signedInfo->getCanonicalizationMethod(), exclusive, comments, onedotone)) { XSECnew(txfm, TXFMC14n(mp_doc)); chain->appendTxfm(txfm); if (comments) txfm->activateComments(); else txfm->stripComments(); if (exclusive) ((TXFMC14n*) txfm)->setExclusive(); if (onedotone) ((TXFMC14n*) txfm)->setInclusive11(); } else { throw XSECException(XSECException::SigVfyError, "Unknown CanonicalizationMethod in DSIGSignature::calculateSignedInfoHash()"); } j_chain.release(); return chain; } unsigned int DSIGSignature::calculateSignedInfoHash(unsigned char* hashBuf, unsigned int hashBufLen) const { // Get the SignedInfo input bytes TXFMChain* chain = getSignedInfoInput(); Janitor<TXFMChain> j_chain(chain); // Check for debugging sink for the data TXFMBase* sink = XSECPlatformUtils::GetReferenceLoggingSink(mp_doc); if (sink) chain->appendTxfm(sink); // Setup Hash // First find the appropriate handler for the URI const XSECAlgorithmHandler* handler = XSECPlatformUtils::g_algorithmMapper->mapURIToHandler( mp_signedInfo->getAlgorithmURI()); if (handler == NULL) { throw XSECException(XSECException::SigVfyError, "Hash method unknown in DSIGSignature::calculateSignedInfoHash()"); } if (!handler->appendSignatureHashTxfm(chain, mp_signedInfo->getAlgorithmURI(), mp_signingKey)) { throw XSECException(XSECException::SigVfyError, "Unexpected error in handler whilst appending Signature Hash transform"); } // Write hash to the buffer return chain->getLastTxfm()->readBytes((XMLByte*) hashBuf, hashBufLen); } unsigned int DSIGSignature::calculateSignedInfoAndReferenceHash(unsigned char* hashBuf, unsigned int hashBufLen) const { // Set up the reference list hashes - including any manifests mp_signedInfo->hash(m_interlockingReferences); // calculaet signed InfoHash return calculateSignedInfoHash(hashBuf,hashBufLen); } // -------------------------------------------------------------------------------- // Verify a signature // -------------------------------------------------------------------------------- bool DSIGSignature::verifySignatureOnlyInternal() const { unsigned char hash[4096]; if (!m_loaded) { // Need to call "load" prior to checking a signature throw XSECException(XSECException::SigVfyError, "DSIGSignature::verify() called prior to DSIGSignature::load()"); } // FIX: CVE-2009-0217 if (mp_signedInfo->getHMACOutputLength() > 0 && mp_signedInfo->getHMACOutputLength() < 80) { throw XSECException(XSECException::SigVfyError, "DSIGSignature::verify() - HMACOutputLength is unsafe"); } // Try to find a key if (mp_signingKey == NULL) { // // Try to load a key from the KeyInfo list // if ((mp_signingKey = m_keyInfoList.findKey()) == NULL) { // throw XSECException(XSECException::SigVfyError, // "DSIGSignature::verify() - no verification key loaded and cannot determine from KeyInfo list"); // } if (mp_KeyInfoResolver == NULL) { throw XSECException(XSECException::SigVfyError, "DSIGSignature::verify() - no verification key loaded and no KeyInfoResolver loaded"); } if ((mp_signingKey = mp_KeyInfoResolver->resolveKey(&m_keyInfoList)) == NULL) { throw XSECException(XSECException::SigVfyError, "DSIGSignature::verify() - no verification key loaded and cannot determine from KeyInfoResolver"); } } // Get the SignedInfo input bytes TXFMChain* chain = getSignedInfoInput(); Janitor<TXFMChain> j_chain(chain); calculateSignedInfoHash(hash, 4096); // Now set up to verify // First find the appropriate handler for the URI const XSECAlgorithmHandler* handler = XSECPlatformUtils::g_algorithmMapper->mapURIToHandler( mp_signedInfo->getAlgorithmURI()); if (handler == NULL) { throw XSECException(XSECException::SigVfyError, "Hash method unknown in DSIGSignature::verifySignatureOnlyInternal()"); } bool sigVfyRet = handler->verifyBase64Signature(chain, mp_signedInfo->getAlgorithmURI(), m_signatureValueSB.rawCharBuffer(), mp_signedInfo->getHMACOutputLength(), mp_signingKey); if (!sigVfyRet) m_errStr.sbXMLChCat("Validation of <SignedInfo> failed"); return sigVfyRet; } bool DSIGSignature::verifySignatureOnly() const { m_errStr.sbTranscodeIn(""); return verifySignatureOnlyInternal(); } bool DSIGSignature::verify() const { // We have a (hopefully) fully loaded signature. Need to // verify bool referenceCheckResult; if (!m_loaded) { // Need to call "load" prior to checking a signature throw XSECException(XSECException::SigVfyError, "DSIGSignature::verify() called prior to DSIGSignature::load()"); } // Reset m_errStr.sbXMLChIn(DSIGConstants::s_unicodeStrEmpty); // First thing to do is check the references referenceCheckResult = mp_signedInfo->verify(m_errStr); // Check the signature bool sigVfyResult = verifySignatureOnlyInternal(); return sigVfyResult & referenceCheckResult; } // -------------------------------------------------------------------------------- // Sign the XML document that has been previously loaded // -------------------------------------------------------------------------------- void DSIGSignature::sign() { // We have a (hopefully) fully loaded signature. Need to // sign if (!m_loaded) { // Need to call "load" prior to checking a signature throw XSECException(XSECException::SigVfyError, "DSIGSignature::sign() called prior to DSIGSignature::load()"); } // Check we have a key if (mp_signingKey == NULL) { throw XSECException(XSECException::SigVfyError, "DSIGSignature::sign() - no signing key loaded"); } // Reset error string in case we have any reference problems. m_errStr.sbXMLChIn(DSIGConstants::s_unicodeStrEmpty); // Set up the reference list hashes - including any manifests mp_signedInfo->hash(m_interlockingReferences); // Get the SignedInfo input bytes TXFMChain* chain = getSignedInfoInput(); Janitor<TXFMChain> j_chain(chain); // Calculate the hash to be signed safeBuffer b64Buf; const XSECAlgorithmHandler* handler = XSECPlatformUtils::g_algorithmMapper->mapURIToHandler( mp_signedInfo->getAlgorithmURI()); if (handler == NULL) { throw XSECException(XSECException::SigVfyError, "Hash method unknown in DSIGSignature::sign()"); } if (!handler->signToSafeBuffer(chain, mp_signedInfo->getAlgorithmURI(), mp_signingKey, mp_signedInfo->getHMACOutputLength(), b64Buf)) { throw XSECException(XSECException::SigVfyError, "Unexpected error in handler whilst appending Signature Hash transform"); } // Now we have the signature - place it in the DOM structures DOMNode*tmpElt = mp_signatureValueNode->getFirstChild(); while (tmpElt != NULL && tmpElt->getNodeType() != DOMNode::TEXT_NODE) tmpElt = tmpElt->getNextSibling(); if (tmpElt == NULL) { // Need to create the underlying TEXT_NODE DOMDocument* doc = mp_signatureValueNode->getOwnerDocument(); tmpElt = doc->createTextNode(b64Buf.sbStrToXMLCh()); mp_signatureValueNode->appendChild(tmpElt); } else { tmpElt->setNodeValue(b64Buf.sbStrToXMLCh()); } // And copy to the local buffer m_signatureValueSB = b64Buf; } // -------------------------------------------------------------------------------- // Key Management // -------------------------------------------------------------------------------- void DSIGSignature::setSigningKey(XSECCryptoKey* k) { if (mp_signingKey != NULL) delete mp_signingKey; mp_signingKey = k; } // -------------------------------------------------------------------------------- // ID Handling // -------------------------------------------------------------------------------- /* * ID handling is really all done within the environment object - just pass the * calls straight through */ void DSIGSignature::setIdByAttributeName(bool flag) { mp_env->setIdByAttributeName(flag); } bool DSIGSignature::getIdByAttributeName() const { return mp_env->getIdByAttributeName(); } void DSIGSignature::registerIdAttributeName(const XMLCh* name) { mp_env->registerIdAttributeName(name); } bool DSIGSignature::deregisterIdAttributeName(const XMLCh* name) { return mp_env->deregisterIdAttributeName(name); } void DSIGSignature::registerIdAttributeNameNS(const XMLCh* ns, const XMLCh* name) { mp_env->registerIdAttributeNameNS(ns, name); } bool DSIGSignature::deregisterIdAttributeNameNS(const XMLCh* ns, const XMLCh* name) { return mp_env->deregisterIdAttributeNameNS(ns, name); } // -------------------------------------------------------------------------------- // Other functions // -------------------------------------------------------------------------------- const XMLCh* DSIGSignature::getSignatureValue() const { if (mp_signatureValueNode == NULL) return NULL; return findFirstChildOfType(mp_signatureValueNode, DOMNode::TEXT_NODE)->getNodeValue(); }