/* * Copyright 2002-2005 The Apache Software Foundation. * * Licensed 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 * * DSIGSignedInfo := Class for checking and setting up signed Info nodes in a DSIG signature * * $Id: DSIGSignedInfo.cpp 450747 2006-09-28 07:54:22Z blautenb $ * */ // XSEC Includes #include #include #include #include #include #include #include XERCES_CPP_NAMESPACE_USE // Constructors and Destructors DSIGSignedInfo::DSIGSignedInfo(DOMDocument *doc, XSECSafeBufferFormatter * pFormatter, DOMNode *signedInfoNode, const XSECEnv * env) { mp_doc = doc; m_HMACOutputLength = 0; mp_formatter = pFormatter; mp_signedInfoNode = signedInfoNode; m_signatureMethod = SIGNATURE_NONE; mp_env = env; mp_referenceList = NULL; m_loaded = false; } DSIGSignedInfo::DSIGSignedInfo(DOMDocument *doc, XSECSafeBufferFormatter * pFormatter, const XSECEnv * env) { mp_doc = doc; m_HMACOutputLength = 0; mp_formatter = pFormatter; mp_signedInfoNode = NULL; m_signatureMethod = SIGNATURE_NONE; mp_env = env; mp_referenceList = NULL; m_loaded = false; } DSIGSignedInfo::~DSIGSignedInfo() { mp_formatter = NULL; mp_env = NULL; if (mp_referenceList != NULL) { delete mp_referenceList; mp_referenceList = NULL; } } signatureMethod DSIGSignedInfo::getSignatureMethod(void) { return m_signatureMethod; } DOMNode * DSIGSignedInfo::getDOMNode() { return mp_signedInfoNode; } canonicalizationMethod DSIGSignedInfo::getCanonicalizationMethod(void) { return m_canonicalizationMethod; } hashMethod DSIGSignedInfo::getHashMethod() { return m_hashMethod; } int DSIGSignedInfo::getHMACOutputLength() { return m_HMACOutputLength; } // -------------------------------------------------------------------------------- // Verify each reference element // -------------------------------------------------------------------------------- bool DSIGSignedInfo::verify(safeBuffer &errStr) { return DSIGReference::verifyReferenceList(mp_referenceList, errStr); } // -------------------------------------------------------------------------------- // Calculate and set hash values for each reference element // -------------------------------------------------------------------------------- void DSIGSignedInfo::hash(bool interlockingReferences) { DSIGReference::hashReferenceList(mp_referenceList, interlockingReferences); } // -------------------------------------------------------------------------------- // Create an empty reference in the signed info // -------------------------------------------------------------------------------- DSIGReference * DSIGSignedInfo::createReference(const XMLCh * URI, hashMethod hm, char * type) { safeBuffer hURI; if (hashMethod2URI(hURI, hm) == false) { throw XSECException(XSECException::UnknownSignatureAlgorithm, "DSIGSignedInfo::createReference - Hash method unknown"); } return createReference(URI, hURI.sbStrToXMLCh(), MAKE_UNICODE_STRING(type));; } DSIGReference * DSIGSignedInfo::createReference( const XMLCh * URI, const XMLCh * hashAlgorithmURI, const XMLCh * type) { DSIGReference * ref; XSECnew(ref, DSIGReference(mp_env)); Janitor j_ref(ref); DOMNode *refNode = ref->createBlankReference(URI, hashAlgorithmURI, type); // Add the node to the end of the childeren mp_signedInfoNode->appendChild(refNode); mp_env->doPrettyPrint(mp_signedInfoNode); // Add to the reference List j_ref.release(); mp_referenceList->addReference(ref); return ref; } // -------------------------------------------------------------------------------- // Create an empty SignedInfo // -------------------------------------------------------------------------------- // deprecated DOMElement *DSIGSignedInfo::createBlankSignedInfo(canonicalizationMethod cm, signatureMethod sm, hashMethod hm) { // This is now deprecated. Because this is so, we go the long way - translate // to URI and then call the "standard" method, which will translate back to // internal enums if possible const XMLCh * cURI; safeBuffer sURI; if ((cURI = canonicalizationMethod2UNICODEURI(cm)) == NULL) { throw XSECException(XSECException::UnknownCanonicalization, "DSIGSignature::createBlankSignature - Canonicalisation method unknown"); } if (signatureHashMethod2URI(sURI, sm, hm) == false) { throw XSECException(XSECException::UnknownSignatureAlgorithm, "DSIGSignature::createBlankSignature - Signature/Hash method unknown"); } return createBlankSignedInfo(cURI, sURI.sbStrToXMLCh()); } DOMElement * DSIGSignedInfo::createBlankSignedInfo( const XMLCh * canonicalizationAlgorithmURI, const XMLCh * signatureAlgorithmURI) { safeBuffer str; const XMLCh * prefixNS = mp_env->getDSIGNSPrefix(); makeQName(str, prefixNS, "SignedInfo"); DOMElement *ret = mp_doc->createElementNS(DSIGConstants::s_unicodeStrURIDSIG, str.rawXMLChBuffer()); mp_signedInfoNode = ret; // Now create the algorithm parts XSECmapURIToCanonicalizationMethod(canonicalizationAlgorithmURI, m_canonicalizationMethod); XSECmapURIToSignatureMethods(signatureAlgorithmURI, m_signatureMethod, m_hashMethod); // Canonicalisation DOMElement *canMeth = mp_doc->createElementNS(DSIGConstants::s_unicodeStrURIDSIG, makeQName(str, prefixNS, "CanonicalizationMethod").rawXMLChBuffer()); mp_env->doPrettyPrint(mp_signedInfoNode); mp_signedInfoNode->appendChild(canMeth); mp_env->doPrettyPrint(mp_signedInfoNode); canMeth->setAttributeNS(NULL,DSIGConstants::s_unicodeStrAlgorithm, canonicalizationAlgorithmURI); // Now the SignatureMethod DOMElement *sigMeth = mp_doc->createElementNS(DSIGConstants::s_unicodeStrURIDSIG, makeQName(str, prefixNS, "SignatureMethod").rawXMLChBuffer()); mp_signedInfoNode->appendChild(sigMeth); mp_env->doPrettyPrint(mp_signedInfoNode); sigMeth->setAttributeNS(NULL, DSIGConstants::s_unicodeStrAlgorithm, signatureAlgorithmURI); // Store the algorithm URI internally mp_algorithmURI = sigMeth->getAttributeNS(NULL, DSIGConstants::s_unicodeStrAlgorithm); // Create an empty reference list XSECnew(mp_referenceList, DSIGReferenceList()); return ret; } // -------------------------------------------------------------------------------- // Load the SignedInfo // -------------------------------------------------------------------------------- void DSIGSignedInfo::load(void) { if (mp_signedInfoNode == 0) { // Attempt to load an empty signature element throw XSECException(XSECException::LoadEmptySignedInfo); } if (!strEquals(getDSIGLocalName(mp_signedInfoNode), "SignedInfo")) { throw XSECException(XSECException::LoadNonSignedInfo); } DOMNode * tmpSI = mp_signedInfoNode->getFirstChild(); // Check for CanonicalizationMethod while (tmpSI != 0 && (tmpSI->getNodeType() != DOMNode::ELEMENT_NODE)) // Skip text and comments tmpSI = tmpSI->getNextSibling(); if (tmpSI == 0 || !strEquals(getDSIGLocalName(tmpSI), "CanonicalizationMethod")) { throw XSECException(XSECException::ExpectedDSIGChildNotFound, "Expected as first child of "); } // Determine what the canonicalization method is DOMNamedNodeMap *tmpAtts = tmpSI->getAttributes(); DOMNode *algorithm = tmpAtts->getNamedItem(DSIGConstants::s_unicodeStrAlgorithm); if (algorithm == 0) { throw XSECException(XSECException::ExpectedDSIGChildNotFound, "Expected Algorithm attribute in "); } safeBuffer tmpSB; tmpSB << (*mp_formatter << algorithm->getNodeValue()); if (tmpSB.sbStrcmp(URI_ID_C14N_NOC) == 0) { m_canonicalizationMethod = CANON_C14N_NOC; } else if (tmpSB.sbStrcmp(URI_ID_C14N_COM) == 0) { m_canonicalizationMethod = CANON_C14N_COM; } else if (tmpSB.sbStrcmp(URI_ID_EXC_C14N_COM) == 0) { m_canonicalizationMethod = CANON_C14NE_COM; } else if (tmpSB.sbStrcmp(URI_ID_EXC_C14N_NOC) == 0) { m_canonicalizationMethod = CANON_C14NE_NOC; } else throw XSECException(XSECException::UnknownCanonicalization); // Now load the SignatureMethod tmpSI = tmpSI->getNextSibling(); while (tmpSI != 0 && (tmpSI->getNodeType() != DOMNode::ELEMENT_NODE)) // Skip text and comments tmpSI = tmpSI->getNextSibling(); if (tmpSI == 0 || !strEquals(getDSIGLocalName(tmpSI), "SignatureMethod")) { throw XSECException(XSECException::ExpectedDSIGChildNotFound, "Expected as child of "); } // Determine the algorithms used to sign this document tmpAtts = tmpSI->getAttributes(); algorithm = tmpAtts->getNamedItem(DSIGConstants::s_unicodeStrAlgorithm); if (algorithm == 0) { throw XSECException(XSECException::ExpectedDSIGChildNotFound, "Expected Algorithm attribute in "); } mp_algorithmURI = algorithm->getNodeValue(); /* NOTE - as of version 1.3.1 all code relating to parsing the algorithm * has been removed. This should all be handled inside the algorithm mappers. * Having code here restricts available algorithms, as this code is not extended for * new algorthms. */ /* Look for maximum output value. Really only applies to HMACs, but as we no * longer know at this point if this is an HMAC, we need to check. */ DOMNode *tmpSOV = tmpSI->getFirstChild(); while (tmpSOV != NULL && tmpSOV->getNodeType() != DOMNode::ELEMENT_NODE && !strEquals(getDSIGLocalName(tmpSOV), "HMACOutputLength")) tmpSOV = tmpSOV->getNextSibling(); if (tmpSOV != NULL) { // Have a max output value! tmpSOV = tmpSOV->getFirstChild(); while (tmpSOV != NULL && tmpSOV->getNodeType() != DOMNode::TEXT_NODE) tmpSOV = tmpSOV->getNextSibling(); if (tmpSOV != NULL) { safeBuffer val; val << (*mp_formatter << tmpSOV->getNodeValue()); m_HMACOutputLength = atoi((char *) val.rawBuffer()); } } // Now look at references.... tmpSI = tmpSI->getNextSibling(); // Run through the rest of the elements until done while (tmpSI != 0 && (tmpSI->getNodeType() != DOMNode::ELEMENT_NODE)) // Skip text and comments tmpSI = tmpSI->getNextSibling(); if (tmpSI != NULL) { // Have an element node - should be a reference, so let's load the list mp_referenceList = DSIGReference::loadReferenceListFromXML(mp_env, tmpSI); } }