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 {
};
/**
- * 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.
+ * <p>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.
+ *
+ * <p>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.
+ *
+ * <p>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;
};
/**
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)
}
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<XSECCryptoKey> 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<XSECCryptoX509*>& certChain,
TrustEngine::KeyInfoIterator& keyInfoSource,
*/
virtual Signature* cloneSignature() const=0;
+ /**
+ * Sign the input data and return a base64-encoded signature. The signature value
+ * <strong>MUST NOT</strong> contain any embedded linefeeds.
+ *
+ * <p>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 <strong>NOT</strong> 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.
+ *
+ * <p>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 <strong>NOT</strong> 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() {}
};
#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;
}
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());
+ }
+}