X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=xmltooling%2Fsecurity%2Fimpl%2FExplicitKeyTrustEngine.cpp;h=09ee002df7dea58730593c49e8fd253d038b5775;hb=a0d768778a8f5f539b909baf5b115e70ea765f0f;hp=4d1eeb26132783df3144f9108b59c5ac39cb3bfe;hpb=b0fd073c49adba3a7d7efc0d27e059382eb336ef;p=shibboleth%2Fcpp-xmltooling.git diff --git a/xmltooling/security/impl/ExplicitKeyTrustEngine.cpp b/xmltooling/security/impl/ExplicitKeyTrustEngine.cpp index 4d1eeb2..09ee002 100644 --- a/xmltooling/security/impl/ExplicitKeyTrustEngine.cpp +++ b/xmltooling/security/impl/ExplicitKeyTrustEngine.cpp @@ -1,157 +1,294 @@ -/* - * Copyright 2001-2005 Internet2 - * - * 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. - */ - -/** - * ExplicitKeyTrustEngine.cpp - * - * TrustEngine based on explicit knowledge of peer key information. - */ - -#include "internal.h" -#include "security/X509TrustEngine.h" -#include "signature/SignatureValidator.h" -#include "util/NDC.h" - -#include -#include -#include - -using namespace xmlsignature; -using namespace xmltooling; -using namespace log4cpp; -using namespace std; - -namespace xmltooling { - class XMLTOOL_DLLLOCAL ExplicitKeyTrustEngine : public X509TrustEngine - { - public: - ExplicitKeyTrustEngine(const DOMElement* e) : X509TrustEngine(e) {} - virtual ~ExplicitKeyTrustEngine() {} - - virtual bool validate( - Signature& sig, - TrustEngine::KeyInfoIterator& keyInfoSource, - const KeyResolver* keyResolver=NULL - ) const; - virtual bool validate( - XSECCryptoX509* certEE, - const vector& certChain, - TrustEngine::KeyInfoIterator& keyInfoSource, - bool checkName=true, - const KeyResolver* keyResolver=NULL - ) const; - }; - - TrustEngine* XMLTOOL_DLLLOCAL ExplicitKeyTrustEngineFactory(const DOMElement* const & e) - { - return new ExplicitKeyTrustEngine(e); - } -}; - -bool ExplicitKeyTrustEngine::validate( - Signature& sig, - TrustEngine::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"); - SignatureValidator sigValidator; - while (keyInfoSource.hasNext()) { - XSECCryptoKey* key = (keyResolver ? keyResolver : m_keyResolver)->resolveKey(keyInfoSource.next()); - if (key) { - log.debug("attempting to validate signature with public key..."); - try { - sigValidator.setKey(key); // key now owned by validator - sigValidator.validate(&sig); - log.info("signature validated with public key"); - return true; - } - catch (ValidationException& 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, - bool checkName, - const KeyResolver* keyResolver - ) const -{ -#ifdef _DEBUG - NDC ndc("validate"); -#endif - Category& log=Category::getInstance(XMLTOOLING_LOGCAT".TrustEngine"); - - if (!certEE) { - log.error("unable to validate, end-entity certificate was null"); - return false; - } - else if (certEE->getProviderName()!=DSIGConstants::s_unicodeStrPROVOpenSSL) { - log.error("only the OpenSSL XSEC provider is supported"); - return false; - } - else if (!keyInfoSource.hasNext()) { - log.warn("unable to validate, no key information available for peer"); - return false; - } - - // The new "basic" trust implementation relies solely on certificates living within the - // role interface to verify the EE certificate. - - log.debug("attempting to match key information from peer with end-entity certificate"); - while (keyInfoSource.hasNext()) { - KeyResolver::ResolvedCertificates resolvedCerts; - if (0 == (keyResolver ? keyResolver : m_keyResolver)->resolveCertificates(keyInfoSource.next(),resolvedCerts)) { - log.debug("key information does not resolve to a certificate, skipping it"); - continue; - } - - log.debug("checking if certificates contained within key information match end-entity certificate"); - if (resolvedCerts.v().front()->getProviderName()!=DSIGConstants::s_unicodeStrPROVOpenSSL) { - log.error("only the OpenSSL XSEC provider is supported"); - continue; - } - else if (!X509_cmp(static_cast(certEE)->getOpenSSLX509(),static_cast(resolvedCerts.v().front())->getOpenSSLX509())) { - log.info("end-entity certificate matches certificate from peer key information"); - return true; - } - } - - log.debug("no certificates within this peer's key information matched the given end-entity certificate"); - return false; -} +/* + * Copyright 2001-2010 Internet2 + * + * 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. + */ + +/** + * ExplicitKeyTrustEngine.cpp + * + * TrustEngine based on explicit knowledge of peer key information. + */ + +#include "internal.h" +#include "logging.h" +#include "security/Credential.h" +#include "security/CredentialCriteria.h" +#include "security/CredentialResolver.h" +#include "security/OpenSSLTrustEngine.h" +#include "security/SignatureTrustEngine.h" +#include "signature/Signature.h" +#include "signature/SignatureValidator.h" +#include "util/NDC.h" + +#include +#include +#include +#include + +using namespace xmlsignature; +using namespace xmltooling::logging; +using namespace xmltooling; +using namespace std; + +using xercesc::DOMElement; + +namespace xmltooling { + class XMLTOOL_DLLLOCAL ExplicitKeyTrustEngine : public SignatureTrustEngine, public OpenSSLTrustEngine + { + public: + ExplicitKeyTrustEngine(const DOMElement* e) : TrustEngine(e) {} + virtual ~ExplicitKeyTrustEngine() {} + + virtual bool validate( + Signature& sig, + const CredentialResolver& credResolver, + CredentialCriteria* criteria=nullptr + ) const; + virtual bool validate( + const XMLCh* sigAlgorithm, + const char* sig, + KeyInfo* keyInfo, + const char* in, + unsigned int in_len, + const CredentialResolver& credResolver, + CredentialCriteria* criteria=nullptr + ) const; + virtual bool validate( + XSECCryptoX509* certEE, + const vector& certChain, + const CredentialResolver& credResolver, + CredentialCriteria* criteria=nullptr + ) const; + virtual bool validate( + X509* certEE, + STACK_OF(X509)* certChain, + const CredentialResolver& credResolver, + CredentialCriteria* criteria=nullptr + ) const; + }; + + TrustEngine* XMLTOOL_DLLLOCAL ExplicitKeyTrustEngineFactory(const DOMElement* const & e) + { + return new ExplicitKeyTrustEngine(e); + } +}; + +bool ExplicitKeyTrustEngine::validate( + Signature& sig, + const CredentialResolver& credResolver, + CredentialCriteria* criteria + ) const +{ +#ifdef _DEBUG + NDC ndc("validate"); +#endif + Category& log=Category::getInstance(XMLTOOLING_LOGCAT".TrustEngine."EXPLICIT_KEY_TRUSTENGINE); + + vector credentials; + if (criteria) { + criteria->setUsage(Credential::SIGNING_CREDENTIAL); + criteria->setSignature(sig, CredentialCriteria::KEYINFO_EXTRACTION_KEY); + credResolver.resolve(credentials,criteria); + } + else { + CredentialCriteria cc; + cc.setUsage(Credential::SIGNING_CREDENTIAL); + cc.setSignature(sig, CredentialCriteria::KEYINFO_EXTRACTION_KEY); + credResolver.resolve(credentials,&cc); + } + if (credentials.empty()) { + log.debug("unable to validate signature, no credentials available from peer"); + return false; + } + + log.debug("attempting to validate signature with the peer's credentials"); + SignatureValidator sigValidator; + for (vector::const_iterator c=credentials.begin(); c!=credentials.end(); ++c) { + sigValidator.setCredential(*c); + try { + sigValidator.validate(&sig); + log.debug("signature validated with credential"); + return true; + } + catch (ValidationException& e) { + log.debug("public key did not validate signature: %s", e.what()); + } + } + + log.debug("no peer credentials validated the signature"); + return false; +} + +bool ExplicitKeyTrustEngine::validate( + const XMLCh* sigAlgorithm, + const char* sig, + KeyInfo* keyInfo, + const char* in, + unsigned int in_len, + const CredentialResolver& credResolver, + CredentialCriteria* criteria + ) const +{ +#ifdef _DEBUG + NDC ndc("validate"); +#endif + Category& log=Category::getInstance(XMLTOOLING_LOGCAT".TrustEngine."EXPLICIT_KEY_TRUSTENGINE); + + vector credentials; + if (criteria) { + criteria->setUsage(Credential::SIGNING_CREDENTIAL); + criteria->setKeyInfo(keyInfo, CredentialCriteria::KEYINFO_EXTRACTION_KEY); + criteria->setXMLAlgorithm(sigAlgorithm); + credResolver.resolve(credentials,criteria); + } + else { + CredentialCriteria cc; + cc.setUsage(Credential::SIGNING_CREDENTIAL); + cc.setKeyInfo(keyInfo, CredentialCriteria::KEYINFO_EXTRACTION_KEY); + cc.setXMLAlgorithm(sigAlgorithm); + credResolver.resolve(credentials,&cc); + } + if (credentials.empty()) { + log.debug("unable to validate signature, no credentials available from peer"); + return false; + } + + log.debug("attempting to validate signature with the peer's credentials"); + for (vector::const_iterator c=credentials.begin(); c!=credentials.end(); ++c) { + if ((*c)->getPublicKey()) { + try { + if (Signature::verifyRawSignature((*c)->getPublicKey(), sigAlgorithm, sig, in, in_len)) { + log.debug("signature validated with public key"); + return true; + } + } + catch (SignatureException& e) { + if (log.isDebugEnabled()) { + log.debug("public key did not validate signature: %s", e.what()); + } + } + } + } + + log.debug("no peer credentials validated the signature"); + return false; +} + +bool ExplicitKeyTrustEngine::validate( + XSECCryptoX509* certEE, + const vector& certChain, + const CredentialResolver& credResolver, + CredentialCriteria* criteria + ) const +{ +#ifdef _DEBUG + NDC ndc("validate"); +#endif + if (!certEE) { + Category::getInstance(XMLTOOLING_LOGCAT".TrustEngine."EXPLICIT_KEY_TRUSTENGINE).error("unable to validate, end-entity certificate was null"); + return false; + } + else if (certEE->getProviderName()!=DSIGConstants::s_unicodeStrPROVOpenSSL) { + Category::getInstance(XMLTOOLING_LOGCAT".TrustEngine."EXPLICIT_KEY_TRUSTENGINE).error("only the OpenSSL XSEC provider is supported"); + return false; + } + + return validate(static_cast(certEE)->getOpenSSLX509(), nullptr, credResolver, criteria); +} + +bool ExplicitKeyTrustEngine::validate( + X509* certEE, + STACK_OF(X509)* certChain, + const CredentialResolver& credResolver, + CredentialCriteria* criteria + ) const +{ +#ifdef _DEBUG + NDC ndc("validate"); +#endif + Category& log=Category::getInstance(XMLTOOLING_LOGCAT".TrustEngine."EXPLICIT_KEY_TRUSTENGINE); + + if (!certEE) { + log.error("unable to validate, end-entity certificate was null"); + return false; + } + + vector credentials; + if (criteria) { + if (criteria->getUsage()==Credential::UNSPECIFIED_CREDENTIAL) + criteria->setUsage(Credential::SIGNING_CREDENTIAL); + credResolver.resolve(credentials,criteria); + } + else { + CredentialCriteria cc; + cc.setUsage(Credential::SIGNING_CREDENTIAL); + credResolver.resolve(credentials,&cc); + } + if (credentials.empty()) { + log.debug("unable to validate certificate, no credentials available from peer"); + return false; + } + + // The "explicit" trust implementation relies solely on keys living within the + // peer resolver to verify the EE certificate. + + log.debug("attempting to match credentials from peer with end-entity certificate"); + for (vector::const_iterator c=credentials.begin(); c!=credentials.end(); ++c) { + XSECCryptoKey* key = (*c)->getPublicKey(); + if (key) { + if (key->getProviderName()!=DSIGConstants::s_unicodeStrPROVOpenSSL) { + log.error("only the OpenSSL XSEC provider is supported"); + continue; + } + switch (key->getKeyType()) { + case XSECCryptoKey::KEY_RSA_PUBLIC: + { + RSA* rsa = static_cast(key)->getOpenSSLRSA(); + EVP_PKEY* evp = X509_PUBKEY_get(X509_get_X509_PUBKEY(certEE)); + if (rsa && evp && evp->type == EVP_PKEY_RSA && + BN_cmp(rsa->n,evp->pkey.rsa->n) == 0 && BN_cmp(rsa->e,evp->pkey.rsa->e) == 0) { + if (evp) + EVP_PKEY_free(evp); + log.debug("end-entity certificate matches peer RSA key information"); + return true; + } + if (evp) + EVP_PKEY_free(evp); + break; + } + + case XSECCryptoKey::KEY_DSA_PUBLIC: + { + DSA* dsa = static_cast(key)->getOpenSSLDSA(); + EVP_PKEY* evp = X509_PUBKEY_get(X509_get_X509_PUBKEY(certEE)); + if (dsa && evp && evp->type == EVP_PKEY_DSA && BN_cmp(dsa->pub_key,evp->pkey.dsa->pub_key) == 0) { + if (evp) + EVP_PKEY_free(evp); + log.debug("end-entity certificate matches peer DSA key information"); + return true; + } + if (evp) + EVP_PKEY_free(evp); + break; + } + + default: + log.warn("unknown peer key type, skipping..."); + } + } + } + + log.debug("no keys within this peer's key information matched the given end-entity certificate"); + return false; +}