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 "security/SignatureTrustEngine.h"
29 #include "signature/SignatureValidator.h"
32 #include <log4cpp/Category.hh>
33 #include <xercesc/util/XMLUniDefs.hpp>
34 #include <xsec/enc/OpenSSL/OpenSSLCryptoKeyDSA.hpp>
35 #include <xsec/enc/OpenSSL/OpenSSLCryptoKeyRSA.hpp>
36 #include <xsec/enc/OpenSSL/OpenSSLCryptoX509.hpp>
38 using namespace xmlsignature;
39 using namespace xmltooling;
40 using namespace log4cpp;
43 namespace xmltooling {
44 class XMLTOOL_DLLLOCAL ExplicitKeyTrustEngine : public SignatureTrustEngine, public OpenSSLTrustEngine
47 ExplicitKeyTrustEngine(const DOMElement* e) : TrustEngine(e) {}
48 virtual ~ExplicitKeyTrustEngine() {}
50 virtual bool validate(
52 const CredentialResolver& credResolver,
53 CredentialCriteria* criteria=NULL
55 virtual bool validate(
56 const XMLCh* sigAlgorithm,
61 const CredentialResolver& credResolver,
62 CredentialCriteria* criteria=NULL
64 virtual bool validate(
65 XSECCryptoX509* certEE,
66 const vector<XSECCryptoX509*>& certChain,
67 const CredentialResolver& credResolver,
68 CredentialCriteria* criteria=NULL
70 virtual bool validate(
72 STACK_OF(X509)* certChain,
73 const CredentialResolver& credResolver,
74 CredentialCriteria* criteria=NULL
78 TrustEngine* XMLTOOL_DLLLOCAL ExplicitKeyTrustEngineFactory(const DOMElement* const & e)
80 return new ExplicitKeyTrustEngine(e);
84 bool ExplicitKeyTrustEngine::validate(
86 const CredentialResolver& credResolver,
87 CredentialCriteria* criteria
93 Category& log=Category::getInstance(XMLTOOLING_LOGCAT".TrustEngine."EXPLICIT_KEY_TRUSTENGINE);
95 vector<const Credential*> credentials;
97 criteria->setUsage(CredentialCriteria::SIGNING_CREDENTIAL);
98 criteria->setSignature(sig, CredentialCriteria::KEYINFO_EXTRACTION_KEY);
99 credResolver.resolve(credentials,criteria);
102 CredentialCriteria cc;
103 cc.setUsage(CredentialCriteria::SIGNING_CREDENTIAL);
104 cc.setSignature(sig, CredentialCriteria::KEYINFO_EXTRACTION_KEY);
105 credResolver.resolve(credentials,&cc);
107 if (credentials.empty()) {
108 log.debug("unable to validate signature, no credentials available from peer");
112 log.debug("attempting to validate signature with the peer's credentials");
113 SignatureValidator sigValidator;
114 for (vector<const Credential*>::const_iterator c=credentials.begin(); c!=credentials.end(); ++c) {
115 sigValidator.setCredential(*c);
117 sigValidator.validate(&sig);
118 log.debug("signature validated with credential");
121 catch (ValidationException& e) {
122 log.debug("public key did not validate signature: %s", e.what());
126 log.debug("no peer credentials validated the signature");
130 bool ExplicitKeyTrustEngine::validate(
131 const XMLCh* sigAlgorithm,
136 const CredentialResolver& credResolver,
137 CredentialCriteria* criteria
143 Category& log=Category::getInstance(XMLTOOLING_LOGCAT".TrustEngine."EXPLICIT_KEY_TRUSTENGINE);
145 vector<const Credential*> credentials;
147 criteria->setUsage(CredentialCriteria::SIGNING_CREDENTIAL);
148 criteria->setKeyInfo(keyInfo, CredentialCriteria::KEYINFO_EXTRACTION_KEY);
149 criteria->setXMLAlgorithm(sigAlgorithm);
150 credResolver.resolve(credentials,criteria);
153 CredentialCriteria cc;
154 cc.setUsage(CredentialCriteria::SIGNING_CREDENTIAL);
155 cc.setKeyInfo(keyInfo, CredentialCriteria::KEYINFO_EXTRACTION_KEY);
156 cc.setXMLAlgorithm(sigAlgorithm);
157 credResolver.resolve(credentials,&cc);
159 if (credentials.empty()) {
160 log.debug("unable to validate signature, no credentials available from peer");
164 log.debug("attempting to validate signature with the peer's credentials");
165 for (vector<const Credential*>::const_iterator c=credentials.begin(); c!=credentials.end(); ++c) {
166 if ((*c)->getPublicKey()) {
168 if (Signature::verifyRawSignature((*c)->getPublicKey(), sigAlgorithm, sig, in, in_len)) {
169 log.debug("signature validated with public key");
173 catch (SignatureException& e) {
174 if (log.isDebugEnabled()) {
175 log.debug("public key did not validate signature: %s", e.what());
181 log.debug("no peer credentials validated the signature");
185 bool ExplicitKeyTrustEngine::validate(
186 XSECCryptoX509* certEE,
187 const vector<XSECCryptoX509*>& certChain,
188 const CredentialResolver& credResolver,
189 CredentialCriteria* criteria
196 Category::getInstance(XMLTOOLING_LOGCAT".TrustEngine."EXPLICIT_KEY_TRUSTENGINE).error("unable to validate, end-entity certificate was null");
199 else if (certEE->getProviderName()!=DSIGConstants::s_unicodeStrPROVOpenSSL) {
200 Category::getInstance(XMLTOOLING_LOGCAT".TrustEngine."EXPLICIT_KEY_TRUSTENGINE).error("only the OpenSSL XSEC provider is supported");
204 return validate(static_cast<OpenSSLCryptoX509*>(certEE)->getOpenSSLX509(), NULL, credResolver, criteria);
207 bool ExplicitKeyTrustEngine::validate(
209 STACK_OF(X509)* certChain,
210 const CredentialResolver& credResolver,
211 CredentialCriteria* criteria
217 Category& log=Category::getInstance(XMLTOOLING_LOGCAT".TrustEngine."EXPLICIT_KEY_TRUSTENGINE);
220 log.error("unable to validate, end-entity certificate was null");
224 vector<const Credential*> credentials;
226 if (criteria->getUsage()==CredentialCriteria::UNSPECIFIED_CREDENTIAL)
227 criteria->setUsage(CredentialCriteria::SIGNING_CREDENTIAL);
228 credResolver.resolve(credentials,criteria);
231 CredentialCriteria cc;
232 cc.setUsage(CredentialCriteria::SIGNING_CREDENTIAL);
233 credResolver.resolve(credentials,&cc);
235 if (credentials.empty()) {
236 log.debug("unable to validate certificate, no credentials available from peer");
240 // The "explicit" trust implementation relies solely on keys living within the
241 // peer resolver to verify the EE certificate.
243 log.debug("attempting to match credentials from peer with end-entity certificate");
244 for (vector<const Credential*>::const_iterator c=credentials.begin(); c!=credentials.end(); ++c) {
245 XSECCryptoKey* key = (*c)->getPublicKey();
247 if (key->getProviderName()!=DSIGConstants::s_unicodeStrPROVOpenSSL) {
248 log.error("only the OpenSSL XSEC provider is supported");
251 switch (key->getKeyType()) {
252 case XSECCryptoKey::KEY_RSA_PUBLIC:
254 RSA* rsa = static_cast<OpenSSLCryptoKeyRSA*>(key)->getOpenSSLRSA();
255 EVP_PKEY* evp = X509_PUBKEY_get(X509_get_X509_PUBKEY(certEE));
256 if (rsa && evp && evp->type == EVP_PKEY_RSA &&
257 BN_cmp(rsa->n,evp->pkey.rsa->n) == 0 && BN_cmp(rsa->e,evp->pkey.rsa->e) == 0) {
260 log.debug("end-entity certificate matches peer RSA key information");
268 case XSECCryptoKey::KEY_DSA_PUBLIC:
270 DSA* dsa = static_cast<OpenSSLCryptoKeyDSA*>(key)->getOpenSSLDSA();
271 EVP_PKEY* evp = X509_PUBKEY_get(X509_get_X509_PUBKEY(certEE));
272 if (dsa && evp && evp->type == EVP_PKEY_DSA && BN_cmp(dsa->pub_key,evp->pkey.dsa->pub_key) == 0) {
275 log.debug("end-entity certificate matches peer DSA key information");
284 log.warn("unknown peer key type, skipping...");
289 log.debug("no keys within this peer's key information matched the given end-entity certificate");