[xmlsec] added pkcs12 support for xmlsec-gnutls



commit c31c85a8aa19f571fcae601ced3dac0e73cf7101
Author: Aleksey Sanin <aleksey aleksey com>
Date:   Sun May 23 23:05:11 2010 -0700

    added pkcs12 support for xmlsec-gnutls

 include/xmlsec/list.h  |    2 +
 src/gnutls/app.c       |  299 ++++++++++++++++++++++++++++++++++++----
 src/gnutls/asymkeys.c  |  202 +++++++++++++++++++++++++++-
 src/gnutls/x509.c      |    8 +-
 src/gnutls/x509utils.c |  357 +++++++++++++++++++++++++++++++++++++++++++++++-
 src/gnutls/x509utils.h |   22 +++-
 src/list.c             |   26 ++++
 src/openssl/app.c      |   71 +++++-----
 tests/testrun.sh       |    2 +-
 9 files changed, 912 insertions(+), 77 deletions(-)
---
diff --git a/include/xmlsec/list.h b/include/xmlsec/list.h
index e7900e7..fed9870 100644
--- a/include/xmlsec/list.h
+++ b/include/xmlsec/list.h
@@ -67,6 +67,8 @@ XMLSEC_EXPORT int               xmlSecPtrListSet                (xmlSecPtrListPt
                                                                  xmlSecSize pos);
 XMLSEC_EXPORT int               xmlSecPtrListRemove             (xmlSecPtrListPtr list,
                                                                  xmlSecSize pos);
+XMLSEC_EXPORT xmlSecPtr         xmlSecPtrListRemoveAndReturn    (xmlSecPtrListPtr list,
+                                                                 xmlSecSize pos);
 XMLSEC_EXPORT void              xmlSecPtrListDebugDump          (xmlSecPtrListPtr list,
                                                                  FILE* output);
 XMLSEC_EXPORT void              xmlSecPtrListDebugXmlDump       (xmlSecPtrListPtr list,
diff --git a/src/gnutls/app.c b/src/gnutls/app.c
index f01598b..18afb37 100644
--- a/src/gnutls/app.c
+++ b/src/gnutls/app.c
@@ -10,10 +10,6 @@
 
 #include <string.h>
 
-#include <gnutls/gnutls.h>
-#include <gnutls/x509.h>
-#include <gnutls/pkcs12.h>
-
 #include <xmlsec/xmlsec.h>
 #include <xmlsec/keys.h>
 #include <xmlsec/transforms.h>
@@ -21,6 +17,9 @@
 
 #include <xmlsec/gnutls/app.h>
 #include <xmlsec/gnutls/crypto.h>
+#include <xmlsec/gnutls/x509.h>
+
+#include "x509utils.h"
 
 /**************************************************************************
  *
@@ -225,18 +224,47 @@ xmlSecGnuTLSAppKeyCertLoadMemory(xmlSecKeyPtr key,
                                  const xmlSecByte* data,
                                  xmlSecSize dataSize,
                                  xmlSecKeyDataFormat format) {
+    gnutls_x509_crt_t cert;
+    xmlSecKeyDataPtr keyData;
+    int ret;
+
     xmlSecAssert2(key != NULL, -1);
     xmlSecAssert2(data != NULL, -1);
     xmlSecAssert2(dataSize > 0, -1);
     xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1);
 
-    /* TODO */
-    xmlSecError(XMLSEC_ERRORS_HERE,
-                NULL,
-                "xmlSecGnuTLSAppKeyCertLoadMemory",
-                XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
-                XMLSEC_ERRORS_NO_MESSAGE);
-    return(-1);
+    keyData = xmlSecKeyEnsureData(key, xmlSecGnuTLSKeyDataX509Id);
+    if(keyData == NULL) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "xmlSecKeyEnsureData",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        return(-1);
+    }
+
+    cert = xmlSecGnuTLSX509CertRead(data, dataSize, format);
+    if(cert == NULL) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "xmlSecGnuTLSX509CertRead",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        return(-1);
+    }
+
+    ret = xmlSecGnuTLSKeyDataX509AdoptCert(keyData, cert);
+    if(ret < 0) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "xmlSecGnuTLSKeyDataX509AdoptCert",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        gnutls_x509_crt_deinit(cert);
+        return(-1);
+    }
+
+    return(0);
 }
 
 /**
@@ -321,19 +349,203 @@ xmlSecGnuTLSAppPkcs12Load(const char *filename,
  */
 xmlSecKeyPtr
 xmlSecGnuTLSAppPkcs12LoadMemory(const xmlSecByte* data, xmlSecSize dataSize,
-                           const char *pwd ATTRIBUTE_UNUSED,
-                           void* pwdCallback ATTRIBUTE_UNUSED,
-                           void* pwdCallbackCtx ATTRIBUTE_UNUSED) {
+                                const char *pwd,
+                                void* pwdCallback ATTRIBUTE_UNUSED,
+                                void* pwdCallbackCtx ATTRIBUTE_UNUSED)
+{
+    xmlSecKeyPtr key = NULL;
+    xmlSecKeyPtr res = NULL;
+    xmlSecPtrList certsList;
+    xmlSecKeyDataPtr keyData = NULL;
+    xmlSecKeyDataPtr x509Data = NULL;
+    gnutls_x509_privkey_t priv_key = NULL;
+    gnutls_x509_crt_t cert = NULL;
+    xmlSecSize certsSize;
+    int err;
+    int ret;
+
     xmlSecAssert2(data != NULL, NULL);
     xmlSecAssert2(dataSize > 0, NULL);
 
-    /* TODO */
-    xmlSecError(XMLSEC_ERRORS_HERE,
-                NULL,
-                "xmlSecGnuTLSAppPkcs12LoadMemory",
-                XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
-                XMLSEC_ERRORS_NO_MESSAGE);
-    return(NULL);
+    /* prepare */
+    ret = xmlSecPtrListInitialize(&(certsList), xmlSecGnuTLSX509CrtListId);
+    if(ret < 0) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "xmlSecPtrListInitialize",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    "certsList");
+        return(NULL);
+    }
+
+    key = xmlSecKeyCreate();
+    if(key == NULL) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "xmlSecKeyCreate",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        goto done;
+    }
+
+    /* load pkcs12 */
+    ret = xmlSecGnuTLSPkcs12LoadMemory(data, dataSize, pwd, &priv_key, &certsList);
+    if((ret < 0) || (priv_key == NULL)) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "xmlSecGnuTLSPkcs12LoadMemory",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        goto done;
+    }
+
+    /* create x509 certs data */
+    certsSize = xmlSecPtrListGetSize(&certsList);
+    if(certsSize > 0) {
+        size_t cert_id_size = 0;
+        size_t key_id_size = 0;
+        xmlSecByte cert_id[100];
+        xmlSecByte key_id[100];
+        xmlSecSize ii;
+
+        x509Data = xmlSecKeyDataCreate(xmlSecGnuTLSKeyDataX509Id);
+        if(x509Data == NULL) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                        NULL,
+                        "xmlSecKeyDataCreate(xmlSecGnuTLSKeyDataX509Id)",
+                        XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                        XMLSEC_ERRORS_NO_MESSAGE);
+            goto done;
+        }
+
+        /* we will search for cert for this key using the key id */
+        key_id_size = sizeof(key_id);
+        err = gnutls_x509_privkey_get_key_id(priv_key, 0, key_id, &key_id_size);
+        if(err != GNUTLS_E_SUCCESS) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                        NULL,
+                        "gnutls_x509_privkey_get_key_id",
+                        XMLSEC_ERRORS_R_CRYPTO_FAILED,
+                        XMLSEC_GNUTLS_REPORT_ERROR(err));
+            goto done;
+        }
+        for(ii = 0; ii < certsSize; ++ii) {
+            cert = xmlSecPtrListRemoveAndReturn(&certsList, ii);
+            if(cert == NULL) {
+                continue;
+            }
+
+            cert_id_size = sizeof(cert_id);
+            err = gnutls_x509_crt_get_key_id(cert, 0, cert_id, &cert_id_size);
+            if(err != GNUTLS_E_SUCCESS) {
+                xmlSecError(XMLSEC_ERRORS_HERE,
+                            NULL,
+                            "gnutls_x509_crt_get_key_id",
+                            XMLSEC_ERRORS_R_CRYPTO_FAILED,
+                            XMLSEC_GNUTLS_REPORT_ERROR(err));
+                goto done;
+            }
+
+            /* if key ids match, then this is THE key cert!!! */
+            if((key_id_size == cert_id_size) && (memcmp(key_id, cert_id, key_id_size) == 0)) {
+                gnutls_x509_crt_t tmpCert;
+
+                tmpCert = xmlSecGnuTLSX509CertDup(cert);
+                if(tmpCert == NULL) {
+                    xmlSecError(XMLSEC_ERRORS_HERE,
+                                NULL,
+                                "xmlSecGnuTLSX509CertDup",
+                                XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                                XMLSEC_ERRORS_NO_MESSAGE);
+                    goto done;
+                }
+
+                ret = xmlSecGnuTLSKeyDataX509AdoptKeyCert(x509Data, tmpCert);
+                if(ret < 0) {
+                    xmlSecError(XMLSEC_ERRORS_HERE,
+                                NULL,
+                                "xmlSecGnuTLSKeyDataX509AdoptKeyCert",
+                                XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                                XMLSEC_ERRORS_NO_MESSAGE);
+                    gnutls_x509_crt_deinit(tmpCert);
+                    goto done;
+                }
+                tmpCert = NULL; /* owned by x509Data now */
+            }
+
+            ret = xmlSecGnuTLSKeyDataX509AdoptCert(x509Data, cert);
+            if(ret < 0) {
+                xmlSecError(XMLSEC_ERRORS_HERE,
+                            NULL,
+                            "xmlSecGnuTLSKeyDataX509AdoptCert",
+                            XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                            XMLSEC_ERRORS_NO_MESSAGE);
+                goto done;
+            }
+            cert = NULL; /* owned by x509Data now */
+        }
+
+        /* set in the key */
+        ret = xmlSecKeyAdoptData(key, x509Data);
+        if(ret < 0) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                        NULL,
+                        "xmlSecKeyAdoptData",
+                        XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                        "data=%s",
+                        xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data)));
+            goto done;
+        }
+        x509Data = NULL; /* owned by key now */
+    }
+
+
+    /* create key value data */
+    keyData = xmlSecGnuTLSCreateKeyDataAndAdoptPrivKey(priv_key);
+    if(keyData == NULL) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "xmlSecGnuTLSCreateKeyDataAndAdoptPrivKey",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        goto done;
+    }
+    priv_key = NULL; /* owned by keyData now */
+
+    ret = xmlSecKeySetValue(key, keyData);
+    if(ret < 0) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "xmlSecKeySetValue",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    "data=%s",
+                    xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data)));
+        goto done;
+    }
+    keyData = NULL; /* owned by key now */
+
+    /* success!!! */
+    res = key;
+    key = NULL;
+
+done:
+    if(cert != NULL) {
+        gnutls_x509_crt_deinit(cert);
+    }
+    if(priv_key != NULL) {
+        gnutls_x509_privkey_deinit(priv_key);
+    }
+    if(keyData != NULL) {
+        xmlSecKeyDataDestroy(keyData);
+    }
+    if(x509Data != NULL) {
+        xmlSecKeyDataDestroy(x509Data);
+    }
+    if(key != NULL) {
+        xmlSecKeyDestroy(key);
+    }
+    xmlSecPtrListFinalize(&certsList);
+    return(res);
 }
 
 /**
@@ -422,19 +634,48 @@ xmlSecGnuTLSAppKeysMngrCertLoadMemory(xmlSecKeysMngrPtr mngr,
                                       const xmlSecByte* data,
                                       xmlSecSize dataSize,
                                       xmlSecKeyDataFormat format,
-                                      xmlSecKeyDataType type ATTRIBUTE_UNUSED) {
+                                      xmlSecKeyDataType type) {
+    xmlSecKeyDataStorePtr x509Store;
+    gnutls_x509_crt_t cert;
+    int ret;
+
     xmlSecAssert2(mngr != NULL, -1);
     xmlSecAssert2(data != NULL, -1);
     xmlSecAssert2(dataSize > 0, -1);
     xmlSecAssert2(format != xmlSecKeyDataFormatUnknown, -1);
 
-    /* TODO */
-    xmlSecError(XMLSEC_ERRORS_HERE,
-                NULL,
-                "xmlSecGnuTLSAppKeysMngrCertLoadMemory",
-                XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
-                XMLSEC_ERRORS_NO_MESSAGE);
-    return(-1);
+    x509Store = xmlSecKeysMngrGetDataStore(mngr, xmlSecGnuTLSX509StoreId);
+    if(x509Store == NULL) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "xmlSecKeysMngrGetDataStore",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    "xmlSecGnuTLSX509StoreId");
+        return(-1);
+    }
+
+    cert = xmlSecGnuTLSX509CertRead(data, dataSize, format);
+    if(cert == NULL) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "xmlSecGnuTLSX509CertRead",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        return(-1);
+    }
+
+    ret = xmlSecGnuTLSX509StoreAdoptCert(x509Store, cert, type);
+    if(ret < 0) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "xmlSecGnuTLSX509StoreAdoptCert",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        gnutls_x509_crt_deinit(cert);
+        return(-1);
+    }
+
+    return(0);
 }
 
 #endif /* XMLSEC_NO_X509 */
diff --git a/src/gnutls/asymkeys.c b/src/gnutls/asymkeys.c
index cbb43ae..e1f7f00 100644
--- a/src/gnutls/asymkeys.c
+++ b/src/gnutls/asymkeys.c
@@ -31,6 +31,51 @@
 #include <xmlsec/gcrypt/crypto.h>
 #include <gcrypt.h>
 
+static void xmlSecGnuTLSDestroyParams(gnutls_datum_t * params, xmlSecSize num) {
+    xmlSecSize ii;
+
+    xmlSecAssert(params != NULL);
+    for(ii = 0; ii < num; ++ii) {
+        gnutls_free(params[ii].data);
+    }
+}
+
+static void xmlSecGnuTLSDestroyMpis(gcry_mpi_t * mpis, xmlSecSize num) {
+    xmlSecSize ii;
+
+    xmlSecAssert(mpis != NULL);
+    for(ii = 0; ii < num; ++ii) {
+        gcry_mpi_release(mpis[ii]);
+    }
+}
+
+static int xmlSecGnuTLSConvertParamsToMpis(gnutls_datum_t * params, xmlSecSize paramsNum,
+                                           gcry_mpi_t * mpis, xmlSecSize mpisNum) {
+
+    xmlSecSize ii;
+    int err;
+
+    xmlSecAssert2(params != NULL, -1);
+    xmlSecAssert2(mpis != NULL, -1);
+    xmlSecAssert2(paramsNum == mpisNum, -1);
+
+    for(ii = 0; ii < paramsNum; ++ii) {
+        err = gcry_mpi_scan(&(mpis[ii]), GCRYMPI_FMT_USG, params[ii].data, params[ii].size, NULL);
+        if((err != GPG_ERR_NO_ERROR) || (mpis[ii] == NULL)) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                        NULL,
+                        "gcry_mpi_scan",
+                        XMLSEC_ERRORS_R_CRYPTO_FAILED,
+                        XMLSEC_GNUTLS_GCRYPT_REPORT_ERROR(err));
+            xmlSecGnuTLSDestroyMpis(mpis, ii); /* destroy up to now */
+            return(-1);
+        }
+    }
+
+    /* done */
+    return(0);
+}
+
 #ifndef XMLSEC_NO_DSA
 
 /**
@@ -56,10 +101,86 @@ xmlSecGnuTLSKeyDataDsaGetKlass(void) {
  */
 int
 xmlSecGnuTLSKeyDataDsaAdoptPrivateKey(xmlSecKeyDataPtr data, gnutls_x509_privkey_t dsa_key) {
+    gnutls_datum_t params[5];
+    gcry_mpi_t mpis[5];
+    gcry_sexp_t priv_key = NULL;
+    gcry_sexp_t pub_key = NULL;
+    int rc;
+    int err;
+    int ret;
+
     xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGnuTLSKeyDataDsaId), -1);
     xmlSecAssert2(dsa_key != NULL, -1);
+    xmlSecAssert2(gnutls_x509_privkey_get_pk_algorithm(dsa_key) == GNUTLS_PK_DSA, -1);
 
-    /* ALEKSEY_TODO */
+    /* get raw values */
+    err = gnutls_x509_privkey_export_dsa_raw(dsa_key,
+            &(params[0]), &(params[1]), &(params[2]),
+            &(params[3]), &(params[4]));
+    if(err != GNUTLS_E_SUCCESS) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "gnutls_x509_privkey_export_dsa_raw",
+                    XMLSEC_ERRORS_R_CRYPTO_FAILED,
+                    XMLSEC_GNUTLS_REPORT_ERROR(err));
+        return(-1);
+    }
+
+    /* convert to mpis */
+    ret = xmlSecGnuTLSConvertParamsToMpis(
+            params, sizeof(params)/sizeof(params[0]),
+            mpis, sizeof(mpis)/sizeof(mpis[0]));
+    if(ret < 0) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "xmlSecGnuTLSConvertParamsToMpis",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        xmlSecGnuTLSDestroyParams(params, sizeof(params)/sizeof(params[0]));
+        return(-1);
+    }
+    xmlSecGnuTLSDestroyParams(params, sizeof(params)/sizeof(params[0]));
+
+    /* build expressions */
+    rc = gcry_sexp_build(&(priv_key), NULL, "(private-key(dsa(p%m)(q%m)(g%m)(y%m)(x%m)))",
+                        mpis[0], mpis[1], mpis[2], mpis[3], mpis[4]);
+    if((err != GPG_ERR_NO_ERROR) || (priv_key == NULL)) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "gcry_sexp_build(private/dsa)",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_GNUTLS_GCRYPT_REPORT_ERROR(err));
+        xmlSecGnuTLSDestroyMpis(mpis, sizeof(mpis)/sizeof(mpis[0]));
+        return(-1);
+    }
+    rc = gcry_sexp_build(&(pub_key), NULL, "(public-key(dsa(p%m)(q%m)(g%m)(y%m)))",
+                        mpis[0], mpis[1], mpis[2], mpis[3]);
+    if((err != GPG_ERR_NO_ERROR) || (priv_key == NULL)) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "gcry_sexp_build(private/rsa)",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_GNUTLS_GCRYPT_REPORT_ERROR(err));
+        gcry_sexp_release(priv_key);
+        xmlSecGnuTLSDestroyMpis(mpis, sizeof(mpis)/sizeof(mpis[0]));
+        return(-1);
+    }
+    xmlSecGnuTLSDestroyMpis(mpis, sizeof(mpis)/sizeof(mpis[0]));
+
+    ret = xmlSecGCryptKeyDataDsaAdoptKeyPair(data, pub_key, priv_key);
+    if(ret < 0) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "xmlSecGCryptKeyDataDsaAdoptKeyPair",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        gcry_sexp_release(pub_key);
+        gcry_sexp_release(priv_key);
+        return(-1);
+    }
+
+    /* done, we "adopted" the key - destroy it! */
+    gnutls_x509_privkey_deinit(dsa_key);
     return(0);
 }
 
@@ -118,10 +239,87 @@ xmlSecGnuTLSKeyDataRsaGetKlass(void) {
  */
 int
 xmlSecGnuTLSKeyDataRsaAdoptPrivateKey(xmlSecKeyDataPtr data, gnutls_x509_privkey_t rsa_key) {
+    gnutls_datum_t params[6];
+    gcry_mpi_t mpis[6];
+    gcry_sexp_t priv_key = NULL;
+    gcry_sexp_t pub_key = NULL;
+    int rc;
+    int err;
+    int ret;
+
     xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGnuTLSKeyDataRsaId), -1);
     xmlSecAssert2(rsa_key != NULL, -1);
+    xmlSecAssert2(gnutls_x509_privkey_get_pk_algorithm(rsa_key) == GNUTLS_PK_RSA, -1);
 
-    /* ALEKSEY_TODO */
+    /* get raw values */
+    err = gnutls_x509_privkey_export_rsa_raw(rsa_key,
+            &(params[0]), &(params[1]), &(params[2]),
+            &(params[3]), &(params[4]), &(params[5]));
+    if(err != GNUTLS_E_SUCCESS) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "gnutls_x509_privkey_export_rsa_raw",
+                    XMLSEC_ERRORS_R_CRYPTO_FAILED,
+                    XMLSEC_GNUTLS_REPORT_ERROR(err));
+        return(-1);
+    }
+
+    /* convert to mpis */
+    ret = xmlSecGnuTLSConvertParamsToMpis(
+            params, sizeof(params)/sizeof(params[0]),
+            mpis, sizeof(mpis)/sizeof(mpis[0]));
+    if(ret < 0) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "xmlSecGnuTLSConvertParamsToMpis",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        xmlSecGnuTLSDestroyParams(params, sizeof(params)/sizeof(params[0]));
+        return(-1);
+    }
+    xmlSecGnuTLSDestroyParams(params, sizeof(params)/sizeof(params[0]));
+
+    /* build expressions */
+    rc = gcry_sexp_build(&(priv_key), NULL, "(private-key(rsa((n%m)(e%m)(d%m)(p%m)(q%m)(u%m))))",
+                        mpis[0], mpis[1], mpis[2],
+                        mpis[3], mpis[4], mpis[5]);
+    if((err != GPG_ERR_NO_ERROR) || (priv_key == NULL)) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "gcry_sexp_build(private/rsa)",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_GNUTLS_GCRYPT_REPORT_ERROR(err));
+        xmlSecGnuTLSDestroyMpis(mpis, sizeof(mpis)/sizeof(mpis[0]));
+        return(-1);
+    }
+    rc = gcry_sexp_build(&(pub_key), NULL, "(public-key(rsa((n%m)(e%m))))",
+                        mpis[0], mpis[1]);
+    if((err != GPG_ERR_NO_ERROR) || (priv_key == NULL)) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "gcry_sexp_build(private/rsa)",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_GNUTLS_GCRYPT_REPORT_ERROR(err));
+        gcry_sexp_release(priv_key);
+        xmlSecGnuTLSDestroyMpis(mpis, sizeof(mpis)/sizeof(mpis[0]));
+        return(-1);
+    }
+    xmlSecGnuTLSDestroyMpis(mpis, sizeof(mpis)/sizeof(mpis[0]));
+
+    ret = xmlSecGCryptKeyDataRsaAdoptKeyPair(data, pub_key, priv_key);
+    if(ret < 0) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "xmlSecGCryptKeyDataRsaAdoptKeyPair",
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    XMLSEC_ERRORS_NO_MESSAGE);
+        gcry_sexp_release(pub_key);
+        gcry_sexp_release(priv_key);
+        return(-1);
+    }
+
+    /* done, we "adopted" the key - destroy it! */
+    gnutls_x509_privkey_deinit(rsa_key);
     return(0);
 }
 
diff --git a/src/gnutls/x509.c b/src/gnutls/x509.c
index 970f5f3..3326dd7 100644
--- a/src/gnutls/x509.c
+++ b/src/gnutls/x509.c
@@ -1425,6 +1425,7 @@ xmlSecGnuTLSX509CertGetKey(gnutls_x509_crt_t cert) {
     }
 
     switch(alg) {
+#ifndef XMLSEC_NO_RSA
     case GNUTLS_PK_RSA:
         {
             gnutls_datum_t m, e;
@@ -1463,7 +1464,9 @@ xmlSecGnuTLSX509CertGetKey(gnutls_x509_crt_t cert) {
             /* m and e are owned by data now */
         }
         break;
+#endif /* XMLSEC_NO_RSA */
 
+#ifndef XMLSEC_NO_DSA
     case GNUTLS_PK_DSA:
         {
             gnutls_datum_t p, q, g, y;
@@ -1504,6 +1507,7 @@ xmlSecGnuTLSX509CertGetKey(gnutls_x509_crt_t cert) {
             /* p, q, g and y are owned by data now */
         }
         break;
+#endif /* XMLSEC_NO_DSA */
 
     default:
         {
@@ -1597,11 +1601,11 @@ xmlSecGnuTLSKeyDataRawX509CertBinRead(xmlSecKeyDataId id, xmlSecKeyPtr key,
     xmlSecAssert2(bufSize > 0, -1);
     xmlSecAssert2(keyInfoCtx != NULL, -1);
 
-    cert = xmlSecGnuTLSX509CertDerRead(buf, bufSize);
+    cert = xmlSecGnuTLSX509CertRead(buf, bufSize, xmlSecKeyDataFormatCertDer);
     if(cert == NULL) {
         xmlSecError(XMLSEC_ERRORS_HERE,
                     NULL,
-                    "xmlSecGnuTLSX509CertDerRead",
+                    "xmlSecGnuTLSX509CertRead",
                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
                     XMLSEC_ERRORS_NO_MESSAGE);
         return(-1);
diff --git a/src/gnutls/x509utils.c b/src/gnutls/x509utils.c
index e87e8cf..14c292f 100644
--- a/src/gnutls/x509utils.c
+++ b/src/gnutls/x509utils.c
@@ -22,6 +22,12 @@
 
 #include <libxml/tree.h>
 
+
+
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+#include <gnutls/pkcs12.h>
+
 #include <xmlsec/xmlsec.h>
 #include <xmlsec/xmltree.h>
 #include <xmlsec/keys.h>
@@ -281,7 +287,6 @@ xmlSecGnuTLSX509CertGetIssuerSerial(gnutls_x509_crt_t cert) {
         xmlFree(buf);
         return(NULL);
     }
-    printf("DEBUG: serial number is %s\n", res);
 
     /* done */
     xmlFree(buf);
@@ -367,18 +372,37 @@ xmlSecGnuTLSX509CertBase64DerRead(xmlChar* buf) {
         return(NULL);
     }
 
-    return(xmlSecGnuTLSX509CertDerRead((const xmlSecByte*)buf, ret));
+    return(xmlSecGnuTLSX509CertRead((const xmlSecByte*)buf, ret, xmlSecKeyDataFormatCertDer));
 }
 
 gnutls_x509_crt_t
-xmlSecGnuTLSX509CertDerRead(const xmlSecByte* buf, xmlSecSize size) {
+xmlSecGnuTLSX509CertRead(const xmlSecByte* buf, xmlSecSize size, xmlSecKeyDataFormat format) {
     gnutls_x509_crt_t cert = NULL;
+    gnutls_x509_crt_fmt_t fmt;
     gnutls_datum_t data;
     int err;
 
     xmlSecAssert2(buf != NULL, NULL);
     xmlSecAssert2(size > 0, NULL);
 
+    /* figure out format */
+    switch(format) {
+    case xmlSecKeyDataFormatCertPem:
+        fmt = GNUTLS_X509_FMT_PEM;
+        break;
+    case xmlSecKeyDataFormatCertDer:
+        fmt = GNUTLS_X509_FMT_DER;
+        break;
+    default:
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    NULL,
+                    XMLSEC_ERRORS_R_INVALID_FORMAT,
+                    "format=%d", format);
+        return(NULL);
+    }
+
+    /* read cert */
     err = gnutls_x509_crt_init(&cert);
     if(err != GNUTLS_E_SUCCESS) {
         xmlSecError(XMLSEC_ERRORS_HERE,
@@ -391,7 +415,7 @@ xmlSecGnuTLSX509CertDerRead(const xmlSecByte* buf, xmlSecSize size) {
 
     data.data = (unsigned char*)buf;
     data.size = size;
-    err = gnutls_x509_crt_import(cert, &data, GNUTLS_X509_FMT_DER);
+    err = gnutls_x509_crt_import(cert, &data, fmt);
     if(err != GNUTLS_E_SUCCESS) {
         xmlSecError(XMLSEC_ERRORS_HERE,
                     NULL,
@@ -538,7 +562,7 @@ xmlSecGnuTLSASN1IntegerWrite(const unsigned char * data, size_t len) {
     int shift = 0;
 
     xmlSecAssert2(data != NULL, NULL);
-    xmlSecAssert2(len <= 8, NULL);
+    xmlSecAssert2(len <= 9, NULL);
 
     /* HACK : to be fixed after GnuTLS provides a way to read opaque ASN1 integer */
     for(ii = len; ii > 0; --ii, shift += 8) {
@@ -559,4 +583,327 @@ xmlSecGnuTLSASN1IntegerWrite(const unsigned char * data, size_t len) {
     return(res);
 }
 
+/*************************************************************************
+ *
+ * pkcs12 utils/helpers
+ *
+ ************************************************************************/
+int
+xmlSecGnuTLSPkcs12LoadMemory(const xmlSecByte* data, xmlSecSize dataSize,
+                             const char *pwd,
+                             gnutls_x509_privkey_t * priv_key,
+                             xmlSecPtrListPtr certsList)
+{
+    gnutls_pkcs12_t pkcs12 = NULL;
+    gnutls_pkcs12_bag_t bag = NULL;
+    gnutls_x509_crt_t cert = NULL;
+    gnutls_datum_t datum;
+    int res = -1;
+    int idx;
+    int err;
+    int ret;
+
+    xmlSecAssert2(data != NULL, -1);
+    xmlSecAssert2(dataSize > 0, -1);
+    xmlSecAssert2(priv_key != NULL, -1);
+    xmlSecAssert2((*priv_key) == NULL, -1);
+    xmlSecAssert2(certsList != NULL, -1);
+
+    /* read pkcs12 in internal structure */
+    err = gnutls_pkcs12_init(&pkcs12);
+    if(err != GNUTLS_E_SUCCESS) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "gnutls_pkcs12_init",
+                    XMLSEC_ERRORS_R_CRYPTO_FAILED,
+                    XMLSEC_GNUTLS_REPORT_ERROR(err));
+        goto done;
+    }
+
+    datum.data = (unsigned char *)data;
+    datum.size = dataSize;
+    err = gnutls_pkcs12_import(pkcs12, &datum, GNUTLS_X509_FMT_DER, 0);
+    if(err != GNUTLS_E_SUCCESS) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "gnutls_pkcs12_import",
+                    XMLSEC_ERRORS_R_CRYPTO_FAILED,
+                    XMLSEC_GNUTLS_REPORT_ERROR(err));
+        goto done;
+    }
+
+    /* verify */
+    err = gnutls_pkcs12_verify_mac(pkcs12, pwd);
+    if(err != GNUTLS_E_SUCCESS) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "gnutls_pkcs12_verify_mac",
+                    XMLSEC_ERRORS_R_CRYPTO_FAILED,
+                    XMLSEC_GNUTLS_REPORT_ERROR(err));
+        goto done;
+    }
+
+    /* scan the pkcs structure and find the first private key */
+    for(idx = 0; ; ++idx) {
+        int bag_type;
+        int elements_in_bag;
+        int ii;
+
+        err = gnutls_pkcs12_bag_init(&bag);
+        if(err != GNUTLS_E_SUCCESS) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                        NULL,
+                        "gnutls_pkcs12_bag_init",
+                        XMLSEC_ERRORS_R_CRYPTO_FAILED,
+                        XMLSEC_GNUTLS_REPORT_ERROR(err));
+            goto done;
+        }
+
+        err = gnutls_pkcs12_get_bag(pkcs12, idx, bag);
+        if(err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
+            /* scanned the whole pkcs12, stop */
+            break;
+        } else if(err != GNUTLS_E_SUCCESS) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                        NULL,
+                        "gnutls_pkcs12_get_bag",
+                        XMLSEC_ERRORS_R_CRYPTO_FAILED,
+                        XMLSEC_GNUTLS_REPORT_ERROR(err));
+            goto done;
+        }
+
+        /* check if we need to decrypt the bag */
+        bag_type = gnutls_pkcs12_bag_get_type(bag, 0);
+        if(bag_type < 0) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                        NULL,
+                        "gnutls_pkcs12_bag_get_type",
+                        XMLSEC_ERRORS_R_CRYPTO_FAILED,
+                        XMLSEC_GNUTLS_REPORT_ERROR(bag_type));
+            goto done;
+        }
+        if(bag_type == GNUTLS_BAG_ENCRYPTED) {
+            err = gnutls_pkcs12_bag_decrypt(bag, pwd);
+            if(err != GNUTLS_E_SUCCESS) {
+                xmlSecError(XMLSEC_ERRORS_HERE,
+                            NULL,
+                            "gnutls_pkcs12_bag_decrypt",
+                            XMLSEC_ERRORS_R_CRYPTO_FAILED,
+                            XMLSEC_GNUTLS_REPORT_ERROR(err));
+                goto done;
+            }
+        }
+
+        /* scan elements in bag */
+        elements_in_bag = gnutls_pkcs12_bag_get_count(bag);
+        if(elements_in_bag < 0) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                        NULL,
+                        "gnutls_pkcs12_bag_get_count",
+                        XMLSEC_ERRORS_R_CRYPTO_FAILED,
+                        XMLSEC_GNUTLS_REPORT_ERROR(bag_type));
+            goto done;
+        }
+        for(ii = 0; ii < elements_in_bag; ++ii) {
+            bag_type = gnutls_pkcs12_bag_get_type(bag, ii);
+            if(bag_type < 0) {
+                xmlSecError(XMLSEC_ERRORS_HERE,
+                            NULL,
+                            "gnutls_pkcs12_bag_get_type",
+                            XMLSEC_ERRORS_R_CRYPTO_FAILED,
+                            XMLSEC_GNUTLS_REPORT_ERROR(bag_type));
+                goto done;
+            }
+
+            err = gnutls_pkcs12_bag_get_data(bag, ii, &datum);
+            if(err != GNUTLS_E_SUCCESS) {
+                xmlSecError(XMLSEC_ERRORS_HERE,
+                            NULL,
+                            "gnutls_pkcs12_bag_get_data",
+                            XMLSEC_ERRORS_R_CRYPTO_FAILED,
+                            XMLSEC_GNUTLS_REPORT_ERROR(err));
+                goto done;
+            }
+
+            switch(bag_type) {
+            case GNUTLS_BAG_PKCS8_ENCRYPTED_KEY:
+            case GNUTLS_BAG_PKCS8_KEY:
+                /* we want only the first private key */
+                if((*priv_key) == NULL) {
+                    err = gnutls_x509_privkey_init(priv_key);
+                    if(err != GNUTLS_E_SUCCESS) {
+                        xmlSecError(XMLSEC_ERRORS_HERE,
+                                    NULL,
+                                    "gnutls_x509_privkey_init",
+                                    XMLSEC_ERRORS_R_CRYPTO_FAILED,
+                                    XMLSEC_GNUTLS_REPORT_ERROR(err));
+                        goto done;
+                    }
+
+                    err = gnutls_x509_privkey_import_pkcs8((*priv_key),
+                                &datum, GNUTLS_X509_FMT_DER,
+                                pwd,
+                                (bag_type == GNUTLS_BAG_PKCS8_KEY) ? GNUTLS_PKCS_PLAIN : 0);
+                    if(err != GNUTLS_E_SUCCESS) {
+                        xmlSecError(XMLSEC_ERRORS_HERE,
+                                    NULL,
+                                    "gnutls_x509_privkey_import_pkcs8",
+                                    XMLSEC_ERRORS_R_CRYPTO_FAILED,
+                                    XMLSEC_GNUTLS_REPORT_ERROR(err));
+                        goto done;
+                    }
+                }
+                break;
+            case GNUTLS_BAG_CERTIFICATE:
+                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));
+                    goto done;
+                }
+
+                err = gnutls_x509_crt_import(cert, &datum, 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));
+                    goto done;
+                }
+
+                ret = xmlSecPtrListAdd(certsList, cert);
+                if(ret < 0) {
+                    xmlSecError(XMLSEC_ERRORS_HERE,
+                                NULL,
+                                "xmlSecPtrListAdd(certsList)",
+                                XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                                XMLSEC_ERRORS_NO_MESSAGE);
+                    goto done;
+                }
+                cert = NULL; /* owned by certsList now */
+                break;
+            default:
+                /* ignore unknown bag element */
+                break;
+            }
+        }
+
+        /* done with bag */
+        gnutls_pkcs12_bag_deinit(bag);
+        bag = NULL;
+    }
+
+    /* check we have private key */
+    if((*priv_key) == NULL) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    NULL,
+                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                    "Private key was not found in pkcs12 object");
+        goto done;
+    }
+
+    /* success!!! */
+    res = 0;
+
+done:
+    if(cert != NULL) {
+        gnutls_x509_crt_deinit(cert);
+    }
+    if(bag != NULL) {
+        gnutls_pkcs12_bag_deinit(bag);
+    }
+    if(pkcs12 != NULL) {
+        gnutls_pkcs12_deinit(pkcs12);
+    }
+    return(res);
+}
+
+xmlSecKeyDataPtr
+xmlSecGnuTLSCreateKeyDataAndAdoptPrivKey(gnutls_x509_privkey_t priv_key) {
+    xmlSecKeyDataPtr res = NULL;
+    int key_alg;
+    int ret;
+
+    xmlSecAssert2(priv_key != NULL, NULL);
+
+    /* create key value data */
+    key_alg = gnutls_x509_privkey_get_pk_algorithm(priv_key);
+    if(key_alg < 0) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "gnutls_x509_privkey_get_pk_algorithm",
+                    XMLSEC_ERRORS_R_CRYPTO_FAILED,
+                    XMLSEC_GNUTLS_REPORT_ERROR(key_alg));
+        return (NULL);
+    }
+    switch(key_alg) {
+#ifndef XMLSEC_NO_RSA
+    case GNUTLS_PK_RSA:
+        res = xmlSecKeyDataCreate(xmlSecGnuTLSKeyDataRsaId);
+        if(res == NULL) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                        NULL,
+                        "xmlSecKeyDataCreate",
+                        XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                        "xmlSecGnuTLSKeyDataRsaId");
+            return(NULL);
+        }
+
+        ret = xmlSecGnuTLSKeyDataRsaAdoptPrivateKey(res, priv_key);
+        if(ret < 0) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                        NULL,
+                        "xmlSecGnuTLSKeyDataRsaAdoptPrivateKey",
+                        XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                        "xmlSecGnuTLSKeyDataRsaId");
+            xmlSecKeyDataDestroy(res);
+            return(NULL);
+        }
+        break;
+#endif /* XMLSEC_NO_RSA */
+
+#ifndef XMLSEC_NO_DSA
+    case GNUTLS_PK_DSA:
+        res = xmlSecKeyDataCreate(xmlSecGnuTLSKeyDataDsaId);
+        if(res == NULL) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                        NULL,
+                        "xmlSecKeyDataCreate",
+                        XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                        "xmlSecGnuTLSKeyDataDsaId");
+            return(NULL);
+        }
+
+        ret = xmlSecGnuTLSKeyDataDsaAdoptPrivateKey(res, priv_key);
+        if(ret < 0) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                        NULL,
+                        "xmlSecGnuTLSKeyDataDsaAdoptPrivateKey",
+                        XMLSEC_ERRORS_R_XMLSEC_FAILED,
+                        "xmlSecGnuTLSKeyDataDsaId");
+            xmlSecKeyDataDestroy(res);
+            return(NULL);
+        }
+        break;
+#endif /* XMLSEC_NO_DSA */
+    default:
+        xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+                    "gnutls_x509_privkey_get_pk_algorithm",
+                    XMLSEC_ERRORS_R_CRYPTO_FAILED,
+                    "Unsupported algorithm %d", (int)key_alg);
+        return(NULL);
+    }
+
+    /* done */
+    return(res);
+}
+
+
+
 #endif /* XMLSEC_NO_X509 */
diff --git a/src/gnutls/x509utils.h b/src/gnutls/x509utils.h
index b0727f2..da5325c 100644
--- a/src/gnutls/x509utils.h
+++ b/src/gnutls/x509utils.h
@@ -34,7 +34,7 @@ xmlSecPtrListId         xmlSecGnuTLSX509CrtListGetKlass         (void);
 
 /*************************************************************************
  *
- * Utils/helpers
+ * x509 utils/helpers
  *
  ************************************************************************/
 gnutls_x509_crt_t       xmlSecGnuTLSX509CertDup                 (gnutls_x509_crt_t src);
@@ -42,8 +42,9 @@ xmlChar *               xmlSecGnuTLSX509CertGetSubjectDN        (gnutls_x509_crt
 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       xmlSecGnuTLSX509CertRead                (const xmlSecByte* buf,
+                                                                 xmlSecSize size,
+                                                                 xmlSecKeyDataFormat format);
 gnutls_x509_crt_t       xmlSecGnuTLSX509CertBase64DerRead       (xmlChar* buf);
 xmlChar*                xmlSecGnuTLSX509CertBase64DerWrite      (gnutls_x509_crt_t cert,
                                                                  int base64LineWrap);
@@ -55,6 +56,21 @@ xmlChar*                xmlSecGnuTLSASN1IntegerWrite            (const unsigned
                                                                  size_t len);
 
 
+
+/*************************************************************************
+ *
+ * pkcs12 utils/helpers
+ *
+ ************************************************************************/
+int                     xmlSecGnuTLSPkcs12LoadMemory            (const xmlSecByte* data,
+                                                                 xmlSecSize dataSize,
+                                                                 const char *pwd,
+                                                                 gnutls_x509_privkey_t * priv_key,
+                                                                 xmlSecPtrListPtr certsList);
+
+xmlSecKeyDataPtr        xmlSecGnuTLSCreateKeyDataAndAdoptPrivKey(gnutls_x509_privkey_t priv_key);
+
+
 #endif /* XMLSEC_NO_X509 */
 
 #ifdef __cplusplus
diff --git a/src/list.c b/src/list.c
index 4ab2677..d1a0053 100644
--- a/src/list.c
+++ b/src/list.c
@@ -368,6 +368,32 @@ xmlSecPtrListRemove(xmlSecPtrListPtr list, xmlSecSize pos) {
 }
 
 /**
+ * xmlSecPtrListRemoveAndReturn:
+ * @list:               the pointer to list.
+ * @pos:                the position.
+ *
+ * Remove the list item at the position @pos and return it back.
+ *
+ * Returns: the pointer to the list item.
+ */
+xmlSecPtr
+xmlSecPtrListRemoveAndReturn(xmlSecPtrListPtr list, xmlSecSize pos) {
+    xmlSecPtr res;
+
+    xmlSecAssert2(xmlSecPtrListIsValid(list), NULL);
+    xmlSecAssert2(list->data != NULL, NULL);
+    xmlSecAssert2(pos < list->use, NULL);
+
+    res = list->data[pos];
+    list->data[pos] = NULL;
+    if(pos == list->use - 1) {
+        --list->use;
+    }
+    return(res);
+}
+
+
+/**
  * xmlSecPtrListDebugDump:
  * @list:               the pointer to list.
  * @output:             the pointer to output FILE.
diff --git a/src/openssl/app.c b/src/openssl/app.c
index 1319b07..d172dcf 100644
--- a/src/openssl/app.c
+++ b/src/openssl/app.c
@@ -685,7 +685,7 @@ xmlSecOpenSSLAppPkcs12LoadBIO(BIO* bio, const char *pwd,
     X509 *cert = NULL;
     X509 *tmpcert = NULL;
     int i;
-        int has_cert;
+    int has_cert;
     int ret;
 
     xmlSecAssert2(bio != NULL, NULL);
@@ -757,50 +757,51 @@ xmlSecOpenSSLAppPkcs12LoadBIO(BIO* bio, const char *pwd,
         }
     }
 
-        /*
+    /*
         The documentation states (http://www.openssl.org/docs/crypto/PKCS12_parse.html):
 
         If successful the private key will be written to "*pkey", the
-    corresponding certificate to "*cert" and any additional certificates
-    to "*ca".
+        corresponding certificate to "*cert" and any additional certificates
+        to "*ca".
 
         In reality, the function sometime returns in the "ca" the certificates
-    including the one it is already returned in "cert".
-        */
-        has_cert = 0;
+        including the one it is already returned in "cert".
+    */
+    has_cert = 0;
     for(i = 0; i < sk_X509_num(chain); ++i) {
-                xmlSecAssert2(sk_X509_value(chain, i), NULL);
+        xmlSecAssert2(sk_X509_value(chain, i), NULL);
 
-                if(X509_cmp(sk_X509_value(chain, i), cert) != 0) {
-                        has_cert = 1;
-                        break;
-                }
+        if(X509_cmp(sk_X509_value(chain, i), cert) != 0) {
+            has_cert = 1;
+            break;
         }
-        if(has_cert != 0) {
-                tmpcert = X509_dup(cert);
-                if(tmpcert == NULL) {
-                xmlSecError(XMLSEC_ERRORS_HERE,
-                                NULL,
-                                "X509_dup",
-                                XMLSEC_ERRORS_R_CRYPTO_FAILED,
-                                "data=%s",
-                                xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data)));
-                goto done;
-                }
-
-                ret = sk_X509_push(chain, tmpcert);
-                if(ret < 1) {
-                xmlSecError(XMLSEC_ERRORS_HERE,
-                                NULL,
-                                "sk_X509_push",
-                                XMLSEC_ERRORS_R_CRYPTO_FAILED,
-                                "data=%s",
-                                xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data)));
-                X509_free(tmpcert);
-                goto done;
-                }
+    }
+
+    if(has_cert != 0) {
+        tmpcert = X509_dup(cert);
+        if(tmpcert == NULL) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                        NULL,
+                        "X509_dup",
+                         XMLSEC_ERRORS_R_CRYPTO_FAILED,
+                        "data=%s",
+                        xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data)));
+            goto done;
         }
 
+        ret = sk_X509_push(chain, tmpcert);
+        if(ret < 1) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+                        NULL,
+                        "sk_X509_push",
+                        XMLSEC_ERRORS_R_CRYPTO_FAILED,
+                        "data=%s",
+                        xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data)));
+            X509_free(tmpcert);
+            goto done;
+        }
+    }
+
     ret = xmlSecOpenSSLKeyDataX509AdoptKeyCert(x509Data, cert);
     if(ret < 0) {
         xmlSecError(XMLSEC_ERRORS_HERE,
diff --git a/tests/testrun.sh b/tests/testrun.sh
index 7642dc2..c1f629b 100755
--- a/tests/testrun.sh
+++ b/tests/testrun.sh
@@ -66,7 +66,7 @@ cert_format=$file_format
 #
 # GCrypt/GnuTLS only supports DER format for now, others are good to go with PKCS12
 #
-if [ "z$crypto" != "zgcrypt" -a "z$crypto" != "zgnutls" ] ; then
+if [ "z$crypto" != "zgcrypt" ] ; then
     priv_key_option="--pkcs12"
     priv_key_format="p12"
 else



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