[xmlsec] added X509Data support to xmlsec-gnutls



commit 178c617e5079774ce7b9dfc72e74596179471b55
Author: Aleksey Sanin <aleksey aleksey com>
Date:   Sun May 23 19:08:25 2010 -0700

    added X509Data support to xmlsec-gnutls

 ChangeLog                         |    3 +
 include/xmlsec/gnutls/Makefile.am |    1 +
 include/xmlsec/gnutls/x509.h      |   99 +++
 src/gnutls/Makefile.am            |    4 +
 src/gnutls/app.c                  |  200 ++++-
 src/gnutls/crypto.c               |   39 +-
 src/gnutls/globals.h              |    3 +
 src/gnutls/x509.c                 | 1644 +++++++++++++++++++++++++++++++++++++
 src/gnutls/x509utils.c            |  562 +++++++++++++
 src/gnutls/x509utils.h            |   65 ++
 src/gnutls/x509vfy.c              |  541 ++++++++++++
 11 files changed, 3128 insertions(+), 33 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index df2422d..08c2365 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,6 @@
+2010-05-23  Aleksey Sanin  <aleksey aleksey com>
+	* Added X509Data support to xmlsec-gnutls
+
 2010-05-12  Aleksey Sanin  <aleksey aleksey com>
 	* Several patches from Roumen: support NSS/NSPR from seamonkey
 	package; reorder libxmlsec as dep. lib for mingw; fix gcrypt/src/asn1.h
diff --git a/include/xmlsec/gnutls/Makefile.am b/include/xmlsec/gnutls/Makefile.am
index 45b03d6..78235c4 100644
--- a/include/xmlsec/gnutls/Makefile.am
+++ b/include/xmlsec/gnutls/Makefile.am
@@ -6,6 +6,7 @@ xmlsecgnutlsinc_HEADERS = \
 app.h \
 crypto.h \
 symbols.h \
+x509.h \
 $(NULL)
 
 install-exec-hook:
diff --git a/include/xmlsec/gnutls/x509.h b/include/xmlsec/gnutls/x509.h
new file mode 100644
index 0000000..f18a864
--- /dev/null
+++ b/include/xmlsec/gnutls/x509.h
@@ -0,0 +1,99 @@
+/**
+ * XMLSec library
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2010 Aleksey Sanin <aleksey aleksey com>
+ */
+#ifndef __XMLSEC_GNUTLS_X509_H__
+#define __XMLSEC_GNUTLS_X509_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#ifndef XMLSEC_NO_X509
+
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/transforms.h>
+
+
+/**************************************************************************
+ *
+ * X509 Key Data
+ *
+ *****************************************************************************/
+/**
+ * xmlSecGnuTLSKeyDataX509Id:
+ *
+ * The GnuTLS X509 data klass.
+ */
+#define xmlSecGnuTLSKeyDataX509Id \
+        xmlSecGnuTLSKeyDataX509GetKlass()
+XMLSEC_CRYPTO_EXPORT xmlSecKeyDataId    xmlSecGnuTLSKeyDataX509GetKlass         (void);
+
+XMLSEC_CRYPTO_EXPORT gnutls_x509_crt_t  xmlSecGnuTLSKeyDataX509GetKeyCert       (xmlSecKeyDataPtr data);
+XMLSEC_CRYPTO_EXPORT int                xmlSecGnuTLSKeyDataX509AdoptKeyCert     (xmlSecKeyDataPtr data,
+                                                                                 gnutls_x509_crt_t cert);
+XMLSEC_CRYPTO_EXPORT int                xmlSecGnuTLSKeyDataX509AdoptCert        (xmlSecKeyDataPtr data,
+                                                                                 gnutls_x509_crt_t cert);
+XMLSEC_CRYPTO_EXPORT gnutls_x509_crt_t  xmlSecGnuTLSKeyDataX509GetCert          (xmlSecKeyDataPtr data,
+                                                                                 xmlSecSize pos);
+XMLSEC_CRYPTO_EXPORT xmlSecSize         xmlSecGnuTLSKeyDataX509GetCertsSize     (xmlSecKeyDataPtr data);
+XMLSEC_CRYPTO_EXPORT xmlSecKeyDataPtr   xmlSecGnuTLSX509CertGetKey              (gnutls_x509_crt_t cert);
+
+/**************************************************************************
+ *
+ * X509 raw cert
+ *
+ *****************************************************************************/
+/**
+ * xmlSecGnuTLSKeyDataRawX509CertId:
+ *
+ * The GnuTLS raw X509 certificate klass.
+ */
+#define xmlSecGnuTLSKeyDataRawX509CertId \
+        xmlSecGnuTLSKeyDataRawX509CertGetKlass()
+XMLSEC_CRYPTO_EXPORT xmlSecKeyDataId    xmlSecGnuTLSKeyDataRawX509CertGetKlass  (void);
+
+/**************************************************************************
+ *
+ * X509 certs store
+ *
+ *****************************************************************************/
+/**
+ * xmlSecGnuTLSX509StoreId:
+ *
+ * The GnuTLS X509 store klass.
+ */
+#define xmlSecGnuTLSX509StoreId \
+        xmlSecGnuTLSX509StoreGetKlass()
+XMLSEC_CRYPTO_EXPORT xmlSecKeyDataStoreId xmlSecGnuTLSX509StoreGetKlass (void);
+XMLSEC_CRYPTO_EXPORT gnutls_x509_crt_t  xmlSecGnuTLSX509StoreFindCert   (const xmlSecKeyDataStorePtr store,
+                                                                         const xmlChar *subjectName,
+                                                                         const xmlChar *issuerName,
+                                                                         const xmlChar *issuerSerial,
+                                                                         const xmlChar *ski,
+                                                                         const xmlSecKeyInfoCtx* keyInfoCtx);
+XMLSEC_CRYPTO_EXPORT gnutls_x509_crt_t  xmlSecGnuTLSX509StoreVerify     (xmlSecKeyDataStorePtr store,
+                                                                         xmlSecPtrListPtr certs,
+                                                                         const xmlSecKeyInfoCtx* keyInfoCtx);
+XMLSEC_CRYPTO_EXPORT int                xmlSecGnuTLSX509StoreAdoptCert  (xmlSecKeyDataStorePtr store,
+                                                                         gnutls_x509_crt_t cert,
+                                                                         xmlSecKeyDataType type);
+
+
+
+
+#endif /* XMLSEC_NO_X509 */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __XMLSEC_GNUTLS_X509_H__ */
diff --git a/src/gnutls/Makefile.am b/src/gnutls/Makefile.am
index bfbf2d8..84ce637 100644
--- a/src/gnutls/Makefile.am
+++ b/src/gnutls/Makefile.am
@@ -29,6 +29,10 @@ libxmlsec1_gnutls_la_SOURCES =\
 	symkeys.c \
 	asymkeys.c \
 	signatures.c \
+	x509utils.h \
+	x509utils.c \
+	x509.c \
+	x509vfy.c \
 	globals.h \
 	$(NULL)
 
diff --git a/src/gnutls/app.c b/src/gnutls/app.c
index d936b8a..f01598b 100644
--- a/src/gnutls/app.c
+++ b/src/gnutls/app.c
@@ -11,6 +11,8 @@
 #include <string.h>
 
 #include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+#include <gnutls/pkcs12.h>
 
 #include <xmlsec/xmlsec.h>
 #include <xmlsec/keys.h>
@@ -41,15 +43,15 @@
  */
 int
 xmlSecGnuTLSAppInit(const char* config) {
-    int ret;
+    int err;
 
-    ret = gnutls_global_init();
-    if(ret != 0) {
+    err = gnutls_global_init();
+    if(err != GNUTLS_E_SUCCESS) {
         xmlSecError(XMLSEC_ERRORS_HERE,
                     NULL,
                     "gnutls_global_init",
                     XMLSEC_ERRORS_R_CRYPTO_FAILED,
-                    "ret=%d", ret);
+                    XMLSEC_GNUTLS_REPORT_ERROR(err));
         return(-1);
     }
 
@@ -89,10 +91,23 @@ xmlSecGnuTLSAppKeyLoad(const char *filename, xmlSecKeyDataFormat format,
                         const char *pwd,
                         void* pwdCallback,
                         void* pwdCallbackCtx) {
+    xmlSecKeyPtr key;
+
     xmlSecAssert2(filename != NULL, NULL);
     xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, NULL);
 
-    return(xmlSecGCryptAppKeyLoad(filename, format, pwd, pwdCallback, pwdCallbackCtx));
+    switch(format) {
+#ifndef XMLSEC_NO_X509
+    case xmlSecKeyDataFormatPkcs12:
+        key = xmlSecGnuTLSAppPkcs12Load(filename, pwd, pwdCallback, pwdCallbackCtx);
+        break;
+#endif /* XMLSEC_NO_X509 */
+    default:
+        key = xmlSecGCryptAppKeyLoad(filename, format, pwd, pwdCallback, pwdCallbackCtx);
+        break;
+    }
+
+    return(key);
 }
 
 /**
@@ -112,10 +127,22 @@ xmlSecKeyPtr
 xmlSecGnuTLSAppKeyLoadMemory(const xmlSecByte* data, xmlSecSize dataSize,
                         xmlSecKeyDataFormat format, const char *pwd,
                         void* pwdCallback, void* pwdCallbackCtx) {
+    xmlSecKeyPtr key;
+
     xmlSecAssert2(data != NULL, NULL);
     xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, NULL);
 
-    return(xmlSecGCryptAppKeyLoadMemory(data, dataSize, format, pwd, pwdCallback, pwdCallbackCtx));
+    switch(format) {
+#ifndef XMLSEC_NO_X509
+    case xmlSecKeyDataFormatPkcs12:
+        key = xmlSecGnuTLSAppPkcs12LoadMemory(data, dataSize, pwd, pwdCallback, pwdCallbackCtx);
+        break;
+#endif /* XMLSEC_NO_X509 */
+    default:
+        key = xmlSecGCryptAppKeyLoadMemory(data, dataSize, format, pwd, pwdCallback, pwdCallbackCtx);
+        break;
+    }
+    return(key);
 }
 
 #ifndef XMLSEC_NO_X509
@@ -133,17 +160,53 @@ xmlSecGnuTLSAppKeyLoadMemory(const xmlSecByte* data, xmlSecSize dataSize,
 int
 xmlSecGnuTLSAppKeyCertLoad(xmlSecKeyPtr key, const char* filename,
                           xmlSecKeyDataFormat format) {
+    xmlSecBuffer buffer;
+    int ret;
+
     xmlSecAssert2(key != NULL, -1);
     xmlSecAssert2(filename != NULL, -1);
     xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1);
 
-    /* TODO */
-    xmlSecError(XMLSEC_ERRORS_HERE,
-                NULL,
-                "xmlSecGnuTLSAppKeyCertLoad",
-                XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
-                XMLSEC_ERRORS_NO_MESSAGE);
-    return(-1);
+    ret = xmlSecBufferInitialize(&buffer, 4*1024);
+    if(ret < 0) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "xmlSecBufferInitialize",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        return(-1);
+    }
+
+    ret = xmlSecBufferReadFile(&buffer, filename);
+    if((ret < 0) || (xmlSecBufferGetData(&buffer) == NULL) || (xmlSecBufferGetSize(&buffer) <= 0)) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "xmlSecBufferReadFile",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    "filename=%s", 
+                    xmlSecErrorsSafeString(filename));
+        xmlSecBufferFinalize(&buffer);
+        return(-1);
+    }
+
+    ret = xmlSecGnuTLSAppKeyCertLoadMemory(key,
+                    xmlSecBufferGetData(&buffer),
+                    xmlSecBufferGetSize(&buffer),
+                    format);
+    if(ret < 0) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "xmlSecGnuTLSAppKeyCertLoadMemory",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    "filename=%s",
+                    xmlSecErrorsSafeString(filename));
+        xmlSecBufferFinalize(&buffer);
+        return(-1);
+    }
+
+    /* cleanup */
+    xmlSecBufferFinalize(&buffer);
+    return(0);
 }
 
 /**
@@ -192,18 +255,54 @@ xmlSecGnuTLSAppKeyCertLoadMemory(xmlSecKeyPtr key,
  */
 xmlSecKeyPtr
 xmlSecGnuTLSAppPkcs12Load(const char *filename,
-                          const char *pwd ATTRIBUTE_UNUSED,
-                          void* pwdCallback ATTRIBUTE_UNUSED,
-                          void* pwdCallbackCtx ATTRIBUTE_UNUSED) {
+                          const char *pwd,
+                          void* pwdCallback,
+                          void* pwdCallbackCtx) {
+    xmlSecKeyPtr key;
+    xmlSecBuffer buffer;
+    int ret;
+
     xmlSecAssert2(filename != NULL, NULL);
 
-    /* TODO */
-    xmlSecError(XMLSEC_ERRORS_HERE,
-                NULL,
-                "xmlSecGnuTLSAppPkcs12Load",
-                XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
-                XMLSEC_ERRORS_NO_MESSAGE);
-    return(NULL);
+    ret = xmlSecBufferInitialize(&buffer, 4*1024);
+    if(ret < 0) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "xmlSecBufferInitialize",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        return(NULL);
+    }
+
+    ret = xmlSecBufferReadFile(&buffer, filename);
+    if((ret < 0) || (xmlSecBufferGetData(&buffer) == NULL) || (xmlSecBufferGetSize(&buffer) <= 0)) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "xmlSecBufferReadFile",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    "filename=%s", 
+                    xmlSecErrorsSafeString(filename));
+        xmlSecBufferFinalize(&buffer);
+        return(NULL);
+    }
+
+    key = xmlSecGnuTLSAppPkcs12LoadMemory(xmlSecBufferGetData(&buffer),
+                    xmlSecBufferGetSize(&buffer),
+                    pwd, pwdCallback, pwdCallbackCtx);
+    if(key == NULL) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "xmlSecGnuTLSAppPkcs12LoadMemory",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    "filename=%s",
+                    xmlSecErrorsSafeString(filename));
+        xmlSecBufferFinalize(&buffer);
+        return(NULL);
+    }
+
+    /* cleanup */
+    xmlSecBufferFinalize(&buffer);
+    return(key);
 }
 
 /**
@@ -251,21 +350,58 @@ xmlSecGnuTLSAppPkcs12LoadMemory(const xmlSecByte* data, xmlSecSize dataSize,
  * Returns: 0 on success or a negative value otherwise.
  */
 int
-xmlSecGnuTLSAppKeysMngrCertLoad(xmlSecKeysMngrPtr mngr, 
+xmlSecGnuTLSAppKeysMngrCertLoad(xmlSecKeysMngrPtr mngr,
                                 const char *filename,
                                 xmlSecKeyDataFormat format,
-                                xmlSecKeyDataType type ATTRIBUTE_UNUSED) {
+                                xmlSecKeyDataType type) {
+    xmlSecBuffer buffer;
+    int ret;
+
     xmlSecAssert2(mngr != NULL, -1);
     xmlSecAssert2(filename != NULL, -1);
     xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1);
 
-    /* TODO */
-    xmlSecError(XMLSEC_ERRORS_HERE,
-                NULL,
-                "xmlSecGnuTLSAppKeysMngrCertLoad",
-                XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
-                XMLSEC_ERRORS_NO_MESSAGE);
-    return(-1);
+    ret = xmlSecBufferInitialize(&buffer, 4*1024);
+    if(ret < 0) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "xmlSecBufferInitialize",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        return(-1);
+    }
+
+    ret = xmlSecBufferReadFile(&buffer, filename);
+    if((ret < 0) || (xmlSecBufferGetData(&buffer) == NULL) || (xmlSecBufferGetSize(&buffer) <= 0)) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "xmlSecBufferReadFile",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    "filename=%s", 
+                    xmlSecErrorsSafeString(filename));
+        xmlSecBufferFinalize(&buffer);
+        return(-1);
+    }
+
+    ret = xmlSecGnuTLSAppKeysMngrCertLoadMemory(mngr,
+                    xmlSecBufferGetData(&buffer),
+                    xmlSecBufferGetSize(&buffer),
+                    format,
+                    type);
+    if(ret < 0) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "xmlSecGnuTLSAppKeysMngrCertLoadMemory",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    "filename=%s",
+                    xmlSecErrorsSafeString(filename));
+        xmlSecBufferFinalize(&buffer);
+        return(-1);
+    }
+
+    /* cleanup */
+    xmlSecBufferFinalize(&buffer);
+    return(0);
 }
 
 /**
diff --git a/src/gnutls/crypto.c b/src/gnutls/crypto.c
index 15f349d..83175e6 100644
--- a/src/gnutls/crypto.c
+++ b/src/gnutls/crypto.c
@@ -21,6 +21,7 @@
 
 #include <xmlsec/gnutls/app.h>
 #include <xmlsec/gnutls/crypto.h>
+#include <xmlsec/gnutls/x509.h>
 
 static xmlSecCryptoDLFunctionsPtr gXmlSecGnuTLSFunctions = NULL;
 
@@ -76,11 +77,19 @@ xmlSecCryptoGetFunctions_gnutls(void) {
     gXmlSecGnuTLSFunctions->keyDataRsaGetKlass          = xmlSecGnuTLSKeyDataRsaGetKlass;
 #endif /* XMLSEC_NO_RSA */
 
+#ifndef XMLSEC_NO_X509
+    gXmlSecGnuTLSFunctions->keyDataX509GetKlass         = xmlSecGnuTLSKeyDataX509GetKlass;
+    gXmlSecGnuTLSFunctions->keyDataRawX509CertGetKlass  = xmlSecGnuTLSKeyDataRawX509CertGetKlass;
+#endif /* XMLSEC_NO_X509 */
+
     /********************************************************************
      *
      * Key data store ids
      *
      ********************************************************************/
+#ifndef XMLSEC_NO_X509
+    gXmlSecGnuTLSFunctions->x509StoreGetKlass           = xmlSecGnuTLSX509StoreGetKlass;
+#endif /* XMLSEC_NO_X509 */
 
     /********************************************************************
      *
@@ -276,9 +285,37 @@ xmlSecGnuTLSShutdown(void) {
  */
 int
 xmlSecGnuTLSKeysMngrInit(xmlSecKeysMngrPtr mngr) {
+    int ret;
+
     xmlSecAssert2(mngr != NULL, -1);
 
-    /* TODO: add key data stores */
+#ifndef XMLSEC_NO_X509
+    /* create x509 store if needed */
+    if(xmlSecKeysMngrGetDataStore(mngr, xmlSecGnuTLSX509StoreId) == NULL) {
+        xmlSecKeyDataStorePtr x509Store;
+
+        x509Store = xmlSecKeyDataStoreCreate(xmlSecGnuTLSX509StoreId);
+        if(x509Store == NULL) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                        NULL,
+                        "xmlSecKeyDataStoreCreate",
+                        XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                        "xmlSecGnuTLSX509StoreId");
+            return(-1);
+        }
+
+        ret = xmlSecKeysMngrAdoptDataStore(mngr, x509Store);
+        if(ret < 0) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                        NULL,
+                        "xmlSecKeysMngrAdoptDataStore",
+                        XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                        XMLSEC_ERRORS_NO_MESSAGE);
+            xmlSecKeyDataStoreDestroy(x509Store);
+            return(-1);
+        }
+    }
+#endif /* XMLSEC_NO_X509 */
     return(0);
 }
 
diff --git a/src/gnutls/globals.h b/src/gnutls/globals.h
index 8436900..b49e240 100644
--- a/src/gnutls/globals.h
+++ b/src/gnutls/globals.h
@@ -24,5 +24,8 @@
 #define XMLSEC_GNUTLS_GCRYPT_REPORT_ERROR(err)  \
         "error code=%d; error message='%s'",    \
         (int)err, xmlSecErrorsSafeString(gcry_strerror((err)))
+#define XMLSEC_GNUTLS_REPORT_ERROR(err)         \
+        "error code=%d; error message='%s'",    \
+        (int)err, xmlSecErrorsSafeString(gnutls_strerror((err)))
 
 #endif /* ! __XMLSEC_GLOBALS_H__ */
diff --git a/src/gnutls/x509.c b/src/gnutls/x509.c
new file mode 100644
index 0000000..970f5f3
--- /dev/null
+++ b/src/gnutls/x509.c
@@ -0,0 +1,1644 @@
+/**
+ * XMLSec library
+ *
+ * X509 support
+ *
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2010 Aleksey Sanin <aleksey aleksey com>
+ */
+#include "globals.h"
+
+#ifndef XMLSEC_NO_X509
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <time.h>
+
+#include <libxml/tree.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/keyinfo.h>
+#include <xmlsec/keysmngr.h>
+#include <xmlsec/x509.h>
+#include <xmlsec/base64.h>
+#include <xmlsec/errors.h>
+#include <xmlsec/private.h>
+
+#include <xmlsec/gnutls/crypto.h>
+#include <xmlsec/gnutls/x509.h>
+
+#include "x509utils.h"
+
+/*************************************************************************
+ *
+ * X509 utility functions
+ *
+ ************************************************************************/
+static int              xmlSecGnuTLSX509DataNodeRead            (xmlSecKeyDataPtr data,
+                                                                 xmlNodePtr node,
+                                                                 xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int              xmlSecGnuTLSX509CertificateNodeRead     (xmlSecKeyDataPtr data,
+                                                                 xmlNodePtr node,
+                                                                 xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int              xmlSecGnuTLSX509CertificateNodeWrite    (gnutls_x509_crt_t cert,
+                                                                 xmlNodePtr node,
+                                                                 xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int              xmlSecGnuTLSX509SubjectNameNodeRead     (xmlSecKeyDataPtr data,
+                                                                 xmlNodePtr node,
+                                                                 xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int              xmlSecGnuTLSX509SubjectNameNodeWrite    (gnutls_x509_crt_t cert,
+                                                                 xmlNodePtr node,
+                                                                 xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int              xmlSecGnuTLSX509IssuerSerialNodeRead    (xmlSecKeyDataPtr data,
+                                                                 xmlNodePtr node,
+                                                                 xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int              xmlSecGnuTLSX509IssuerSerialNodeWrite   (gnutls_x509_crt_t cert,
+                                                                 xmlNodePtr node,
+                                                                 xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int              xmlSecGnuTLSX509SKINodeRead             (xmlSecKeyDataPtr data,
+                                                                 xmlNodePtr node,
+                                                                 xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int              xmlSecGnuTLSX509SKINodeWrite            (gnutls_x509_crt_t cert,
+                                                                 xmlNodePtr node,
+                                                                 xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int              xmlSecGnuTLSKeyDataX509VerifyAndExtractKey(xmlSecKeyDataPtr data,
+                                                                 xmlSecKeyPtr key,
+                                                                 xmlSecKeyInfoCtxPtr keyInfoCtx);
+
+/*************************************************************************
+ *
+ * Internal GnuTLS X509 data CTX
+ *
+ ************************************************************************/
+typedef struct _xmlSecGnuTLSX509DataCtx                         xmlSecGnuTLSX509DataCtx,
+                                                                *xmlSecGnuTLSX509DataCtxPtr;
+struct _xmlSecGnuTLSX509DataCtx {
+    gnutls_x509_crt_t   keyCert;
+    xmlSecPtrList       certsList;
+};
+
+
+/**************************************************************************
+ *
+ * <dsig:X509Data> processing
+ *
+ *
+ * The X509Data  Element (http://www.w3.org/TR/xmldsig-core/#sec-X509Data)
+ *
+ * An X509Data element within KeyInfo contains one or more identifiers of keys
+ * or X509 certificates (or certificates' identifiers or a revocation list).
+ * The content of X509Data is:
+ *
+ *  1. At least one element, from the following set of element types; any of these may appear together or more than once iff (if and only if) each instance describes or is related to the same certificate:
+ *  2.
+ *    * The X509IssuerSerial element, which contains an X.509 issuer
+ *      distinguished name/serial number pair that SHOULD be compliant
+ *      with RFC2253 [LDAP-DN],
+ *    * The X509SubjectName element, which contains an X.509 subject
+ *      distinguished name that SHOULD be compliant with RFC2253 [LDAP-DN],
+ *    * The X509SKI element, which contains the base64 encoded plain (i.e.
+ *      non-DER-encoded) value of a X509 V.3 SubjectKeyIdentifier extension.
+ *    * The X509Certificate element, which contains a base64-encoded [X509v3]
+ *      certificate, and
+ *    * Elements from an external namespace which accompanies/complements any
+ *      of the elements above.
+ *    * The X509CRL element, which contains a base64-encoded certificate
+ *      revocation list (CRL) [X509v3].
+ *
+ * Any X509IssuerSerial, X509SKI, and X509SubjectName elements that appear
+ * MUST refer to the certificate or certificates containing the validation key.
+ * All such elements that refer to a particular individual certificate MUST be
+ * grouped inside a single X509Data element and if the certificate to which
+ * they refer appears, it MUST also be in that X509Data element.
+ *
+ * Any X509IssuerSerial, X509SKI, and X509SubjectName elements that relate to
+ * the same key but different certificates MUST be grouped within a single
+ * KeyInfo but MAY occur in multiple X509Data elements.
+ *
+ * All certificates appearing in an X509Data element MUST relate to the
+ * validation key by either containing it or being part of a certification
+ * chain that terminates in a certificate containing the validation key.
+ *
+ * No ordering is implied by the above constraints.
+ *
+ * Note, there is no direct provision for a PKCS#7 encoded "bag" of
+ * certificates or CRLs. However, a set of certificates and CRLs can occur
+ * within an X509Data element and multiple X509Data elements can occur in a
+ * KeyInfo. Whenever multiple certificates occur in an X509Data element, at
+ * least one such certificate must contain the public key which verifies the
+ * signature.
+ *
+ * Schema Definition
+ *
+ *  <element name="X509Data" type="ds:X509DataType"/>
+ *  <complexType name="X509DataType">
+ *    <sequence maxOccurs="unbounded">
+ *      <choice>
+ *        <element name="X509IssuerSerial" type="ds:X509IssuerSerialType"/>
+ *        <element name="X509SKI" type="base64Binary"/>
+ *        <element name="X509SubjectName" type="string"/>
+ *        <element name="X509Certificate" type="base64Binary"/>
+ *        <element name="X509CRL" type="base64Binary"/>
+ *        <any namespace="##other" processContents="lax"/>
+ *      </choice>
+ *    </sequence>
+ *  </complexType>
+ *  <complexType name="X509IssuerSerialType">
+ *    <sequence>
+ *       <element name="X509IssuerName" type="string"/>
+ *       <element name="X509SerialNumber" type="integer"/>
+ *     </sequence>
+ *  </complexType>
+ *
+ *  DTD
+ *
+ *    <!ELEMENT X509Data ((X509IssuerSerial | X509SKI | X509SubjectName |
+ *                          X509Certificate | X509CRL)+ %X509.ANY;)>
+ *    <!ELEMENT X509IssuerSerial (X509IssuerName, X509SerialNumber) >
+ *    <!ELEMENT X509IssuerName (#PCDATA) >
+ *    <!ELEMENT X509SubjectName (#PCDATA) >
+ *    <!ELEMENT X509SerialNumber (#PCDATA) >
+ *    <!ELEMENT X509SKI (#PCDATA) >
+ *    <!ELEMENT X509Certificate (#PCDATA) >
+ *    <!ELEMENT X509CRL (#PCDATA) >
+ *
+ * -----------------------------------------------------------------------
+ *
+ * xmlSecGnuTLSX509DataCtx is located after xmlSecTransform
+ *
+ *************************************************************************/
+#define xmlSecGnuTLSX509DataSize       \
+    (sizeof(xmlSecKeyData) + sizeof(xmlSecGnuTLSX509DataCtx))
+#define xmlSecGnuTLSX509DataGetCtx(data) \
+    ((xmlSecGnuTLSX509DataCtxPtr)(((xmlSecByte*)(data)) + sizeof(xmlSecKeyData)))
+
+static int              xmlSecGnuTLSKeyDataX509Initialize      (xmlSecKeyDataPtr data);
+static int              xmlSecGnuTLSKeyDataX509Duplicate       (xmlSecKeyDataPtr dst,
+                                                                 xmlSecKeyDataPtr src);
+static void             xmlSecGnuTLSKeyDataX509Finalize        (xmlSecKeyDataPtr data);
+static int              xmlSecGnuTLSKeyDataX509XmlRead         (xmlSecKeyDataId id,
+                                                                 xmlSecKeyPtr key,
+                                                                 xmlNodePtr node,
+                                                                 xmlSecKeyInfoCtxPtr keyInfoCtx);
+static int              xmlSecGnuTLSKeyDataX509XmlWrite        (xmlSecKeyDataId id,
+                                                                 xmlSecKeyPtr key,
+                                                                 xmlNodePtr node,
+                                                                 xmlSecKeyInfoCtxPtr keyInfoCtx);
+static xmlSecKeyDataType xmlSecGnuTLSKeyDataX509GetType        (xmlSecKeyDataPtr data);
+static const xmlChar*   xmlSecGnuTLSKeyDataX509GetIdentifier   (xmlSecKeyDataPtr data);
+
+static void             xmlSecGnuTLSKeyDataX509DebugDump       (xmlSecKeyDataPtr data,
+                                                                 FILE* output);
+static void             xmlSecGnuTLSKeyDataX509DebugXmlDump    (xmlSecKeyDataPtr data,
+                                                                 FILE* output);
+
+
+
+static xmlSecKeyDataKlass xmlSecGnuTLSKeyDataX509Klass = {
+    sizeof(xmlSecKeyDataKlass),
+    xmlSecGnuTLSX509DataSize,
+
+    /* data */
+    xmlSecNameX509Data,
+    xmlSecKeyDataUsageKeyInfoNode | xmlSecKeyDataUsageRetrievalMethodNodeXml,
+                                                /* xmlSecKeyDataUsage usage; */
+    xmlSecHrefX509Data,                         /* const xmlChar* href; */
+    xmlSecNodeX509Data,                         /* const xmlChar* dataNodeName; */
+    xmlSecDSigNs,                               /* const xmlChar* dataNodeNs; */
+
+    /* constructors/destructor */
+    xmlSecGnuTLSKeyDataX509Initialize,         /* xmlSecKeyDataInitializeMethod initialize; */
+    xmlSecGnuTLSKeyDataX509Duplicate,          /* xmlSecKeyDataDuplicateMethod duplicate; */
+    xmlSecGnuTLSKeyDataX509Finalize,           /* xmlSecKeyDataFinalizeMethod finalize; */
+    NULL,                                       /* xmlSecKeyDataGenerateMethod generate; */
+
+    /* get info */
+    xmlSecGnuTLSKeyDataX509GetType,            /* xmlSecKeyDataGetTypeMethod getType; */
+    NULL,                                       /* xmlSecKeyDataGetSizeMethod getSize; */
+    xmlSecGnuTLSKeyDataX509GetIdentifier,      /* xmlSecKeyDataGetIdentifier getIdentifier; */
+
+    /* read/write */
+    xmlSecGnuTLSKeyDataX509XmlRead,            /* xmlSecKeyDataXmlReadMethod xmlRead; */
+    xmlSecGnuTLSKeyDataX509XmlWrite,           /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
+    NULL,                                       /* xmlSecKeyDataBinReadMethod binRead; */
+    NULL,                                       /* xmlSecKeyDataBinWriteMethod binWrite; */
+
+    /* debug */
+    xmlSecGnuTLSKeyDataX509DebugDump,          /* xmlSecKeyDataDebugDumpMethod debugDump; */
+    xmlSecGnuTLSKeyDataX509DebugXmlDump,       /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
+
+    /* reserved for the future */
+    NULL,                                       /* void* reserved0; */
+    NULL,                                       /* void* reserved1; */
+};
+
+/**
+ * xmlSecGnuTLSKeyDataX509GetKlass:
+ *
+ * The GnuTLS X509 key data klass (http://www.w3.org/TR/xmldsig-core/#sec-X509Data).
+ *
+ * Returns: the X509 data klass.
+ */
+xmlSecKeyDataId
+xmlSecGnuTLSKeyDataX509GetKlass(void) {
+    return(&xmlSecGnuTLSKeyDataX509Klass);
+}
+
+/**
+ * xmlSecGnuTLSKeyDataX509GetKeyCert:
+ * @data:               the pointer to X509 key data.
+ *
+ * Gets the certificate from which the key was extracted.
+ *
+ * Returns: the key's certificate or NULL if key data was not used for key
+ * extraction or an error occurs.
+ */
+gnutls_x509_crt_t
+xmlSecGnuTLSKeyDataX509GetKeyCert(xmlSecKeyDataPtr data) {
+    xmlSecGnuTLSX509DataCtxPtr ctx;
+
+    xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGnuTLSKeyDataX509Id), NULL);
+
+    ctx = xmlSecGnuTLSX509DataGetCtx(data);
+    xmlSecAssert2(ctx != NULL, NULL);
+
+    return(ctx->keyCert);
+}
+
+/**
+ * xmlSecGnuTLSKeyDataX509AdoptKeyCert:
+ * @data:               the pointer to X509 key data.
+ * @cert:               the pointer to GnuTLS X509 certificate.
+ *
+ * Sets the key's certificate in @data.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecGnuTLSKeyDataX509AdoptKeyCert(xmlSecKeyDataPtr data, gnutls_x509_crt_t cert) {
+    xmlSecGnuTLSX509DataCtxPtr ctx;
+
+    xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGnuTLSKeyDataX509Id), -1);
+    xmlSecAssert2(cert != NULL, -1);
+
+    ctx = xmlSecGnuTLSX509DataGetCtx(data);
+    xmlSecAssert2(ctx != NULL, -1);
+
+    if(ctx->keyCert != NULL) {
+        gnutls_x509_crt_deinit(ctx->keyCert);
+    }
+    ctx->keyCert = cert;
+    return(0);
+}
+
+/**
+ * xmlSecGnuTLSKeyDataX509AdoptCert:
+ * @data:               the pointer to X509 key data.
+ * @cert:               the pointer to GnuTLS X509 certificate.
+ *
+ * Adds certificate to the X509 key data.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecGnuTLSKeyDataX509AdoptCert(xmlSecKeyDataPtr data, gnutls_x509_crt_t cert) {
+    xmlSecGnuTLSX509DataCtxPtr ctx;
+    int ret;
+
+    xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGnuTLSKeyDataX509Id), -1);
+    xmlSecAssert2(cert != NULL, -1);
+
+    ctx = xmlSecGnuTLSX509DataGetCtx(data);
+    xmlSecAssert2(ctx != NULL, -1);
+
+    ret = xmlSecPtrListAdd(&(ctx->certsList), cert);
+    if(ret < 0) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+                    "xmlSecPtrListAdd",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        return(-1);
+    }
+
+    return(0);
+}
+
+/**
+ * xmlSecGnuTLSKeyDataX509GetCert:
+ * @data:               the pointer to X509 key data.
+ * @pos:                the desired certificate position.
+ *
+ * Gets a certificate from X509 key data.
+ *
+ * Returns: the pointer to certificate or NULL if @pos is larger than the
+ * number of certificates in @data or an error occurs.
+ */
+gnutls_x509_crt_t
+xmlSecGnuTLSKeyDataX509GetCert(xmlSecKeyDataPtr data, xmlSecSize pos) {
+    xmlSecGnuTLSX509DataCtxPtr ctx;
+
+    xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGnuTLSKeyDataX509Id), NULL);
+
+    ctx = xmlSecGnuTLSX509DataGetCtx(data);
+    xmlSecAssert2(ctx != NULL, NULL);
+
+    return(xmlSecPtrListGetItem(&(ctx->certsList), pos));
+}
+
+/**
+ * xmlSecGnuTLSKeyDataX509GetCertsSize:
+ * @data:               the pointer to X509 key data.
+ *
+ * Gets the number of certificates in @data.
+ *
+ * Returns: te number of certificates in @data.
+ */
+xmlSecSize
+xmlSecGnuTLSKeyDataX509GetCertsSize(xmlSecKeyDataPtr data) {
+    xmlSecGnuTLSX509DataCtxPtr ctx;
+
+    xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGnuTLSKeyDataX509Id), 0);
+
+    ctx = xmlSecGnuTLSX509DataGetCtx(data);
+    xmlSecAssert2(ctx != NULL, 0);
+
+    return(xmlSecPtrListGetSize(&(ctx->certsList)));
+}
+
+static int
+xmlSecGnuTLSKeyDataX509Initialize(xmlSecKeyDataPtr data) {
+    xmlSecGnuTLSX509DataCtxPtr ctx;
+    int ret;
+
+    xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGnuTLSKeyDataX509Id), -1);
+
+    ctx = xmlSecGnuTLSX509DataGetCtx(data);
+    xmlSecAssert2(ctx != NULL, -1);
+
+    memset(ctx, 0, sizeof(xmlSecGnuTLSX509DataCtx));
+
+    ret = xmlSecPtrListInitialize(&(ctx->certsList), xmlSecGnuTLSX509CrtListId);
+    if(ret < 0) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+                    "xmlSecPtrListInitialize",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    "certsList");
+        return(-1);
+    }
+
+    return(0);
+}
+
+static int
+xmlSecGnuTLSKeyDataX509Duplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) {
+    xmlSecGnuTLSX509DataCtxPtr ctxSrc;
+    xmlSecGnuTLSX509DataCtxPtr ctxDst;
+    int ret;
+
+    xmlSecAssert2(xmlSecKeyDataCheckId(dst, xmlSecGnuTLSKeyDataX509Id), -1);
+    xmlSecAssert2(xmlSecKeyDataCheckId(src, xmlSecGnuTLSKeyDataX509Id), -1);
+
+    ctxSrc = xmlSecGnuTLSX509DataGetCtx(src);
+    xmlSecAssert2(ctxSrc != NULL, 0);
+    ctxDst = xmlSecGnuTLSX509DataGetCtx(dst);
+    xmlSecAssert2(ctxDst != NULL, 0);
+
+    /* copy key cert if exist */
+    if(ctxDst->keyCert != NULL) {
+        gnutls_x509_crt_deinit(ctxDst->keyCert);
+        ctxDst->keyCert = NULL;
+    }
+    if(ctxSrc->keyCert != NULL) {
+        ctxDst->keyCert = xmlSecGnuTLSX509CertDup(ctxSrc->keyCert);
+        if(ctxDst->keyCert == NULL) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                        xmlSecErrorsSafeString(xmlSecKeyDataGetName(src)),
+                        "xmlSecGnuTLSX509CertDup",
+                        XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                        XMLSEC_ERRORS_NO_MESSAGE);
+            return(-1);
+        }
+    }
+
+    /* copy certsList if exists */
+    xmlSecPtrListEmpty(&(ctxDst->certsList));
+    ret = xmlSecPtrListCopy(&(ctxDst->certsList), &(ctxSrc->certsList));
+    if(ret < 0) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    xmlSecErrorsSafeString(xmlSecKeyDataGetName(src)),
+                    "xmlSecPtrListCopy",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    "certsList");
+        return(-1);
+    }
+
+    /* done */
+    return(0);
+}
+
+static void
+xmlSecGnuTLSKeyDataX509Finalize(xmlSecKeyDataPtr data) {
+    xmlSecGnuTLSX509DataCtxPtr ctx;
+
+    xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecGnuTLSKeyDataX509Id));
+
+    ctx = xmlSecGnuTLSX509DataGetCtx(data);
+    xmlSecAssert(ctx != NULL);
+
+    xmlSecPtrListFinalize(&(ctx->certsList));
+    if(ctx->keyCert != NULL) {
+        gnutls_x509_crt_deinit(ctx->keyCert);
+    }
+    memset(ctx, 0, sizeof(xmlSecGnuTLSX509DataCtx));
+}
+
+static int
+xmlSecGnuTLSKeyDataX509XmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key,
+                                xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+    xmlSecKeyDataPtr data;
+    int ret;
+
+    xmlSecAssert2(id == xmlSecGnuTLSKeyDataX509Id, -1);
+    xmlSecAssert2(key != NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+    xmlSecAssert2(keyInfoCtx != NULL, -1);
+
+    data = xmlSecKeyEnsureData(key, id);
+    if(data == NULL) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+                    "xmlSecKeyEnsureData",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        return(-1);
+    }
+
+    ret = xmlSecGnuTLSX509DataNodeRead(data, node, keyInfoCtx);
+    if(ret < 0) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+                    "xmlSecGnuTLSX509DataNodeRead",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        return(-1);
+    }
+
+    if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_X509DATA_DONT_VERIFY_CERTS) == 0) {
+        ret = xmlSecGnuTLSKeyDataX509VerifyAndExtractKey(data, key, keyInfoCtx);
+        if(ret < 0) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                        xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+                        "xmlSecGnuTLSKeyDataX509VerifyAndExtractKey",
+                        XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                        XMLSEC_ERRORS_NO_MESSAGE);
+            return(-1);
+        }
+    }
+    return(0);
+}
+
+static int
+xmlSecGnuTLSKeyDataX509XmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key,
+                                xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+    xmlSecKeyDataPtr data;
+    gnutls_x509_crt_t cert;
+    xmlSecSize size, pos;
+    int content;
+    int ret;
+
+    xmlSecAssert2(id == xmlSecGnuTLSKeyDataX509Id, -1);
+    xmlSecAssert2(key != NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+    xmlSecAssert2(keyInfoCtx != NULL, -1);
+
+    content = xmlSecX509DataGetNodeContent (node, 1, keyInfoCtx);
+    if (content < 0) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+                    "xmlSecX509DataGetNodeContent",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    "content=%d", content);
+        return(-1);
+    } else if(content == 0) {
+        /* by default we are writing certificates and crls */
+        content = XMLSEC_X509DATA_DEFAULT;
+    }
+
+    /* get x509 data */
+    data = xmlSecKeyGetData(key, id);
+    if(data == NULL) {
+        /* no x509 data in the key */
+        return(0);
+    }
+
+    /* write certs */
+    size = xmlSecGnuTLSKeyDataX509GetCertsSize(data);
+    for(pos = 0; pos < size; ++pos) {
+        cert = xmlSecGnuTLSKeyDataX509GetCert(data, pos);
+        if(cert == NULL) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                        xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+                        "xmlSecGnuTLSKeyDataX509GetCert",
+                        XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                        "pos=%d", pos);
+            return(-1);
+        }
+
+        if((content & XMLSEC_X509DATA_CERTIFICATE_NODE) != 0) {
+            ret = xmlSecGnuTLSX509CertificateNodeWrite(cert, node, keyInfoCtx);
+            if(ret < 0) {
+                xmlSecError(XMLSEC_ERRORS_HERE,
+                            xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+                            "xmlSecGnuTLSX509CertificateNodeWrite",
+                            XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                            "pos=%d", pos);
+                return(-1);
+            }
+        }
+
+        if((content & XMLSEC_X509DATA_SUBJECTNAME_NODE) != 0) {
+            ret = xmlSecGnuTLSX509SubjectNameNodeWrite(cert, node, keyInfoCtx);
+            if(ret < 0) {
+                xmlSecError(XMLSEC_ERRORS_HERE,
+                            xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+                            "xmlSecGnuTLSX509SubjectNameNodeWrite",
+                            XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                            "pos=%d", pos);
+                return(-1);
+            }
+        }
+
+        if((content & XMLSEC_X509DATA_ISSUERSERIAL_NODE) != 0) {
+            ret = xmlSecGnuTLSX509IssuerSerialNodeWrite(cert, node, keyInfoCtx);
+            if(ret < 0) {
+                xmlSecError(XMLSEC_ERRORS_HERE,
+                            xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+                            "xmlSecGnuTLSX509IssuerSerialNodeWrite",
+                            XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                            "pos=%d", pos);
+                return(-1);
+            }
+        }
+
+        if((content & XMLSEC_X509DATA_SKI_NODE) != 0) {
+            ret = xmlSecGnuTLSX509SKINodeWrite(cert, node, keyInfoCtx);
+            if(ret < 0) {
+                xmlSecError(XMLSEC_ERRORS_HERE,
+                            xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+                            "xmlSecGnuTLSX509SKINodeWrite",
+                            XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                            "pos=%d", pos);
+                return(-1);
+            }
+        }
+    }
+
+    return(0);
+}
+
+
+static xmlSecKeyDataType
+xmlSecGnuTLSKeyDataX509GetType(xmlSecKeyDataPtr data) {
+    xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGnuTLSKeyDataX509Id), xmlSecKeyDataTypeUnknown);
+
+    /* TODO: return verified/not verified status */
+    return(xmlSecKeyDataTypeUnknown);
+}
+
+static const xmlChar*
+xmlSecGnuTLSKeyDataX509GetIdentifier(xmlSecKeyDataPtr data) {
+    xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGnuTLSKeyDataX509Id), NULL);
+
+    /* TODO */
+    return(NULL);
+}
+
+static void
+xmlSecGnuTLSKeyDataX509DebugDump(xmlSecKeyDataPtr data, FILE* output) {
+    gnutls_x509_crt_t cert;
+    xmlSecSize size, pos;
+
+    xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecGnuTLSKeyDataX509Id));
+    xmlSecAssert(output != NULL);
+
+    fprintf(output, "=== X509 Data:\n");
+    cert = xmlSecGnuTLSKeyDataX509GetKeyCert(data);
+    if(cert != NULL) {
+        fprintf(output, "==== Key Certificate:\n");
+        xmlSecGnuTLSX509CertDebugDump(cert, output);
+    }
+
+    size = xmlSecGnuTLSKeyDataX509GetCertsSize(data);
+    for(pos = 0; pos < size; ++pos) {
+        cert = xmlSecGnuTLSKeyDataX509GetCert(data, pos);
+        if(cert == NULL) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                        xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+                        "xmlSecGnuTLSKeyDataX509GetCert",
+                        XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                        "pos=%d", pos);
+            return;
+        }
+        fprintf(output, "==== Certificate:\n");
+        xmlSecGnuTLSX509CertDebugDump(cert, output);
+    }
+
+    /* we don't print out crls */
+}
+
+static void
+xmlSecGnuTLSKeyDataX509DebugXmlDump(xmlSecKeyDataPtr data, FILE* output) {
+    gnutls_x509_crt_t cert;
+    xmlSecSize size, pos;
+
+    xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecGnuTLSKeyDataX509Id));
+    xmlSecAssert(output != NULL);
+
+    fprintf(output, "<X509Data>\n");
+    cert = xmlSecGnuTLSKeyDataX509GetKeyCert(data);
+    if(cert != NULL) {
+        fprintf(output, "<KeyCertificate>\n");
+        xmlSecGnuTLSX509CertDebugXmlDump(cert, output);
+        fprintf(output, "</KeyCertificate>\n");
+    }
+
+    size = xmlSecGnuTLSKeyDataX509GetCertsSize(data);
+    for(pos = 0; pos < size; ++pos) {
+        cert = xmlSecGnuTLSKeyDataX509GetCert(data, pos);
+        if(cert == NULL) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                        xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+                        "xmlSecGnuTLSKeyDataX509GetCert",
+                        XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                        "pos=%d", pos);
+            return;
+        }
+        fprintf(output, "<Certificate>\n");
+        xmlSecGnuTLSX509CertDebugXmlDump(cert, output);
+        fprintf(output, "</Certificate>\n");
+    }
+
+    /* we don't print out crls */
+    fprintf(output, "</X509Data>\n");
+}
+
+static int
+xmlSecGnuTLSX509DataNodeRead(xmlSecKeyDataPtr data, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+    xmlNodePtr cur;
+    int ret;
+
+    xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGnuTLSKeyDataX509Id), -1);
+    xmlSecAssert2(node != NULL, -1);
+    xmlSecAssert2(keyInfoCtx != NULL, -1);
+
+    for(cur = xmlSecGetNextElementNode(node->children);
+        cur != NULL;
+        cur = xmlSecGetNextElementNode(cur->next)) {
+
+        ret = 0;
+        if(xmlSecCheckNodeName(cur, xmlSecNodeX509Certificate, xmlSecDSigNs)) {
+            ret = xmlSecGnuTLSX509CertificateNodeRead(data, cur, keyInfoCtx);
+        } else if(xmlSecCheckNodeName(cur, xmlSecNodeX509SubjectName, xmlSecDSigNs)) {
+            ret = xmlSecGnuTLSX509SubjectNameNodeRead(data, cur, keyInfoCtx);
+        } else if(xmlSecCheckNodeName(cur, xmlSecNodeX509IssuerSerial, xmlSecDSigNs)) {
+            ret = xmlSecGnuTLSX509IssuerSerialNodeRead(data, cur, keyInfoCtx);
+        } else if(xmlSecCheckNodeName(cur, xmlSecNodeX509SKI, xmlSecDSigNs)) {
+            ret = xmlSecGnuTLSX509SKINodeRead(data, cur, keyInfoCtx);
+        } else if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_X509DATA_STOP_ON_UNKNOWN_CHILD) != 0) {
+            /* laxi schema validation: ignore unknown nodes */
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                        xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+                        xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+                        XMLSEC_ERRORS_R_UNEXPECTED_NODE,
+                        XMLSEC_ERRORS_NO_MESSAGE);
+            return(-1);
+        }
+        if(ret < 0) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                        xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+                        xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+                        XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                        "read node failed");
+            return(-1);
+        }
+    }
+    return(0);
+}
+
+static int
+xmlSecGnuTLSX509CertificateNodeRead(xmlSecKeyDataPtr data, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+    xmlChar *content;
+    gnutls_x509_crt_t cert;
+    int ret;
+
+    xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGnuTLSKeyDataX509Id), -1);
+    xmlSecAssert2(node != NULL, -1);
+    xmlSecAssert2(keyInfoCtx != NULL, -1);
+
+    content = xmlNodeGetContent(node);
+    if((content == NULL) || (xmlSecIsEmptyString(content) == 1)) {
+        if(content != NULL) {
+            xmlFree(content);
+        }
+        if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_STOP_ON_EMPTY_NODE) != 0) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                        xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+                        xmlSecErrorsSafeString(xmlSecNodeGetName(node)),
+                        XMLSEC_ERRORS_R_INVALID_NODE_CONTENT,
+                        XMLSEC_ERRORS_NO_MESSAGE);
+            return(-1);
+        }
+        return(0);
+    }
+
+    cert = xmlSecGnuTLSX509CertBase64DerRead(content);
+    if(cert == NULL) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+                    "xmlSecGnuTLSX509CertBase64DerRead",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        xmlFree(content);
+        return(-1);
+    }
+
+    ret = xmlSecGnuTLSKeyDataX509AdoptCert(data, cert);
+    if(ret < 0) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+                    "xmlSecGnuTLSKeyDataX509AdoptCert",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        gnutls_x509_crt_deinit(cert);
+        xmlFree(content);
+        return(-1);
+    }
+
+    xmlFree(content);
+    return(0);
+}
+
+static int
+xmlSecGnuTLSX509CertificateNodeWrite(gnutls_x509_crt_t cert, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+    xmlChar* buf;
+    xmlNodePtr cur;
+
+    xmlSecAssert2(cert != NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+    xmlSecAssert2(keyInfoCtx != NULL, -1);
+
+    /* set base64 lines size from context */
+    buf = xmlSecGnuTLSX509CertBase64DerWrite(cert, keyInfoCtx->base64LineSize);
+    if(buf == NULL) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "xmlSecGnuTLSX509CertBase64DerWrite",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        return(-1);
+    }
+
+    cur = xmlSecAddChild(node, xmlSecNodeX509Certificate, xmlSecDSigNs);
+    if(cur == NULL) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "xmlSecAddChild",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    "node=%s",
+                    xmlSecErrorsSafeString(xmlSecNodeX509Certificate));
+        xmlFree(buf);
+        return(-1);
+    }
+
+    /* todo: add \n around base64 data - from context */
+    /* todo: add errors check */
+    xmlNodeSetContent(cur, xmlSecStringCR);
+    xmlNodeSetContent(cur, buf);
+    xmlFree(buf);
+    return(0);
+}
+
+static int
+xmlSecGnuTLSX509SubjectNameNodeRead(xmlSecKeyDataPtr data, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+    xmlSecKeyDataStorePtr x509Store;
+    xmlChar* subject;
+    gnutls_x509_crt_t cert;
+    gnutls_x509_crt_t cert2;
+    int ret;
+
+    xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGnuTLSKeyDataX509Id), -1);
+    xmlSecAssert2(node != NULL, -1);
+    xmlSecAssert2(keyInfoCtx != NULL, -1);
+    xmlSecAssert2(keyInfoCtx->keysMngr != NULL, -1);
+
+    x509Store = xmlSecKeysMngrGetDataStore(keyInfoCtx->keysMngr, xmlSecGnuTLSX509StoreId);
+    if(x509Store == NULL) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+                    "xmlSecKeysMngrGetDataStore",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        return(-1);
+    }
+
+    subject = xmlNodeGetContent(node);
+    if((subject == NULL) || (xmlSecIsEmptyString(subject) == 1)) {
+        if(subject != NULL) {
+            xmlFree(subject);
+        }
+        if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_STOP_ON_EMPTY_NODE) != 0) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                        xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+                        xmlSecErrorsSafeString(xmlSecNodeGetName(node)),
+                        XMLSEC_ERRORS_R_INVALID_NODE_CONTENT,
+                        XMLSEC_ERRORS_NO_MESSAGE);
+            return(-1);
+        }
+        return(0);
+    }
+
+    cert = xmlSecGnuTLSX509StoreFindCert(x509Store, subject, NULL, NULL, NULL, keyInfoCtx);
+    if(cert == NULL){
+
+        if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_X509DATA_STOP_ON_UNKNOWN_CERT) != 0) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                        xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+                        NULL,
+                        XMLSEC_ERRORS_R_CERT_NOT_FOUND,
+                        "subject=%s",
+                        xmlSecErrorsSafeString(subject));
+            xmlFree(subject);
+            return(-1);
+        }
+
+        xmlFree(subject);
+        return(0);
+    }
+
+    cert2 = xmlSecGnuTLSX509CertDup(cert);
+    if(cert2 == NULL) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+                    "xmlSecGnuTLSX509CertDup",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+
+        xmlFree(subject);
+        return(-1);
+    }
+
+    ret = xmlSecGnuTLSKeyDataX509AdoptCert(data, cert2);
+    if(ret < 0) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+                    "xmlSecGnuTLSKeyDataX509AdoptCert",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        gnutls_x509_crt_deinit(cert2);
+        xmlFree(subject);
+        return(-1);
+    }
+
+    xmlFree(subject);
+    return(0);
+}
+
+static int
+xmlSecGnuTLSX509SubjectNameNodeWrite(gnutls_x509_crt_t cert, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx ATTRIBUTE_UNUSED) {
+    xmlChar* buf = NULL;
+    xmlNodePtr cur = NULL;
+
+    xmlSecAssert2(cert != NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+
+    /* add node */
+    cur = xmlSecAddChild(node, xmlSecNodeX509SubjectName, xmlSecDSigNs);
+    if(cur == NULL) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+            NULL,
+            "xmlSecAddChild",
+            XMLSEC_ERRORS_R_XMLSEC_FAILED,
+            "node=%s",
+            xmlSecErrorsSafeString(xmlSecNodeX509SubjectName));
+        return(-1);
+    }
+
+    /* get subject */
+    buf = xmlSecGnuTLSX509CertGetSubjectDN(cert);
+    if(buf == NULL) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+            NULL,
+            "xmlSecGnuTLSX509CertGetSubjectDN",
+            XMLSEC_ERRORS_R_XMLSEC_FAILED,
+            XMLSEC_ERRORS_NO_MESSAGE);
+        return(-1);
+    }
+
+    /* set value */
+    xmlSecNodeEncodeAndSetContent(cur, buf);
+
+    /* done */
+    xmlFree(buf);
+    return(0);
+}
+
+static int
+xmlSecGnuTLSX509IssuerSerialNodeRead(xmlSecKeyDataPtr data, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+    xmlSecKeyDataStorePtr x509Store;
+    xmlNodePtr cur;
+    xmlChar *issuerName;
+    xmlChar *issuerSerial;
+    gnutls_x509_crt_t cert;
+    gnutls_x509_crt_t cert2;
+    int ret;
+
+    xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGnuTLSKeyDataX509Id), -1);
+    xmlSecAssert2(node != NULL, -1);
+    xmlSecAssert2(keyInfoCtx != NULL, -1);
+    xmlSecAssert2(keyInfoCtx->keysMngr != NULL, -1);
+
+    x509Store = xmlSecKeysMngrGetDataStore(keyInfoCtx->keysMngr, xmlSecGnuTLSX509StoreId);
+    if(x509Store == NULL) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+                    "xmlSecKeysMngrGetDataStore",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        return(-1);
+    }
+
+    cur = xmlSecGetNextElementNode(node->children);
+    if(cur == NULL) {
+        if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_STOP_ON_EMPTY_NODE) != 0) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                        xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+                        xmlSecErrorsSafeString(xmlSecNodeX509IssuerName),
+                        XMLSEC_ERRORS_R_NODE_NOT_FOUND,
+                        "node=%s",
+                        xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
+            return(-1);
+        }
+        return(0);
+    }
+
+    /* the first is required node X509IssuerName */
+    if(!xmlSecCheckNodeName(cur, xmlSecNodeX509IssuerName, xmlSecDSigNs)) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+                    xmlSecErrorsSafeString(xmlSecNodeX509IssuerName),
+                    XMLSEC_ERRORS_R_NODE_NOT_FOUND,
+                    "node=%s",
+                    xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
+        return(-1);
+    }
+    issuerName = xmlNodeGetContent(cur);
+    if(issuerName == NULL) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+                    xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+                    XMLSEC_ERRORS_R_INVALID_NODE_CONTENT,
+                    "node=%s",
+                    xmlSecErrorsSafeString(xmlSecNodeX509IssuerName));
+        return(-1);
+    }
+    cur = xmlSecGetNextElementNode(cur->next);
+
+    /* next is required node X509SerialNumber */
+    if((cur == NULL) || !xmlSecCheckNodeName(cur, xmlSecNodeX509SerialNumber, xmlSecDSigNs)) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+                    xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+                    XMLSEC_ERRORS_R_NODE_NOT_FOUND,
+                    "node=%s",
+                    xmlSecErrorsSafeString(xmlSecNodeX509SerialNumber));
+        xmlFree(issuerName);
+        return(-1);
+    }
+    issuerSerial = xmlNodeGetContent(cur);
+    if(issuerSerial == NULL) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+                    xmlSecErrorsSafeString(xmlSecNodeX509SerialNumber),
+                    XMLSEC_ERRORS_R_INVALID_NODE_CONTENT,
+                    "node=%s",
+                    xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
+        xmlFree(issuerName);
+        return(-1);
+    }
+    cur = xmlSecGetNextElementNode(cur->next);
+
+    if(cur != NULL) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+                    xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+                    XMLSEC_ERRORS_R_UNEXPECTED_NODE,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        xmlFree(issuerSerial);
+        xmlFree(issuerName);
+        return(-1);
+    }
+
+    cert = xmlSecGnuTLSX509StoreFindCert(x509Store, NULL, issuerName, issuerSerial, NULL, keyInfoCtx);
+    if(cert == NULL){
+
+        if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_X509DATA_STOP_ON_UNKNOWN_CERT) != 0) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                        xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+                        NULL,
+                        XMLSEC_ERRORS_R_CERT_NOT_FOUND,
+                        "issuerName=%s;issuerSerial=%s",
+                        xmlSecErrorsSafeString(issuerName),
+                        xmlSecErrorsSafeString(issuerSerial));
+            xmlFree(issuerSerial);
+            xmlFree(issuerName);
+            return(-1);
+        }
+        xmlFree(issuerSerial);
+        xmlFree(issuerName);
+        return(0);
+    }
+
+    cert2 = xmlSecGnuTLSX509CertDup(cert);
+    if(cert2 == NULL) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+                    "xmlSecGnuTLSX509CertDup",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        xmlFree(issuerSerial);
+        xmlFree(issuerName);
+        return(-1);
+    }
+
+    ret = xmlSecGnuTLSKeyDataX509AdoptCert(data, cert2);
+    if(ret < 0) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+                    "xmlSecGnuTLSKeyDataX509AdoptCert",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        gnutls_x509_crt_deinit(cert2);
+        xmlFree(issuerSerial);
+        xmlFree(issuerName);
+        return(-1);
+    }
+
+    xmlFree(issuerSerial);
+    xmlFree(issuerName);
+    return(0);
+}
+
+static int
+xmlSecGnuTLSX509IssuerSerialNodeWrite(gnutls_x509_crt_t cert, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx ATTRIBUTE_UNUSED) {
+    xmlNodePtr cur;
+    xmlNodePtr issuerNameNode;
+    xmlNodePtr issuerNumberNode;
+    xmlChar* buf;
+
+    xmlSecAssert2(cert != NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+
+    /* create xml nodes */
+    cur = xmlSecAddChild(node, xmlSecNodeX509IssuerSerial, xmlSecDSigNs);
+    if(cur == NULL) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "xmlSecAddChild",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    "node=%s",
+                    xmlSecErrorsSafeString(xmlSecNodeX509IssuerSerial));
+        return(-1);
+    }
+
+    issuerNameNode = xmlSecAddChild(cur, xmlSecNodeX509IssuerName, xmlSecDSigNs);
+    if(issuerNameNode == NULL) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "xmlSecAddChild",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    "node=%s",
+                    xmlSecErrorsSafeString(xmlSecNodeX509IssuerName));
+        return(-1);
+    }
+
+    issuerNumberNode = xmlSecAddChild(cur, xmlSecNodeX509SerialNumber, xmlSecDSigNs);
+    if(issuerNumberNode == NULL) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "xmlSecAddChild",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    "node=%s",
+                    xmlSecErrorsSafeString(xmlSecNodeX509SerialNumber));
+        return(-1);
+    }
+
+    /* write data */
+    buf = xmlSecGnuTLSX509CertGetIssuerDN(cert);
+    if(buf == NULL) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "xmlSecGnuTLSX509CertGetIssuerDN",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        return(-1);
+    }
+    xmlSecNodeEncodeAndSetContent(issuerNameNode, buf);
+    xmlFree(buf);
+
+    buf = xmlSecGnuTLSX509CertGetIssuerSerial(cert);
+    if(buf == NULL) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "xmlSecGnuTLSX509CertGetIssuerSerial",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        return(-1);
+    }
+    xmlSecNodeEncodeAndSetContent(issuerNumberNode, buf);
+    xmlFree(buf);
+
+    return(0);
+}
+
+
+static int
+xmlSecGnuTLSX509SKINodeRead(xmlSecKeyDataPtr data, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+    xmlSecKeyDataStorePtr x509Store;
+    xmlChar* ski;
+    gnutls_x509_crt_t cert;
+    gnutls_x509_crt_t cert2;
+    int ret;
+
+    xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGnuTLSKeyDataX509Id), -1);
+    xmlSecAssert2(node != NULL, -1);
+    xmlSecAssert2(keyInfoCtx != NULL, -1);
+    xmlSecAssert2(keyInfoCtx->keysMngr != NULL, -1);
+
+    x509Store = xmlSecKeysMngrGetDataStore(keyInfoCtx->keysMngr, xmlSecGnuTLSX509StoreId);
+    if(x509Store == NULL) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+                    "xmlSecKeysMngrGetDataStore",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        return(-1);
+    }
+
+    ski = xmlNodeGetContent(node);
+    if((ski == NULL) || (xmlSecIsEmptyString(ski) == 1)) {
+        if(ski != NULL) {
+            xmlFree(ski);
+        }
+        if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_STOP_ON_EMPTY_NODE) != 0) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                        xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+                        xmlSecErrorsSafeString(xmlSecNodeGetName(node)),
+                        XMLSEC_ERRORS_R_INVALID_NODE_CONTENT,
+                        "node=%s",
+                        xmlSecErrorsSafeString(xmlSecNodeX509SKI));
+            return(-1);
+        }
+        return(0);
+    }
+
+    cert = xmlSecGnuTLSX509StoreFindCert(x509Store, NULL, NULL, NULL, ski, keyInfoCtx);
+    if(cert == NULL){
+        xmlFree(ski);
+
+        if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_X509DATA_STOP_ON_UNKNOWN_CERT) != 0) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                        xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+                        NULL,
+                        XMLSEC_ERRORS_R_CERT_NOT_FOUND,
+                        "ski=%s",
+                        xmlSecErrorsSafeString(ski));
+            return(-1);
+        }
+        return(0);
+    }
+
+    cert2 = xmlSecGnuTLSX509CertDup(cert);
+    if(cert2 == NULL) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+                    "xmlSecGnuTLSX509CertDup",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        xmlFree(ski);
+        return(-1);
+    }
+
+    ret = xmlSecGnuTLSKeyDataX509AdoptCert(data, cert2);
+    if(ret < 0) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+                    "xmlSecGnuTLSKeyDataX509AdoptCert",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        gnutls_x509_crt_deinit(cert2);
+        xmlFree(ski);
+        return(-1);
+    }
+
+    xmlFree(ski);
+    return(0);
+}
+
+static int
+xmlSecGnuTLSX509SKINodeWrite(gnutls_x509_crt_t cert, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx ATTRIBUTE_UNUSED) {
+    xmlChar *buf = NULL;
+    xmlNodePtr cur = NULL;
+
+    xmlSecAssert2(cert != NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+
+    /* add node */
+    cur = xmlSecAddChild(node, xmlSecNodeX509SKI, xmlSecDSigNs);
+    if(cur == NULL) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "xmlSecAddChild",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    "new_node=%s",
+                    xmlSecErrorsSafeString(xmlSecNodeX509SKI));
+        return(-1);
+    }
+
+    /* write value */
+    buf = xmlSecGnuTLSX509CertGetSKI(cert);
+    if(buf == NULL) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "xmlSecGnuTLSX509CertGetSKI",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        return(-1);
+    }
+
+    xmlSecNodeEncodeAndSetContent(cur, buf);
+    xmlFree(buf);
+
+    return(0);
+}
+
+static int
+xmlSecGnuTLSKeyDataX509VerifyAndExtractKey(xmlSecKeyDataPtr data, xmlSecKeyPtr key,
+                                    xmlSecKeyInfoCtxPtr keyInfoCtx) {
+    xmlSecGnuTLSX509DataCtxPtr ctx;
+    xmlSecKeyDataStorePtr x509Store;
+    int ret;
+
+    xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGnuTLSKeyDataX509Id), -1);
+    xmlSecAssert2(key != NULL, -1);
+    xmlSecAssert2(keyInfoCtx != NULL, -1);
+    xmlSecAssert2(keyInfoCtx->keysMngr != NULL, -1);
+
+    ctx = xmlSecGnuTLSX509DataGetCtx(data);
+    xmlSecAssert2(ctx != NULL, -1);
+
+    x509Store = xmlSecKeysMngrGetDataStore(keyInfoCtx->keysMngr, xmlSecGnuTLSX509StoreId);
+    if(x509Store == NULL) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+                    "xmlSecKeysMngrGetDataStore",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        return(-1);
+    }
+
+    if((ctx->keyCert == NULL) && (xmlSecPtrListGetSize(&(ctx->certsList)) > 0) && (xmlSecKeyGetValue(key) == NULL)) {
+        gnutls_x509_crt_t cert;
+
+        cert = xmlSecGnuTLSX509StoreVerify(x509Store, &(ctx->certsList), keyInfoCtx);
+        if(cert != NULL) {
+            xmlSecKeyDataPtr keyValue;
+
+            ctx->keyCert = xmlSecGnuTLSX509CertDup(cert);
+            if(ctx->keyCert == NULL) {
+                xmlSecError(XMLSEC_ERRORS_HERE,
+                            xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+                            "xmlSecGnuTLSX509CertDup",
+                            XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                            XMLSEC_ERRORS_NO_MESSAGE);
+                return(-1);
+            }
+
+            keyValue = xmlSecGnuTLSX509CertGetKey(ctx->keyCert);
+            if(keyValue == NULL) {
+                xmlSecError(XMLSEC_ERRORS_HERE,
+                            xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+                            "xmlSecGnuTLSX509CertGetKey",
+                            XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                            XMLSEC_ERRORS_NO_MESSAGE);
+                return(-1);
+            }
+
+            /* verify that the key matches our expectations */
+            if(xmlSecKeyReqMatchKeyValue(&(keyInfoCtx->keyReq), keyValue) != 1) {
+                xmlSecError(XMLSEC_ERRORS_HERE,
+                            xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+                            "xmlSecKeyReqMatchKeyValue",
+                            XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                            XMLSEC_ERRORS_NO_MESSAGE);
+                xmlSecKeyDataDestroy(keyValue);
+                return(-1);
+            }
+
+            ret = xmlSecKeySetValue(key, keyValue);
+            if(ret < 0) {
+                xmlSecError(XMLSEC_ERRORS_HERE,
+                            xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+                            "xmlSecKeySetValue",
+                            XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                            XMLSEC_ERRORS_NO_MESSAGE);
+                xmlSecKeyDataDestroy(keyValue);
+                return(-1);
+            }
+
+            /* get expiration time */
+            key->notValidBefore = gnutls_x509_crt_get_activation_time(ctx->keyCert);
+            if(key->notValidBefore == (time_t)-1) {
+                xmlSecError(XMLSEC_ERRORS_HERE,
+                            xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+                            "gnutls_x509_crt_get_activation_time",
+                            XMLSEC_ERRORS_R_CRYPTO_FAILED,
+                            XMLSEC_ERRORS_NO_MESSAGE);
+                return(-1);
+            }
+            key->notValidAfter = gnutls_x509_crt_get_expiration_time(ctx->keyCert);
+            if(key->notValidAfter == (time_t)-1) {
+                xmlSecError(XMLSEC_ERRORS_HERE,
+                            xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+                            "gnutls_x509_crt_get_expiration_time",
+                            XMLSEC_ERRORS_R_CRYPTO_FAILED,
+                            XMLSEC_ERRORS_NO_MESSAGE);
+                return(-1);
+            }
+        } else if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_X509DATA_STOP_ON_INVALID_CERT) != 0) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                        xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+                        NULL,
+                        XMLSEC_ERRORS_R_CERT_NOT_FOUND,
+                        XMLSEC_ERRORS_NO_MESSAGE);
+            return(-1);
+        }
+    }
+    return(0);
+}
+
+/**
+ * xmlSecGnuTLSX509CertGetKey:
+ * @cert:               the certificate.
+ *
+ * Extracts public key from the @cert.
+ *
+ * Returns: public key value or NULL if an error occurs.
+ */
+xmlSecKeyDataPtr
+xmlSecGnuTLSX509CertGetKey(gnutls_x509_crt_t cert) {
+    xmlSecKeyDataPtr data;
+    int alg;
+    unsigned int bits;
+    int err;
+    int ret;
+
+    xmlSecAssert2(cert != NULL, NULL);
+
+    alg = gnutls_x509_crt_get_pk_algorithm(cert, &bits);
+    if(alg < 0) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "gnutls_x509_crt_get_pk_algorithm",
+                    XMLSEC_ERRORS_R_CRYPTO_FAILED,
+                    XMLSEC_GNUTLS_REPORT_ERROR(alg));
+        return(NULL);
+    }
+
+    switch(alg) {
+    case GNUTLS_PK_RSA:
+        {
+            gnutls_datum_t m, e;
+
+            data = xmlSecKeyDataCreate(xmlSecGnuTLSKeyDataRsaId);
+            if(data == NULL) {
+                xmlSecError(XMLSEC_ERRORS_HERE,
+                            NULL,
+                            "xmlSecKeyDataCreate",
+                            XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                            "xmlSecGnuTLSKeyDataRsaId");
+                return(NULL);
+            }
+
+            err = gnutls_x509_crt_get_pk_rsa_raw(cert, &m, &e);
+            if(err != GNUTLS_E_SUCCESS) {
+                xmlSecError(XMLSEC_ERRORS_HERE,
+                            NULL,
+                            "gnutls_x509_crt_get_pk_rsa_raw",
+                            XMLSEC_ERRORS_R_CRYPTO_FAILED,
+                            XMLSEC_GNUTLS_REPORT_ERROR(err));
+                return(NULL);
+            }
+
+            ret = xmlSecGnuTLSKeyDataRsaAdoptPublicKey(data, &m, &e);
+            if(ret < 0) {
+                xmlSecError(XMLSEC_ERRORS_HERE,
+                            NULL,
+                            "xmlSecGnuTLSKeyDataRsaAdoptPublicKey",
+                            XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                            XMLSEC_ERRORS_NO_MESSAGE);
+                gnutls_free(m.data);
+                gnutls_free(e.data);
+                return(NULL);
+            }
+            /* m and e are owned by data now */
+        }
+        break;
+
+    case GNUTLS_PK_DSA:
+        {
+            gnutls_datum_t p, q, g, y;
+
+            data = xmlSecKeyDataCreate(xmlSecGnuTLSKeyDataDsaId);
+            if(data == NULL) {
+                xmlSecError(XMLSEC_ERRORS_HERE,
+                            NULL,
+                            "xmlSecKeyDataCreate",
+                            XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                            "xmlSecGnuTLSKeyDataDsaId");
+                return(NULL);
+            }
+
+            err = gnutls_x509_crt_get_pk_dsa_raw(cert, &p, &q, &g, &y);
+            if(err != GNUTLS_E_SUCCESS) {
+                xmlSecError(XMLSEC_ERRORS_HERE,
+                            NULL,
+                            "gnutls_x509_crt_get_pk_dsa_raw",
+                            XMLSEC_ERRORS_R_CRYPTO_FAILED,
+                            XMLSEC_GNUTLS_REPORT_ERROR(err));
+                return(NULL);
+            }
+
+            ret = xmlSecGnuTLSKeyDataDsaAdoptPublicKey(data, &p, &q, &g, &y);
+            if(ret < 0) {
+                xmlSecError(XMLSEC_ERRORS_HERE,
+                            NULL,
+                            "xmlSecGnuTLSKeyDataDsaAdoptPublicKey",
+                            XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                            XMLSEC_ERRORS_NO_MESSAGE);
+                gnutls_free(p.data);
+                gnutls_free(q.data);
+                gnutls_free(g.data);
+                gnutls_free(y.data);
+                return(NULL);
+            }
+            /* p, q, g and y are owned by data now */
+        }
+        break;
+
+    default:
+        {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                        NULL,
+                        "gnutls_x509_crt_get_pk_algorithm",
+                        XMLSEC_ERRORS_R_CRYPTO_FAILED,
+                        "Unsupported algorithm %d", (int)alg);
+            return(NULL);
+        }
+    }
+
+    /* data */
+    return(data);
+}
+
+
+/**************************************************************************
+ *
+ * Raw X509 Certificate processing
+ *
+ *
+ *************************************************************************/
+static int              xmlSecGnuTLSKeyDataRawX509CertBinRead  (xmlSecKeyDataId id,
+                                                                 xmlSecKeyPtr key,
+                                                                 const xmlSecByte* buf,
+                                                                 xmlSecSize bufSize,
+                                                                 xmlSecKeyInfoCtxPtr keyInfoCtx);
+
+static xmlSecKeyDataKlass xmlSecGnuTLSKeyDataRawX509CertKlass = {
+    sizeof(xmlSecKeyDataKlass),
+    sizeof(xmlSecKeyData),
+
+    /* data */
+    xmlSecNameRawX509Cert,
+    xmlSecKeyDataUsageRetrievalMethodNodeBin,
+                                                /* xmlSecKeyDataUsage usage; */
+    xmlSecHrefRawX509Cert,                      /* const xmlChar* href; */
+    NULL,                                       /* const xmlChar* dataNodeName; */
+    xmlSecDSigNs,                               /* const xmlChar* dataNodeNs; */
+
+    /* constructors/destructor */
+    NULL,                                       /* xmlSecKeyDataInitializeMethod initialize; */
+    NULL,                                       /* xmlSecKeyDataDuplicateMethod duplicate; */
+    NULL,                                       /* xmlSecKeyDataFinalizeMethod finalize; */
+    NULL,                                       /* xmlSecKeyDataGenerateMethod generate; */
+
+    /* get info */
+    NULL,                                       /* xmlSecKeyDataGetTypeMethod getType; */
+    NULL,                                       /* xmlSecKeyDataGetSizeMethod getSize; */
+    NULL,                                       /* xmlSecKeyDataGetIdentifier getIdentifier; */
+
+    /* read/write */
+    NULL,                                       /* xmlSecKeyDataXmlReadMethod xmlRead; */
+    NULL,                                       /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
+    xmlSecGnuTLSKeyDataRawX509CertBinRead,     /* xmlSecKeyDataBinReadMethod binRead; */
+    NULL,                                       /* xmlSecKeyDataBinWriteMethod binWrite; */
+
+    /* debug */
+    NULL,                                       /* xmlSecKeyDataDebugDumpMethod debugDump; */
+    NULL,                                       /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
+
+    /* reserved for the future */
+    NULL,                                       /* void* reserved0; */
+    NULL,                                       /* void* reserved1; */
+};
+
+/**
+ * xmlSecGnuTLSKeyDataRawX509CertGetKlass:
+ *
+ * The raw X509 certificates key data klass.
+ *
+ * Returns: raw X509 certificates key data klass.
+ */
+xmlSecKeyDataId
+xmlSecGnuTLSKeyDataRawX509CertGetKlass(void) {
+    return(&xmlSecGnuTLSKeyDataRawX509CertKlass);
+}
+
+static int
+xmlSecGnuTLSKeyDataRawX509CertBinRead(xmlSecKeyDataId id, xmlSecKeyPtr key,
+                                    const xmlSecByte* buf, xmlSecSize bufSize,
+                                    xmlSecKeyInfoCtxPtr keyInfoCtx) {
+    xmlSecKeyDataPtr data;
+    gnutls_x509_crt_t cert;
+    int ret;
+
+    xmlSecAssert2(id == xmlSecGnuTLSKeyDataRawX509CertId, -1);
+    xmlSecAssert2(key != NULL, -1);
+    xmlSecAssert2(buf != NULL, -1);
+    xmlSecAssert2(bufSize > 0, -1);
+    xmlSecAssert2(keyInfoCtx != NULL, -1);
+
+    cert = xmlSecGnuTLSX509CertDerRead(buf, bufSize);
+    if(cert == NULL) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "xmlSecGnuTLSX509CertDerRead",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        return(-1);
+    }
+
+    data = xmlSecKeyEnsureData(key, xmlSecGnuTLSKeyDataX509Id);
+    if(data == NULL) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+                    "xmlSecKeyEnsureData",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        gnutls_x509_crt_deinit(cert);
+        return(-1);
+    }
+
+    ret = xmlSecGnuTLSKeyDataX509AdoptCert(data, cert);
+    if(ret < 0) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+                    "xmlSecGnuTLSKeyDataX509AdoptCert",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        gnutls_x509_crt_deinit(cert);
+        return(-1);
+    }
+
+    ret = xmlSecGnuTLSKeyDataX509VerifyAndExtractKey(data, key, keyInfoCtx);
+    if(ret < 0) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+                    "xmlSecGnuTLSKeyDataX509VerifyAndExtractKey",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        return(-1);
+    }
+    return(0);
+}
+
+#endif /* XMLSEC_NO_X509 */
diff --git a/src/gnutls/x509utils.c b/src/gnutls/x509utils.c
new file mode 100644
index 0000000..e87e8cf
--- /dev/null
+++ b/src/gnutls/x509utils.c
@@ -0,0 +1,562 @@
+/**
+ * XMLSec library
+ *
+ * X509 support
+ *
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2010 Aleksey Sanin <aleksey aleksey com>
+ */
+#include "globals.h"
+
+#ifndef XMLSEC_NO_X509
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <time.h>
+
+#include <libxml/tree.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/keyinfo.h>
+#include <xmlsec/keysmngr.h>
+#include <xmlsec/x509.h>
+#include <xmlsec/base64.h>
+#include <xmlsec/errors.h>
+#include <xmlsec/private.h>
+
+#include <xmlsec/gnutls/crypto.h>
+#include <xmlsec/gnutls/x509.h>
+
+#include "x509utils.h"
+
+
+/**************************************************************************
+ *
+ * X509 crt list
+ *
+ *****************************************************************************/
+static xmlSecPtr        xmlSecGnuTLSX509CrtListDuplicateItem    (xmlSecPtr ptr);
+static void             xmlSecGnuTLSX509CrtListDestroyItem      (xmlSecPtr ptr);
+static void             xmlSecGnuTLSX509CrtListDebugDumpItem    (xmlSecPtr ptr,
+                                                                 FILE* output);
+static void             xmlSecGnuTLSX509CrtListDebugXmlDumpItem (xmlSecPtr ptr,
+                                                                 FILE* output);
+
+static xmlSecPtrListKlass xmlSecGnuTLSX509CrtListKlass = {
+    BAD_CAST "gnutls-x509-crt-list",
+    xmlSecGnuTLSX509CrtListDuplicateItem,       /* xmlSecPtrDuplicateItemMethod duplicateItem; */
+    xmlSecGnuTLSX509CrtListDestroyItem,         /* xmlSecPtrDestroyItemMethod destroyItem; */
+    xmlSecGnuTLSX509CrtListDebugDumpItem,       /* xmlSecPtrDebugDumpItemMethod debugDumpItem; */
+    xmlSecGnuTLSX509CrtListDebugXmlDumpItem,    /* xmlSecPtrDebugDumpItemMethod debugXmlDumpItem; */
+};
+
+xmlSecPtrListId
+xmlSecGnuTLSX509CrtListGetKlass(void) {
+    return(&xmlSecGnuTLSX509CrtListKlass);
+}
+
+static xmlSecPtr
+xmlSecGnuTLSX509CrtListDuplicateItem(xmlSecPtr ptr) {
+    xmlSecAssert2(ptr != NULL, NULL);
+
+    return xmlSecGnuTLSX509CertDup((gnutls_x509_crt_t)ptr);
+}
+
+static void
+xmlSecGnuTLSX509CrtListDestroyItem(xmlSecPtr ptr) {
+    xmlSecAssert(ptr != NULL);
+
+    gnutls_x509_crt_deinit((gnutls_x509_crt_t)ptr);
+}
+
+static void
+xmlSecGnuTLSX509CrtListDebugDumpItem(xmlSecPtr ptr, FILE* output) {
+    xmlSecAssert(ptr != NULL);
+    xmlSecAssert(output != NULL);
+
+    xmlSecGnuTLSX509CertDebugDump((gnutls_x509_crt_t)ptr, output);
+}
+
+
+static void
+xmlSecGnuTLSX509CrtListDebugXmlDumpItem(xmlSecPtr ptr, FILE* output) {
+    xmlSecAssert(ptr != NULL);
+    xmlSecAssert(output != NULL);
+
+    xmlSecGnuTLSX509CertDebugXmlDump((gnutls_x509_crt_t)ptr, output);
+}
+
+/*************************************************************************
+ *
+ * Utils/helpers
+ *
+ ************************************************************************/
+
+/* HACK: gnutls doesn't have cert duplicate function, so we simply 
+ write cert out and then read it back */
+gnutls_x509_crt_t
+xmlSecGnuTLSX509CertDup(gnutls_x509_crt_t src) {
+    xmlChar * buf = NULL;
+    gnutls_x509_crt_t res = NULL;
+
+    xmlSecAssert2(src != NULL, NULL);
+
+    buf = xmlSecGnuTLSX509CertBase64DerWrite(src, 0);
+    if(buf == NULL) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "xmlSecGnuTLSX509CertBase64DerWrite",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        return (NULL);
+    }
+
+    res = xmlSecGnuTLSX509CertBase64DerRead(buf);
+    if(res == NULL) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "xmlSecGnuTLSX509CertBase64DerRead",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        xmlFree(buf);
+        return (NULL);
+    }
+
+    /* done */
+    xmlFree(buf);
+    return (res);
+}
+
+xmlChar *
+xmlSecGnuTLSX509CertGetSubjectDN(gnutls_x509_crt_t cert) {
+    char* buf = NULL;
+    size_t bufSize = 0;
+    int err;
+
+    xmlSecAssert2(cert != NULL, NULL);
+
+    /* get subject size */
+    err = gnutls_x509_crt_get_dn(cert, NULL, &bufSize);
+    if((err != GNUTLS_E_SHORT_MEMORY_BUFFER) || (bufSize <= 0)) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "gnutls_x509_crt_get_dn",
+                    XMLSEC_ERRORS_R_CRYPTO_FAILED,
+                    XMLSEC_GNUTLS_REPORT_ERROR(err));
+        return(NULL);
+    }
+
+    /* allocate buffer */
+    buf = (char *)xmlMalloc(bufSize + 1);
+    if(buf == NULL) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "xmlMalloc",
+                    XMLSEC_ERRORS_R_MALLOC_FAILED,
+                    "size=%d", (int)bufSize);
+        return(NULL);
+    }
+
+    /* finally write it out */
+    err = gnutls_x509_crt_get_dn(cert, buf, &bufSize);
+    if(err != GNUTLS_E_SUCCESS) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "gnutls_x509_crt_get_dn",
+                    XMLSEC_ERRORS_R_CRYPTO_FAILED,
+                    XMLSEC_GNUTLS_REPORT_ERROR(err));
+        xmlFree(buf);
+        return(NULL);
+    }
+
+    /* done */
+    return(BAD_CAST buf);
+}
+
+xmlChar *
+xmlSecGnuTLSX509CertGetIssuerDN(gnutls_x509_crt_t cert) {
+    char* buf = NULL;
+    size_t bufSize = 0;
+    int err;
+
+    xmlSecAssert2(cert != NULL, NULL);
+
+    /* get issuer size */
+    err = gnutls_x509_crt_get_issuer_dn(cert, NULL, &bufSize);
+    if((err != GNUTLS_E_SHORT_MEMORY_BUFFER) || (bufSize <= 0)) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "gnutls_x509_crt_get_issuer_dn",
+                    XMLSEC_ERRORS_R_CRYPTO_FAILED,
+                    XMLSEC_GNUTLS_REPORT_ERROR(err));
+        return(NULL);
+    }
+
+    /* allocate buffer */
+    buf = (char *)xmlMalloc(bufSize + 1);
+    if(buf == NULL) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "xmlMalloc",
+                    XMLSEC_ERRORS_R_MALLOC_FAILED,
+                    "size=%d", (int)bufSize);
+        return(NULL);
+    }
+
+    /* finally write it out */
+    err = gnutls_x509_crt_get_issuer_dn(cert, buf, &bufSize);
+    if(err != GNUTLS_E_SUCCESS) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "gnutls_x509_crt_get_issuer_dn",
+                    XMLSEC_ERRORS_R_CRYPTO_FAILED,
+                    XMLSEC_GNUTLS_REPORT_ERROR(err));
+        xmlFree(buf);
+        return(NULL);
+    }
+
+    /* done */
+    return(BAD_CAST buf);
+}
+
+xmlChar *
+xmlSecGnuTLSX509CertGetIssuerSerial(gnutls_x509_crt_t cert) {
+    xmlChar * res = NULL;
+    unsigned char* buf = NULL;
+    size_t bufSize = 0;
+    int err;
+
+    xmlSecAssert2(cert != NULL, NULL);
+
+    /* get issuer serial size */
+    err = gnutls_x509_crt_get_serial(cert, NULL, &bufSize);
+    if((err != GNUTLS_E_SHORT_MEMORY_BUFFER) || (bufSize <= 0)) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "gnutls_x509_crt_get_serial",
+                    XMLSEC_ERRORS_R_CRYPTO_FAILED,
+                    XMLSEC_GNUTLS_REPORT_ERROR(err));
+        return(NULL);
+    }
+
+    /* allocate buffer */
+    buf = (unsigned char *)xmlMalloc(bufSize + 1);
+    if(buf == NULL) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "xmlMalloc",
+                    XMLSEC_ERRORS_R_MALLOC_FAILED,
+                    "size=%d", (int)bufSize);
+        return(NULL);
+    }
+
+    /* write it out */
+    err = gnutls_x509_crt_get_serial(cert, buf, &bufSize);
+    if(err != GNUTLS_E_SUCCESS) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "gnutls_x509_crt_get_serial",
+                    XMLSEC_ERRORS_R_CRYPTO_FAILED,
+                    XMLSEC_GNUTLS_REPORT_ERROR(err));
+        xmlFree(buf);
+        return(NULL);
+    }
+
+    /* convert to string */
+    res = xmlSecGnuTLSASN1IntegerWrite(buf, bufSize);
+    if(res == NULL) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "xmlSecGnuTLSASN1IntegerWrite",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        xmlFree(buf);
+        return(NULL);
+    }
+    printf("DEBUG: serial number is %s\n", res);
+
+    /* done */
+    xmlFree(buf);
+    return(res);
+}
+
+xmlChar *
+xmlSecGnuTLSX509CertGetSKI(gnutls_x509_crt_t cert) {
+    xmlChar * res = NULL;
+    xmlSecByte* buf = NULL;
+    size_t bufSize = 0;
+    unsigned int critical = 0;
+    int err;
+
+    xmlSecAssert2(cert != NULL, NULL);
+
+    /* get ski size */
+    err = gnutls_x509_crt_get_subject_key_id(cert, NULL, &bufSize, &critical);
+    if((err != GNUTLS_E_SHORT_MEMORY_BUFFER) || (bufSize <= 0)) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "gnutls_x509_crt_get_subject_key_id",
+                    XMLSEC_ERRORS_R_CRYPTO_FAILED,
+                    XMLSEC_GNUTLS_REPORT_ERROR(err));
+        return(NULL);
+    }
+
+    /* allocate buffer */
+    buf = (xmlSecByte *)xmlMalloc(bufSize + 1);
+    if(buf == NULL) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "xmlMalloc",
+                    XMLSEC_ERRORS_R_MALLOC_FAILED,
+                    "size=%d", (int)bufSize);
+        return(NULL);
+    }
+
+    /* write it out */
+    err = gnutls_x509_crt_get_subject_key_id(cert, buf, &bufSize, &critical);
+    if(err != GNUTLS_E_SUCCESS) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "gnutls_x509_crt_get_subject_key_id",
+                    XMLSEC_ERRORS_R_CRYPTO_FAILED,
+                    XMLSEC_GNUTLS_REPORT_ERROR(err));
+        xmlFree(buf);
+        return(NULL);
+    }
+
+    /* convert to string */
+    res = xmlSecBase64Encode(buf, bufSize, 0);
+    if(res == NULL) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "xmlSecBase64Encode",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        xmlFree(buf);
+        return(NULL);
+    }
+
+    /* done */
+    xmlFree(buf);
+    return(res);
+}
+
+
+gnutls_x509_crt_t
+xmlSecGnuTLSX509CertBase64DerRead(xmlChar* buf) {
+    int ret;
+
+    xmlSecAssert2(buf != NULL, NULL);
+
+    /* usual trick with base64 decoding "in-place" */
+    ret = xmlSecBase64Decode(buf, (xmlSecByte*)buf, xmlStrlen(buf));
+    if(ret < 0) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "xmlSecBase64Decode",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        return(NULL);
+    }
+
+    return(xmlSecGnuTLSX509CertDerRead((const xmlSecByte*)buf, ret));
+}
+
+gnutls_x509_crt_t
+xmlSecGnuTLSX509CertDerRead(const xmlSecByte* buf, xmlSecSize size) {
+    gnutls_x509_crt_t cert = NULL;
+    gnutls_datum_t data;
+    int err;
+
+    xmlSecAssert2(buf != NULL, NULL);
+    xmlSecAssert2(size > 0, NULL);
+
+    err = gnutls_x509_crt_init(&cert);
+    if(err != GNUTLS_E_SUCCESS) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "gnutls_x509_crt_init",
+                    XMLSEC_ERRORS_R_CRYPTO_FAILED,
+                    XMLSEC_GNUTLS_REPORT_ERROR(err));
+        return(NULL);
+    }
+
+    data.data = (unsigned char*)buf;
+    data.size = size;
+    err = gnutls_x509_crt_import(cert, &data, GNUTLS_X509_FMT_DER);
+    if(err != GNUTLS_E_SUCCESS) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "gnutls_x509_crt_import",
+                    XMLSEC_ERRORS_R_CRYPTO_FAILED,
+                    XMLSEC_GNUTLS_REPORT_ERROR(err));
+        gnutls_x509_crt_deinit(cert);
+        return(NULL);
+    }
+
+    return(cert);
+}
+
+xmlChar*
+xmlSecGnuTLSX509CertBase64DerWrite(gnutls_x509_crt_t cert, int base64LineWrap) {
+    xmlChar * res = NULL;
+    xmlSecByte* buf = NULL;
+    size_t bufSize = 0;
+    int err;
+
+    xmlSecAssert2(cert != NULL, NULL);
+
+    /* get size */
+    err = gnutls_x509_crt_export(cert, GNUTLS_X509_FMT_DER, NULL, &bufSize);
+    if((err != GNUTLS_E_SHORT_MEMORY_BUFFER) || (bufSize <= 0)) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "gnutls_x509_crt_export(GNUTLS_X509_FMT_DER)",
+                    XMLSEC_ERRORS_R_CRYPTO_FAILED,
+                    XMLSEC_GNUTLS_REPORT_ERROR(err));
+        return(NULL);
+    }
+
+    /* allocate buffer */
+    buf = (xmlSecByte *)xmlMalloc(bufSize + 1);
+    if(buf == NULL) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "xmlMalloc",
+                    XMLSEC_ERRORS_R_MALLOC_FAILED,
+                    "size=%d", (int)bufSize);
+        return(NULL);
+    }
+
+    /* write it out */
+    err = gnutls_x509_crt_export(cert, GNUTLS_X509_FMT_DER, buf, &bufSize);
+    if(err != GNUTLS_E_SUCCESS) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "gnutls_x509_crt_export(GNUTLS_X509_FMT_DER)",
+                    XMLSEC_ERRORS_R_CRYPTO_FAILED,
+                    XMLSEC_GNUTLS_REPORT_ERROR(err));
+        xmlFree(buf);
+        return(NULL);
+    }
+
+    /* convert to string */
+    res = xmlSecBase64Encode(buf, bufSize, base64LineWrap);
+    if(res == NULL) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "xmlSecBase64Encode",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        xmlFree(buf);
+        return(NULL);
+    }
+
+    /* done */
+    xmlFree(buf);
+    return(res);
+}
+
+void
+xmlSecGnuTLSX509CertDebugDump(gnutls_x509_crt_t cert, FILE* output) {
+    xmlChar * buf;
+
+    xmlSecAssert(cert != NULL);
+    xmlSecAssert(output != NULL);
+
+    buf = xmlSecGnuTLSX509CertGetSubjectDN(cert);
+    if(buf != NULL) {
+        fprintf(output, "==== Subject Name: %s\n", buf);
+        xmlFree(buf);
+    } else {
+        fprintf(output, "==== Subject Name: unknown\n");
+    }
+
+    buf = xmlSecGnuTLSX509CertGetIssuerDN(cert);
+    if(buf != NULL) {
+        fprintf(output, "==== Issuer Name: %s\n", buf);
+        xmlFree(buf);
+    } else {
+        fprintf(output, "==== Issuer Name: unknown\n");
+    }
+
+    buf = xmlSecGnuTLSX509CertGetIssuerSerial(cert);
+    if(buf != NULL) {
+        fprintf(output, "==== Issuer Serial: %s\n", buf);
+        xmlFree(buf);
+    } else {
+        fprintf(output, "==== Issuer Serial: unknown\n");
+    }
+}
+
+void
+xmlSecGnuTLSX509CertDebugXmlDump(gnutls_x509_crt_t cert, FILE* output) {
+    xmlChar * buf;
+
+    xmlSecAssert(cert != NULL);
+    xmlSecAssert(output != NULL);
+
+    buf = xmlSecGnuTLSX509CertGetSubjectDN(cert);
+    if(buf != NULL) {
+        fprintf(output, "<SubjectName>%s</SubjectName>\n", buf);
+        xmlFree(buf);
+    } else {
+        fprintf(output, "<SubjectName>unknown</SubjectName>\n");
+    }
+
+    buf = xmlSecGnuTLSX509CertGetIssuerDN(cert);
+    if(buf != NULL) {
+        fprintf(output, "<IssuerName>%s</IssuerName>\n", buf);
+        xmlFree(buf);
+    } else {
+        fprintf(output, "<IssuerName>unknown</IssuerName>\n");
+    }
+
+    buf = xmlSecGnuTLSX509CertGetIssuerSerial(cert);
+    if(buf != NULL) {
+        fprintf(output, "<SerialNumber>%s</SerialNumber>\n", buf);
+        xmlFree(buf);
+    } else {
+        fprintf(output, "<SerialNumber>unknown</SerialNumber>\n");
+    }
+}
+
+xmlChar*
+xmlSecGnuTLSASN1IntegerWrite(const unsigned char * data, size_t len) {
+    xmlChar *res = NULL;
+    int resLen = 64; /* not more than 64 chars */
+    unsigned long long int val = 0;
+    size_t ii = 0;
+    int shift = 0;
+
+    xmlSecAssert2(data != NULL, NULL);
+    xmlSecAssert2(len <= 8, NULL);
+
+    /* HACK : to be fixed after GnuTLS provides a way to read opaque ASN1 integer */
+    for(ii = len; ii > 0; --ii, shift += 8) {
+        val |= ((unsigned long long)data[ii - 1]) << shift;
+    }
+
+    res = (xmlChar*)xmlMalloc(resLen + 1);
+    if(res == NULL) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "xmlMalloc",
+                    XMLSEC_ERRORS_R_MALLOC_FAILED,
+                    "size=%d", (int)resLen);
+        return (NULL);
+    }
+
+    xmlSecStrPrintf(res, resLen, BAD_CAST "%llu", val);
+    return(res);
+}
+
+#endif /* XMLSEC_NO_X509 */
diff --git a/src/gnutls/x509utils.h b/src/gnutls/x509utils.h
new file mode 100644
index 0000000..b0727f2
--- /dev/null
+++ b/src/gnutls/x509utils.h
@@ -0,0 +1,65 @@
+/*
+ * XML Security Library
+ *
+ * THIS IS A PRIVATE XMLSEC HEADER FILE
+ * DON'T USE IT IN YOUR APPLICATION
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2010 Aleksey Sanin <aleksey aleksey com>
+ */
+#ifndef __XMLSEC_GNUTLS_X509UTILS_H__
+#define __XMLSEC_GNUTLS_X509UTILS_H__
+
+#ifndef XMLSEC_PRIVATE
+#error "gnutls/x509utils.h file contains private xmlsec definitions and should not be used outside xmlsec or xmlsec-<crypto> libraries"
+#endif /* XMLSEC_PRIVATE */
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#ifndef XMLSEC_NO_X509
+
+/**************************************************************************
+ *
+ * X509 certs list
+ *
+ *****************************************************************************/
+#define xmlSecGnuTLSX509CrtListId   \
+        xmlSecGnuTLSX509CrtListGetKlass()
+xmlSecPtrListId         xmlSecGnuTLSX509CrtListGetKlass         (void);
+
+
+/*************************************************************************
+ *
+ * Utils/helpers
+ *
+ ************************************************************************/
+gnutls_x509_crt_t       xmlSecGnuTLSX509CertDup                 (gnutls_x509_crt_t src);
+xmlChar *               xmlSecGnuTLSX509CertGetSubjectDN        (gnutls_x509_crt_t cert);
+xmlChar *               xmlSecGnuTLSX509CertGetIssuerDN         (gnutls_x509_crt_t cert);
+xmlChar *               xmlSecGnuTLSX509CertGetIssuerSerial     (gnutls_x509_crt_t cert);
+xmlChar *               xmlSecGnuTLSX509CertGetSKI              (gnutls_x509_crt_t cert);
+gnutls_x509_crt_t       xmlSecGnuTLSX509CertDerRead             (const xmlSecByte* buf,
+                                                                 xmlSecSize size);
+gnutls_x509_crt_t       xmlSecGnuTLSX509CertBase64DerRead       (xmlChar* buf);
+xmlChar*                xmlSecGnuTLSX509CertBase64DerWrite      (gnutls_x509_crt_t cert,
+                                                                 int base64LineWrap);
+void                    xmlSecGnuTLSX509CertDebugDump           (gnutls_x509_crt_t cert,
+                                                                 FILE* output);
+void                    xmlSecGnuTLSX509CertDebugXmlDump        (gnutls_x509_crt_t cert,
+                                                                 FILE* output);
+xmlChar*                xmlSecGnuTLSASN1IntegerWrite            (const unsigned char * data, 
+                                                                 size_t len);
+
+
+#endif /* XMLSEC_NO_X509 */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* ! __XMLSEC_GNUTLS_X509UTILS_H__ */
diff --git a/src/gnutls/x509vfy.c b/src/gnutls/x509vfy.c
new file mode 100644
index 0000000..e4bb7d1
--- /dev/null
+++ b/src/gnutls/x509vfy.c
@@ -0,0 +1,541 @@
+/**
+ * XMLSec library
+ *
+ * X509 support
+ *
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ *
+ * Copyright (C) 2010 Aleksey Sanin <aleksey aleksey com>
+ */
+#include "globals.h"
+
+#ifndef XMLSEC_NO_X509
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include <libxml/tree.h>
+
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/keys.h>
+#include <xmlsec/keyinfo.h>
+#include <xmlsec/keysmngr.h>
+#include <xmlsec/base64.h>
+#include <xmlsec/errors.h>
+
+#include <xmlsec/gnutls/crypto.h>
+#include <xmlsec/gnutls/x509.h>
+
+#include "x509utils.h"
+
+/**************************************************************************
+ *
+ * Internal GnuTLS X509 store CTX
+ *
+ *************************************************************************/
+typedef struct _xmlSecGnuTLSX509StoreCtx                xmlSecGnuTLSX509StoreCtx,
+                                                        *xmlSecGnuTLSX509StoreCtxPtr;
+struct _xmlSecGnuTLSX509StoreCtx {
+    xmlSecPtrList certsTrusted;
+    xmlSecPtrList certsUntrusted;
+};
+
+/****************************************************************************
+ *
+ * xmlSecGnuTLSKeyDataStoreX509Id:
+ *
+ * xmlSecGnuTLSX509StoreCtx is located after xmlSecTransform
+ *
+ ***************************************************************************/
+#define xmlSecGnuTLSX509StoreGetCtx(store) \
+    ((xmlSecGnuTLSX509StoreCtxPtr)(((xmlSecByte*)(store)) + \
+                                    sizeof(xmlSecKeyDataStoreKlass)))
+#define xmlSecGnuTLSX509StoreSize      \
+    (sizeof(xmlSecKeyDataStoreKlass) + sizeof(xmlSecGnuTLSX509StoreCtx))
+
+static int              xmlSecGnuTLSX509StoreInitialize                 (xmlSecKeyDataStorePtr store);
+static void             xmlSecGnuTLSX509StoreFinalize                   (xmlSecKeyDataStorePtr store);
+
+static xmlSecKeyDataStoreKlass xmlSecGnuTLSX509StoreKlass = {
+    sizeof(xmlSecKeyDataStoreKlass),
+    xmlSecGnuTLSX509StoreSize,
+
+    /* data */
+    xmlSecNameX509Store,                        /* const xmlChar* name; */
+
+    /* constructors/destructor */
+    xmlSecGnuTLSX509StoreInitialize,            /* xmlSecKeyDataStoreInitializeMethod initialize; */
+    xmlSecGnuTLSX509StoreFinalize,              /* xmlSecKeyDataStoreFinalizeMethod finalize; */
+
+    /* reserved for the future */
+    NULL,                                       /* void* reserved0; */
+    NULL,                                       /* void* reserved1; */
+};
+
+static gnutls_x509_crt_t xmlSecGnuTLSX509FindCert                       (xmlSecPtrListPtr certs,
+                                                                         const xmlChar *subjectName,
+                                                                         const xmlChar *issuerName,
+                                                                         const xmlChar *issuerSerial,
+                                                                         const xmlChar *ski);
+
+/**
+ * xmlSecGnuTLSX509StoreGetKlass:
+ *
+ * The GnuTLS X509 certificates key data store klass.
+ *
+ * Returns: pointer to GnuTLS X509 certificates key data store klass.
+ */
+xmlSecKeyDataStoreId
+xmlSecGnuTLSX509StoreGetKlass(void) {
+    return(&xmlSecGnuTLSX509StoreKlass);
+}
+
+/**
+ * xmlSecGnuTLSX509StoreFindCert:
+ * @store:              the pointer to X509 key data store klass.
+ * @subjectName:        the desired certificate name.
+ * @issuerName:         the desired certificate issuer name.
+ * @issuerSerial:       the desired certificate issuer serial number.
+ * @ski:                the desired certificate SKI.
+ * @keyInfoCtx:         the pointer to <dsig:KeyInfo/> element processing context.
+ *
+ * Searches @store for a certificate that matches given criteria.
+ *
+ * Returns: pointer to found certificate or NULL if certificate is not found
+ * or an error occurs.
+ */
+gnutls_x509_crt_t
+xmlSecGnuTLSX509StoreFindCert(xmlSecKeyDataStorePtr store,
+                              const xmlChar *subjectName,
+                              const xmlChar *issuerName,
+                              const xmlChar *issuerSerial,
+                              const xmlChar *ski,
+                              const xmlSecKeyInfoCtx* keyInfoCtx) {
+    xmlSecGnuTLSX509StoreCtxPtr ctx;
+    gnutls_x509_crt_t res = NULL;
+
+    xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecGnuTLSX509StoreId), NULL);
+    xmlSecAssert2(keyInfoCtx != NULL, NULL);
+
+    ctx = xmlSecGnuTLSX509StoreGetCtx(store);
+    xmlSecAssert2(ctx != NULL, NULL);
+
+    if(res == NULL) {
+        res = xmlSecGnuTLSX509FindCert(&(ctx->certsTrusted), subjectName, issuerName, issuerSerial, ski);
+    }
+    if(res == NULL) {
+        res = xmlSecGnuTLSX509FindCert(&(ctx->certsUntrusted), subjectName, issuerName, issuerSerial, ski);
+    }
+    return(res);
+}
+
+/**
+ * xmlSecGnuTLSX509StoreVerify:
+ * @store:              the pointer to X509 key data store klass.
+ * @certs:              the untrusted certificates stack.
+ * @keyInfoCtx:         the pointer to <dsig:KeyInfo/> element processing context.
+ *
+ * Verifies @certs list.
+ *
+ * Returns: pointer to the first verified certificate from @certs.
+ */
+gnutls_x509_crt_t
+xmlSecGnuTLSX509StoreVerify(xmlSecKeyDataStorePtr store,
+                            xmlSecPtrListPtr certs,
+                            const xmlSecKeyInfoCtx* keyInfoCtx) {
+    return(NULL);
+
+#ifdef TODO
+    xmlSecGnuTLSX509StoreCtxPtr ctx;
+    STACK_OF(X509)* certs2 = NULL;
+    X509 * res = NULL;
+    X509 * cert;
+    X509 * err_cert = NULL;
+    char buf[256];
+    int err = 0, depth;
+    int i;
+    int ret;
+
+    xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecGnuTLSX509StoreId), NULL);
+    xmlSecAssert2(certs != NULL, NULL);
+    xmlSecAssert2(keyInfoCtx != NULL, NULL);
+
+    ctx = xmlSecGnuTLSX509StoreGetCtx(store);
+    xmlSecAssert2(ctx != NULL, NULL);
+    xmlSecAssert2(ctx->xst != NULL, NULL);
+
+    /* dup certs */
+    certs2 = sk_X509_dup(certs);
+    if(certs2 == NULL) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+                    "sk_X509_dup",
+                    XMLSEC_ERRORS_R_CRYPTO_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        goto done;
+    }
+
+    /* add untrusted certs from the store */
+    for(i = 0; i < sk_X509_num(ctx->certsUntrusted); ++i) {
+        ret = sk_X509_push(certs2, sk_X509_value(ctx->certsUntrusted, i));
+        if(ret < 1) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                        xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+                        "sk_X509_push",
+                        XMLSEC_ERRORS_R_CRYPTO_FAILED,
+                        XMLSEC_ERRORS_NO_MESSAGE);
+            goto done;
+        }
+    }
+
+    /* TODO: remove all revoked certs */
+
+    /* get one cert after another and try to verify */
+    for(i = 0; i < sk_X509_num(certs2); ++i) {
+        cert = sk_X509_value(certs2, i);
+        if(xmlSecGnuTLSX509FindNextChainCert(certs2, cert) == NULL) {
+            X509_STORE_CTX xsc;
+
+#if !defined(XMLSEC_OPENSSL_096) && !defined(XMLSEC_OPENSSL_097)
+            X509_VERIFY_PARAM * vpm = NULL;
+            unsigned long vpm_flags = 0;
+
+            vpm = X509_VERIFY_PARAM_new();
+            if(vpm == NULL) {
+                xmlSecError(XMLSEC_ERRORS_HERE,
+                            xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+                            "X509_VERIFY_PARAM_new",
+                            XMLSEC_ERRORS_R_CRYPTO_FAILED,
+                            XMLSEC_ERRORS_NO_MESSAGE);
+                goto done;
+            }
+            vpm_flags = vpm->flags;
+/*
+            vpm_flags &= (~X509_V_FLAG_X509_STRICT);
+*/
+
+            X509_VERIFY_PARAM_set_depth(vpm, 9);
+            X509_VERIFY_PARAM_set_flags(vpm, vpm_flags);
+#endif /* !defined(XMLSEC_OPENSSL_096) && !defined(XMLSEC_OPENSSL_097) */
+
+
+            X509_STORE_CTX_init (&xsc, ctx->xst, cert, certs2);
+
+            if(keyInfoCtx->certsVerificationTime > 0) {
+#if !defined(XMLSEC_OPENSSL_096) && !defined(XMLSEC_OPENSSL_097)
+                vpm_flags |= X509_V_FLAG_USE_CHECK_TIME;
+                X509_VERIFY_PARAM_set_time(vpm, keyInfoCtx->certsVerificationTime);
+#endif /* !defined(XMLSEC_OPENSSL_096) && !defined(XMLSEC_OPENSSL_097) */
+                X509_STORE_CTX_set_time(&xsc, 0, keyInfoCtx->certsVerificationTime);
+            }
+
+#if !defined(XMLSEC_OPENSSL_096) && !defined(XMLSEC_OPENSSL_097)
+            X509_STORE_CTX_set0_param(&xsc, vpm);
+#endif /* !defined(XMLSEC_OPENSSL_096) && !defined(XMLSEC_OPENSSL_097) */
+
+
+            ret         = X509_verify_cert(&xsc);
+            err_cert    = X509_STORE_CTX_get_current_cert(&xsc);
+            err         = X509_STORE_CTX_get_error(&xsc);
+            depth       = X509_STORE_CTX_get_error_depth(&xsc);
+
+            X509_STORE_CTX_cleanup (&xsc);
+
+            if(ret == 1) {
+                res = cert;
+                goto done;
+            } else if(ret < 0) {
+                const char* err_msg;
+
+                buf[0] = '\0';
+                X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof buf);
+                err_msg = X509_verify_cert_error_string(err);
+                xmlSecError(XMLSEC_ERRORS_HERE,
+                            xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+                            "X509_verify_cert",
+                            XMLSEC_ERRORS_R_CRYPTO_FAILED,
+                            "subj=%s;err=%d;msg=%s",
+                            xmlSecErrorsSafeString(buf),
+                            err,
+                            xmlSecErrorsSafeString(err_msg));
+                goto done;
+            } else if(ret == 0) {
+                const char* err_msg;
+
+                buf[0] = '\0';
+                X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof buf);
+                err_msg = X509_verify_cert_error_string(err);
+                xmlSecError(XMLSEC_ERRORS_HERE,
+                            xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+                            "X509_verify_cert",
+                            XMLSEC_ERRORS_R_CRYPTO_FAILED,
+                            "subj=%s;err=%d;msg=%s",
+                            xmlSecErrorsSafeString(buf),
+                            err,
+                            xmlSecErrorsSafeString(err_msg));
+            }
+        }
+    }
+
+    /* if we came here then we found nothing. do we have any error? */
+    if((err != 0) && (err_cert != NULL)) {
+        const char* err_msg;
+
+        err_msg = X509_verify_cert_error_string(err);
+        switch (err) {
+        case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
+            X509_NAME_oneline(X509_get_issuer_name(err_cert), buf, sizeof buf);
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                        xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+                        NULL,
+                        XMLSEC_ERRORS_R_CERT_ISSUER_FAILED,
+                        "err=%d;msg=%s;issuer=%s",
+                        err,
+                        xmlSecErrorsSafeString(err_msg),
+                        xmlSecErrorsSafeString(buf));
+            break;
+        case X509_V_ERR_CERT_NOT_YET_VALID:
+        case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                        xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+                        NULL,
+                        XMLSEC_ERRORS_R_CERT_NOT_YET_VALID,
+                        "err=%d;msg=%s", err,
+                        xmlSecErrorsSafeString(err_msg));
+            break;
+        case X509_V_ERR_CERT_HAS_EXPIRED:
+        case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                        xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+                        NULL,
+                        XMLSEC_ERRORS_R_CERT_HAS_EXPIRED,
+                        "err=%d;msg=%s", err,
+                        xmlSecErrorsSafeString(err_msg));
+            break;
+        default:
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                        xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+                        NULL,
+                        XMLSEC_ERRORS_R_CERT_VERIFY_FAILED,
+                        "err=%d;msg=%s", err,
+                        xmlSecErrorsSafeString(err_msg));
+        }
+    }
+
+done:
+    if(certs2 != NULL) {
+        sk_X509_free(certs2);
+    }
+    return(res);
+#endif /* TODO */
+}
+
+/**
+ * xmlSecGnuTLSX509StoreAdoptCert:
+ * @store:              the pointer to X509 key data store klass.
+ * @cert:               the pointer to GnuTLS X509 certificate.
+ * @type:               the certificate type (trusted/untrusted).
+ *
+ * Adds trusted (root) or untrusted certificate to the store.
+ *
+ * Returns: 0 on success or a negative value if an error occurs.
+ */
+int
+xmlSecGnuTLSX509StoreAdoptCert(xmlSecKeyDataStorePtr store, gnutls_x509_crt_t cert, xmlSecKeyDataType type) {
+    xmlSecGnuTLSX509StoreCtxPtr ctx;
+    int ret;
+
+    xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecGnuTLSX509StoreId), -1);
+    xmlSecAssert2(cert != NULL, -1);
+
+    ctx = xmlSecGnuTLSX509StoreGetCtx(store);
+    xmlSecAssert2(ctx != NULL, -1);
+
+    if((type & xmlSecKeyDataTypeTrusted) != 0) {
+        ret = xmlSecPtrListAdd(&(ctx->certsTrusted), cert);
+        if(ret < 0) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                        xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+                        "xmlSecPtrListAdd(trusted)",
+                        XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                        XMLSEC_ERRORS_NO_MESSAGE);
+            return(-1);
+        }
+    } else {
+        ret = xmlSecPtrListAdd(&(ctx->certsUntrusted), cert);
+        if(ret < 0) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                        xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+                        "xmlSecPtrListAdd(untrusted)",
+                        XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                        XMLSEC_ERRORS_NO_MESSAGE);
+            return(-1);
+        }
+    }
+
+    /* done */
+    return(0);
+}
+
+static int
+xmlSecGnuTLSX509StoreInitialize(xmlSecKeyDataStorePtr store) {
+    xmlSecGnuTLSX509StoreCtxPtr ctx;
+    int ret;
+
+    xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecGnuTLSX509StoreId), -1);
+
+    ctx = xmlSecGnuTLSX509StoreGetCtx(store);
+    xmlSecAssert2(ctx != NULL, -1);
+
+    memset(ctx, 0, sizeof(xmlSecGnuTLSX509StoreCtx));
+
+    ret = xmlSecPtrListInitialize(&(ctx->certsTrusted), xmlSecGnuTLSX509CrtListId);
+    if(ret < 0) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+                    "xmlSecPtrListInitialize(trusted)",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        return(-1);
+    }
+
+    ret = xmlSecPtrListInitialize(&(ctx->certsUntrusted), xmlSecGnuTLSX509CrtListId);
+    if(ret < 0) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)),
+                    "xmlSecPtrListInitialize(untrusted)",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        return(-1);
+    }
+
+    return(0);
+}
+
+static void
+xmlSecGnuTLSX509StoreFinalize(xmlSecKeyDataStorePtr store) {
+    xmlSecGnuTLSX509StoreCtxPtr ctx;
+    xmlSecAssert(xmlSecKeyDataStoreCheckId(store, xmlSecGnuTLSX509StoreId));
+
+    ctx = xmlSecGnuTLSX509StoreGetCtx(store);
+    xmlSecAssert(ctx != NULL);
+
+    xmlSecPtrListFinalize(&(ctx->certsTrusted));
+    xmlSecPtrListFinalize(&(ctx->certsUntrusted));
+
+    memset(ctx, 0, sizeof(xmlSecGnuTLSX509StoreCtx));
+}
+
+
+/*****************************************************************************
+ *
+ * Low-level x509 functions
+ *
+ *****************************************************************************/
+static gnutls_x509_crt_t
+xmlSecGnuTLSX509FindCert(xmlSecPtrListPtr certs,
+                         const xmlChar *subjectName,
+                         const xmlChar *issuerName,
+                         const xmlChar *issuerSerial,
+                         const xmlChar *ski) {
+    xmlSecSize ii, sz;
+
+    xmlSecAssert2(certs != NULL, NULL);
+
+
+    /* todo: this is not the fastest way to search certs */
+    sz = xmlSecPtrListGetSize(certs);
+    for(ii = 0; (ii < sz); ++ii) {
+        gnutls_x509_crt_t cert = xmlSecPtrListGetItem(certs, ii);
+        if(cert == NULL) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                        NULL,
+                        "xmlSecPtrListGetItem",
+                        XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                        "pos=%i", (int)ii);
+            return(NULL);
+        }
+
+        if(subjectName != NULL) {
+            xmlChar * tmp;
+
+            tmp = xmlSecGnuTLSX509CertGetSubjectDN(cert);
+            if(tmp == NULL) {
+                xmlSecError(XMLSEC_ERRORS_HERE,
+                            NULL,
+                            "xmlSecGnuTLSX509CertGetSubjectDN",
+                            XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                            "pos=%i", (int)ii);
+                return(NULL);
+            }
+
+            if(xmlStrEqual(subjectName, tmp)) {
+                xmlFree(tmp);
+                return(cert);
+            }
+            xmlFree(tmp);
+        } else if((issuerName != NULL) && (issuerSerial != NULL)) {
+            xmlChar * tmp1;
+            xmlChar * tmp2;
+
+            tmp1 = xmlSecGnuTLSX509CertGetIssuerDN(cert);
+            if(tmp1 == NULL) {
+                xmlSecError(XMLSEC_ERRORS_HERE,
+                            NULL,
+                            "xmlSecGnuTLSX509CertGetIssuerDN",
+                            XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                            "pos=%i", (int)ii);
+                return(NULL);
+            }
+
+            tmp2 = xmlSecGnuTLSX509CertGetIssuerSerial(cert);
+            if(tmp2 == NULL) {
+                xmlSecError(XMLSEC_ERRORS_HERE,
+                            NULL,
+                            "xmlSecGnuTLSX509CertGetIssuerSerial",
+                            XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                            "pos=%i", (int)ii);
+                xmlFree(tmp1);
+                return(NULL);
+            }
+
+            if(xmlStrEqual(issuerName, tmp1) && xmlStrEqual(issuerSerial, tmp2)) {
+                xmlFree(tmp1);
+                xmlFree(tmp2);
+                return(cert);
+            }
+            xmlFree(tmp1);
+            xmlFree(tmp2);
+        } else if(ski != NULL) {
+            xmlChar * tmp;
+
+            tmp = xmlSecGnuTLSX509CertGetSKI(cert);
+            if(tmp == NULL) {
+                xmlSecError(XMLSEC_ERRORS_HERE,
+                            NULL,
+                            "xmlSecGnuTLSX509CertGetSKI",
+                            XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                            "pos=%i", (int)ii);
+                return(NULL);
+            }
+
+            if(xmlStrEqual(ski, tmp)) {
+                xmlFree(tmp);
+                return(cert);
+            }
+            xmlFree(tmp);
+        }
+    }
+
+    return(NULL);
+}
+
+#endif /* XMLSEC_NO_X509 */
+
+



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]