/*
-* Copyright 2001-2006 Internet2
+* Copyright 2001-2007 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include "internal.h"
#include "exceptions.h"
+#include "logging.h"
#include "impl/UnknownElement.h"
+#include "security/Credential.h"
#include "signature/KeyInfo.h"
#include "signature/Signature.h"
#include "util/NDC.h"
#include "util/XMLConstants.h"
#include "util/XMLHelper.h"
-#include <log4cpp/Category.hh>
#include <xercesc/framework/MemBufInputSource.hpp>
#include <xercesc/framework/Wrapper4InputSource.hpp>
#include <xercesc/util/XMLUniDefs.hpp>
#include <xsec/dsig/DSIGKeyInfoX509.hpp>
#include <xsec/dsig/DSIGReference.hpp>
#include <xsec/enc/XSECCryptoException.hpp>
+#include <xsec/framework/XSECAlgorithmHandler.hpp>
+#include <xsec/framework/XSECAlgorithmMapper.hpp>
#include <xsec/framework/XSECException.hpp>
+#include <xsec/transformers/TXFMSB.hpp>
+#include <xsec/transformers/TXFMChain.hpp>
+#include <xsec/transformers/TXFMOutputFile.hpp>
using namespace xmlsignature;
+using namespace xmltooling::logging;
using namespace xmltooling;
-using namespace log4cpp;
using namespace std;
using xmlconstants::XMLSIG_NS;
using xmlconstants::XMLSIG_PREFIX;
class XMLTOOL_DLLLOCAL XMLSecSignatureImpl : public UnknownElementImpl, public virtual Signature
{
public:
- XMLSecSignatureImpl() : UnknownElementImpl(XMLSIG_NS, Signature::LOCAL_NAME, XMLSIG_PREFIX),
+ XMLSecSignatureImpl() : AbstractXMLObject(XMLSIG_NS, Signature::LOCAL_NAME, XMLSIG_PREFIX),
+ UnknownElementImpl(XMLSIG_NS, Signature::LOCAL_NAME, XMLSIG_PREFIX),
m_signature(NULL), m_c14n(NULL), m_sm(NULL), m_key(NULL), m_keyInfo(NULL), m_reference(NULL) {}
virtual ~XMLSecSignatureImpl();
XMLObject* clone() const;
Signature* cloneSignature() const;
- DOMElement* marshall(DOMDocument* document=NULL, const vector<Signature*>* sigs=NULL) const;
- DOMElement* marshall(DOMElement* parentElement, const vector<Signature*>* sigs=NULL) const;
+ DOMElement* marshall(DOMDocument* document=NULL, const vector<Signature*>* sigs=NULL, const Credential* credential=NULL) const;
+ DOMElement* marshall(DOMElement* parentElement, const vector<Signature*>* sigs=NULL, const Credential* credential=NULL) const;
XMLObject* unmarshall(DOMElement* element, bool bindDocument=false);
// Getters
- const XMLCh* getCanonicalizationMethod() const { return m_c14n ? m_c14n : DSIGConstants::s_unicodeStrURIEXC_C14N_NOC; }
- const XMLCh* getSignatureAlgorithm() const { return m_sm ? m_sm : DSIGConstants::s_unicodeStrURIRSA_SHA1; }
+ const XMLCh* getCanonicalizationMethod() const {
+ if (m_signature)
+ return canonicalizationMethod2UNICODEURI(m_signature->getCanonicalizationMethod());
+ return m_c14n ? m_c14n : DSIGConstants::s_unicodeStrURIEXC_C14N_NOC;
+ }
+ const XMLCh* getSignatureAlgorithm() const {
+ if (!m_sm && m_signature) {
+ safeBuffer sURI;
+ if (signatureHashMethod2URI(sURI, m_signature->getSignatureMethod(), m_signature->getHashMethod()) == false)
+ return NULL;
+ m_sm = XMLString::replicate(sURI.sbStrToXMLCh());
+ }
+ return m_sm ? m_sm : DSIGConstants::s_unicodeStrURIRSA_SHA1;
+ }
+
KeyInfo* getKeyInfo() const { return m_keyInfo; }
ContentReference* getContentReference() const { return m_reference; }
DSIGSignature* getXMLSignature() const { return m_signature; }
m_reference=reference;
}
- void sign();
+ void sign(const Credential* credential=NULL);
private:
mutable DSIGSignature* m_signature;
XMLCh* m_c14n;
- XMLCh* m_sm;
+ mutable XMLCh* m_sm;
XSECCryptoKey* m_key;
- KeyInfo* m_keyInfo;
+ mutable KeyInfo* m_keyInfo;
ContentReference* m_reference;
};
return ret;
}
-void XMLSecSignatureImpl::sign()
+void XMLSecSignatureImpl::sign(const Credential* credential)
{
Category& log=Category::getInstance(XMLTOOLING_LOGCAT".Signature");
log.debug("applying signature");
if (!m_signature)
throw SignatureException("Only a marshalled Signature object can be signed.");
- else if (!m_key)
- throw SignatureException("No signing key available for signature creation.");
else if (!m_reference)
throw SignatureException("No ContentReference object set for signature creation.");
+ XSECCryptoKey* key = credential ? credential->getPrivateKey() : m_key;
+ if (!key)
+ throw SignatureException("No signing key available for signature creation.");
+
try {
log.debug("creating signature reference(s)");
DSIGReferenceList* refs = m_signature->getReferenceList();
m_reference->createReferences(m_signature);
log.debug("computing signature");
- m_signature->setSigningKey(m_key->clone());
+ m_signature->setSigningKey(key->clone());
m_signature->sign();
}
catch(XSECException& e) {
}
}
-DOMElement* XMLSecSignatureImpl::marshall(DOMDocument* document, const vector<Signature*>* sigs) const
+DOMElement* XMLSecSignatureImpl::marshall(DOMDocument* document, const vector<Signature*>* sigs, const Credential* credential) const
{
#ifdef _DEBUG
xmltooling::NDC ndc("marshall");
#endif
- Category& log=Category::getInstance(XMLTOOLING_LOGCAT".Signature");
+ Category& log=Category::getInstance(XMLTOOLING_LOGCAT".XMLObject.Signature");
log.debug("marshalling ds:Signature");
DOMElement* cachedDOM=getDOM();
document=DOMImplementationRegistry::getDOMImplementation(NULL)->createDocument();
bindDocument=true;
}
- m_signature=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignature();
- m_signature->setDSIGNSPrefix(XMLSIG_PREFIX);
- cachedDOM=m_signature->createBlankSignature(document, getCanonicalizationMethod(), getSignatureAlgorithm());
+ DSIGSignature* temp=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignature();
+ temp->setDSIGNSPrefix(XMLSIG_PREFIX);
+ cachedDOM=temp->createBlankSignature(document, getCanonicalizationMethod(), getSignatureAlgorithm());
+ m_signature = temp;
}
else {
// We need to reparse the XML we saved off into a new DOM.
}
// Marshall KeyInfo data.
+ if (credential) {
+ delete m_keyInfo;
+ m_keyInfo = NULL;
+ m_keyInfo = credential->getKeyInfo();
+ }
if (m_keyInfo && (!m_signature->getKeyInfoList() || m_signature->getKeyInfoList()->isEmpty())) {
m_keyInfo->marshall(cachedDOM);
}
return cachedDOM;
}
-DOMElement* XMLSecSignatureImpl::marshall(DOMElement* parentElement, const vector<Signature*>* sigs) const
+DOMElement* XMLSecSignatureImpl::marshall(DOMElement* parentElement, const vector<Signature*>* sigs, const Credential* credential) const
{
#ifdef _DEBUG
xmltooling::NDC ndc("marshall");
#endif
- Category& log=Category::getInstance(XMLTOOLING_LOGCAT".Signature");
+ Category& log=Category::getInstance(XMLTOOLING_LOGCAT".XMLObject.Signature");
log.debug("marshalling ds:Signature");
DOMElement* cachedDOM=getDOM();
if (m_xml.empty()) {
// Fresh signature, so we just create an empty one.
log.debug("creating empty Signature element");
- m_signature=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignature();
- m_signature->setDSIGNSPrefix(XMLSIG_PREFIX);
- cachedDOM=m_signature->createBlankSignature(
- parentElement->getOwnerDocument(), getCanonicalizationMethod(), getSignatureAlgorithm()
- );
+ DSIGSignature* temp=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignature();
+ temp->setDSIGNSPrefix(XMLSIG_PREFIX);
+ cachedDOM=temp->createBlankSignature(parentElement->getOwnerDocument(), getCanonicalizationMethod(), getSignatureAlgorithm());
+ m_signature = temp;
}
else {
MemBufInputSource src(reinterpret_cast<const XMLByte*>(m_xml.c_str()),m_xml.length(),"XMLSecSignatureImpl");
}
// Marshall KeyInfo data.
+ if (credential) {
+ delete m_keyInfo;
+ m_keyInfo = NULL;
+ m_keyInfo = credential->getKeyInfo();
+ }
if (m_keyInfo && (!m_signature->getKeyInfoList() || m_signature->getKeyInfoList()->isEmpty())) {
m_keyInfo->marshall(cachedDOM);
}
XMLObject* XMLSecSignatureImpl::unmarshall(DOMElement* element, bool bindDocument)
{
- Category::getInstance(XMLTOOLING_LOGCAT".Signature").debug("unmarshalling ds:Signature");
+ Category::getInstance(XMLTOOLING_LOGCAT".XMLObject.Signature").debug("unmarshalling ds:Signature");
try {
m_signature=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newSignatureFromDOM(
return this;
}
-Signature* SignatureBuilder::buildObject(
+#ifdef HAVE_COVARIANT_RETURNS
+Signature*
+#else
+XMLObject*
+#endif
+SignatureBuilder::buildObject(
const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType
) const
{
return buildObject();
}
-Signature* SignatureBuilder::buildObject() const
+#ifdef HAVE_COVARIANT_RETURNS
+Signature*
+#else
+XMLObject*
+#endif
+SignatureBuilder::buildObject() const
{
return new XMLSecSignatureImpl();
}
const XMLCh Signature::LOCAL_NAME[] = UNICODE_LITERAL_9(S,i,g,n,a,t,u,r,e);
+
+// Raw signature methods.
+
+unsigned int Signature::createRawSignature(
+ XSECCryptoKey* key, const XMLCh* sigAlgorithm, const char* in, unsigned int in_len, char* out, unsigned int out_len
+ )
+{
+ try {
+ XSECAlgorithmHandler* handler = XSECPlatformUtils::g_algorithmMapper->mapURIToHandler(sigAlgorithm);
+ if (!handler) {
+ auto_ptr_char alg(sigAlgorithm);
+ throw SignatureException("Unsupported signature algorithm ($1).", params(1,alg.get()));
+ }
+
+ // Move input into a safeBuffer to source the transform chain.
+ safeBuffer sb,sbout;
+ sb.sbStrncpyIn(in,in_len);
+ TXFMSB* sbt = new TXFMSB(NULL);
+ sbt->setInput(sb, in_len);
+ TXFMChain tx(sbt);
+
+ // Sign the chain.
+ unsigned int siglen = handler->signToSafeBuffer(&tx, sigAlgorithm, key, out_len-1, sbout);
+ if (siglen >= out_len)
+ throw SignatureException("Signature size exceeded output buffer size.");
+
+ // Push all non-whitespace into buffer.
+ unsigned int ret_len = 0;
+ const char* source = sbout.rawCharBuffer();
+ while (siglen--) {
+ if (isspace(*source))
+ ++source;
+ else {
+ *out++ = *source++;
+ ++ret_len;
+ }
+ }
+ *out = 0;
+ return ret_len;
+ }
+ catch(XSECException& e) {
+ auto_ptr_char temp(e.getMsg());
+ throw SignatureException(string("Caught an XMLSecurity exception while creating raw signature: ") + temp.get());
+ }
+ catch(XSECCryptoException& e) {
+ throw SignatureException(string("Caught an XMLSecurity exception while creating raw signature: ") + e.getMsg());
+ }
+}
+
+bool Signature::verifyRawSignature(
+ XSECCryptoKey* key, const XMLCh* sigAlgorithm, const char* signature, const char* in, unsigned int in_len
+ )
+{
+ try {
+ XSECAlgorithmHandler* handler = XSECPlatformUtils::g_algorithmMapper->mapURIToHandler(sigAlgorithm);
+ if (!handler) {
+ auto_ptr_char alg(sigAlgorithm);
+ throw SignatureException("Unsupported signature algorithm ($1).", params(1,alg.get()));
+ }
+
+ // Move input into a safeBuffer to source the transform chain.
+ safeBuffer sb;
+ sb.sbStrncpyIn(in,in_len);
+ TXFMSB* sbt = new TXFMSB(NULL);
+ sbt->setInput(sb, in_len);
+ TXFMChain tx(sbt);
+
+ // Verify the chain.
+ return handler->verifyBase64Signature(&tx, sigAlgorithm, signature, 0, key);
+ }
+ catch(XSECException& e) {
+ auto_ptr_char temp(e.getMsg());
+ throw SignatureException(string("Caught an XMLSecurity exception while verifying raw signature: ") + temp.get());
+ }
+ catch(XSECCryptoException& e) {
+ throw SignatureException(string("Caught an XMLSecurity exception while verifying raw signature: ") + e.getMsg());
+ }
+}
+
+void Signature::extractNames(DSIGKeyInfoList* keyInfo, set<string>& names)
+{
+ char* kn;
+ const XMLCh* n;
+
+ for (size_t s=0; s<keyInfo->getSize(); s++) {
+ n=keyInfo->item(s)->getKeyName();
+ if (n && *n) {
+ kn=toUTF8(n);
+ names.insert(kn);
+ delete[] kn;
+ }
+ }
+}