2 * Licensed to the University Corporation for Advanced Internet
3 * Development, Inc. (UCAID) under one or more contributor license
4 * agreements. See the NOTICE file distributed with this work for
5 * additional information regarding copyright ownership.
7 * UCAID licenses this file to you under the Apache License,
8 * Version 2.0 (the "License"); you may not use this file except
9 * in compliance with the License. You may obtain a copy of the
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
17 * either express or implied. See the License for the specific
18 * language governing permissions and limitations under the License.
22 * ExplicitKeyTrustEngine.cpp
24 * TrustEngine based on explicit knowledge of peer key information.
29 #include "security/Credential.h"
30 #include "security/CredentialCriteria.h"
31 #include "security/CredentialResolver.h"
32 #include "security/OpenSSLTrustEngine.h"
33 #include "security/SignatureTrustEngine.h"
34 #include "signature/Signature.h"
35 #include "signature/SignatureValidator.h"
38 #include <xercesc/util/XMLUniDefs.hpp>
39 #include <xsec/enc/OpenSSL/OpenSSLCryptoKeyDSA.hpp>
40 #include <xsec/enc/OpenSSL/OpenSSLCryptoKeyRSA.hpp>
41 #include <xsec/enc/OpenSSL/OpenSSLCryptoX509.hpp>
43 using namespace xmlsignature;
44 using namespace xmltooling::logging;
45 using namespace xmltooling;
48 using xercesc::DOMElement;
50 namespace xmltooling {
51 class XMLTOOL_DLLLOCAL ExplicitKeyTrustEngine : public SignatureTrustEngine, public OpenSSLTrustEngine
54 ExplicitKeyTrustEngine(const DOMElement* e) : TrustEngine(e) {}
55 virtual ~ExplicitKeyTrustEngine() {}
57 virtual bool validate(
59 const CredentialResolver& credResolver,
60 CredentialCriteria* criteria=nullptr
62 virtual bool validate(
63 const XMLCh* sigAlgorithm,
68 const CredentialResolver& credResolver,
69 CredentialCriteria* criteria=nullptr
71 virtual bool validate(
72 XSECCryptoX509* certEE,
73 const vector<XSECCryptoX509*>& certChain,
74 const CredentialResolver& credResolver,
75 CredentialCriteria* criteria=nullptr
77 virtual bool validate(
79 STACK_OF(X509)* certChain,
80 const CredentialResolver& credResolver,
81 CredentialCriteria* criteria=nullptr
85 TrustEngine* XMLTOOL_DLLLOCAL ExplicitKeyTrustEngineFactory(const DOMElement* const & e)
87 return new ExplicitKeyTrustEngine(e);
91 bool ExplicitKeyTrustEngine::validate(
93 const CredentialResolver& credResolver,
94 CredentialCriteria* criteria
100 Category& log=Category::getInstance(XMLTOOLING_LOGCAT ".TrustEngine." EXPLICIT_KEY_TRUSTENGINE);
102 vector<const Credential*> credentials;
104 criteria->setUsage(Credential::SIGNING_CREDENTIAL);
105 criteria->setSignature(sig, CredentialCriteria::KEYINFO_EXTRACTION_KEY);
106 credResolver.resolve(credentials,criteria);
109 CredentialCriteria cc;
110 cc.setUsage(Credential::SIGNING_CREDENTIAL);
111 cc.setSignature(sig, CredentialCriteria::KEYINFO_EXTRACTION_KEY);
112 credResolver.resolve(credentials,&cc);
114 if (credentials.empty()) {
115 log.debug("unable to validate signature, no credentials available from peer");
119 log.debug("attempting to validate signature with the peer's credentials");
120 SignatureValidator sigValidator;
121 for (vector<const Credential*>::const_iterator c=credentials.begin(); c!=credentials.end(); ++c) {
122 sigValidator.setCredential(*c);
124 sigValidator.validate(&sig);
125 log.debug("signature validated with credential");
128 catch (ValidationException& e) {
129 log.debug("public key did not validate signature: %s", e.what());
133 log.debug("no peer credentials validated the signature");
137 bool ExplicitKeyTrustEngine::validate(
138 const XMLCh* sigAlgorithm,
143 const CredentialResolver& credResolver,
144 CredentialCriteria* criteria
150 Category& log=Category::getInstance(XMLTOOLING_LOGCAT ".TrustEngine." EXPLICIT_KEY_TRUSTENGINE);
152 vector<const Credential*> credentials;
154 criteria->setUsage(Credential::SIGNING_CREDENTIAL);
155 criteria->setKeyInfo(keyInfo, CredentialCriteria::KEYINFO_EXTRACTION_KEY);
156 criteria->setXMLAlgorithm(sigAlgorithm);
157 credResolver.resolve(credentials,criteria);
160 CredentialCriteria cc;
161 cc.setUsage(Credential::SIGNING_CREDENTIAL);
162 cc.setKeyInfo(keyInfo, CredentialCriteria::KEYINFO_EXTRACTION_KEY);
163 cc.setXMLAlgorithm(sigAlgorithm);
164 credResolver.resolve(credentials,&cc);
166 if (credentials.empty()) {
167 log.debug("unable to validate signature, no credentials available from peer");
171 log.debug("attempting to validate signature with the peer's credentials");
172 for (vector<const Credential*>::const_iterator c=credentials.begin(); c!=credentials.end(); ++c) {
173 if ((*c)->getPublicKey()) {
175 if (Signature::verifyRawSignature((*c)->getPublicKey(), sigAlgorithm, sig, in, in_len)) {
176 log.debug("signature validated with public key");
180 catch (SignatureException& e) {
181 if (log.isDebugEnabled()) {
182 log.debug("public key did not validate signature: %s", e.what());
188 log.debug("no peer credentials validated the signature");
192 bool ExplicitKeyTrustEngine::validate(
193 XSECCryptoX509* certEE,
194 const vector<XSECCryptoX509*>& certChain,
195 const CredentialResolver& credResolver,
196 CredentialCriteria* criteria
203 Category::getInstance(XMLTOOLING_LOGCAT ".TrustEngine." EXPLICIT_KEY_TRUSTENGINE).error("unable to validate, end-entity certificate was null");
206 else if (certEE->getProviderName()!=DSIGConstants::s_unicodeStrPROVOpenSSL) {
207 Category::getInstance(XMLTOOLING_LOGCAT ".TrustEngine." EXPLICIT_KEY_TRUSTENGINE).error("only the OpenSSL XSEC provider is supported");
211 return validate(static_cast<OpenSSLCryptoX509*>(certEE)->getOpenSSLX509(), nullptr, credResolver, criteria);
214 bool ExplicitKeyTrustEngine::validate(
216 STACK_OF(X509)* certChain,
217 const CredentialResolver& credResolver,
218 CredentialCriteria* criteria
224 Category& log=Category::getInstance(XMLTOOLING_LOGCAT ".TrustEngine." EXPLICIT_KEY_TRUSTENGINE);
227 log.error("unable to validate, end-entity certificate was null");
231 vector<const Credential*> credentials;
233 if (criteria->getUsage()==Credential::UNSPECIFIED_CREDENTIAL)
234 criteria->setUsage(Credential::SIGNING_CREDENTIAL);
235 credResolver.resolve(credentials,criteria);
238 CredentialCriteria cc;
239 cc.setUsage(Credential::SIGNING_CREDENTIAL);
240 credResolver.resolve(credentials,&cc);
242 if (credentials.empty()) {
243 log.debug("unable to validate certificate, no credentials available from peer");
247 // The "explicit" trust implementation relies solely on keys living within the
248 // peer resolver to verify the EE certificate.
250 log.debug("attempting to match credentials from peer with end-entity certificate");
251 for (vector<const Credential*>::const_iterator c=credentials.begin(); c!=credentials.end(); ++c) {
252 XSECCryptoKey* key = (*c)->getPublicKey();
254 if (key->getProviderName()!=DSIGConstants::s_unicodeStrPROVOpenSSL) {
255 log.error("only the OpenSSL XSEC provider is supported");
258 switch (key->getKeyType()) {
259 case XSECCryptoKey::KEY_RSA_PUBLIC:
261 RSA* rsa = static_cast<OpenSSLCryptoKeyRSA*>(key)->getOpenSSLRSA();
262 EVP_PKEY* evp = X509_PUBKEY_get(X509_get_X509_PUBKEY(certEE));
263 if (rsa && evp && evp->type == EVP_PKEY_RSA &&
264 BN_cmp(rsa->n,evp->pkey.rsa->n) == 0 && BN_cmp(rsa->e,evp->pkey.rsa->e) == 0) {
267 log.debug("end-entity certificate matches peer RSA key information");
275 case XSECCryptoKey::KEY_DSA_PUBLIC:
277 DSA* dsa = static_cast<OpenSSLCryptoKeyDSA*>(key)->getOpenSSLDSA();
278 EVP_PKEY* evp = X509_PUBKEY_get(X509_get_X509_PUBKEY(certEE));
279 if (dsa && evp && evp->type == EVP_PKEY_DSA && BN_cmp(dsa->pub_key,evp->pkey.dsa->pub_key) == 0) {
282 log.debug("end-entity certificate matches peer DSA key information");
291 log.warn("unknown peer key type, skipping...");
296 log.debug("no keys within this peer's key information matched the given end-entity certificate");