Base TrustEngine APIs and explicit key engine impl.
authorScott Cantor <cantor.2@osu.edu>
Thu, 17 Aug 2006 01:22:57 +0000 (01:22 +0000)
committerScott Cantor <cantor.2@osu.edu>
Thu, 17 Aug 2006 01:22:57 +0000 (01:22 +0000)
xmltooling/Makefile.am
xmltooling/XMLToolingConfig.cpp
xmltooling/XMLToolingConfig.h
xmltooling/security/TrustEngine.h [new file with mode: 0644]
xmltooling/security/X509TrustEngine.h [new file with mode: 0644]
xmltooling/security/impl/ExplicitKeyTrustEngine.cpp [new file with mode: 0644]
xmltooling/security/impl/TrustEngine.cpp [new file with mode: 0644]
xmltooling/signature/SignatureValidator.h
xmltooling/xmltooling.vcproj

index cf26b0a..b882463 100644 (file)
@@ -54,6 +54,10 @@ ioinclude_HEADERS = \
        io/AbstractXMLObjectMarshaller.h \
        io/AbstractXMLObjectUnmarshaller.h
 
+secinclude_HEADERS = \
+       security/TrustEngine.h \
+       security/X509TrustEngine.h
+
 siginclude_HEADERS = \
        signature/CachingKeyResolver.h \
        signature/ContentReference.h \
@@ -84,6 +88,8 @@ if BUILD_XMLSEC
 xmlsec_sources = \
        encryption/impl/Decrypter.cpp \
        encryption/impl/Encrypter.cpp \
+       security/impl/TrustEngine.cpp \
+       security/impl/ExplicitKeyTrustEngine.cpp \
        signature/impl/CredentialResolver.cpp \
        signature/impl/FilesystemCredentialResolver.cpp \
        signature/impl/InlineKeyResolver.cpp \
index ae102b9..e80b136 100644 (file)
@@ -25,9 +25,8 @@
 #include "XMLToolingConfig.h"
 #include "encryption/Encryption.h"
 #include "impl/UnknownElement.h"
+#include "security/TrustEngine.h"
 #include "signature/CredentialResolver.h"
-#include "signature/KeyResolver.h"
-#include "signature/Signature.h"
 #include "util/NDC.h"
 #include "util/XMLConstants.h"
 #include "validation/Validator.h"
@@ -179,6 +178,7 @@ bool XMLToolingInternalConfig::init()
         REGISTER_EXCEPTION_FACTORY(SignatureException,xmlsignature);
         registerKeyResolvers();
         registerCredentialResolvers();
+        registerTrustEngines();
 #endif
     }
     catch (const xercesc::XMLException&) {
@@ -198,6 +198,7 @@ void XMLToolingInternalConfig::term()
     XMLToolingException::deregisterFactories();
 
 #ifndef XMLTOOLING_NO_XMLSEC
+    TrustEngineManager.deregisterFactories();
     CredentialResolverManager.deregisterFactories();
     KeyResolverManager.deregisterFactories();
 #endif
index e2845b8..9995cdb 100644 (file)
@@ -40,6 +40,8 @@ namespace xmlsignature {
 #endif\r
 \r
 namespace xmltooling {\r
+    \r
+    class XMLTOOL_API TrustEngine;\r
 \r
     /**\r
      * Singleton object that manages library startup/shutdown.configuration.\r
@@ -133,6 +135,11 @@ namespace xmltooling {
          * Manages factories for CredentialResolver plugins.\r
          */\r
         xmltooling::PluginManager<xmlsignature::CredentialResolver,const DOMElement*> CredentialResolverManager;\r
+\r
+        /**\r
+         * Manages factories for TrustEngine plugins.\r
+         */\r
+        xmltooling::PluginManager<TrustEngine,const DOMElement*> TrustEngineManager;\r
 #endif\r
 \r
     protected:\r
diff --git a/xmltooling/security/TrustEngine.h b/xmltooling/security/TrustEngine.h
new file mode 100644 (file)
index 0000000..e07d062
--- /dev/null
@@ -0,0 +1,118 @@
+/*\r
+ *  Copyright 2001-2006 Internet2\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+/**\r
+ * @file security/TrustEngine.h\r
+ * \r
+ * Evaluates the trustworthiness and validity of XML Signatures against\r
+ * implementation-specific requirements.\r
+ */\r
+\r
+#if !defined(__xmltooling_trust_h__) && !defined(XMLTOOLING_NO_XMLSEC)\r
+#define __xmltooling_trust_h__\r
+\r
+#include <xmltooling/signature/KeyResolver.h>\r
+#include <xmltooling/signature/Signature.h>\r
+\r
+namespace xmltooling {\r
+\r
+    /**\r
+     * Evaluates the trustworthiness and validity of XML Signatures against\r
+     * implementation-specific requirements.\r
+     */\r
+    class XMLTOOL_API TrustEngine {\r
+        MAKE_NONCOPYABLE(TrustEngine);\r
+    protected:\r
+        /**\r
+         * Constructor.\r
+         * \r
+         * If a DOM is supplied, the following XML content is supported:\r
+         * \r
+         * <ul>\r
+         *  <li>&lt;KeyResolver&gt; elements with a type attribute\r
+         * </ul>\r
+         * \r
+         * XML namespaces are ignored in the processing of this content.\r
+         * \r
+         * @param e DOM to supply configuration for provider\r
+         */\r
+        TrustEngine(const DOMElement* e=NULL);\r
+        \r
+        /** Default KeyResolver instance. */\r
+        xmlsignature::KeyResolver* m_keyResolver;\r
+        \r
+    public:\r
+        virtual ~TrustEngine();\r
+        \r
+        /**\r
+         * Callback interface to supply KeyInfo objects to a TrustEngine.\r
+         * Applications can adapt TrustEngines to their environment by supplying\r
+         * implementations of this interface, or create specialized TrustEngine APIs\r
+         * by combining a KeyInfoIterator with a delegated TrustEngine. \r
+         */\r
+        class XMLTOOL_API KeyInfoIterator {\r
+            MAKE_NONCOPYABLE(KeyInfoIterator);\r
+        protected:\r
+            KeyInfoIterator() {}\r
+        public:\r
+            virtual ~KeyInfoIterator() {}\r
+            \r
+            /**\r
+             * Indicates whether additional KeyInfo objects are available.\r
+             * \r
+             * @return true iff another KeyInfo object can be fetched\r
+             */\r
+            virtual bool hasNext() const=0;\r
+            \r
+            /**\r
+             * Returns the next KeyInfo object available.\r
+             * \r
+             * @return the next KeyInfo object, or NULL if none are left\r
+             */\r
+            virtual const xmlsignature::KeyInfo* next()=0;\r
+        };\r
+        \r
+        /**\r
+         * Determines whether a signature is correct and valid with respect to the\r
+         * KeyInfo data supplied. It is the responsibility of the application to\r
+         * ensure that the KeyInfo information supplied is in fact associated with\r
+         * the peer who created the signature. \r
+         * \r
+         * A custom KeyResolver can be supplied from outside the TrustEngine.\r
+         * Alternatively, one may be specified to the plugin constructor.\r
+         * A non-caching, inline resolver will be used as a fallback.\r
+         * \r
+         * @param sig           reference to a signature object to validate\r
+         * @param keyInfoSource supplies KeyInfo objects to the TrustEngine\r
+         * @param keyResolver   optional externally supplied KeyResolver, or NULL\r
+         */\r
+        virtual bool validate(\r
+            xmlsignature::Signature& sig,\r
+            KeyInfoIterator& keyInfoSource,\r
+            const xmlsignature::KeyResolver* keyResolver=NULL\r
+            )=0;\r
+    };\r
+\r
+    /**\r
+     * Registers TrustEngine classes into the runtime.\r
+     */\r
+    void XMLTOOL_API registerTrustEngines();\r
+\r
+    /** TrustEngine based on explicit knowledge of peer key information. */\r
+    #define EXPLICIT_KEY_TRUSTENGINE  "org.opensaml.xmlooling.security.ExplicitKeyTrustEngine"\r
+};\r
+\r
+#endif /* __xmltooling_trust_h__ */\r
diff --git a/xmltooling/security/X509TrustEngine.h b/xmltooling/security/X509TrustEngine.h
new file mode 100644 (file)
index 0000000..b36ff8f
--- /dev/null
@@ -0,0 +1,80 @@
+/*\r
+ *  Copyright 2001-2006 Internet2\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+/**\r
+ * @file security/X509TrustEngine.h\r
+ * \r
+ * Extended TrustEngine interface that adds validation of X.509 credentials.\r
+ */\r
+\r
+#if !defined(__xmltooling_x509trust_h__) && !defined(XMLTOOLING_NO_XMLSEC)\r
+#define __xmltooling_x509trust_h__\r
+\r
+#include <xmltooling/security/TrustEngine.h>\r
+\r
+namespace xmltooling {\r
+\r
+    /**\r
+     * Extended TrustEngine interface that adds validation of X.509 credentials.\r
+     */\r
+    class XMLTOOL_API X509TrustEngine : public TrustEngine {\r
+    protected:\r
+        /**\r
+         * Constructor.\r
+         * \r
+         * If a DOM is supplied, the following XML content is supported:\r
+         * \r
+         * <ul>\r
+         *  <li>&lt;KeyResolver&gt; elements with a type attribute\r
+         * </ul>\r
+         * \r
+         * XML namespaces are ignored in the processing of this content.\r
+         * \r
+         * @param e DOM to supply configuration for provider\r
+         */\r
+        X509TrustEngine(const DOMElement* e=NULL) : TrustEngine(e) {}\r
+        \r
+    public:\r
+        virtual ~X509TrustEngine() {}\r
+        \r
+        /**\r
+         * Determines whether an X.509 credential is valid with respect to the\r
+         * KeyInfo data supplied. It is the responsibility of the application to\r
+         * ensure that the KeyInfo information supplied is in fact associated with\r
+         * the peer who presented the signature. \r
+         * \r
+         * A custom KeyResolver can be supplied from outside the TrustEngine.\r
+         * Alternatively, one may be specified to the plugin constructor.\r
+         * A non-caching, inline resolver will be used as a fallback.\r
+         * \r
+         * @param certEE        end-entity certificate to validate\r
+         * @param certChain     the complete set of certificates presented for validation (includes certEE)\r
+         * @param keyInfoSource supplies KeyInfo objects to the TrustEngine\r
+         * @param checkName     true iff certificate subject/name checking has <b>NOT</b> already occurred\r
+         * @param keyResolver   optional externally supplied KeyResolver, or NULL\r
+         */\r
+        virtual bool validate(\r
+            XSECCryptoX509* certEE,\r
+            const std::vector<XSECCryptoX509*>& certChain,\r
+            TrustEngine::KeyInfoIterator& keyInfoSource,\r
+            bool checkName=true,\r
+            const xmlsignature::KeyResolver* keyResolver=NULL\r
+            )=0;\r
+    };\r
+    \r
+};\r
+\r
+#endif /* __xmltooling_x509trust_h__ */\r
diff --git a/xmltooling/security/impl/ExplicitKeyTrustEngine.cpp b/xmltooling/security/impl/ExplicitKeyTrustEngine.cpp
new file mode 100644 (file)
index 0000000..b6fc513
--- /dev/null
@@ -0,0 +1,160 @@
+/*\r
+ *  Copyright 2001-2005 Internet2\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+/**\r
+ * ExplicitKeyTrustEngine.cpp\r
+ * \r
+ * TrustEngine based on explicit knowledge of peer key information.\r
+ */\r
+\r
+#include "internal.h"\r
+#include "security/X509TrustEngine.h"\r
+#include "signature/SignatureValidator.h"\r
+#include "util/NDC.h"\r
+\r
+#include <log4cpp/Category.hh>\r
+#include <xercesc/util/XMLUniDefs.hpp>\r
+#include <xsec/enc/openssl/OpenSSLCryptoX509.hpp>\r
+\r
+using namespace xmlsignature;\r
+using namespace xmltooling;\r
+using namespace log4cpp;\r
+using namespace std;\r
+\r
+namespace xmltooling {\r
+    class XMLTOOL_DLLLOCAL ExplicitKeyTrustEngine : public X509TrustEngine\r
+    {\r
+    public:\r
+        ExplicitKeyTrustEngine(const DOMElement* e) : X509TrustEngine(e) {}\r
+        virtual ~ExplicitKeyTrustEngine() {}\r
+\r
+        virtual bool validate(\r
+            Signature& sig,\r
+            TrustEngine::KeyInfoIterator& keyInfoSource,\r
+            const KeyResolver* keyResolver=NULL\r
+            );\r
+        virtual bool validate(\r
+            XSECCryptoX509* certEE,\r
+            const vector<XSECCryptoX509*>& certChain,\r
+            TrustEngine::KeyInfoIterator& keyInfoSource,\r
+            bool checkName=true,\r
+            const KeyResolver* keyResolver=NULL\r
+            );\r
+\r
+    private:\r
+    };\r
+\r
+    TrustEngine* XMLTOOL_DLLLOCAL ExplicitKeyTrustEngineFactory(const DOMElement* const & e)\r
+    {\r
+        return new ExplicitKeyTrustEngine(e);\r
+    }\r
+};\r
+\r
+bool ExplicitKeyTrustEngine::validate(\r
+    Signature& sig,\r
+    TrustEngine::KeyInfoIterator& keyInfoSource,\r
+    const KeyResolver* keyResolver\r
+    )\r
+{\r
+#ifdef _DEBUG\r
+    NDC ndc("validate");\r
+#endif\r
+    Category& log=Category::getInstance(XMLTOOLING_LOGCAT".TrustEngine");\r
+    \r
+    if (!keyInfoSource.hasNext()) {\r
+        log.warn("unable to validate signature, no key information available for peer");\r
+        return false;\r
+    }\r
+    \r
+    log.debug("attempting to validate signature with the key information for peer");\r
+    SignatureValidator sigValidator;\r
+    while (keyInfoSource.hasNext()) {\r
+        XSECCryptoKey* key = (keyResolver ? keyResolver : m_keyResolver)->resolveKey(keyInfoSource.next());\r
+        if (key) {\r
+            log.debug("attempting to validate signature with public key...");\r
+            try {\r
+                sigValidator.setKey(key);   // key now owned by validator\r
+                sigValidator.validate(&sig);\r
+                log.info("signature validated with public key");\r
+                return true;\r
+            }\r
+            catch (ValidationException& e) {\r
+                if (log.isDebugEnabled()) {\r
+                    log.debug("public key did not validate signature: %s", e.what());\r
+                }\r
+            }\r
+        }\r
+        else {\r
+            log.debug("key information does not resolve to a public key, skipping it");\r
+        }\r
+    }\r
+\r
+    log.error("no peer key information validated the signature");\r
+    return false;\r
+}\r
+\r
+bool ExplicitKeyTrustEngine::validate(\r
+    XSECCryptoX509* certEE,\r
+    const vector<XSECCryptoX509*>& certChain,\r
+    TrustEngine::KeyInfoIterator& keyInfoSource,\r
+    bool checkName,\r
+    const KeyResolver* keyResolver\r
+    )\r
+{\r
+#ifdef _DEBUG\r
+    NDC ndc("validate");\r
+#endif\r
+    Category& log=Category::getInstance(XMLTOOLING_LOGCAT".TrustEngine");\r
+    \r
+    if (!certEE) {\r
+        log.error("unable to validate, end-entity certificate was null");\r
+        return false;\r
+    }\r
+    else if (certEE->getProviderName()!=DSIGConstants::s_unicodeStrPROVOpenSSL) {\r
+        log.error("only the OpenSSL XSEC provider is supported");\r
+        return false;\r
+    }\r
+    else if (!keyInfoSource.hasNext()) {\r
+        log.warn("unable to validate, no key information available for peer");\r
+        return false;\r
+    }\r
+\r
+    // The new "basic" trust implementation relies solely on certificates living within the\r
+    // role interface to verify the EE certificate.\r
+\r
+    log.debug("attempting to match key information from peer with end-entity certificate");\r
+    vector<XSECCryptoX509*> resolvedCerts;\r
+    while (keyInfoSource.hasNext()) {\r
+        resolvedCerts.clear();\r
+        if (0 == (keyResolver ? keyResolver : m_keyResolver)->resolveCertificates(keyInfoSource.next(),resolvedCerts)) {\r
+            log.debug("key information does not resolve to a certificate, skipping it");\r
+            continue;\r
+        }\r
+\r
+        log.debug("checking if certificates contained within key information match end-entity certificate");\r
+        if (resolvedCerts.front()->getProviderName()!=DSIGConstants::s_unicodeStrPROVOpenSSL) {\r
+            log.error("only the OpenSSL XSEC provider is supported");\r
+            continue;\r
+        }\r
+        else if (!X509_cmp(static_cast<OpenSSLCryptoX509*>(certEE)->getOpenSSLX509(),static_cast<OpenSSLCryptoX509*>(resolvedCerts.front())->getOpenSSLX509())) {\r
+            log.info("end-entity certificate matches certificate from peer key information");\r
+            return true;\r
+        }\r
+    }\r
+\r
+    log.debug("no certificates within this peer's key information matched the given end-entity certificate");\r
+    return false;\r
+}\r
diff --git a/xmltooling/security/impl/TrustEngine.cpp b/xmltooling/security/impl/TrustEngine.cpp
new file mode 100644 (file)
index 0000000..3158fb8
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ *  Copyright 2001-2006 Internet2
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * TrustEngine.cpp
+ * 
+ * Registration of factories for built-in engines
+ */
+
+#include "internal.h"
+#include "security/TrustEngine.h"
+
+#include <xercesc/util/XMLUniDefs.hpp>
+
+using namespace xmltooling;
+using namespace std;
+
+namespace xmltooling {
+    XMLTOOL_DLLLOCAL PluginManager<TrustEngine,const DOMElement*>::Factory ExplicitKeyTrustEngineFactory; 
+};
+
+void XMLTOOL_API xmltooling::registerTrustEngines()
+{
+    XMLToolingConfig& conf=XMLToolingConfig::getConfig();
+    conf.TrustEngineManager.registerFactory(EXPLICIT_KEY_TRUSTENGINE, ExplicitKeyTrustEngineFactory);
+}
+
+static const XMLCh GenericKeyResolver[] =           UNICODE_LITERAL_11(K,e,y,R,e,s,o,l,v,e,r);
+static const XMLCh type[] =                         UNICODE_LITERAL_4(t,y,p,e);
+
+TrustEngine::TrustEngine(const DOMElement* e) : m_keyResolver(NULL)
+{
+    DOMElement* child = e ? XMLHelper::getFirstChildElement(e,GenericKeyResolver) : NULL;
+    if (child) {
+        auto_ptr_char t(child->getAttributeNS(NULL,type));
+        if (t.get())
+            m_keyResolver = XMLToolingConfig::getConfig().KeyResolverManager.newPlugin(t.get(),child);
+        else
+            throw UnknownExtensionException("<KeyResolver> element found with no type attribute");
+    }
+    else if (!m_keyResolver) {
+        m_keyResolver = XMLToolingConfig::getConfig().KeyResolverManager.newPlugin(INLINE_KEY_RESOLVER, child);
+    }
+}
+
+TrustEngine::~TrustEngine()
+{
+    delete m_keyResolver;
+}
index 16dd084..7f7fa7d 100644 (file)
 namespace xmlsignature {\r
 \r
     /**\r
-     * Validator for signatures based on a KeyResolver\r
+     * Validator for signatures based on a Key or a KeyResolver\r
      */\r
-    class XMLTOOL_API SignatureValidator : public virtual xmltooling::Validator\r
+    class XMLTOOL_API SignatureValidator : public xmltooling::Validator\r
     {\r
     public:\r
         /**\r
-         * Constructor\r
+         * Constructor using a KeyResolver\r
          * \r
-         * @param resolver   the key resolver to use, will be freed by Validator\r
+         * @param resolver the key resolver to use, will be freed by Validator\r
          */\r
-        SignatureValidator(KeyResolver* resolver) : m_resolver(resolver) {\r
+        SignatureValidator(KeyResolver* resolver) : m_key(NULL), m_resolver(resolver) {\r
+        }\r
+\r
+        /**\r
+         * Constructor using a Key\r
+         * \r
+         * @param key the verification key to use, will be freed by Validator\r
+         */\r
+        SignatureValidator(XSECCryptoKey* key=NULL) : m_key(key), m_resolver(NULL) {\r
         }\r
         \r
         virtual ~SignatureValidator() {\r
+            delete m_key;\r
             delete m_resolver;\r
         }\r
 \r
-        void validate(const xmltooling::XMLObject* xmlObject) const;\r
+        virtual void validate(const xmltooling::XMLObject* xmlObject) const;\r
 \r
         virtual void validate(const Signature* signature) const;\r
         \r
         /**\r
+         * Replace the current Key, if any, with a new one.\r
+         * \r
+         * @param key  the Key to attach \r
+         */\r
+        void setKey(XSECCryptoKey* key) {\r
+            delete m_key;\r
+            delete m_resolver;\r
+            m_resolver=NULL;\r
+            m_key=key;\r
+        }\r
+\r
+        /**\r
          * Replace the current KeyResolver, if any, with a new one.\r
          * \r
          * @param resolver  the KeyResolver to attach \r
          */\r
         void setKeyResolver(KeyResolver* resolver) {\r
+            delete m_key;\r
             delete m_resolver;\r
+            m_key=NULL;\r
             m_resolver=resolver;\r
         }\r
     \r
     protected:\r
+        XSECCryptoKey* m_key;\r
         KeyResolver* m_resolver;\r
     };\r
 \r
index 9860bce..f897226 100644 (file)
                                        </File>\r
                                </Filter>\r
                        </Filter>\r
+                       <Filter\r
+                               Name="security"\r
+                               >\r
+                               <Filter\r
+                                       Name="impl"\r
+                                       >\r
+                                       <File\r
+                                               RelativePath=".\security\impl\ExplicitKeyTrustEngine.cpp"\r
+                                               >\r
+                                       </File>\r
+                                       <File\r
+                                               RelativePath=".\security\impl\TrustEngine.cpp"\r
+                                               >\r
+                                       </File>\r
+                               </Filter>\r
+                       </Filter>\r
                </Filter>\r
                <Filter\r
                        Name="Header Files"\r
                                        >\r
                                </File>\r
                        </Filter>\r
+                       <Filter\r
+                               Name="security"\r
+                               >\r
+                               <File\r
+                                       RelativePath=".\security\TrustEngine.h"\r
+                                       >\r
+                               </File>\r
+                               <File\r
+                                       RelativePath=".\security\X509TrustEngine.h"\r
+                                       >\r
+                               </File>\r
+                       </Filter>\r
                </Filter>\r
                <Filter\r
                        Name="Resource Files"\r