2 * Copyright 2001-2007 Internet2
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 * ExplicitKeyTrustEngine.cpp
20 * TrustEngine based on explicit knowledge of peer key information.
24 #include "security/OpenSSLTrustEngine.h"
25 #include "signature/SignatureValidator.h"
28 #include <log4cpp/Category.hh>
29 #include <xercesc/util/XMLUniDefs.hpp>
30 #include <xsec/enc/OpenSSL/OpenSSLCryptoKeyDSA.hpp>
31 #include <xsec/enc/OpenSSL/OpenSSLCryptoKeyRSA.hpp>
32 #include <xsec/enc/OpenSSL/OpenSSLCryptoX509.hpp>
34 using namespace xmlsignature;
35 using namespace xmltooling;
36 using namespace log4cpp;
39 namespace xmltooling {
40 class XMLTOOL_DLLLOCAL ExplicitKeyTrustEngine : public OpenSSLTrustEngine
43 ExplicitKeyTrustEngine(const DOMElement* e) : OpenSSLTrustEngine(e) {}
44 virtual ~ExplicitKeyTrustEngine() {}
46 virtual bool validate(
48 const KeyInfoSource& keyInfoSource,
49 const KeyResolver* keyResolver=NULL
51 virtual bool validate(
52 const XMLCh* sigAlgorithm,
57 const KeyInfoSource& keyInfoSource,
58 const KeyResolver* keyResolver=NULL
60 virtual bool validate(
61 XSECCryptoX509* certEE,
62 const vector<XSECCryptoX509*>& certChain,
63 const KeyInfoSource& keyInfoSource,
65 const KeyResolver* keyResolver=NULL
67 virtual bool validate(
69 STACK_OF(X509)* certChain,
70 const KeyInfoSource& keyInfoSource,
72 const KeyResolver* keyResolver=NULL
76 TrustEngine* XMLTOOL_DLLLOCAL ExplicitKeyTrustEngineFactory(const DOMElement* const & e)
78 return new ExplicitKeyTrustEngine(e);
82 bool ExplicitKeyTrustEngine::validate(
84 const KeyInfoSource& keyInfoSource,
85 const KeyResolver* keyResolver
91 Category& log=Category::getInstance(XMLTOOLING_LOGCAT".TrustEngine");
93 auto_ptr<KeyInfoIterator> keyInfoIter(keyInfoSource.getKeyInfoIterator());
94 if (!keyInfoIter->hasNext()) {
95 log.warn("unable to validate signature, no key information available for peer");
99 log.debug("attempting to validate signature with the key information for peer");
100 SignatureValidator sigValidator;
101 while (keyInfoIter->hasNext()) {
102 XSECCryptoKey* key = (keyResolver ? keyResolver : m_keyResolver)->resolveKey(keyInfoIter->next());
104 log.debug("attempting to validate signature with public key...");
106 sigValidator.setKey(key); // key now owned by validator
107 sigValidator.validate(&sig);
108 log.debug("signature validated with public key");
111 catch (ValidationException& e) {
112 log.debug("public key did not validate signature: %s", e.what());
116 log.debug("key information does not resolve to a public key, skipping it");
120 log.error("no peer key information validated the signature");
124 bool ExplicitKeyTrustEngine::validate(
125 const XMLCh* sigAlgorithm,
130 const KeyInfoSource& keyInfoSource,
131 const KeyResolver* keyResolver
137 Category& log=Category::getInstance(XMLTOOLING_LOGCAT".TrustEngine");
139 auto_ptr<KeyInfoIterator> keyInfoIter(keyInfoSource.getKeyInfoIterator());
140 if (!keyInfoIter->hasNext()) {
141 log.warn("unable to validate signature, no key information available for peer");
145 log.debug("attempting to validate signature with the key information for peer");
146 while (keyInfoIter->hasNext()) {
147 auto_ptr<XSECCryptoKey> key((keyResolver ? keyResolver : m_keyResolver)->resolveKey(keyInfoIter->next()));
149 log.debug("attempting to validate signature with public key...");
151 if (Signature::verifyRawSignature(key.get(), sigAlgorithm, sig, in, in_len)) {
152 log.debug("signature validated with public key");
156 catch (SignatureException& e) {
157 if (log.isDebugEnabled()) {
158 log.debug("public key did not validate signature: %s", e.what());
163 log.debug("key information does not resolve to a public key, skipping it");
167 log.error("no peer key information validated the signature");
171 bool ExplicitKeyTrustEngine::validate(
172 XSECCryptoX509* certEE,
173 const vector<XSECCryptoX509*>& certChain,
174 const KeyInfoSource& keyInfoSource,
176 const KeyResolver* keyResolver
183 Category::getInstance(XMLTOOLING_LOGCAT".TrustEngine").error("unable to validate, end-entity certificate was null");
186 else if (certEE->getProviderName()!=DSIGConstants::s_unicodeStrPROVOpenSSL) {
187 Category::getInstance(XMLTOOLING_LOGCAT".TrustEngine").error("only the OpenSSL XSEC provider is supported");
191 return validate(static_cast<OpenSSLCryptoX509*>(certEE)->getOpenSSLX509(), NULL, keyInfoSource, checkName, keyResolver);
194 bool ExplicitKeyTrustEngine::validate(
196 STACK_OF(X509)* certChain,
197 const KeyInfoSource& keyInfoSource,
199 const KeyResolver* keyResolver
205 Category& log=Category::getInstance(XMLTOOLING_LOGCAT".TrustEngine");
208 log.error("unable to validate, end-entity certificate was null");
212 auto_ptr<KeyInfoIterator> keyInfoIter(keyInfoSource.getKeyInfoIterator());
213 if (!keyInfoIter->hasNext()) {
214 log.warn("unable to validate, no key information available for peer");
218 // The "explicit" trust implementation relies solely on keys living within the
219 // peer interface to verify the EE certificate.
221 log.debug("attempting to match key information from peer with end-entity certificate");
222 while (keyInfoIter->hasNext()) {
223 auto_ptr<XSECCryptoKey> key((keyResolver ? keyResolver : m_keyResolver)->resolveKey(keyInfoIter->next()));
225 log.debug("checking if peer key matches end-entity certificate");
226 if (key->getProviderName()!=DSIGConstants::s_unicodeStrPROVOpenSSL) {
227 log.error("only the OpenSSL XSEC provider is supported");
230 switch (key->getKeyType()) {
231 case XSECCryptoKey::KEY_RSA_PUBLIC:
233 RSA* rsa = static_cast<OpenSSLCryptoKeyRSA*>(key.get())->getOpenSSLRSA();
234 EVP_PKEY* evp = X509_PUBKEY_get(X509_get_X509_PUBKEY(certEE));
235 if (rsa && evp && evp->type == EVP_PKEY_RSA &&
236 BN_cmp(rsa->n,evp->pkey.rsa->n) == 0 && BN_cmp(rsa->e,evp->pkey.rsa->e) == 0) {
237 log.debug("end-entity certificate matches peer RSA key information");
247 case XSECCryptoKey::KEY_DSA_PUBLIC:
249 DSA* dsa = static_cast<OpenSSLCryptoKeyDSA*>(key.get())->getOpenSSLDSA();
250 EVP_PKEY* evp = X509_PUBKEY_get(X509_get_X509_PUBKEY(certEE));
251 if (dsa && evp && evp->type == EVP_PKEY_DSA && BN_cmp(dsa->pub_key,evp->pkey.dsa->pub_key) == 0) {
252 log.debug("end-entity certificate matches peer DSA key information");
263 log.warn("unknown peer key type, skipping...");
267 log.debug("key information does not resolve to a public key, skipping it");
271 log.debug("no keys within this peer's key information matched the given end-entity certificate");