From 6a74376ff5e381c5f355ba3de6f492487eee3335 Mon Sep 17 00:00:00 2001 From: cantor Date: Tue, 7 Nov 2006 04:55:38 +0000 Subject: [PATCH] Raw signature operations and trust engine support. git-svn-id: https://svn.middleware.georgetown.edu/cpp-xmltooling/trunk@191 de75baf8-a10c-0410-a50a-987c0e22f00f --- xmltooling/security/TrustEngine.h | 42 +++++++++-- .../security/impl/ExplicitKeyTrustEngine.cpp | 55 ++++++++++++++ xmltooling/signature/Signature.h | 45 ++++++++++++ xmltooling/signature/impl/XMLSecSignatureImpl.cpp | 83 ++++++++++++++++++++++ 4 files changed, 221 insertions(+), 4 deletions(-) diff --git a/xmltooling/security/TrustEngine.h b/xmltooling/security/TrustEngine.h index 33049a0..1d836d9 100644 --- a/xmltooling/security/TrustEngine.h +++ b/xmltooling/security/TrustEngine.h @@ -30,7 +30,7 @@ namespace xmltooling { /** - * Evaluates the trustworthiness and validity of XML Signatures against + * Evaluates the trustworthiness and validity of XML or raw Signatures against * implementation-specific requirements. */ class XMLTOOL_API TrustEngine { @@ -86,24 +86,58 @@ namespace xmltooling { }; /** - * Determines whether a signature is correct and valid with respect to the - * KeyInfo data supplied. It is the responsibility of the application to + * Determines whether an XML signature is correct and valid with respect to + * the KeyInfo data supplied. It is the responsibility of the application to * ensure that the KeyInfo information supplied is in fact associated with * the peer who created the signature. * - * A custom KeyResolver can be supplied from outside the TrustEngine. + *

A custom KeyResolver can be supplied from outside the TrustEngine. * Alternatively, one may be specified to the plugin constructor. * A non-caching, inline resolver will be used as a fallback. * * @param sig reference to a signature object to validate * @param keyInfoSource supplies KeyInfo objects to the TrustEngine * @param keyResolver optional externally supplied KeyResolver, or NULL + * @return true iff the signature validates */ virtual bool validate( xmlsignature::Signature& sig, KeyInfoIterator& keyInfoSource, const xmlsignature::KeyResolver* keyResolver=NULL ) const=0; + + /** + * Determines whether a raw signature is correct and valid with respect to + * the KeyInfo data supplied. It is the responsibility of the application to + * ensure that the KeyInfo information supplied is in fact associated with + * the peer who created the signature. + * + *

A custom KeyResolver can be supplied from outside the TrustEngine. + * Alternatively, one may be specified to the plugin constructor. + * A non-caching, inline resolver will be used as a fallback. + * + *

Note that the keyInfo parameter is not part of the implicitly trusted + * set of key information supplied via the iterator, but rather advisory data + * that may have accompanied the signature itself. + * + * @param sigAlgorithm XML Signature identifier for the algorithm used + * @param sig null-terminated base64-encoded signature value + * @param keyInfo KeyInfo object accompanying the signature, if any + * @param in the input data over which the signature was created + * @param in_len size of input data in bytes + * @param keyInfoSource supplies KeyInfo objects to the TrustEngine + * @param keyResolver optional externally supplied KeyResolver, or NULL + * @return true iff the signature validates + */ + virtual bool validate( + const XMLCh* sigAlgorithm, + const char* sig, + xmlsignature::KeyInfo* keyInfo, + const char* in, + unsigned int in_len, + KeyInfoIterator& keyInfoSource, + const xmlsignature::KeyResolver* keyResolver=NULL + ) const=0; }; /** diff --git a/xmltooling/security/impl/ExplicitKeyTrustEngine.cpp b/xmltooling/security/impl/ExplicitKeyTrustEngine.cpp index f64cf12..db63081 100644 --- a/xmltooling/security/impl/ExplicitKeyTrustEngine.cpp +++ b/xmltooling/security/impl/ExplicitKeyTrustEngine.cpp @@ -53,6 +53,15 @@ namespace xmltooling { bool checkName=true, const KeyResolver* keyResolver=NULL ) const; + virtual bool validate( + const XMLCh* sigAlgorithm, + const char* sig, + KeyInfo* keyInfo, + const char* in, + unsigned int in_len, + KeyInfoIterator& keyInfoSource, + const KeyResolver* keyResolver=NULL + ) const; }; TrustEngine* XMLTOOL_DLLLOCAL ExplicitKeyTrustEngineFactory(const DOMElement* const & e) @@ -105,6 +114,52 @@ bool ExplicitKeyTrustEngine::validate( } bool ExplicitKeyTrustEngine::validate( + const XMLCh* sigAlgorithm, + const char* sig, + KeyInfo* keyInfo, + const char* in, + unsigned int in_len, + KeyInfoIterator& keyInfoSource, + const KeyResolver* keyResolver + ) const +{ +#ifdef _DEBUG + NDC ndc("validate"); +#endif + Category& log=Category::getInstance(XMLTOOLING_LOGCAT".TrustEngine"); + + if (!keyInfoSource.hasNext()) { + log.warn("unable to validate signature, no key information available for peer"); + return false; + } + + log.debug("attempting to validate signature with the key information for peer"); + while (keyInfoSource.hasNext()) { + auto_ptr key((keyResolver ? keyResolver : m_keyResolver)->resolveKey(keyInfoSource.next())); + if (key.get()) { + log.debug("attempting to validate signature with public key..."); + try { + if (Signature::verifyRawSignature(key.get(), sigAlgorithm, sig, in, in_len)) { + log.info("signature validated with public key"); + return true; + } + } + catch (SignatureException& e) { + if (log.isDebugEnabled()) { + log.debug("public key did not validate signature: %s", e.what()); + } + } + } + else { + log.debug("key information does not resolve to a public key, skipping it"); + } + } + + log.error("no peer key information validated the signature"); + return false; +} + +bool ExplicitKeyTrustEngine::validate( XSECCryptoX509* certEE, const vector& certChain, TrustEngine::KeyInfoIterator& keyInfoSource, diff --git a/xmltooling/signature/Signature.h b/xmltooling/signature/Signature.h index 33fc083..db95c20 100644 --- a/xmltooling/signature/Signature.h +++ b/xmltooling/signature/Signature.h @@ -132,6 +132,51 @@ namespace xmlsignature { */ virtual Signature* cloneSignature() const=0; + /** + * Sign the input data and return a base64-encoded signature. The signature value + * MUST NOT contain any embedded linefeeds. + * + *

Allows specialized applications to create raw signatures over any input using + * the same cryptography layer as XML Signatures use. + * + * @param key key to sign with, will NOT be freed + * @param sigAlgorithm XML signature algorithm identifier + * @param in input data + * @param in_len size of input data in bytes + * @param out output buffer + * @param out_len size of output buffer in bytes + * @return size in bytes of base64-encoded signature + */ + static unsigned int createRawSignature( + XSECCryptoKey* key, + const XMLCh* sigAlgorithm, + const char* in, + unsigned int in_len, + char* out, + unsigned int out_len + ); + + /** + * Verifies a base-64 encoded signature over the input data. + * + *

Allows specialized applications to verify raw signatures over any input using + * the same cryptography layer as XML Signatures use. + * + * @param key key to verify with, will NOT be freed + * @param sigAlgorithm XML signature algorithm identifier + * @param signature base64-encoded signature value + * @param in input data + * @param in_len size of input data in bytes + * @return true iff signature verifies + */ + static bool verifyRawSignature( + XSECCryptoKey* key, + const XMLCh* sigAlgorithm, + const char* signature, + const char* in, + unsigned int in_len + ); + protected: Signature() {} }; diff --git a/xmltooling/signature/impl/XMLSecSignatureImpl.cpp b/xmltooling/signature/impl/XMLSecSignatureImpl.cpp index 30bc1dc..4f33d90 100644 --- a/xmltooling/signature/impl/XMLSecSignatureImpl.cpp +++ b/xmltooling/signature/impl/XMLSecSignatureImpl.cpp @@ -36,7 +36,12 @@ #include #include #include +#include +#include #include +#include +#include +#include using namespace xmlsignature; using namespace xmltooling; @@ -409,3 +414,81 @@ Signature* SignatureBuilder::buildObject() const } 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()); + } +} -- 2.1.4