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/Credential.h"
25 #include "security/CredentialCriteria.h"
26 #include "security/CredentialResolver.h"
27 #include "security/OpenSSLTrustEngine.h"
28 #include "signature/SignatureValidator.h"
31 #include <log4cpp/Category.hh>
32 #include <xercesc/util/XMLUniDefs.hpp>
33 #include <xsec/enc/OpenSSL/OpenSSLCryptoKeyDSA.hpp>
34 #include <xsec/enc/OpenSSL/OpenSSLCryptoKeyRSA.hpp>
35 #include <xsec/enc/OpenSSL/OpenSSLCryptoX509.hpp>
37 using namespace xmlsignature;
38 using namespace xmltooling;
39 using namespace log4cpp;
42 namespace xmltooling {
43 class XMLTOOL_DLLLOCAL ExplicitKeyTrustEngine : public OpenSSLTrustEngine
46 ExplicitKeyTrustEngine(const DOMElement* e) : OpenSSLTrustEngine(e) {}
47 virtual ~ExplicitKeyTrustEngine() {}
49 virtual bool validate(
51 const CredentialResolver& credResolver,
52 CredentialCriteria* criteria=NULL
54 virtual bool validate(
55 const XMLCh* sigAlgorithm,
60 const CredentialResolver& credResolver,
61 CredentialCriteria* criteria=NULL
63 virtual bool validate(
64 XSECCryptoX509* certEE,
65 const vector<XSECCryptoX509*>& certChain,
66 const CredentialResolver& credResolver,
67 CredentialCriteria* criteria=NULL
69 virtual bool validate(
71 STACK_OF(X509)* certChain,
72 const CredentialResolver& credResolver,
73 CredentialCriteria* criteria=NULL
77 TrustEngine* XMLTOOL_DLLLOCAL ExplicitKeyTrustEngineFactory(const DOMElement* const & e)
79 return new ExplicitKeyTrustEngine(e);
83 bool ExplicitKeyTrustEngine::validate(
85 const CredentialResolver& credResolver,
86 CredentialCriteria* criteria
92 Category& log=Category::getInstance(XMLTOOLING_LOGCAT".TrustEngine");
94 vector<const Credential*> credentials;
96 criteria->setUsage(CredentialCriteria::SIGNING_CREDENTIAL);
97 criteria->setSignature(sig);
98 credResolver.resolve(credentials,criteria);
101 CredentialCriteria cc;
102 cc.setUsage(CredentialCriteria::SIGNING_CREDENTIAL);
103 cc.setSignature(sig);
104 credResolver.resolve(credentials,&cc);
106 if (credentials.empty()) {
107 log.warn("unable to validate signature, no credentials available from peer");
111 log.debug("attempting to validate signature with the peer's credentials");
112 SignatureValidator sigValidator;
113 for (vector<const Credential*>::const_iterator c=credentials.begin(); c!=credentials.end(); ++c) {
114 sigValidator.setCredential(*c);
116 sigValidator.validate(&sig);
117 log.debug("signature validated with credential");
120 catch (ValidationException& e) {
121 log.debug("public key did not validate signature: %s", e.what());
125 log.error("no peer credentials validated the signature");
129 bool ExplicitKeyTrustEngine::validate(
130 const XMLCh* sigAlgorithm,
135 const CredentialResolver& credResolver,
136 CredentialCriteria* criteria
142 Category& log=Category::getInstance(XMLTOOLING_LOGCAT".TrustEngine");
144 vector<const Credential*> credentials;
146 criteria->setUsage(CredentialCriteria::SIGNING_CREDENTIAL);
147 criteria->setKeyInfo(keyInfo);
148 credResolver.resolve(credentials,criteria);
151 CredentialCriteria cc;
152 cc.setUsage(CredentialCriteria::SIGNING_CREDENTIAL);
153 cc.setKeyInfo(keyInfo);
154 credResolver.resolve(credentials,&cc);
156 if (credentials.empty()) {
157 log.warn("unable to validate signature, no credentials available from peer");
161 log.debug("attempting to validate signature with the peer's credentials");
162 for (vector<const Credential*>::const_iterator c=credentials.begin(); c!=credentials.end(); ++c) {
163 if ((*c)->getPublicKey()) {
165 if (Signature::verifyRawSignature((*c)->getPublicKey(), sigAlgorithm, sig, in, in_len)) {
166 log.debug("signature validated with public key");
170 catch (SignatureException& e) {
171 if (log.isDebugEnabled()) {
172 log.debug("public key did not validate signature: %s", e.what());
178 log.error("no peer credentials validated the signature");
182 bool ExplicitKeyTrustEngine::validate(
183 XSECCryptoX509* certEE,
184 const vector<XSECCryptoX509*>& certChain,
185 const CredentialResolver& credResolver,
186 CredentialCriteria* criteria
193 Category::getInstance(XMLTOOLING_LOGCAT".TrustEngine").error("unable to validate, end-entity certificate was null");
196 else if (certEE->getProviderName()!=DSIGConstants::s_unicodeStrPROVOpenSSL) {
197 Category::getInstance(XMLTOOLING_LOGCAT".TrustEngine").error("only the OpenSSL XSEC provider is supported");
201 return validate(static_cast<OpenSSLCryptoX509*>(certEE)->getOpenSSLX509(), NULL, credResolver, criteria);
204 bool ExplicitKeyTrustEngine::validate(
206 STACK_OF(X509)* certChain,
207 const CredentialResolver& credResolver,
208 CredentialCriteria* criteria
214 Category& log=Category::getInstance(XMLTOOLING_LOGCAT".TrustEngine");
217 log.error("unable to validate, end-entity certificate was null");
221 vector<const Credential*> credentials;
223 if (criteria->getUsage()==CredentialCriteria::UNSPECIFIED_CREDENTIAL)
224 criteria->setUsage(CredentialCriteria::SIGNING_CREDENTIAL);
225 credResolver.resolve(credentials,criteria);
228 CredentialCriteria cc;
229 cc.setUsage(CredentialCriteria::SIGNING_CREDENTIAL);
230 credResolver.resolve(credentials,&cc);
232 if (credentials.empty()) {
233 log.warn("unable to validate certificate, no credentials available from peer");
237 // The "explicit" trust implementation relies solely on keys living within the
238 // peer resolver to verify the EE certificate.
240 log.debug("attempting to match credentials from peer with end-entity certificate");
241 for (vector<const Credential*>::const_iterator c=credentials.begin(); c!=credentials.end(); ++c) {
242 XSECCryptoKey* key = (*c)->getPublicKey();
244 log.debug("checking if peer key matches end-entity certificate");
245 if (key->getProviderName()!=DSIGConstants::s_unicodeStrPROVOpenSSL) {
246 log.error("only the OpenSSL XSEC provider is supported");
249 switch (key->getKeyType()) {
250 case XSECCryptoKey::KEY_RSA_PUBLIC:
252 RSA* rsa = static_cast<OpenSSLCryptoKeyRSA*>(key)->getOpenSSLRSA();
253 EVP_PKEY* evp = X509_PUBKEY_get(X509_get_X509_PUBKEY(certEE));
254 if (rsa && evp && evp->type == EVP_PKEY_RSA &&
255 BN_cmp(rsa->n,evp->pkey.rsa->n) == 0 && BN_cmp(rsa->e,evp->pkey.rsa->e) == 0) {
258 log.debug("end-entity certificate matches peer RSA key information");
266 case XSECCryptoKey::KEY_DSA_PUBLIC:
268 DSA* dsa = static_cast<OpenSSLCryptoKeyDSA*>(key)->getOpenSSLDSA();
269 EVP_PKEY* evp = X509_PUBKEY_get(X509_get_X509_PUBKEY(certEE));
270 if (dsa && evp && evp->type == EVP_PKEY_DSA && BN_cmp(dsa->pub_key,evp->pkey.dsa->pub_key) == 0) {
273 log.debug("end-entity certificate matches peer DSA key information");
282 log.warn("unknown peer key type, skipping...");
287 log.debug("no keys within this peer's key information matched the given end-entity certificate");