2 * Copyright 2001-2010 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.
25 #include "security/Credential.h"
26 #include "security/CredentialCriteria.h"
27 #include "security/CredentialResolver.h"
28 #include "security/OpenSSLTrustEngine.h"
29 #include "security/SignatureTrustEngine.h"
30 #include "signature/Signature.h"
31 #include "signature/SignatureValidator.h"
34 #include <xercesc/util/XMLUniDefs.hpp>
35 #include <xsec/enc/OpenSSL/OpenSSLCryptoKeyDSA.hpp>
36 #include <xsec/enc/OpenSSL/OpenSSLCryptoKeyRSA.hpp>
37 #include <xsec/enc/OpenSSL/OpenSSLCryptoX509.hpp>
39 using namespace xmlsignature;
40 using namespace xmltooling::logging;
41 using namespace xmltooling;
44 using xercesc::DOMElement;
46 namespace xmltooling {
47 class XMLTOOL_DLLLOCAL ExplicitKeyTrustEngine : public SignatureTrustEngine, public OpenSSLTrustEngine
50 ExplicitKeyTrustEngine(const DOMElement* e) : TrustEngine(e) {}
51 virtual ~ExplicitKeyTrustEngine() {}
53 virtual bool validate(
55 const CredentialResolver& credResolver,
56 CredentialCriteria* criteria=nullptr
58 virtual bool validate(
59 const XMLCh* sigAlgorithm,
64 const CredentialResolver& credResolver,
65 CredentialCriteria* criteria=nullptr
67 virtual bool validate(
68 XSECCryptoX509* certEE,
69 const vector<XSECCryptoX509*>& certChain,
70 const CredentialResolver& credResolver,
71 CredentialCriteria* criteria=nullptr
73 virtual bool validate(
75 STACK_OF(X509)* certChain,
76 const CredentialResolver& credResolver,
77 CredentialCriteria* criteria=nullptr
81 TrustEngine* XMLTOOL_DLLLOCAL ExplicitKeyTrustEngineFactory(const DOMElement* const & e)
83 return new ExplicitKeyTrustEngine(e);
87 bool ExplicitKeyTrustEngine::validate(
89 const CredentialResolver& credResolver,
90 CredentialCriteria* criteria
96 Category& log=Category::getInstance(XMLTOOLING_LOGCAT".TrustEngine."EXPLICIT_KEY_TRUSTENGINE);
98 vector<const Credential*> credentials;
100 criteria->setUsage(Credential::SIGNING_CREDENTIAL);
101 criteria->setSignature(sig, CredentialCriteria::KEYINFO_EXTRACTION_KEY);
102 credResolver.resolve(credentials,criteria);
105 CredentialCriteria cc;
106 cc.setUsage(Credential::SIGNING_CREDENTIAL);
107 cc.setSignature(sig, CredentialCriteria::KEYINFO_EXTRACTION_KEY);
108 credResolver.resolve(credentials,&cc);
110 if (credentials.empty()) {
111 log.debug("unable to validate signature, no credentials available from peer");
115 log.debug("attempting to validate signature with the peer's credentials");
116 SignatureValidator sigValidator;
117 for (vector<const Credential*>::const_iterator c=credentials.begin(); c!=credentials.end(); ++c) {
118 sigValidator.setCredential(*c);
120 sigValidator.validate(&sig);
121 log.debug("signature validated with credential");
124 catch (ValidationException& e) {
125 log.debug("public key did not validate signature: %s", e.what());
129 log.debug("no peer credentials validated the signature");
133 bool ExplicitKeyTrustEngine::validate(
134 const XMLCh* sigAlgorithm,
139 const CredentialResolver& credResolver,
140 CredentialCriteria* criteria
146 Category& log=Category::getInstance(XMLTOOLING_LOGCAT".TrustEngine."EXPLICIT_KEY_TRUSTENGINE);
148 vector<const Credential*> credentials;
150 criteria->setUsage(Credential::SIGNING_CREDENTIAL);
151 criteria->setKeyInfo(keyInfo, CredentialCriteria::KEYINFO_EXTRACTION_KEY);
152 criteria->setXMLAlgorithm(sigAlgorithm);
153 credResolver.resolve(credentials,criteria);
156 CredentialCriteria cc;
157 cc.setUsage(Credential::SIGNING_CREDENTIAL);
158 cc.setKeyInfo(keyInfo, CredentialCriteria::KEYINFO_EXTRACTION_KEY);
159 cc.setXMLAlgorithm(sigAlgorithm);
160 credResolver.resolve(credentials,&cc);
162 if (credentials.empty()) {
163 log.debug("unable to validate signature, no credentials available from peer");
167 log.debug("attempting to validate signature with the peer's credentials");
168 for (vector<const Credential*>::const_iterator c=credentials.begin(); c!=credentials.end(); ++c) {
169 if ((*c)->getPublicKey()) {
171 if (Signature::verifyRawSignature((*c)->getPublicKey(), sigAlgorithm, sig, in, in_len)) {
172 log.debug("signature validated with public key");
176 catch (SignatureException& e) {
177 if (log.isDebugEnabled()) {
178 log.debug("public key did not validate signature: %s", e.what());
184 log.debug("no peer credentials validated the signature");
188 bool ExplicitKeyTrustEngine::validate(
189 XSECCryptoX509* certEE,
190 const vector<XSECCryptoX509*>& certChain,
191 const CredentialResolver& credResolver,
192 CredentialCriteria* criteria
199 Category::getInstance(XMLTOOLING_LOGCAT".TrustEngine."EXPLICIT_KEY_TRUSTENGINE).error("unable to validate, end-entity certificate was null");
202 else if (certEE->getProviderName()!=DSIGConstants::s_unicodeStrPROVOpenSSL) {
203 Category::getInstance(XMLTOOLING_LOGCAT".TrustEngine."EXPLICIT_KEY_TRUSTENGINE).error("only the OpenSSL XSEC provider is supported");
207 return validate(static_cast<OpenSSLCryptoX509*>(certEE)->getOpenSSLX509(), nullptr, credResolver, criteria);
210 bool ExplicitKeyTrustEngine::validate(
212 STACK_OF(X509)* certChain,
213 const CredentialResolver& credResolver,
214 CredentialCriteria* criteria
220 Category& log=Category::getInstance(XMLTOOLING_LOGCAT".TrustEngine."EXPLICIT_KEY_TRUSTENGINE);
223 log.error("unable to validate, end-entity certificate was null");
227 vector<const Credential*> credentials;
229 if (criteria->getUsage()==Credential::UNSPECIFIED_CREDENTIAL)
230 criteria->setUsage(Credential::SIGNING_CREDENTIAL);
231 credResolver.resolve(credentials,criteria);
234 CredentialCriteria cc;
235 cc.setUsage(Credential::SIGNING_CREDENTIAL);
236 credResolver.resolve(credentials,&cc);
238 if (credentials.empty()) {
239 log.debug("unable to validate certificate, no credentials available from peer");
243 // The "explicit" trust implementation relies solely on keys living within the
244 // peer resolver to verify the EE certificate.
246 log.debug("attempting to match credentials from peer with end-entity certificate");
247 for (vector<const Credential*>::const_iterator c=credentials.begin(); c!=credentials.end(); ++c) {
248 XSECCryptoKey* key = (*c)->getPublicKey();
250 if (key->getProviderName()!=DSIGConstants::s_unicodeStrPROVOpenSSL) {
251 log.error("only the OpenSSL XSEC provider is supported");
254 switch (key->getKeyType()) {
255 case XSECCryptoKey::KEY_RSA_PUBLIC:
257 RSA* rsa = static_cast<OpenSSLCryptoKeyRSA*>(key)->getOpenSSLRSA();
258 EVP_PKEY* evp = X509_PUBKEY_get(X509_get_X509_PUBKEY(certEE));
259 if (rsa && evp && evp->type == EVP_PKEY_RSA &&
260 BN_cmp(rsa->n,evp->pkey.rsa->n) == 0 && BN_cmp(rsa->e,evp->pkey.rsa->e) == 0) {
263 log.debug("end-entity certificate matches peer RSA key information");
271 case XSECCryptoKey::KEY_DSA_PUBLIC:
273 DSA* dsa = static_cast<OpenSSLCryptoKeyDSA*>(key)->getOpenSSLDSA();
274 EVP_PKEY* evp = X509_PUBKEY_get(X509_get_X509_PUBKEY(certEE));
275 if (dsa && evp && evp->type == EVP_PKEY_DSA && BN_cmp(dsa->pub_key,evp->pkey.dsa->pub_key) == 0) {
278 log.debug("end-entity certificate matches peer DSA key information");
287 log.warn("unknown peer key type, skipping...");
292 log.debug("no keys within this peer's key information matched the given end-entity certificate");