gnutls-commit
[Top][All Lists]
Advanced

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

[SCM] GNU gnutls branch, new, updated. gnutls_2_9_10-55-gaa36f50


From: Nikos Mavrogiannopoulos
Subject: [SCM] GNU gnutls branch, new, updated. gnutls_2_9_10-55-gaa36f50
Date: Sat, 22 May 2010 13:23:54 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU gnutls".

http://git.savannah.gnu.org/cgit/gnutls.git/commit/?id=aa36f503bee962e314f12f7b3abbb19a34893b0a

The branch, new has been updated
       via  aa36f503bee962e314f12f7b3abbb19a34893b0a (commit)
       via  f8b9beb6a2d765a8d09dfa5af748db499f51dca7 (commit)
       via  25743fd804de1cca0a2fb1538ed40f378a7aba7d (commit)
      from  0627fb68a819799119d46134623d59911ee4b936 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit aa36f503bee962e314f12f7b3abbb19a34893b0a
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Sat May 22 15:13:20 2010 +0200

    Added gnutls_pubkey_t abstract type to handle public keys. It can currently
    import/export public keys from existing certificate types as well as from 
PKCS #11
    URL. This allows generating a certificate or certificate request from a 
given public key
    (currently one could only generate them from a given private key).
    
    PKCS#11 API augmented to allow reading arbitrary objects instead of just 
certificates.
    Certtool updated to list those objects.

commit f8b9beb6a2d765a8d09dfa5af748db499f51dca7
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Sat May 22 10:34:00 2010 +0200

    Added gnutls_pkcs11_token_get_flags() to distinguish between hardware and 
soft tokens.

commit 25743fd804de1cca0a2fb1538ed40f378a7aba7d
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Sat May 22 10:06:50 2010 +0200

    Export all symbols from C++ library. This library doesn't contain any
    internal symbols anyway and there is no reason to mess with the C++ ABI
    that hasn't got the problems of C.

-----------------------------------------------------------------------

Summary of changes:
 lib/Makefile.am                |    4 +-
 lib/gnutls_pubkey.c            |  670 ++++++++++++++++++++++++++++++++++++++++
 lib/gnutls_x509.c              |    6 +-
 lib/includes/gnutls/abstract.h |   54 +++-
 lib/includes/gnutls/pkcs11.h   |   99 +++----
 lib/libgnutls.map              |   31 ++-
 lib/libgnutlsxx.map            |   17 +-
 lib/m4/hooks.m4                |    4 +
 lib/pkcs11.c                   |  443 +++++++++++++++++++--------
 lib/pkcs11_int.h               |    9 +-
 lib/pkcs11_privkey.c           |    2 +-
 lib/x509/common.c              |   38 ++-
 lib/x509/common.h              |    8 +
 lib/x509/mpi.c                 |   31 +-
 lib/x509/x509.c                |   49 +++-
 lib/x509/x509_int.h            |    2 +
 src/certtool-common.h          |    4 +-
 src/certtool-gaa.c             |  295 ++++++++++--------
 src/certtool-gaa.h             |   50 ++--
 src/certtool.c                 |  215 ++++++++++++-
 src/certtool.gaa               |   12 +-
 src/pkcs11.c                   |   75 +++--
 22 files changed, 1673 insertions(+), 445 deletions(-)
 create mode 100644 lib/gnutls_pubkey.c

diff --git a/lib/Makefile.am b/lib/Makefile.am
index 51137ed..8230fb1 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -82,7 +82,7 @@ COBJECTS = gnutls_record.c gnutls_compress.c debug.c 
gnutls_cipher.c  \
        auth_dh_common.c gnutls_helper.c gnutls_supplemental.c          \
        crypto.c random.c  ext_signature.c cryptodev.c \
        crypto-api.c ext_safe_renegotiation.c gnutls_privkey.c \
-       pkcs11.c pkcs11_privkey.c
+       pkcs11.c pkcs11_privkey.c gnutls_pubkey.c
 
 if ENABLE_NETTLE
 SUBDIRS += nettle
@@ -171,7 +171,7 @@ lib_LTLIBRARIES += libgnutlsxx.la
 libgnutlsxx_la_SOURCES = gnutlsxx.cpp libgnutlsxx.map
 
 libgnutlsxx_la_LDFLAGS = -no-undefined \
-       -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)
+       -version-info $(CXX_LT_CURRENT):$(CXX_LT_REVISION):$(CXX_LT_AGE)
 
 libgnutlsxx_la_LIBADD = libgnutls.la
 
diff --git a/lib/gnutls_pubkey.c b/lib/gnutls_pubkey.c
new file mode 100644
index 0000000..985f473
--- /dev/null
+++ b/lib/gnutls_pubkey.c
@@ -0,0 +1,670 @@
+/*
+ * GnuTLS PKCS#11 support
+ * Copyright (C) 2010 Free Software Foundation
+ * 
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA
+*/
+
+#include <gnutls_int.h>
+#include <pakchois/pakchois.h>
+#include <gnutls/pkcs11.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <string.h>
+#include <gnutls_errors.h>
+#include <gnutls_datum.h>
+#include <pkcs11_int.h>
+#include <gnutls/abstract.h>
+#include <sign.h>
+#include <gnutls_pk.h>
+#include <x509_int.h>
+#include <openpgp/openpgp_int.h>
+#include <pkcs11_int.h>
+
+#define PK_PEM_HEADER "PUBLIC KEY"
+
+
+struct gnutls_pubkey_st {
+       gnutls_pk_algorithm_t pk_algorithm;
+       unsigned int bits;      /* an indication of the security parameter */
+
+       /* the size of params depends on the public
+        * key algorithm
+        * RSA: [0] is modulus
+        *      [1] is public exponent
+        * DSA: [0] is p
+        *      [1] is q
+        *      [2] is g
+        *      [3] is public key
+        */
+       bigint_t params[MAX_PUBLIC_PARAMS_SIZE];
+       int params_size;        /* holds the size of MPI params */
+
+       unsigned int key_usage; /* bits from GNUTLS_KEY_* */
+};
+
+/**
+ * gnutls_pubkey_get_pk_algorithm:
+ * @key: should contain a #gnutls_pubkey_t structure
+ * @bits: If set will return the number of bits of the parameters (may be NULL)
+ *
+ * This function will return the public key algorithm of a public
+ * key and if possible will return a number of bits that indicates
+ * the security parameter of the key.
+ *
+ * Returns: a member of the #gnutls_pk_algorithm_t enumeration on
+ *   success, or a negative value on error.
+ **/
+int gnutls_pubkey_get_pk_algorithm(gnutls_pubkey_t key, unsigned int *bits)
+{
+       if (bits)
+               *bits = key->bits;
+
+       return key->pk_algorithm;
+}
+
+/**
+ * gnutls_pubkey_get_key_usage:
+ * @key: should contain a #gnutls_pubkey_t structure
+ * @usage: If set will return the number of bits of the parameters (may be 
NULL)
+ *
+ * This function will return the key usage of the public key.
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
+ *   negative error value.
+ **/
+int gnutls_pubkey_get_key_usage(gnutls_pubkey_t key, unsigned int *usage)
+{
+       if (usage)
+               *usage = key->key_usage;
+
+       return 0;
+}
+
+/**
+ * gnutls_pubkey_init:
+ * @key: The structure to be initialized
+ *
+ * This function will initialize an public key structure.
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
+ *   negative error value.
+ **/
+int gnutls_pubkey_init(gnutls_pubkey_t * key)
+{
+       *key = gnutls_calloc(1, sizeof(struct gnutls_pubkey_st));
+       if (*key == NULL) {
+               gnutls_assert();
+               return GNUTLS_E_MEMORY_ERROR;
+       }
+
+       return 0;
+}
+
+/**
+ * gnutls_pubkey_deinit:
+ * @key: The structure to be deinitialized
+ *
+ * This function will deinitialize a public key structure.
+ **/
+void gnutls_pubkey_deinit(gnutls_pubkey_t key)
+{
+       gnutls_free(key);
+}
+
+/**
+ * gnutls_pubkey_import_x509:
+ * @key: The public key
+ * @crt: The certificate to be imported
+ * @flags: should be zero
+ *
+ * This function will import the given public key to the abstract
+ * #gnutls_pubkey_t structure.
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
+ *   negative error value.
+ **/
+int gnutls_pubkey_import_x509(gnutls_pubkey_t key, gnutls_x509_crt_t crt,
+                             unsigned int flags)
+{
+       int ret;
+
+       key->pk_algorithm =
+           gnutls_x509_crt_get_pk_algorithm(crt, &key->bits);
+
+       ret = gnutls_x509_crt_get_key_usage(crt, &key->key_usage, NULL);
+       if (ret < 0)
+               key->key_usage = 0;
+
+       key->params_size = sizeof(key->params) / sizeof(key->params[0]);
+       switch (key->pk_algorithm) {
+       case GNUTLS_PK_RSA:
+               ret =
+                   _gnutls_x509_crt_get_mpis(crt, key->params,
+                                             &key->params_size);
+               if (ret < 0) {
+                       gnutls_assert();
+                       return ret;
+               }
+               break;
+       case GNUTLS_PK_DSA:
+               ret =
+                   _gnutls_x509_crt_get_mpis(crt, key->params,
+                                             &key->params_size);
+               if (ret < 0) {
+                       gnutls_assert();
+                       return ret;
+               }
+
+               break;
+       default:
+               gnutls_assert();
+               return GNUTLS_E_INVALID_REQUEST;
+       }
+
+       return 0;
+}
+
+/**
+ * gnutls_pubkey_import_openpgp:
+ * @key: The public key
+ * @crt: The certificate to be imported
+ * @flags: should be zero
+ *
+ * This function will import the given public key to the abstract
+ * #gnutls_pubkey_t structure.
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
+ *   negative error value.
+ **/
+int gnutls_pubkey_import_openpgp(gnutls_pubkey_t key,
+                                gnutls_openpgp_crt_t crt,
+                                gnutls_openpgp_keyid_t keyid,
+                                unsigned int flags)
+{
+       int ret;
+       uint32_t kid32[2];
+
+       ret = gnutls_openpgp_crt_get_preferred_key_id(crt, keyid);
+       if (ret < 0) {
+               gnutls_assert();
+               return ret;
+       }
+
+       KEYID_IMPORT(kid32, keyid);
+
+       key->pk_algorithm =
+           gnutls_openpgp_crt_get_pk_algorithm(crt, &key->bits);
+
+       ret = gnutls_openpgp_crt_get_key_usage(crt, &key->key_usage);
+       if (ret < 0)
+               key->key_usage = 0;
+
+       switch (key->pk_algorithm) {
+       case GNUTLS_PK_RSA:
+               ret =
+                   _gnutls_openpgp_crt_get_mpis(crt, kid32, key->params,
+                                                &key->params_size);
+               if (ret < 0) {
+                       gnutls_assert();
+                       return ret;
+               }
+               break;
+       case GNUTLS_PK_DSA:
+               ret =
+                   _gnutls_openpgp_crt_get_mpis(crt, kid32, key->params,
+                                                &key->params_size);
+               if (ret < 0) {
+                       gnutls_assert();
+                       return ret;
+               }
+               break;
+       default:
+               gnutls_assert();
+               return GNUTLS_E_INVALID_REQUEST;
+       }
+
+       return 0;
+}
+
+/**
+ * gnutls_pubkey_export:
+ * @key: Holds the certificate
+ * @format: the format of output params. One of PEM or DER.
+ * @output_data: will contain a certificate PEM or DER encoded
+ * @output_data_size: holds the size of output_data (and will be
+ *   replaced by the actual size of parameters)
+ *
+ * This function will export the certificate to DER or PEM format.
+ *
+ * If the buffer provided is not long enough to hold the output, then
+ * *output_data_size is updated and GNUTLS_E_SHORT_MEMORY_BUFFER will
+ * be returned.
+ *
+ * If the structure is PEM encoded, it will have a header
+ * of "BEGIN CERTIFICATE".
+ *
+ * Return value: In case of failure a negative value will be
+ *   returned, and 0 on success.
+ **/
+int
+gnutls_pubkey_export(gnutls_pubkey_t key,
+                    gnutls_x509_crt_fmt_t format, void *output_data,
+                    size_t * output_data_size)
+{
+       int result;
+       ASN1_TYPE spk = ASN1_TYPE_EMPTY;
+
+       if (key == NULL) {
+               gnutls_assert();
+               return GNUTLS_E_INVALID_REQUEST;
+       }
+
+       if ((result = asn1_create_element
+            (_gnutls_get_pkix(), "PKIX1.SubjectPublicKeyInfo", &spk))
+           != ASN1_SUCCESS) {
+               gnutls_assert();
+               return _gnutls_asn2err(result);
+       }
+
+       result =
+           _gnutls_x509_encode_and_copy_PKI_params(spk, "",
+                                                   key->pk_algorithm,
+                                                   key->params,
+                                                   key->params_size);
+       if (result < 0) {
+               gnutls_assert();
+               goto cleanup;
+       }
+
+       result = _gnutls_x509_export_int_named(spk, "",
+                                              format, PK_PEM_HEADER,
+                                              output_data,
+                                              output_data_size);
+       if (result < 0) {
+               gnutls_assert();
+               goto cleanup;
+       }
+
+       result = 0;
+
+      cleanup:
+       asn1_delete_structure(&spk);
+
+       return result;
+
+}
+
+/**
+ * gnutls_pubkey_get_key_id:
+ * @key: Holds the public key
+ * @flags: should be 0 for now
+ * @output_data: will contain the key ID
+ * @output_data_size: holds the size of output_data (and will be
+ *   replaced by the actual size of parameters)
+ *
+ * This function will return a unique ID the depends on the public
+ * key parameters. This ID can be used in checking whether a
+ * certificate corresponds to the given public key.
+ *
+ * If the buffer provided is not long enough to hold the output, then
+ * *output_data_size is updated and GNUTLS_E_SHORT_MEMORY_BUFFER will
+ * be returned.  The output will normally be a SHA-1 hash output,
+ * which is 20 bytes.
+ *
+ * Return value: In case of failure a negative value will be
+ *   returned, and 0 on success.
+ **/
+int
+gnutls_pubkey_get_key_id(gnutls_pubkey_t key, unsigned int flags,
+                        unsigned char *output_data,
+                        size_t * output_data_size)
+{
+       int ret = 0;
+
+       if (key == NULL) {
+               gnutls_assert();
+               return GNUTLS_E_INVALID_REQUEST;
+       }
+
+       ret =
+           _gnutls_get_key_id(key->pk_algorithm, key->params,
+                              key->params_size, output_data,
+                              output_data_size);
+       if (ret < 0) {
+               gnutls_assert();
+               return ret;
+       }
+
+       return 0;
+}
+
+/**
+ * gnutls_pubkey_get_pk_rsa_raw:
+ * @crt: Holds the certificate
+ * @m: will hold the modulus
+ * @e: will hold the public exponent
+ *
+ * This function will export the RSA public key's parameters found in
+ * the given structure.  The new parameters will be allocated using
+ * gnutls_malloc() and will be stored in the appropriate datum.
+ *
+ * Returns: %GNUTLS_E_SUCCESS on success, otherwise an error.
+ **/
+int
+gnutls_pubkey_get_pk_rsa_raw(gnutls_pubkey_t key,
+                            gnutls_datum_t * m, gnutls_datum_t * e)
+{
+       int ret;
+       int i;
+
+       if (key == NULL) {
+               gnutls_assert();
+               return GNUTLS_E_INVALID_REQUEST;
+       }
+
+       if (key->pk_algorithm != GNUTLS_PK_RSA) {
+               gnutls_assert();
+               return GNUTLS_E_INVALID_REQUEST;
+       }
+
+       ret = _gnutls_mpi_dprint(key->params[0], m);
+       if (ret < 0) {
+               gnutls_assert();
+               return ret;
+       }
+
+       ret = _gnutls_mpi_dprint(key->params[1], e);
+       if (ret < 0) {
+               gnutls_assert();
+               _gnutls_free_datum(m);
+               return ret;
+       }
+
+       return 0;
+}
+
+/**
+ * gnutls_pubkey_get_pk_dsa_raw:
+ * @crt: Holds the certificate
+ * @p: will hold the p
+ * @q: will hold the q
+ * @g: will hold the g
+ * @y: will hold the y
+ *
+ * This function will export the DSA public key's parameters found in
+ * the given certificate.  The new parameters will be allocated using
+ * gnutls_malloc() and will be stored in the appropriate datum.
+ *
+ * Returns: %GNUTLS_E_SUCCESS on success, otherwise an error.
+ **/
+int
+gnutls_pubkey_get_pk_dsa_raw(gnutls_pubkey_t key,
+                            gnutls_datum_t * p, gnutls_datum_t * q,
+                            gnutls_datum_t * g, gnutls_datum_t * y)
+{
+       int ret;
+       bigint_t params[MAX_PUBLIC_PARAMS_SIZE];
+       int params_size = MAX_PUBLIC_PARAMS_SIZE;
+       int i;
+
+       if (key == NULL) {
+               gnutls_assert();
+               return GNUTLS_E_INVALID_REQUEST;
+       }
+
+       if (key->pk_algorithm != GNUTLS_PK_DSA) {
+               gnutls_assert();
+               return GNUTLS_E_INVALID_REQUEST;
+       }
+
+       /* P */
+       ret = _gnutls_mpi_dprint(key->params[0], p);
+       if (ret < 0) {
+               gnutls_assert();
+               return ret;
+       }
+
+       /* Q */
+       ret = _gnutls_mpi_dprint(key->params[1], q);
+       if (ret < 0) {
+               gnutls_assert();
+               _gnutls_free_datum(p);
+               return ret;
+       }
+
+
+       /* G */
+       ret = _gnutls_mpi_dprint(key->params[2], g);
+       if (ret < 0) {
+               gnutls_assert();
+               _gnutls_free_datum(p);
+               _gnutls_free_datum(q);
+               return ret;
+       }
+
+
+       /* Y */
+       ret = _gnutls_mpi_dprint(key->params[3], y);
+       if (ret < 0) {
+               gnutls_assert();
+               _gnutls_free_datum(p);
+               _gnutls_free_datum(g);
+               _gnutls_free_datum(q);
+               return ret;
+       }
+
+       return 0;
+}
+
+/**
+ * gnutls_pubkey_import:
+ * @key: The structure to store the parsed certificate. 
+ * @data: The DER or PEM encoded certificate. 
+ * @format: One of DER or PEM 
+ * 
+ * This function will convert the given DER or PEM encoded Public key 
+ * to the native gnutls_pubkey_t format.The output will be stored * in @ key. 
+ * If the Certificate is PEM encoded it should have a header of "PUBLIC KEY". 
+ * 
+ * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
+ * negative error value.
+ **/
+int gnutls_pubkey_import(gnutls_pubkey_t key,
+                    const gnutls_datum_t * data,
+                    gnutls_x509_crt_fmt_t format)
+{
+       int result = 0, need_free = 0;
+       gnutls_datum_t _data;
+       ASN1_TYPE spk;
+
+       if (key == NULL) {
+               gnutls_assert();
+               return GNUTLS_E_INVALID_REQUEST;
+       }
+
+       _data.data = data->data;
+       _data.size = data->size;
+
+       /* If the Certificate is in PEM format then decode it
+        */
+       if (format == GNUTLS_X509_FMT_PEM) {
+               opaque *out;
+
+               /* Try the first header */
+               result =
+                   _gnutls_fbase64_decode(PK_PEM_HEADER, data->data,
+                                          data->size, &out);
+
+               if (result <= 0) {
+                       if (result == 0)
+                               result = GNUTLS_E_INTERNAL_ERROR;
+                       gnutls_assert();
+                       return result;
+               }
+
+               _data.data = out;
+               _data.size = result;
+
+               need_free = 1;
+       }
+
+       if ((result = asn1_create_element
+            (_gnutls_get_pkix(), "PKIX1.SubjectPublicKeyInfo", &spk))
+           != ASN1_SUCCESS) {
+               gnutls_assert();
+               result = _gnutls_asn2err(result);
+               goto cleanup;
+       }
+
+       result = asn1_der_decoding (&spk, _data.data, _data.size, NULL);
+       if (result != ASN1_SUCCESS) {
+               gnutls_assert ();
+               result = _gnutls_asn2err (result);
+               goto cleanup;
+       }
+
+       key->params_size = sizeof(key->params) / sizeof(key->params[0]);
+       result =
+           _gnutls_get_asn_mpis(spk, "", key->params, &key->params_size);
+       if (result < 0) {
+               gnutls_assert();
+               goto cleanup;
+       }
+       
+       /* this has already been called by get_asn_mpis() thus it cannot
+        * fail.
+        */
+       key->pk_algorithm = _gnutls_x509_get_pk_algorithm (spk, "", NULL);
+
+       result = 0;
+
+cleanup:
+       asn1_delete_structure(&spk);
+
+       if (need_free)
+               _gnutls_free_datum(&_data);
+       return result;
+}
+
+int gnutls_x509_crt_set_pubkey (gnutls_x509_crt_t crt,
+                              gnutls_pubkey_t key)
+{
+  int result;
+
+  if (crt == NULL)
+    {
+      gnutls_assert ();
+      return GNUTLS_E_INVALID_REQUEST;
+    }
+
+  result = _gnutls_x509_encode_and_copy_PKI_params (crt->cert,
+                                                   
"tbsCertificate.subjectPublicKeyInfo",
+                                                   key->pk_algorithm,
+                                                   key->params,
+                                                   key->params_size);
+
+  if (result < 0)
+    {
+      gnutls_assert ();
+      return result;
+    }
+
+       if (key->key_usage)
+               gnutls_x509_crt_set_key_usage(crt, key->key_usage);
+
+  return 0;
+}
+
+int gnutls_x509_crq_set_pubkey (gnutls_x509_crq_t crq,
+                              gnutls_pubkey_t key)
+{
+  int result;
+
+  if (crq == NULL)
+    {
+      gnutls_assert ();
+      return GNUTLS_E_INVALID_REQUEST;
+    }
+
+  result = _gnutls_x509_encode_and_copy_PKI_params
+    (crq->crq,
+     "certificationRequestInfo.subjectPKInfo",
+     key->pk_algorithm, key->params, key->params_size);
+
+  if (result < 0)
+    {
+      gnutls_assert ();
+      return result;
+    }
+
+       if (key->key_usage)
+               gnutls_x509_crq_set_key_usage(crq, key->key_usage);
+
+  return 0;
+}
+
+/**
+ * gnutls_pubkey_set_key_usage:
+ * @crt: a certificate of type #gnutls_x509_crt_t
+ * @usage: an ORed sequence of the GNUTLS_KEY_* elements.
+ *
+ * This function will set the keyUsage certificate extension.
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
+ *   negative error value.
+ **/
+int
+gnutls_pubkey_set_key_usage (gnutls_pubkey_t key, unsigned int usage)
+{
+       key->key_usage = usage;
+       
+       return 0;
+}
+
+int gnutls_pubkey_import_pkcs11_url( gnutls_pubkey_t key, const char* url)
+{
+    gnutls_pkcs11_obj_t pcrt;
+    int ret;
+    
+    ret = gnutls_pkcs11_obj_init ( &pcrt);
+    if (ret < 0) {
+        gnutls_assert();
+        return ret;
+    }
+
+    ret = gnutls_pkcs11_obj_import_url (pcrt, url);
+    if (ret < 0) {
+        gnutls_assert();
+        goto cleanup;
+    }
+
+    ret = gnutls_pubkey_import(key, &pcrt->raw, GNUTLS_X509_FMT_DER);
+    if (ret < 0) {
+        gnutls_assert();
+        goto cleanup;
+    }
+    
+    ret = 0;
+cleanup:
+
+    gnutls_pkcs11_obj_deinit(pcrt);
+    
+    return ret;
+}
+
diff --git a/lib/gnutls_x509.c b/lib/gnutls_x509.c
index 78953c4..03f71a0 100644
--- a/lib/gnutls_x509.c
+++ b/lib/gnutls_x509.c
@@ -566,10 +566,10 @@ static int read_cas_url (gnutls_certificate_credentials_t 
res, const char* url)
 {
 int ret;
 gnutls_x509_crt_t * xcrt_list = NULL;
-gnutls_pkcs11_crt_t *pcrt_list=NULL;
+gnutls_pkcs11_obj_t *pcrt_list=NULL;
 unsigned int pcrt_list_size = 0;
 
-       ret = gnutls_pkcs11_crt_list_import_url( NULL, &pcrt_list_size, url, 
GNUTLS_PKCS11_CRT_ATTR_TRUSTED);
+       ret = gnutls_pkcs11_obj_list_import_url( NULL, &pcrt_list_size, url, 
GNUTLS_PKCS11_OBJ_ATTR_CRT_TRUSTED);
        if (ret < 0 && ret != GNUTLS_E_SHORT_MEMORY_BUFFER) {
                gnutls_assert();
                return ret;
@@ -586,7 +586,7 @@ unsigned int pcrt_list_size = 0;
                return GNUTLS_E_MEMORY_ERROR;
        }
        
-       ret = gnutls_pkcs11_crt_list_import_url( pcrt_list, &pcrt_list_size, 
url, GNUTLS_PKCS11_CRT_ATTR_TRUSTED);
+       ret = gnutls_pkcs11_obj_list_import_url( pcrt_list, &pcrt_list_size, 
url, GNUTLS_PKCS11_OBJ_ATTR_CRT_TRUSTED);
        if (ret < 0) {
                gnutls_assert();
                goto cleanup;
diff --git a/lib/includes/gnutls/abstract.h b/lib/includes/gnutls/abstract.h
index 8e75dce..8305f9c 100644
--- a/lib/includes/gnutls/abstract.h
+++ b/lib/includes/gnutls/abstract.h
@@ -1,5 +1,5 @@
-#ifndef __GNUTLS_PRIVKEY_H
-#define __GNUTLS_PRIVKEY_H
+#ifndef __GNUTLS_ABSTRACT_H
+#define __GNUTLS_ABSTRACT_H
 
 #include <stdarg.h>
 #include <gnutls/gnutls.h>
@@ -7,6 +7,55 @@
 #include <gnutls/pkcs11.h>
 #include <gnutls/openpgp.h>
 
+/* Public key operations */
+
+struct gnutls_pubkey_st;
+typedef struct gnutls_pubkey_st* gnutls_pubkey_t;
+
+int gnutls_pubkey_init (gnutls_pubkey_t * key);
+void gnutls_pubkey_deinit (gnutls_pubkey_t key);
+int gnutls_pubkey_get_pk_algorithm (gnutls_pubkey_t key, unsigned int* bits);
+
+int gnutls_pubkey_import_x509(gnutls_pubkey_t pkey, gnutls_x509_crt_t crt, 
unsigned int flags);
+int gnutls_pubkey_import_openpgp(gnutls_pubkey_t pkey,
+                                gnutls_openpgp_crt_t crt,
+                                gnutls_openpgp_keyid_t keyid,
+                                unsigned int flags);
+
+int gnutls_pubkey_get_pk_rsa_raw (gnutls_pubkey_t crt,
+                               gnutls_datum_t * m, gnutls_datum_t * e);
+int gnutls_pubkey_get_pk_dsa_raw (gnutls_pubkey_t crt,
+                               gnutls_datum_t * p, gnutls_datum_t * q,
+                               gnutls_datum_t * g, gnutls_datum_t * y);
+
+int gnutls_pubkey_export (gnutls_pubkey_t key,
+                             gnutls_x509_crt_fmt_t format,
+                             void *output_data, size_t * output_data_size);
+
+int gnutls_pubkey_get_key_id (gnutls_pubkey_t key, unsigned int flags,
+                           unsigned char *output_data,
+                           size_t * output_data_size);
+
+int gnutls_pubkey_get_key_usage(gnutls_pubkey_t key, unsigned int *usage);
+int gnutls_pubkey_set_key_usage (gnutls_pubkey_t key, unsigned int usage);
+
+int gnutls_pubkey_import (gnutls_pubkey_t key,
+                             const gnutls_datum_t * data,
+                             gnutls_x509_crt_fmt_t format);
+
+
+int gnutls_pubkey_import_pkcs11_url( gnutls_pubkey_t key, const char* url);
+
+
+int gnutls_x509_crt_set_pubkey (gnutls_x509_crt_t crt,
+                              gnutls_pubkey_t key);
+
+int gnutls_x509_crq_set_pubkey (gnutls_x509_crq_t crq,
+                              gnutls_pubkey_t key);
+
+
+/* Private key operations */
+
 struct gnutls_privkey_st;
 typedef struct gnutls_privkey_st* gnutls_privkey_t;
 
@@ -15,6 +64,7 @@ void gnutls_privkey_deinit (gnutls_privkey_t key);
 int gnutls_privkey_get_pk_algorithm (gnutls_privkey_t key, unsigned int* bits);
 gnutls_privkey_type_t gnutls_privkey_get_type (gnutls_privkey_t key);
 
+
 #define GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE 1
 int gnutls_privkey_import_pkcs11 (gnutls_privkey_t pkey, 
gnutls_pkcs11_privkey_t key, unsigned int flags);
 int gnutls_privkey_import_x509 (gnutls_privkey_t pkey, gnutls_x509_privkey_t 
key, unsigned int flags);
diff --git a/lib/includes/gnutls/pkcs11.h b/lib/includes/gnutls/pkcs11.h
index a54b96c..b5d1d6e 100644
--- a/lib/includes/gnutls/pkcs11.h
+++ b/lib/includes/gnutls/pkcs11.h
@@ -67,8 +67,8 @@ typedef int (*gnutls_pkcs11_pin_callback_t)(void *userdata, 
int attempt,
 /**
  * @brief PKCS#11 certificate reference.
  */
-struct gnutls_pkcs11_crt_st;
-typedef struct gnutls_pkcs11_crt_st* gnutls_pkcs11_crt_t;
+struct gnutls_pkcs11_obj_st;
+typedef struct gnutls_pkcs11_obj_st* gnutls_pkcs11_obj_t;
 
 
 
@@ -132,30 +132,11 @@ int gnutls_pkcs11_add_provider (const char * name, const 
char * params);
  * @param certificate  Certificate reference to free.
  * @return gnutls stauts.
  */
-int gnutls_pkcs11_crt_init ( gnutls_pkcs11_crt_t *certificate);
+int gnutls_pkcs11_obj_init ( gnutls_pkcs11_obj_t *certificate);
 
-/**
- * @brief Deserialize a certificate reference.
- * @param serialized   Serialized certificate.
- * @param p_certificate        Certificate reference.
- * @return gnutls status.
- */
-int gnutls_pkcs11_crt_import_url (gnutls_pkcs11_crt_t p_certificate, const 
char * url);
-
-/**
- * @brief Serialize a certificate reference.
- * @param certificate  Certificate reference to serialize.
- * @param serialized   Serialize result (string). Use gnutls_free() to free it.
- * @return gnutls status.
- */
-int gnutls_pkcs11_crt_export_url (gnutls_pkcs11_crt_t certificate, char** url);
-
-/**
- * @brief Free certificate reference.
- * @param certificate  Certificate reference to free.
- * @return gnutls stauts.
- */
-void gnutls_pkcs11_crt_deinit ( gnutls_pkcs11_crt_t certificate);
+int gnutls_pkcs11_obj_import_url (gnutls_pkcs11_obj_t, const char * url);
+int gnutls_pkcs11_obj_export_url (gnutls_pkcs11_obj_t, char** url);
+void gnutls_pkcs11_obj_deinit ( gnutls_pkcs11_obj_t);
 
 /**
  * @brief Release array of certificate references.
@@ -163,25 +144,27 @@ void gnutls_pkcs11_crt_deinit ( gnutls_pkcs11_crt_t 
certificate);
  * @param ncertificates        Array size.
  * @return gnutls status.
  */
-int gnutls_pkcs11_crt_list_deinit (gnutls_pkcs11_crt_t * certificates, const 
unsigned int ncertificates);
+int gnutls_pkcs11_obj_list_deinit (gnutls_pkcs11_obj_t * , const unsigned int 
nobjs);
 
 typedef enum {
-       GNUTLS_PKCS11_CRT_ID_HEX=1,
-       GNUTLS_PKCS11_CRT_LABEL,
-       GNUTLS_PKCS11_CRT_TOKEN_LABEL,
-       GNUTLS_PKCS11_CRT_TOKEN_SERIAL,
-       GNUTLS_PKCS11_CRT_TOKEN_MANUFACTURER,
-       GNUTLS_PKCS11_CRT_TOKEN_MODEL,
-       GNUTLS_PKCS11_CRT_ID,
-} gnutls_pkcs11_cert_info_t;
+       GNUTLS_PKCS11_OBJ_ID_HEX=1,
+       GNUTLS_PKCS11_OBJ_LABEL,
+       GNUTLS_PKCS11_OBJ_TOKEN_LABEL,
+       GNUTLS_PKCS11_OBJ_TOKEN_SERIAL,
+       GNUTLS_PKCS11_OBJ_TOKEN_MANUFACTURER,
+       GNUTLS_PKCS11_OBJ_TOKEN_MODEL,
+       GNUTLS_PKCS11_OBJ_ID,
+} gnutls_pkcs11_obj_info_t;
 
-int gnutls_pkcs11_crt_get_info(gnutls_pkcs11_crt_t crt, 
gnutls_pkcs11_cert_info_t itype, void* output, size_t* output_size);
+int gnutls_pkcs11_obj_get_info(gnutls_pkcs11_obj_t crt, 
gnutls_pkcs11_obj_info_t itype, void* output, size_t* output_size);
 
 typedef enum {
-       GNUTLS_PKCS11_CRT_ATTR_ALL=1,
-       GNUTLS_PKCS11_CRT_ATTR_TRUSTED, /* marked as trusted */
-       GNUTLS_PKCS11_CRT_ATTR_WITH_PK, /* with corresponding private key */
-} gnutls_pkcs11_crt_attr_t;
+       GNUTLS_PKCS11_OBJ_ATTR_CRT_ALL=1, /* all certificates */
+       GNUTLS_PKCS11_OBJ_ATTR_CRT_TRUSTED, /* certificates marked as trusted */
+       GNUTLS_PKCS11_OBJ_ATTR_CRT_WITH_PRIVKEY, /* certificates with 
corresponding private key */
+       GNUTLS_PKCS11_OBJ_ATTR_PUBKEY, /* public keys */
+       GNUTLS_PKCS11_OBJ_ATTR_ALL, /* everything! */
+} gnutls_pkcs11_obj_attr_t;
 
 /* token info */
 typedef enum {
@@ -191,32 +174,32 @@ typedef enum {
        GNUTLS_PKCS11_TOKEN_MODEL,
 } gnutls_pkcs11_token_info_t;
 
+typedef enum {
+       GNUTLS_PKCS11_OBJ_UNKNOWN,
+       GNUTLS_PKCS11_OBJ_X509_CRT,
+       GNUTLS_PKCS11_OBJ_PUBKEY,
+       GNUTLS_PKCS11_OBJ_PRIVKEY,
+       GNUTLS_PKCS11_OBJ_SECRET_KEY,
+       GNUTLS_PKCS11_OBJ_DATA,
+} gnutls_pkcs11_obj_type_t;
+
 int gnutls_pkcs11_token_get_url (unsigned int seq, char** url);
 int gnutls_pkcs11_token_get_info(const char* url, gnutls_pkcs11_token_info_t, 
void* output, size_t *output_size);
-/**
- * @brief Enumerate available certificates.
- * @param p_list       Location to store the list.
- * @param n_list       Location to store end list length.
- * @param url          Enumerate only certificates found in token(s) pointed 
by url
- * @param attributes Only export certificates that match this attribute
- * @return gnutls status.
- * @note the p_list is should not be initialized.
- */
-int gnutls_pkcs11_crt_list_import_url (gnutls_pkcs11_crt_t * p_list, unsigned 
int *const n_list, const char* url, gnutls_pkcs11_crt_attr_t flags);
 
-int gnutls_x509_crt_import_pkcs11( gnutls_x509_crt_t crt, gnutls_pkcs11_crt_t 
pkcs11_crt);
+#define GNUTLS_PKCS11_TOKEN_HW 1
+int gnutls_pkcs11_token_get_flags(const char* url, unsigned int *flags);
+
+int gnutls_pkcs11_obj_list_import_url (gnutls_pkcs11_obj_t * p_list, unsigned 
int *const n_list, const char* url, gnutls_pkcs11_obj_attr_t flags);
+
+int gnutls_x509_crt_import_pkcs11( gnutls_x509_crt_t crt, gnutls_pkcs11_obj_t 
pkcs11_crt);
 int gnutls_x509_crt_import_pkcs11_url( gnutls_x509_crt_t crt, const char* url);
 
-/**
- * @brief Return the type of the certificate
- * @param certificate  Certificate reference.
- * @return gnutls status.
- */
-gnutls_certificate_type_t gnutls_pkcs11_crt_get_type (gnutls_pkcs11_crt_t 
certificate);
+gnutls_pkcs11_obj_type_t gnutls_pkcs11_obj_get_type (gnutls_pkcs11_obj_t 
certificate);
+const char* gnutls_pkcs11_type_get_name (gnutls_pkcs11_obj_type_t);
 
 int gnutls_x509_crt_list_import_pkcs11 (gnutls_x509_crt_t * certs,
                                    unsigned int cert_max,
-                                   gnutls_pkcs11_crt_t * const pkcs11_certs,
+                                   gnutls_pkcs11_obj_t * const pkcs11_certs,
                                    unsigned int flags);
 
 
@@ -224,7 +207,7 @@ int gnutls_x509_crt_list_import_pkcs11 (gnutls_x509_crt_t * 
certs,
 int gnutls_pkcs11_privkey_init (gnutls_pkcs11_privkey_t * key);
 void gnutls_pkcs11_privkey_deinit (gnutls_pkcs11_privkey_t key);
 int gnutls_pkcs11_privkey_get_pk_algorithm (gnutls_pkcs11_privkey_t key, 
unsigned int* bits);
-int gnutls_pkcs11_privkey_get_info(gnutls_pkcs11_privkey_t crt, 
gnutls_pkcs11_cert_info_t itype, void* output, size_t* output_size);
+int gnutls_pkcs11_privkey_get_info(gnutls_pkcs11_privkey_t crt, 
gnutls_pkcs11_obj_info_t itype, void* output, size_t* output_size);
 int gnutls_pkcs11_privkey_import_url (gnutls_pkcs11_privkey_t key,
                                  const char* url);
 
diff --git a/lib/libgnutls.map b/lib/libgnutls.map
index dd234f7..cfe30f2 100644
--- a/lib/libgnutls.map
+++ b/lib/libgnutls.map
@@ -613,17 +613,17 @@ GNUTLS_2_11
         gnutls_pkcs11_set_pin_function;
        gnutls_pkcs11_set_token_function;
         gnutls_pkcs11_add_provider;
-        gnutls_pkcs11_crt_init;
-        gnutls_pkcs11_crt_import_url;
-        gnutls_pkcs11_crt_export_url;
-        gnutls_pkcs11_crt_deinit;
-        gnutls_pkcs11_crt_list_deinit;
-        gnutls_pkcs11_crt_list_import_url;
+        gnutls_pkcs11_obj_init;
+        gnutls_pkcs11_obj_import_url;
+        gnutls_pkcs11_obj_export_url;
+        gnutls_pkcs11_obj_deinit;
+        gnutls_pkcs11_obj_list_deinit;
+        gnutls_pkcs11_obj_list_import_url;
         gnutls_x509_crt_import_pkcs11;
-        gnutls_pkcs11_crt_get_type;
+        gnutls_pkcs11_obj_get_type;
         gnutls_x509_crt_list_import_pkcs11;
        gnutls_x509_crt_import_pkcs11_url;
-       gnutls_pkcs11_crt_get_info;
+       gnutls_pkcs11_obj_get_info;
        gnutls_pkcs11_token_get_info;
        gnutls_pkcs11_token_get_url;
        gnutls_pkcs11_privkey_init;
@@ -649,7 +649,22 @@ GNUTLS_2_11
        gnutls_x509_crq_privkey_sign;
        gnutls_x509_crl_privkey_sign;
        gnutls_x509_crt_privkey_sign;
+       gnutls_pubkey_init;
+       gnutls_pubkey_deinit;
+       gnutls_pubkey_get_pk_algorithm;
+       gnutls_pubkey_import_x509;
+       gnutls_pubkey_import_openpgp;
+       gnutls_pubkey_get_pk_rsa_raw;
+       gnutls_pubkey_get_pk_dsa_raw;
+       gnutls_pubkey_export;
+       gnutls_pubkey_get_key_id;
+       gnutls_pubkey_get_key_usage;
+       gnutls_pkcs11_type_get_name;
 
+       gnutls_pubkey_import_pkcs11_url;
+       gnutls_pubkey_import;
+       gnutls_x509_crt_set_pubkey;
+       gnutls_x509_crq_set_pubkey;
 } GNUTLS_2_10;
 
 GNUTLS_PRIVATE {
diff --git a/lib/libgnutlsxx.map b/lib/libgnutlsxx.map
index b3e2e76..c782f31 100644
--- a/lib/libgnutlsxx.map
+++ b/lib/libgnutlsxx.map
@@ -20,22 +20,13 @@
 # Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 # MA 02110-1301, USA
 
-GNUTLS_1_6
+GNUTLS_2_10
 {
   global:
     extern "C++" {
-      # To specify a class we also need to specify its typeinfo,
-      # typeinfo name and vtable objects.
-      # For example for class gnutls::psk_client_credentials,
-      # we need to declare this 4 lines:
-      #
-      # gnutls::psk_client_credentials::*;
-      # "typeinfo for gnutls::psk_client_credentials";
-      # "typeinfo name for gnutls::psk_client_credentials";
-      # "vtable for gnutls::psk_client_credentials";
+      # Allow all symbols for C++. It has its own way to keep
+      # symbol namespaces.
 
-      *gnutls::*;
+      *;
   };
-
-  local: *;
 };
diff --git a/lib/m4/hooks.m4 b/lib/m4/hooks.m4
index 2582b7d..a70eaab 100644
--- a/lib/m4/hooks.m4
+++ b/lib/m4/hooks.m4
@@ -30,6 +30,10 @@ AC_DEFUN([LIBGNUTLS_HOOKS],
   AC_SUBST(LT_REVISION, 6)
   AC_SUBST(LT_AGE, 16)
 
+  AC_SUBST(CXX_LT_CURRENT, 27)
+  AC_SUBST(CXX_LT_REVISION, 0)
+  AC_SUBST(CXX_LT_AGE, 0)
+
   # Used when creating the Windows libgnutls-XX.def files.
   DLL_VERSION=`expr ${LT_CURRENT} - ${LT_AGE}`
   AC_SUBST(DLL_VERSION)
diff --git a/lib/pkcs11.c b/lib/pkcs11.c
index 6bc291d..9eaeab6 100644
--- a/lib/pkcs11.c
+++ b/lib/pkcs11.c
@@ -43,21 +43,20 @@ struct gnutls_pkcs11_provider_s {
     ck_slot_id_t *slots;
 };
 
-struct gnutls_pkcs11_crt_st {
-    gnutls_datum_t raw;
-    gnutls_certificate_type_t type;
-    struct pkcs11_url_info info;
+struct url_find_data_st {
+    gnutls_pkcs11_obj_t crt;
 };
 
-struct url_find_data_st {
-    gnutls_pkcs11_crt_t crt;
+struct flags_find_data_st {
+    struct pkcs11_url_info info;
+    unsigned int slot_flags;
 };
 
 struct crt_find_data_st {
-    gnutls_pkcs11_crt_t *p_list;
+    gnutls_pkcs11_obj_t *p_list;
     unsigned int* n_list;
     unsigned int current;
-    gnutls_pkcs11_crt_attr_t flags;
+    gnutls_pkcs11_obj_attr_t flags;
     struct pkcs11_url_info info;
 };
 
@@ -138,8 +137,8 @@ fail:
 
 
 /**
- * gnutls_pkcs11_crt_get_info:
- * @crt: should contain a #gnutls_pkcs11_crt_t structure
+ * gnutls_pkcs11_obj_get_info:
+ * @crt: should contain a #gnutls_pkcs11_obj_t structure
  * @itype: Denotes the type of information requested
  * @output: where output will be stored
  * @output_size: contains the maximum size of the output and will be 
overwritten with actual
@@ -151,20 +150,20 @@ fail:
  *
  * Returns: zero on success or a negative value on error.
  **/
-int gnutls_pkcs11_crt_get_info(gnutls_pkcs11_crt_t crt, 
gnutls_pkcs11_cert_info_t itype, 
+int gnutls_pkcs11_obj_get_info(gnutls_pkcs11_obj_t crt, 
gnutls_pkcs11_obj_info_t itype, 
     void* output, size_t* output_size)
 {
     return pkcs11_get_info(&crt->info, itype, output, output_size);
 }
 
-int pkcs11_get_info(struct pkcs11_url_info *info, gnutls_pkcs11_cert_info_t 
itype, 
+int pkcs11_get_info(struct pkcs11_url_info *info, gnutls_pkcs11_obj_info_t 
itype, 
     void* output, size_t* output_size)
 {
     const char* str = NULL;
     size_t len;
     
     switch(itype) {
-        case GNUTLS_PKCS11_CRT_ID:
+        case GNUTLS_PKCS11_OBJ_ID:
             if (*output_size < info->certid_raw_size) {
                 *output_size = info->certid_raw_size;
                 return GNUTLS_E_SHORT_MEMORY_BUFFER;
@@ -173,22 +172,22 @@ int pkcs11_get_info(struct pkcs11_url_info *info, 
gnutls_pkcs11_cert_info_t ityp
             *output_size = info->certid_raw_size;
             
             return 0;
-        case GNUTLS_PKCS11_CRT_ID_HEX:
+        case GNUTLS_PKCS11_OBJ_ID_HEX:
             str = info->id;
             break;
-        case GNUTLS_PKCS11_CRT_LABEL:
+        case GNUTLS_PKCS11_OBJ_LABEL:
             str = info->label;
             break;
-        case GNUTLS_PKCS11_CRT_TOKEN_LABEL:
+        case GNUTLS_PKCS11_OBJ_TOKEN_LABEL:
             str = info->token;
             break;
-        case GNUTLS_PKCS11_CRT_TOKEN_SERIAL:
+        case GNUTLS_PKCS11_OBJ_TOKEN_SERIAL:
             str = info->serial;
             break;
-        case GNUTLS_PKCS11_CRT_TOKEN_MANUFACTURER:
+        case GNUTLS_PKCS11_OBJ_TOKEN_MANUFACTURER:
             str = info->manufacturer;
             break;
-        case GNUTLS_PKCS11_CRT_TOKEN_MODEL:
+        case GNUTLS_PKCS11_OBJ_TOKEN_MODEL:
             str = info->model;
             break;
         default:
@@ -578,6 +577,15 @@ int pkcs11_info_to_url(const struct pkcs11_url_info* info, 
char** url)
         init = 1;
     }
 
+    if (info->type[0]) {
+        ret = append(&str, info->type, "objecttype", init);
+        if (ret < 0) {
+                gnutls_assert();
+                goto cleanup;
+        }
+        init = 1;
+    }
+
     if (info->id[0] != 0) {
         ret = _gnutls_string_append_printf(&str, ";id=%s", info->id);
         if (ret < 0) {
@@ -598,7 +606,7 @@ cleanup:
 }
 
 /**
- * gnutls_pkcs11_crt_init:
+ * gnutls_pkcs11_obj_init:
  * @crt: The structure to be initialized
  *
  * This function will initialize a pkcs11 certificate structure.
@@ -606,9 +614,9 @@ cleanup:
  * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
  *   negative error value.
  **/
-int gnutls_pkcs11_crt_init(gnutls_pkcs11_crt_t * crt)
+int gnutls_pkcs11_obj_init(gnutls_pkcs11_obj_t * crt)
 {
-    *crt = gnutls_calloc(1, sizeof(struct gnutls_pkcs11_crt_st));
+    *crt = gnutls_calloc(1, sizeof(struct gnutls_pkcs11_obj_st));
     if (*crt == NULL) {
         gnutls_assert();
         return GNUTLS_E_MEMORY_ERROR;
@@ -618,12 +626,12 @@ int gnutls_pkcs11_crt_init(gnutls_pkcs11_crt_t * crt)
 }
 
 /**
- * gnutls_pkcs11_crt_deinit:
+ * gnutls_pkcs11_obj_deinit:
  * @key: The structure to be initialized
  *
  * This function will deinitialize a certificate structure.
  **/
-void gnutls_pkcs11_crt_deinit(gnutls_pkcs11_crt_t crt)
+void gnutls_pkcs11_obj_deinit(gnutls_pkcs11_obj_t crt)
 {
     free(crt);
 }
@@ -706,19 +714,62 @@ finish:
     return ret;
 }
 
-/* imports a raw certificate from a token to a pkcs11_crt_t structure.
+static const char* pkcs11_obj_type_to_str(gnutls_pkcs11_obj_type_t type)
+{
+    switch(type) {
+        case GNUTLS_PKCS11_OBJ_X509_CRT:
+            return "cert";
+        case GNUTLS_PKCS11_OBJ_PUBKEY:
+            return "public";
+        case GNUTLS_PKCS11_OBJ_PRIVKEY:
+            return "private";
+        case GNUTLS_PKCS11_OBJ_SECRET_KEY:
+            return "secretkey";
+        case GNUTLS_PKCS11_OBJ_DATA:
+            return "data";
+        case GNUTLS_PKCS11_OBJ_UNKNOWN:
+        default:
+            return "unknown";
+    }
+}
+
+/* imports a raw certificate from a token to a pkcs11_obj_t structure.
  */
-static int pkcs11_crt_import(gnutls_pkcs11_crt_t crt, const gnutls_datum_t* 
data, 
+static int pkcs11_obj_import(unsigned int class, gnutls_pkcs11_obj_t crt, 
const gnutls_datum_t* data, 
    const gnutls_datum_t * id, const gnutls_datum_t * label, struct 
ck_token_info* tinfo)
 {
     char *s;
     int ret;
     
-    crt->type = GNUTLS_CRT_X509;
-    ret = _gnutls_set_datum(&crt->raw, data->data, data->size);
-    if (ret < 0) {
-        gnutls_assert();
-        return ret;
+    switch(class) {
+        case CKO_CERTIFICATE:
+            crt->type = GNUTLS_PKCS11_OBJ_X509_CRT;
+            break;
+        case CKO_PUBLIC_KEY:
+            crt->type = GNUTLS_PKCS11_OBJ_PUBKEY;
+            break;
+        case CKO_PRIVATE_KEY:
+            crt->type = GNUTLS_PKCS11_OBJ_PRIVKEY;
+            break;
+        case CKO_SECRET_KEY:
+            crt->type = GNUTLS_PKCS11_OBJ_SECRET_KEY;
+            break;
+        case CKO_DATA:
+            crt->type = GNUTLS_PKCS11_OBJ_DATA;
+            break;
+        default:
+            crt->type = GNUTLS_PKCS11_OBJ_UNKNOWN;
+    }
+    
+    if (crt->type != GNUTLS_PKCS11_OBJ_UNKNOWN)
+        strcpy(crt->info.type, pkcs11_obj_type_to_str(crt->type));
+
+    if (data && data->data) {
+        ret = _gnutls_set_datum(&crt->raw, data->data, data->size);
+        if (ret < 0) {
+            gnutls_assert();
+            return ret;
+        }
     }
 
     terminate_string(tinfo->manufacturer_id, sizeof tinfo->manufacturer_id);
@@ -732,19 +783,21 @@ static int pkcs11_crt_import(gnutls_pkcs11_crt_t crt, 
const gnutls_datum_t* data
     snprintf(crt->info.model, sizeof(crt->info.model), "%s", tinfo->model);
     snprintf(crt->info.serial, sizeof(crt->info.serial), "%s", 
tinfo->serial_number);
 
-    memcpy(crt->info.label, label->data, label->size);
-    crt->info.label[label->size] = 0;
+    if (label && label->data) {
+        memcpy(crt->info.label, label->data, label->size);
+        crt->info.label[label->size] = 0;
+    }
 
-    strcpy(crt->info.type, "cert");
+    if (id && id->data) {
+        s = _gnutls_bin2hex(id->data, id->size, crt->info.id, 
sizeof(crt->info.id), ":");
+        if (s == NULL) {
+            gnutls_assert();
+            return GNUTLS_E_PKCS11_ERROR;
+        }
     
-    s = _gnutls_bin2hex(id->data, id->size, crt->info.id, 
sizeof(crt->info.id), ":");
-    if (s == NULL) {
-        gnutls_assert();
-        return GNUTLS_E_PKCS11_ERROR;
+        memmove(crt->info.certid_raw, id->data, id->size);
+        crt->info.certid_raw_size = id->size;
     }
-    
-    memmove(crt->info.certid_raw, id->data, id->size);
-    crt->info.certid_raw_size = id->size;
 
     return 0;
 }
@@ -843,7 +896,7 @@ static int find_cert_url(pakchois_session_t *pks, struct 
token_info *info, void*
             gnutls_datum_t data = { a[0].value, a[0].value_len };
             gnutls_datum_t label = { a[1].value, a[1].value_len };
             
-            ret = pkcs11_crt_import(find_data->crt, &data, &id, &label, 
&info->tinfo);
+            ret = pkcs11_obj_import(CKO_CERTIFICATE, find_data->crt, &data, 
&id, &label, &info->tinfo);
             if (ret < 0) {
                 gnutls_assert();
                 goto cleanup;
@@ -877,14 +930,14 @@ cleanup:
  * @url: a PKCS 11 url identifying the key
  *
  * This function will "import" a PKCS 11 URL identifying a certificate
- * key to the #gnutls_pkcs11_crt_t structure. This does not involve any
- * parsing (such as X.509 or OpenPGP) since the #gnutls_pkcs11_crt_t is
+ * key to the #gnutls_pkcs11_obj_t structure. This does not involve any
+ * parsing (such as X.509 or OpenPGP) since the #gnutls_pkcs11_obj_t is
  * format agnostic. Only data are transferred.
  *
  * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
  *   negative error value.
  **/
-int gnutls_pkcs11_crt_import_url (gnutls_pkcs11_crt_t cert, const char * url)
+int gnutls_pkcs11_obj_import_url (gnutls_pkcs11_obj_t cert, const char * url)
 {
     int ret;
     struct url_find_data_st find_data;
@@ -973,6 +1026,7 @@ int gnutls_pkcs11_token_get_url (unsigned int seq, char** 
url)
     return 0;
 
 }
+
 /**
  * gnutls_pkcs11_token_get_info:
  * @url: should contain a PKCS 11 URL
@@ -980,7 +1034,7 @@ int gnutls_pkcs11_token_get_url (unsigned int seq, char** 
url)
  * @output: where output will be stored
  * @output_size: contains the maximum size of the output and will be 
overwritten with actual
  *
- * This function will return information about the PKCS 11 private key such
+ * This function will return information about the PKCS 11 token such
  * as the label, id as well as token information where the key is stored.
  *
  * Returns: zero on success or a negative value on error.
@@ -1031,7 +1085,7 @@ int gnutls_pkcs11_token_get_info(const char* url, 
gnutls_pkcs11_token_info_t tty
 }
 
 /**
- * gnutls_pkcs11_crt_export_url:
+ * gnutls_pkcs11_obj_export_url:
  * @crt: Holds the PKCS 11 certificate
  * @url: will contain an allocated url
  *
@@ -1040,7 +1094,7 @@ int gnutls_pkcs11_token_get_info(const char* url, 
gnutls_pkcs11_token_info_t tty
  * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
  *   negative error value.
  **/
-int gnutls_pkcs11_crt_export_url (gnutls_pkcs11_crt_t cert, char ** url)
+int gnutls_pkcs11_obj_export_url (gnutls_pkcs11_obj_t cert, char ** url)
 {
 int ret;
 
@@ -1054,7 +1108,7 @@ int ret;
 }
 
 /**
- * gnutls_pkcs11_crt_get_type:
+ * gnutls_pkcs11_obj_get_type:
  * @certificate: Holds the PKCS 11 certificate
  *
  * This function will return the type of the certificate being
@@ -1062,9 +1116,9 @@ int ret;
  *
  * Returns: The type of the certificate.
  **/
-gnutls_certificate_type_t gnutls_pkcs11_crt_get_type (gnutls_pkcs11_crt_t 
certificate)
+gnutls_pkcs11_obj_type_t gnutls_pkcs11_obj_get_type (gnutls_pkcs11_obj_t obj)
 {
-    return certificate->type;
+    return obj->type;
 }
 
 struct pkey_list {
@@ -1086,7 +1140,6 @@ int pkcs11_login(pakchois_session_t *pks, struct 
token_info *info)
     /* force login on HW tokens. Some tokens will not list private keys
      * if login has not been performed.
      */
-//    if (!(info->sinfo.flags & CKF_HW_SLOT) && (info->tinfo.flags & 
CKF_LOGIN_REQUIRED) == 0) {
     if ((info->tinfo.flags & CKF_LOGIN_REQUIRED) == 0) {
         gnutls_assert();
         _gnutls_debug_log( "pk11: No login required.\n");
@@ -1157,7 +1210,6 @@ int pkcs11_login(pakchois_session_t *pks, struct 
token_info *info)
     return (rv == CKR_OK || rv == CKR_USER_ALREADY_LOGGED_IN) ? 0 : 
GNUTLS_E_PKCS11_ERROR;
 }
 
-
 static int find_privkeys(pakchois_session_t *pks, struct token_info* info, 
struct pkey_list *list)
 {
     struct ck_attribute a[3];
@@ -1170,12 +1222,6 @@ static int find_privkeys(pakchois_session_t *pks, struct 
token_info* info, struc
 
     class = CKO_PRIVATE_KEY;
 
-    ret = pkcs11_login(pks, info);
-    if (ret < 0) {
-        gnutls_assert();
-        return ret;
-    }
-
     /* Find an object with private key class and a certificate ID
      * which matches the certificate. */
     /* FIXME: also match the cert subject. */
@@ -1248,7 +1294,7 @@ static int find_privkeys(pakchois_session_t *pks, struct 
token_info* info, struc
 /* Recover certificate list from tokens */
 
 
-static int find_crts(pakchois_session_t *pks, struct token_info *info, void* 
input)
+static int find_objs(pakchois_session_t *pks, struct token_info *info, void* 
input)
 {
     struct crt_find_data_st* find_data = input;
     struct ck_attribute a[4];
@@ -1263,6 +1309,7 @@ static int find_crts(pakchois_session_t *pks, struct 
token_info *info, void* inp
     char label_tmp[PKCS11_LABEL_SIZE];
     int ret, i;
     struct pkey_list plist; /* private key holder */
+    int tot_values = 0;
 
     if (info == NULL) { /* final call */
         if (find_data->current <= *find_data->n_list)
@@ -1297,15 +1344,14 @@ static int find_crts(pakchois_session_t *pks, struct 
token_info *info, void* inp
             return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
     }
 
-    if (find_data->info.type[0] != 0) {
-        if (strcmp(find_data->info.type, "cert") != 0) {
+    memset(&plist, 0, sizeof(plist));
+    if (find_data->flags==GNUTLS_PKCS11_OBJ_ATTR_CRT_WITH_PRIVKEY) {
+        ret = pkcs11_login(pks, info);
+        if (ret < 0) {
             gnutls_assert();
-            return GNUTLS_E_UNIMPLEMENTED_FEATURE;
+            return ret;
         }
-    }
 
-    memset(&plist, 0, sizeof(plist));
-    if (find_data->flags==GNUTLS_PKCS11_CRT_ATTR_WITH_PK) {
         ret = find_privkeys(pks, info, &plist);
         if (ret < 0) {
             gnutls_assert();
@@ -1316,6 +1362,12 @@ static int find_crts(pakchois_session_t *pks, struct 
token_info *info, void* inp
             gnutls_assert();
             return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
         }
+    } else if (find_data->flags==GNUTLS_PKCS11_OBJ_ATTR_ALL) {
+        ret = pkcs11_login(pks, info);
+        if (ret < 0) {
+            gnutls_assert();
+            return ret;
+        }
     }
 
     cert_data = gnutls_malloc(MAX_CERT_SIZE);
@@ -1325,27 +1377,51 @@ static int find_crts(pakchois_session_t *pks, struct 
token_info *info, void* inp
     }
 
     /* Find objects with cert class and X.509 cert type. */
-    class = CKO_CERTIFICATE;
-    type = CKC_X_509;
-    trusted = 1;
-
-    a[0].type = CKA_CLASS;
-    a[0].value = &class;
-    a[0].value_len = sizeof class;
     
-    if (find_data->flags == GNUTLS_PKCS11_CRT_ATTR_ALL || 
find_data->flags==GNUTLS_PKCS11_CRT_ATTR_WITH_PK) {
+    if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_CRT_ALL || 
find_data->flags==GNUTLS_PKCS11_OBJ_ATTR_CRT_WITH_PRIVKEY) {
+        class = CKO_CERTIFICATE;
+        type = CKC_X_509;
+        trusted = 1;
+
+        a[0].type = CKA_CLASS;
+        a[0].value = &class;
+        a[0].value_len = sizeof class;
+
         a[1].type = CKA_CERTIFICATE_TYPE;
         a[1].value = &type;
         a[1].value_len = sizeof type;
-    }
+        
+        tot_values = 2;
+    } else if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_CRT_TRUSTED) {
+        class = CKO_CERTIFICATE;
+        type = CKC_X_509;
+        trusted = 1;
+
+        a[0].type = CKA_CLASS;
+        a[0].value = &class;
+        a[0].value_len = sizeof class;
 
-    if (find_data->flags == GNUTLS_PKCS11_CRT_ATTR_TRUSTED) {
         a[1].type = CKA_TRUSTED;
         a[1].value = &trusted;
         a[1].value_len = sizeof trusted;
+        
+        tot_values = 2;
+    } else if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_PUBKEY) {
+        class = CKO_PUBLIC_KEY;
+
+        a[0].type = CKA_CLASS;
+        a[0].value = &class;
+        a[0].value_len = sizeof class;
+        
+        tot_values = 1;
+    } else if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_ALL) {
+        tot_values = 0;
+    } else {
+        gnutls_assert();
+        return GNUTLS_E_INVALID_REQUEST;
     }
 
-    rv = pakchois_find_objects_init(pks, a, 2);
+    rv = pakchois_find_objects_init(pks, a, tot_values);
     if (rv != CKR_OK) {
         gnutls_assert();
         _gnutls_debug_log("pk11: FindObjectsInit failed.\n");
@@ -1354,54 +1430,75 @@ static int find_crts(pakchois_session_t *pks, struct 
token_info *info, void* inp
 
     while (pakchois_find_objects(pks, &obj, 1, &count) == CKR_OK
            && count == 1) {
+        gnutls_datum_t label, id, value;
+
+        a[0].type = CKA_LABEL;
+        a[0].value = label_tmp;
+        a[0].value_len = sizeof label_tmp;
+
+        if (pakchois_get_attribute_value(pks, obj, a, 1) == CKR_OK) {
+            label.data = a[0].value;
+            label.size = a[0].value_len;
+        } else {
+            label.data = NULL;
+            label.size = 0;
+        }
+
+        a[0].type = CKA_ID;
+        a[0].value = certid_tmp;
+        a[0].value_len = sizeof certid_tmp;
+        if (pakchois_get_attribute_value(pks, obj, a, 1) == CKR_OK) {
+            id.data = a[0].value;
+            id.size = a[0].value_len;
+        } else {
+            id.data = NULL;
+            id.size = 0;
+        }        
 
         a[0].type = CKA_VALUE;
         a[0].value = cert_data;
         a[0].value_len = MAX_CERT_SIZE;
-        a[1].type = CKA_ID;
-        a[1].value = certid_tmp;
-        a[1].value_len = sizeof(certid_tmp);
-        a[2].type = CKA_LABEL;
-        a[2].value = label_tmp;
-        a[2].value_len = sizeof label_tmp;
-
-        if (pakchois_get_attribute_value(pks, obj, a, 3) == CKR_OK) {
-            gnutls_datum_t data = { a[0].value, a[0].value_len };
-            gnutls_datum_t id = { a[1].value, a[1].value_len };
-            gnutls_datum_t label = { a[2].value, a[2].value_len };
-
-            /* XXX check also ID with find_data->info.id */
+        if (pakchois_get_attribute_value(pks, obj, a, 1) == CKR_OK) {
+            value.data = a[0].value;
+            value.size = a[0].value_len;
+        } else {
+            value.data = NULL;
+            value.size = 0;
+        }        
 
-            if (find_data->flags == GNUTLS_PKCS11_CRT_ATTR_WITH_PK) {
-                for (i=0;i<plist.key_ids_size;i++) {
-                    if (plist.key_ids[i].length != a[1].value_len || 
memcmp(plist.key_ids[i].data, a[1].value, a[1].value_len)!=0) {
-                        /* not found */
-                        continue;
-                    }
-                }
-            }
+        if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_ALL) {
+            a[0].type = CKA_CLASS;
+            a[0].value = &class;
+            a[0].value_len = sizeof class;
 
-            if (find_data->current < *find_data->n_list) {
+            pakchois_get_attribute_value(pks, obj, a, 1);
+        }
 
-                ret = 
gnutls_pkcs11_crt_init(&find_data->p_list[find_data->current]);
-                if (ret < 0) {
-                    gnutls_assert();
-                    goto fail;
+        if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_CRT_WITH_PRIVKEY) {
+            for (i=0;i<plist.key_ids_size;i++) {
+                if (plist.key_ids[i].length != a[1].value_len || 
memcmp(plist.key_ids[i].data, a[1].value, a[1].value_len)!=0) {
+                    /* not found */
+                    continue;
                 }
+            }
+        }
 
-                ret = pkcs11_crt_import(find_data->p_list[find_data->current], 
&data, &id, &label, &info->tinfo);
-                if (ret < 0) {
-                    gnutls_assert();
-                    goto fail;
-                }
+        if (find_data->current < *find_data->n_list) {
+            ret = 
gnutls_pkcs11_obj_init(&find_data->p_list[find_data->current]);
+            if (ret < 0) {
+                gnutls_assert();
+                goto fail;
             }
-            
-            find_data->current++;
 
+            ret = pkcs11_obj_import(class, 
find_data->p_list[find_data->current], &value, &id, &label, &info->tinfo);
+            if (ret < 0) {
+                gnutls_assert();
+                goto fail;
+            }
         }
-        else {
-            _gnutls_debug_log("pk11: Skipped cert, missing attrs.\n");
-        }
+                
+        find_data->current++;
+
     }
 
     gnutls_free(cert_data);
@@ -1419,7 +1516,7 @@ fail:
         gnutls_free( plist.key_ids);
     }
     for (i=0;i<find_data->current;i++) {
-        gnutls_pkcs11_crt_deinit(find_data->p_list[i]);
+        gnutls_pkcs11_obj_deinit(find_data->p_list[i]);
     }
     find_data->current = 0;
 
@@ -1427,11 +1524,11 @@ fail:
 }
 
 /**
- * gnutls_pkcs11_crt_list_import_url:
+ * gnutls_pkcs11_obj_list_import_url:
  * @p_list: An uninitialized certificate list (may be NULL)
  * @n_list: initially should hold the maximum size of the list. Will contain 
the actual size.
  * @url: A PKCS 11 url identifying a set of certificates
- * @flags: Attributes of type #gnutls_pkcs11_crt_attr_t that can be used to 
limit output
+ * @flags: Attributes of type #gnutls_pkcs11_obj_attr_t that can be used to 
limit output
  *
  * This function will initialize and set value to a certificate list
  * specified by a PKCS 11 URL.
@@ -1439,7 +1536,7 @@ fail:
  * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
  *   negative error value.
  **/
-int gnutls_pkcs11_crt_list_import_url (gnutls_pkcs11_crt_t * p_list, unsigned 
int *n_list, const char* url, gnutls_pkcs11_crt_attr_t flags)
+int gnutls_pkcs11_obj_list_import_url (gnutls_pkcs11_obj_t * p_list, unsigned 
int *n_list, const char* url, gnutls_pkcs11_obj_attr_t flags)
 {
     int ret;
     struct crt_find_data_st find_data;
@@ -1460,7 +1557,7 @@ int gnutls_pkcs11_crt_list_import_url 
(gnutls_pkcs11_crt_t * p_list, unsigned in
         return ret;
     }
 
-    ret = _pkcs11_traverse_tokens(find_crts, &find_data, 0);
+    ret = _pkcs11_traverse_tokens(find_objs, &find_data, 0);
     if (ret < 0) {
         gnutls_assert();
         return ret;
@@ -1475,7 +1572,7 @@ int gnutls_pkcs11_crt_list_import_url 
(gnutls_pkcs11_crt_t * p_list, unsigned in
  * @url: A PKCS 11 url
  *
  * This function will import a PKCS 11 certificate directly from a token
- * without involving the #gnutls_pkcs11_crt_t structure. This function will
+ * without involving the #gnutls_pkcs11_obj_t structure. This function will
  * fail if the certificate stored is not of X.509 type.
  *
  * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
@@ -1483,16 +1580,16 @@ int gnutls_pkcs11_crt_list_import_url 
(gnutls_pkcs11_crt_t * p_list, unsigned in
  **/
 int gnutls_x509_crt_import_pkcs11_url( gnutls_x509_crt_t crt, const char* url)
 {
-    gnutls_pkcs11_crt_t pcrt;
+    gnutls_pkcs11_obj_t pcrt;
     int ret;
     
-    ret = gnutls_pkcs11_crt_init ( &pcrt);
+    ret = gnutls_pkcs11_obj_init ( &pcrt);
     if (ret < 0) {
         gnutls_assert();
         return ret;
     }
 
-    ret = gnutls_pkcs11_crt_import_url (pcrt, url);
+    ret = gnutls_pkcs11_obj_import_url (pcrt, url);
     if (ret < 0) {
         gnutls_assert();
         goto cleanup;
@@ -1507,7 +1604,7 @@ int gnutls_x509_crt_import_pkcs11_url( gnutls_x509_crt_t 
crt, const char* url)
     ret = 0;
 cleanup:
 
-    gnutls_pkcs11_crt_deinit(pcrt);
+    gnutls_pkcs11_obj_deinit(pcrt);
     
     return ret;
 }
@@ -1516,7 +1613,7 @@ cleanup:
 /**
  * gnutls_x509_crt_import_pkcs11:
  * @crt: A certificate of type #gnutls_x509_crt_t
- * @pkcs11_crt: A PKCS 11 certificate
+ * @pkcs11_obj: A PKCS 11 object that contains a certificate
  *
  * This function will import a PKCS 11 certificate to a #gnutls_x509_crt_t
  * structure.
@@ -1524,13 +1621,13 @@ cleanup:
  * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
  *   negative error value.
  **/
-int gnutls_x509_crt_import_pkcs11( gnutls_x509_crt_t crt, gnutls_pkcs11_crt_t 
pkcs11_crt)
+int gnutls_x509_crt_import_pkcs11( gnutls_x509_crt_t crt, gnutls_pkcs11_obj_t 
pkcs11_crt)
 {
     return gnutls_x509_crt_import(crt, &pkcs11_crt->raw, GNUTLS_X509_FMT_DER);
 }
 
 int gnutls_x509_crt_list_import_pkcs11 (gnutls_x509_crt_t * certs,
-    unsigned int cert_max, gnutls_pkcs11_crt_t * const pkcs11_certs,
+    unsigned int cert_max, gnutls_pkcs11_obj_t * const pkcs11_certs,
     unsigned int flags)
 {
     int i, j;
@@ -1560,3 +1657,97 @@ cleanup:
     return ret;
 }
 
+static int find_flags(pakchois_session_t *pks, struct token_info *info, void* 
input)
+{
+    struct flags_find_data_st* find_data = input;
+    
+    if (info == NULL) { /* we don't support multiple calls */
+        gnutls_assert();
+        return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
+    }
+
+    /* do not bother reading the token if basic fields do not match
+     */
+    if (find_data->info.manufacturer[0] != 0) {
+        if (strcmp(find_data->info.manufacturer, info->tinfo.manufacturer_id) 
!= 0)
+            return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
+    }
+
+    if (find_data->info.token[0] != 0) {
+        if (strcmp(find_data->info.token, info->tinfo.label) != 0)
+            return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
+    }
+
+    if (find_data->info.model[0] != 0) {
+        if (strcmp(find_data->info.model, info->tinfo.model) != 0)
+            return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
+    }
+
+    if (find_data->info.serial[0] != 0) {
+        if (strcmp(find_data->info.serial, info->tinfo.serial_number) != 0)
+            return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
+    }
+
+    /* found token! */
+
+    find_data->slot_flags = info->sinfo.flags;
+
+    return 0;
+}
+
+/**
+ * gnutls_pkcs11_token_get_flags:
+ * @url: should contain a PKCS 11 URL
+ * @flags: The output flags
+ *
+ * This function will return information about the PKCS 11 token flags.
+ *
+ * Returns: zero on success or a negative value on error.
+ **/
+int gnutls_pkcs11_token_get_flags(const char* url, unsigned int *flags)
+{
+    const char* str;
+    size_t len;
+    
+    struct flags_find_data_st find_data;
+    int ret;
+
+    ret = pkcs11_url_to_info(url, &find_data.info);
+    if (ret < 0) {
+        gnutls_assert();
+        return ret;
+    }
+
+    ret = _pkcs11_traverse_tokens(find_flags, &find_data, 0);
+    if (ret < 0) {
+        gnutls_assert();
+        return ret;
+    }
+
+    *flags = 0;
+    if (find_data.slot_flags & CKF_HW_SLOT)
+        *flags |= GNUTLS_PKCS11_TOKEN_HW;
+    
+    return 0;
+
+}
+
+
+const char* gnutls_pkcs11_type_get_name (gnutls_pkcs11_obj_type_t type)
+{
+    switch(type) {
+        case GNUTLS_PKCS11_OBJ_X509_CRT:
+            return "X.509 Certificate";
+        case GNUTLS_PKCS11_OBJ_PUBKEY:
+            return "Public key";
+        case GNUTLS_PKCS11_OBJ_PRIVKEY:
+            return "Private key";
+        case GNUTLS_PKCS11_OBJ_SECRET_KEY:
+            return "Secret key";
+        case GNUTLS_PKCS11_OBJ_DATA:
+            return "Data";
+        case GNUTLS_PKCS11_OBJ_UNKNOWN:
+        default:
+            return "Unknown";
+    }
+}
diff --git a/lib/pkcs11_int.h b/lib/pkcs11_int.h
index c070832..86cbba1 100644
--- a/lib/pkcs11_int.h
+++ b/lib/pkcs11_int.h
@@ -29,6 +29,12 @@ struct pkcs11_url_info
     size_t certid_raw_size;
 };
 
+struct gnutls_pkcs11_obj_st {
+    gnutls_datum_t raw;
+    gnutls_pkcs11_obj_type_t type;
+    struct pkcs11_url_info info;
+};
+
 /* thus function is called for every token in the traverse_tokens
  * function. Once everything is traversed it is called with NULL tinfo.
  * It should return 0 if found what it was looking for.
@@ -38,7 +44,7 @@ typedef int (*find_func_t)(pakchois_session_t *pks, struct 
token_info* tinfo, vo
 int _pkcs11_traverse_tokens (find_func_t find_func, void* input, int 
leave_session);
 int pkcs11_url_to_info(const char* url, struct pkcs11_url_info* info);
 
-int pkcs11_get_info(struct pkcs11_url_info *info, gnutls_pkcs11_cert_info_t 
itype, 
+int pkcs11_get_info(struct pkcs11_url_info *info, gnutls_pkcs11_obj_info_t 
itype, 
     void* output, size_t* output_size);
 int pkcs11_login(pakchois_session_t *pks, struct token_info *info);
 
@@ -48,4 +54,5 @@ extern void* token_data;
 void pkcs11_rescan_slots(void);
 int pkcs11_info_to_url(const struct pkcs11_url_info* info, char** url);
 
+
 #endif
diff --git a/lib/pkcs11_privkey.c b/lib/pkcs11_privkey.c
index 60a6888..913b11d 100644
--- a/lib/pkcs11_privkey.c
+++ b/lib/pkcs11_privkey.c
@@ -112,7 +112,7 @@ int 
gnutls_pkcs11_privkey_get_pk_algorithm(gnutls_pkcs11_privkey_t key, unsigned
  * Returns: zero on success or a negative value on error.
  **/
 int gnutls_pkcs11_privkey_get_info(gnutls_pkcs11_privkey_t pkey,
-                                  gnutls_pkcs11_cert_info_t itype,
+                                  gnutls_pkcs11_obj_info_t itype,
                                   void *output, size_t * output_size)
 {
        return pkcs11_get_info(&pkey->info, itype, output, output_size);
diff --git a/lib/x509/common.c b/lib/x509/common.c
index 445a932..ccda343 100644
--- a/lib/x509/common.c
+++ b/lib/x509/common.c
@@ -1138,6 +1138,18 @@ cleanup:
   return result;
 }
 
+void _asnstr_append_name(char* name, size_t name_size, const char* part1, 
const char* part2)
+{
+  if (part1[0] != 0) 
+    {
+         _gnutls_str_cpy (name, name_size, part1);
+         _gnutls_str_cat (name, name_size, part2);
+    }
+  else
+         _gnutls_str_cpy (name, name_size, part2+1 /* remove initial dot */);
+}
+
+
 /* Encodes and copies the private key parameters into a
  * subjectPublicKeyInfo structure.
  *
@@ -1163,8 +1175,8 @@ _gnutls_x509_encode_and_copy_PKI_params (ASN1_TYPE dst,
 
   /* write the OID
    */
-  _gnutls_str_cpy (name, sizeof (name), dst_name);
-  _gnutls_str_cat (name, sizeof (name), ".algorithm.algorithm");
+  _asnstr_append_name(name, sizeof(name), dst_name, ".algorithm.algorithm");
+
   result = asn1_write_value (dst, name, pk, 1);
   if (result != ASN1_SUCCESS)
     {
@@ -1176,8 +1188,8 @@ _gnutls_x509_encode_and_copy_PKI_params (ASN1_TYPE dst,
     {
       /* disable parameters, which are not used in RSA.
        */
-      _gnutls_str_cpy (name, sizeof (name), dst_name);
-      _gnutls_str_cat (name, sizeof (name), ".algorithm.parameters");
+         _asnstr_append_name(name, sizeof(name), dst_name, 
".algorithm.parameters");
+
       result = asn1_write_value (dst, name, NULL, 0);
       if (result != ASN1_SUCCESS)
        {
@@ -1194,8 +1206,7 @@ _gnutls_x509_encode_and_copy_PKI_params (ASN1_TYPE dst,
 
       /* Write the DER parameters. (in bits)
        */
-      _gnutls_str_cpy (name, sizeof (name), dst_name);
-      _gnutls_str_cat (name, sizeof (name), ".subjectPublicKey");
+         _asnstr_append_name(name, sizeof(name), dst_name, 
".subjectPublicKey");
       result = asn1_write_value (dst, name, der.data, der.size * 8);
 
       _gnutls_free_datum (&der);
@@ -1218,8 +1229,7 @@ _gnutls_x509_encode_and_copy_PKI_params (ASN1_TYPE dst,
 
       /* Write the DER parameters.
        */
-      _gnutls_str_cpy (name, sizeof (name), dst_name);
-      _gnutls_str_cat (name, sizeof (name), ".algorithm.parameters");
+         _asnstr_append_name(name, sizeof(name), dst_name, 
".algorithm.parameters");
       result = asn1_write_value (dst, name, der.data, der.size);
 
       _gnutls_free_datum (&der);
@@ -1237,8 +1247,7 @@ _gnutls_x509_encode_and_copy_PKI_params (ASN1_TYPE dst,
          return result;
        }
 
-      _gnutls_str_cpy (name, sizeof (name), dst_name);
-      _gnutls_str_cat (name, sizeof (name), ".subjectPublicKey");
+         _asnstr_append_name(name, sizeof(name), dst_name, 
".subjectPublicKey");
       result = asn1_write_value (dst, name, der.data, der.size * 8);
 
       _gnutls_free_datum (&der);
@@ -1271,9 +1280,8 @@ _gnutls_x509_get_pk_algorithm (ASN1_TYPE src, const char 
*src_name,
   bigint_t params[MAX_PUBLIC_PARAMS_SIZE];
   char name[128];
 
-  _gnutls_str_cpy (name, sizeof (name), src_name);
-  _gnutls_str_cat (name, sizeof (name), ".algorithm.algorithm");
 
+  _asnstr_append_name(name, sizeof(name), src_name, ".algorithm.algorithm");
   len = sizeof (oid);
   result = asn1_read_value (src, name, oid, &len);
 
@@ -1297,8 +1305,7 @@ _gnutls_x509_get_pk_algorithm (ASN1_TYPE src, const char 
*src_name,
 
   /* Now read the parameters' bits 
    */
-  _gnutls_str_cpy (name, sizeof (name), src_name);
-  _gnutls_str_cat (name, sizeof (name), ".subjectPublicKey");
+  _asnstr_append_name(name, sizeof(name), src_name, ".subjectPublicKey");
 
   len = 0;
   result = asn1_read_value (src, name, NULL, &len);
@@ -1323,8 +1330,7 @@ _gnutls_x509_get_pk_algorithm (ASN1_TYPE src, const char 
*src_name,
       return GNUTLS_E_MEMORY_ERROR;
     }
 
-  _gnutls_str_cpy (name, sizeof (name), src_name);
-  _gnutls_str_cat (name, sizeof (name), ".subjectPublicKey");
+  _asnstr_append_name(name, sizeof(name), src_name, ".subjectPublicKey");
 
   result = asn1_read_value (src, name, str, &len);
 
diff --git a/lib/x509/common.h b/lib/x509/common.h
index 29bffd1..bf73cb9 100644
--- a/lib/x509/common.h
+++ b/lib/x509/common.h
@@ -129,4 +129,12 @@ int _gnutls_x509_get_signed_data (ASN1_TYPE src, const 
char *src_name,
 int _gnutls_x509_get_signature (ASN1_TYPE src, const char *src_name,
                                gnutls_datum_t * signature);
 
+int _gnutls_get_asn_mpis (ASN1_TYPE asn, const char *root,
+          bigint_t * params, int *params_size);
+
+int _gnutls_get_key_id (gnutls_pk_algorithm_t pk, bigint_t* params, int 
params_size,
+                   unsigned char *output_data, size_t * output_data_size);
+
+void _asnstr_append_name(char* name, size_t name_size, const char* part1, 
const char* part2);
+
 #endif
diff --git a/lib/x509/mpi.c b/lib/x509/mpi.c
index 3a3bc22..fac9e46 100644
--- a/lib/x509/mpi.c
+++ b/lib/x509/mpi.c
@@ -206,23 +206,32 @@ _gnutls_x509_read_dsa_pubkey (opaque * der, int dersize, 
bigint_t * params)
 
 /* Extracts DSA and RSA parameters from a certificate.
  */
-static int
-get_mpis (int pk_algorithm, ASN1_TYPE asn, const char *root,
+int
+_gnutls_get_asn_mpis (ASN1_TYPE asn, const char *root,
          bigint_t * params, int *params_size)
 {
   int result;
   char name[256];
   gnutls_datum_t tmp = { NULL, 0 };
+  gnutls_pk_algorithm pk_algorithm;
+
+  result = _gnutls_x509_get_pk_algorithm(asn, root, NULL);
+  if (result < 0)
+    {
+      gnutls_assert();
+      return result;
+    }
+  
+  pk_algorithm = result;
 
   /* Read the algorithm's parameters
    */
-  snprintf (name, sizeof (name), "%s.subjectPublicKey", root);
+  _asnstr_append_name(name, sizeof(name), root, ".subjectPublicKey");
   result = _gnutls_x509_read_value (asn, name, &tmp, 2);
 
   if (result < 0)
     {
       gnutls_assert ();
-      fprintf (stderr, "name: %s\n", name);
       return result;
     }
 
@@ -275,7 +284,7 @@ get_mpis (int pk_algorithm, ASN1_TYPE asn, const char *root,
        */
       _gnutls_free_datum (&tmp);
 
-      snprintf (name, sizeof (name), "%s.algorithm.parameters", root);
+      _asnstr_append_name(name, sizeof(name), root, ".algorithm.parameters");
       result = _gnutls_x509_read_value (asn, name, &tmp, 0);
 
       /* FIXME: If the parameters are not included in the certificate
@@ -321,13 +330,9 @@ int
 _gnutls_x509_crt_get_mpis (gnutls_x509_crt_t cert,
                           bigint_t * params, int *params_size)
 {
-  int pk_algorithm;
-
   /* Read the algorithm's OID
    */
-  pk_algorithm = gnutls_x509_crt_get_pk_algorithm (cert, NULL);
-
-  return get_mpis (pk_algorithm, cert->cert,
+  return _gnutls_get_asn_mpis (cert->cert,
                   "tbsCertificate.subjectPublicKeyInfo", params,
                   params_size);
 }
@@ -340,13 +345,9 @@ int
 _gnutls_x509_crq_get_mpis (gnutls_x509_crq_t cert,
                           bigint_t * params, int *params_size)
 {
-  int pk_algorithm;
-
   /* Read the algorithm's OID
    */
-  pk_algorithm = gnutls_x509_crq_get_pk_algorithm (cert, NULL);
-
-  return get_mpis (pk_algorithm, cert->crq,
+  return _gnutls_get_asn_mpis (cert->crq,
                   "certificationRequestInfo.subjectPKInfo", params,
                   params_size);
 }
diff --git a/lib/x509/x509.c b/lib/x509/x509.c
index 173cbc1..4244f93 100644
--- a/lib/x509/x509.c
+++ b/lib/x509/x509.c
@@ -2189,22 +2189,19 @@ gnutls_x509_crt_export (gnutls_x509_crt_t cert,
                                  output_data, output_data_size);
 }
 
-
-static int
-rsadsa_get_key_id (gnutls_x509_crt_t crt, int pk,
+int
+_gnutls_get_key_id (gnutls_pk_algorithm_t pk, bigint_t* params, int 
params_size,
                   unsigned char *output_data, size_t * output_data_size)
 {
-  bigint_t params[MAX_PUBLIC_PARAMS_SIZE];
-  int params_size = MAX_PUBLIC_PARAMS_SIZE;
   int i, result = 0;
   gnutls_datum_t der = { NULL, 0 };
   digest_hd_st hd;
 
-  result = _gnutls_x509_crt_get_mpis (crt, params, &params_size);
-  if (result < 0)
+  if (output_data==NULL || *output_data_size < 0)
     {
-      gnutls_assert ();
-      return result;
+      gnutls_assert();
+      *output_data_size = 20;
+      return GNUTLS_E_SHORT_MEMORY_BUFFER;
     }
 
   if (pk == GNUTLS_PK_RSA)
@@ -2245,6 +2242,37 @@ rsadsa_get_key_id (gnutls_x509_crt_t crt, int pk,
 cleanup:
 
   _gnutls_free_datum (&der);
+  return result;
+}
+
+
+static int
+rsadsa_get_key_id (gnutls_x509_crt_t crt, int pk,
+                  unsigned char *output_data, size_t * output_data_size)
+{
+  bigint_t params[MAX_PUBLIC_PARAMS_SIZE];
+  int params_size = MAX_PUBLIC_PARAMS_SIZE;
+  int i, result = 0;
+  gnutls_datum_t der = { NULL, 0 };
+  digest_hd_st hd;
+
+  result = _gnutls_x509_crt_get_mpis (crt, params, &params_size);
+  if (result < 0)
+    {
+      gnutls_assert ();
+      return result;
+    }
+
+  result = _gnutls_get_key_id(pk, params, params_size, output_data, 
output_data_size);
+  if (result < 0)
+    {
+      gnutls_assert ();
+      goto cleanup;
+    }
+
+  result = 0;
+
+cleanup:
 
   /* release all allocated MPIs
    */
@@ -2313,6 +2341,9 @@ gnutls_x509_crt_get_key_id (gnutls_x509_crt_t crt, 
unsigned int flags,
       return rsadsa_get_key_id (crt, pk, output_data, output_data_size);
     }
 
+  /* FIXME: what does this code do here? Isn't identical to the code
+   * in rsadsa_get_key_id?
+   */
   pubkey.size = 0;
   result = asn1_der_coding (crt->cert, "tbsCertificate.subjectPublicKeyInfo",
                            NULL, &pubkey.size, NULL);
diff --git a/lib/x509/x509_int.h b/lib/x509/x509_int.h
index 12597e9..c1f4126 100644
--- a/lib/x509/x509_int.h
+++ b/lib/x509/x509_int.h
@@ -303,6 +303,8 @@ int _gnutls_x509_write_uint32 (ASN1_TYPE node, const char 
*value,
 int _gnutls_x509_write_sig_params (ASN1_TYPE dst, const char *dst_name,
                                   gnutls_pk_algorithm_t pk_algorithm,
                                   gnutls_digest_algorithm_t);
+
+
 /* pkcs12.h */
 #include <gnutls/pkcs12.h>
 
diff --git a/src/certtool-common.h b/src/certtool-common.h
index ae6891e..f5db0ab 100644
--- a/src/certtool-common.h
+++ b/src/certtool-common.h
@@ -29,6 +29,7 @@ enum
   ACTION_PKCS11_LIST,
   ACTION_PKCS11_TOKENS,
   ACTION_PKCS11_EXPORT_URL,
+  ACTION_PUBKEY_INFO,
 };
 
 #define TYPE_CRT 1
@@ -39,9 +40,10 @@ void pkcs11_list( FILE*outfile, const char* url, int type);
 void pkcs11_export(FILE* outfile, const char *pkcs11_url);
 void pkcs11_token_list(FILE* outfile);
 
-#define PKCS11_TYPE_ALL 1
+#define PKCS11_TYPE_CRT_ALL 1
 #define PKCS11_TYPE_TRUSTED 2
 #define PKCS11_TYPE_PK 3
+#define PKCS11_TYPE_ALL 4
 
 extern unsigned char buffer[];
 extern const int buffer_size;
diff --git a/src/certtool-gaa.c b/src/certtool-gaa.c
index aae181d..e24a0a4 100644
--- a/src/certtool-gaa.c
+++ b/src/certtool-gaa.c
@@ -141,6 +141,7 @@ void gaa_help(void)
        __gaa_helpsingle(0, "generate-dh-params", "", "Generate PKCS #3 encoded 
Diffie-Hellman parameters.");
        __gaa_helpsingle(0, "get-dh-params", "", "Get the included PKCS #3 
encoded Diffie-Hellman parameters.");
        __gaa_helpsingle(0, "load-privkey", "FILE ", "Private key file to 
use.");
+       __gaa_helpsingle(0, "load-pubkey", "FILE ", "Private key file to use.");
        __gaa_helpsingle(0, "load-request", "FILE ", "Certificate request file 
to use.");
        __gaa_helpsingle(0, "load-certificate", "FILE ", "Certificate file to 
use.");
        __gaa_helpsingle(0, "load-ca-privkey", "FILE ", "Certificate 
authority's private key file to use.");
@@ -157,6 +158,7 @@ void gaa_help(void)
        __gaa_helpsingle(0, "smime-to-p7", "", "Convert S/MIME to PKCS #7 
structure.");
        __gaa_helpsingle('k', "key-info", "", "Print information on a private 
key.");
        __gaa_helpsingle(0, "pgp-key-info", "", "Print information on a OpenPGP 
private key.");
+       __gaa_helpsingle(0, "pubkey-info", "", "Print information on a public 
key.");
        __gaa_helpsingle(0, "fix-key", "", "Regenerate the parameters in a 
private key.");
        __gaa_helpsingle(0, "v1", "", "Generate an X.509 version 1 certificate 
(no extensions).");
        __gaa_helpsingle(0, "to-p12", "", "Generate a PKCS #12 structure.");
@@ -177,8 +179,9 @@ void gaa_help(void)
        __gaa_helpsingle(0, "pkcs-cipher", "CIPHER ", "Cipher to use for pkcs 
operations (3des,aes-128,aes-192,aes-256,rc2-40).");
        __gaa_helpsingle(0, "pkcs11-provider", "Library ", "Specify the pkcs11 
provider library");
        __gaa_helpsingle(0, "pkcs11-export-url", "URL ", "Export data specified 
a pkcs11 URL");
-       __gaa_helpsingle(0, "pkcs11-list", "", "List objects specified by a 
PKCS#11 URL");
-       __gaa_helpsingle(0, "pkcs11-list-trusted", "", "List objects marked as 
trusted, specified by a PKCS#11 URL");
+       __gaa_helpsingle(0, "pkcs11-list-certs", "", "List certificates 
specified by a PKCS#11 URL");
+       __gaa_helpsingle(0, "pkcs11-list-trusted", "", "List certificates 
marked as trusted, specified by a PKCS#11 URL");
+       __gaa_helpsingle(0, "pkcs11-list-all-certs", "", "List all certificates 
specified by a PKCS#11 URL");
        __gaa_helpsingle(0, "pkcs11-list-all", "", "List all objects specified 
by a PKCS#11 URL");
        __gaa_helpsingle(0, "pkcs11-list-tokens", "", "List all available 
tokens");
        __gaa_helpsingle('d', "debug", "LEVEL ", "specify the debug level. 
Default is 1.");
@@ -198,54 +201,56 @@ typedef struct _gaainfo gaainfo;
 
 struct _gaainfo
 {
-#line 143 "certtool.gaa"
+#line 149 "certtool.gaa"
        int debug;
-#line 137 "certtool.gaa"
+#line 142 "certtool.gaa"
        int pkcs11_type;
-#line 134 "certtool.gaa"
+#line 139 "certtool.gaa"
        char* pkcs11_url;
-#line 131 "certtool.gaa"
+#line 136 "certtool.gaa"
        char* pkcs11_provider;
-#line 128 "certtool.gaa"
+#line 133 "certtool.gaa"
        char *pkcs_cipher;
-#line 125 "certtool.gaa"
+#line 130 "certtool.gaa"
        char *template;
-#line 122 "certtool.gaa"
+#line 127 "certtool.gaa"
        char *infile;
-#line 119 "certtool.gaa"
+#line 124 "certtool.gaa"
        char *outfile;
-#line 116 "certtool.gaa"
+#line 121 "certtool.gaa"
        int quick_random;
-#line 113 "certtool.gaa"
+#line 118 "certtool.gaa"
        int bits;
-#line 109 "certtool.gaa"
+#line 114 "certtool.gaa"
        int outcert_format;
-#line 105 "certtool.gaa"
+#line 110 "certtool.gaa"
        int incert_format;
-#line 102 "certtool.gaa"
+#line 107 "certtool.gaa"
        int export;
-#line 99 "certtool.gaa"
+#line 104 "certtool.gaa"
        char *hash;
-#line 96 "certtool.gaa"
+#line 101 "certtool.gaa"
        int dsa;
-#line 93 "certtool.gaa"
+#line 98 "certtool.gaa"
        int pkcs8;
-#line 85 "certtool.gaa"
+#line 90 "certtool.gaa"
        int v1_cert;
-#line 82 "certtool.gaa"
+#line 87 "certtool.gaa"
        int fix_key;
-#line 67 "certtool.gaa"
+#line 70 "certtool.gaa"
        int crq_extensions;
-#line 54 "certtool.gaa"
+#line 57 "certtool.gaa"
        char *pass;
-#line 51 "certtool.gaa"
+#line 54 "certtool.gaa"
        char *ca;
-#line 48 "certtool.gaa"
+#line 51 "certtool.gaa"
        char *ca_privkey;
-#line 45 "certtool.gaa"
+#line 48 "certtool.gaa"
        char *cert;
-#line 42 "certtool.gaa"
+#line 45 "certtool.gaa"
        char *request;
+#line 42 "certtool.gaa"
+       char *pubkey;
 #line 39 "certtool.gaa"
        char *privkey;
 #line 17 "certtool.gaa"
@@ -306,62 +311,65 @@ static int gaa_error = 0;
 #define GAA_MULTIPLE_OPTION     3
 
 #define GAA_REST                0
-#define GAA_NB_OPTION           55
+#define GAA_NB_OPTION           58
 #define GAAOPTID_version       1
 #define GAAOPTID_help  2
 #define GAAOPTID_debug 3
 #define GAAOPTID_pkcs11_list_tokens    4
 #define GAAOPTID_pkcs11_list_all       5
-#define GAAOPTID_pkcs11_list_trusted   6
-#define GAAOPTID_pkcs11_list   7
-#define GAAOPTID_pkcs11_export_url     8
-#define GAAOPTID_pkcs11_provider       9
-#define GAAOPTID_pkcs_cipher   10
-#define GAAOPTID_template      11
-#define GAAOPTID_infile        12
-#define GAAOPTID_outfile       13
-#define GAAOPTID_disable_quick_random  14
-#define GAAOPTID_bits  15
-#define GAAOPTID_outraw        16
-#define GAAOPTID_outder        17
-#define GAAOPTID_inraw 18
-#define GAAOPTID_inder 19
-#define GAAOPTID_export_ciphers        20
-#define GAAOPTID_hash  21
-#define GAAOPTID_dsa   22
-#define GAAOPTID_pkcs8 23
-#define GAAOPTID_to_p8 24
-#define GAAOPTID_to_p12        25
-#define GAAOPTID_v1    26
-#define GAAOPTID_fix_key       27
-#define GAAOPTID_pgp_key_info  28
-#define GAAOPTID_key_info      29
-#define GAAOPTID_smime_to_p7   30
-#define GAAOPTID_p7_info       31
-#define GAAOPTID_p12_info      32
-#define GAAOPTID_no_crq_extensions     33
-#define GAAOPTID_crq_info      34
-#define GAAOPTID_crl_info      35
-#define GAAOPTID_pgp_ring_info 36
-#define GAAOPTID_pgp_certificate_info  37
-#define GAAOPTID_certificate_info      38
-#define GAAOPTID_password      39
-#define GAAOPTID_load_ca_certificate   40
-#define GAAOPTID_load_ca_privkey       41
-#define GAAOPTID_load_certificate      42
-#define GAAOPTID_load_request  43
-#define GAAOPTID_load_privkey  44
-#define GAAOPTID_get_dh_params 45
-#define GAAOPTID_generate_dh_params    46
-#define GAAOPTID_verify_crl    47
-#define GAAOPTID_verify_chain  48
-#define GAAOPTID_generate_request      49
-#define GAAOPTID_generate_privkey      50
-#define GAAOPTID_update_certificate    51
-#define GAAOPTID_generate_crl  52
-#define GAAOPTID_generate_proxy        53
-#define GAAOPTID_generate_certificate  54
-#define GAAOPTID_generate_self_signed  55
+#define GAAOPTID_pkcs11_list_all_certs 6
+#define GAAOPTID_pkcs11_list_trusted   7
+#define GAAOPTID_pkcs11_list_certs     8
+#define GAAOPTID_pkcs11_export_url     9
+#define GAAOPTID_pkcs11_provider       10
+#define GAAOPTID_pkcs_cipher   11
+#define GAAOPTID_template      12
+#define GAAOPTID_infile        13
+#define GAAOPTID_outfile       14
+#define GAAOPTID_disable_quick_random  15
+#define GAAOPTID_bits  16
+#define GAAOPTID_outraw        17
+#define GAAOPTID_outder        18
+#define GAAOPTID_inraw 19
+#define GAAOPTID_inder 20
+#define GAAOPTID_export_ciphers        21
+#define GAAOPTID_hash  22
+#define GAAOPTID_dsa   23
+#define GAAOPTID_pkcs8 24
+#define GAAOPTID_to_p8 25
+#define GAAOPTID_to_p12        26
+#define GAAOPTID_v1    27
+#define GAAOPTID_fix_key       28
+#define GAAOPTID_pubkey_info   29
+#define GAAOPTID_pgp_key_info  30
+#define GAAOPTID_key_info      31
+#define GAAOPTID_smime_to_p7   32
+#define GAAOPTID_p7_info       33
+#define GAAOPTID_p12_info      34
+#define GAAOPTID_no_crq_extensions     35
+#define GAAOPTID_crq_info      36
+#define GAAOPTID_crl_info      37
+#define GAAOPTID_pgp_ring_info 38
+#define GAAOPTID_pgp_certificate_info  39
+#define GAAOPTID_certificate_info      40
+#define GAAOPTID_password      41
+#define GAAOPTID_load_ca_certificate   42
+#define GAAOPTID_load_ca_privkey       43
+#define GAAOPTID_load_certificate      44
+#define GAAOPTID_load_request  45
+#define GAAOPTID_load_pubkey   46
+#define GAAOPTID_load_privkey  47
+#define GAAOPTID_get_dh_params 48
+#define GAAOPTID_generate_dh_params    49
+#define GAAOPTID_verify_crl    50
+#define GAAOPTID_verify_chain  51
+#define GAAOPTID_generate_request      52
+#define GAAOPTID_generate_privkey      53
+#define GAAOPTID_update_certificate    54
+#define GAAOPTID_generate_crl  55
+#define GAAOPTID_generate_proxy        56
+#define GAAOPTID_generate_certificate  57
+#define GAAOPTID_generate_self_signed  58
 
 #line 168 "gaa.skel"
 
@@ -632,6 +640,12 @@ struct GAAOPTION_load_request
        int size1;
 };
 
+struct GAAOPTION_load_pubkey 
+{
+       char* arg1;
+       int size1;
+};
+
 struct GAAOPTION_load_privkey 
 {
        char* arg1;
@@ -681,6 +695,7 @@ static int gaa_get_option_num(char *str, int status)
                        GAA_CHECK1STR("", GAAOPTID_load_ca_privkey);
                        GAA_CHECK1STR("", GAAOPTID_load_certificate);
                        GAA_CHECK1STR("", GAAOPTID_load_request);
+                       GAA_CHECK1STR("", GAAOPTID_load_pubkey);
                        GAA_CHECK1STR("", GAAOPTID_load_privkey);
         case GAA_MULTIPLE_OPTION:
 #line 375 "gaa.skel"
@@ -688,8 +703,9 @@ static int gaa_get_option_num(char *str, int status)
                        GAA_CHECK1STR("h", GAAOPTID_help);
                        GAA_CHECK1STR("", GAAOPTID_pkcs11_list_tokens);
                        GAA_CHECK1STR("", GAAOPTID_pkcs11_list_all);
+                       GAA_CHECK1STR("", GAAOPTID_pkcs11_list_all_certs);
                        GAA_CHECK1STR("", GAAOPTID_pkcs11_list_trusted);
-                       GAA_CHECK1STR("", GAAOPTID_pkcs11_list);
+                       GAA_CHECK1STR("", GAAOPTID_pkcs11_list_certs);
                        GAA_CHECK1STR("", GAAOPTID_disable_quick_random);
                        GAA_CHECK1STR("", GAAOPTID_outraw);
                        GAA_CHECK1STR("", GAAOPTID_outder);
@@ -702,6 +718,7 @@ static int gaa_get_option_num(char *str, int status)
                        GAA_CHECK1STR("", GAAOPTID_to_p12);
                        GAA_CHECK1STR("", GAAOPTID_v1);
                        GAA_CHECK1STR("", GAAOPTID_fix_key);
+                       GAA_CHECK1STR("", GAAOPTID_pubkey_info);
                        GAA_CHECK1STR("", GAAOPTID_pgp_key_info);
                        GAA_CHECK1STR("k", GAAOPTID_key_info);
                        GAA_CHECK1STR("", GAAOPTID_smime_to_p7);
@@ -733,8 +750,9 @@ static int gaa_get_option_num(char *str, int status)
                        GAA_CHECKSTR("debug", GAAOPTID_debug);
                        GAA_CHECKSTR("pkcs11-list-tokens", 
GAAOPTID_pkcs11_list_tokens);
                        GAA_CHECKSTR("pkcs11-list-all", 
GAAOPTID_pkcs11_list_all);
+                       GAA_CHECKSTR("pkcs11-list-all-certs", 
GAAOPTID_pkcs11_list_all_certs);
                        GAA_CHECKSTR("pkcs11-list-trusted", 
GAAOPTID_pkcs11_list_trusted);
-                       GAA_CHECKSTR("pkcs11-list", GAAOPTID_pkcs11_list);
+                       GAA_CHECKSTR("pkcs11-list-certs", 
GAAOPTID_pkcs11_list_certs);
                        GAA_CHECKSTR("pkcs11-export-url", 
GAAOPTID_pkcs11_export_url);
                        GAA_CHECKSTR("pkcs11-provider", 
GAAOPTID_pkcs11_provider);
                        GAA_CHECKSTR("pkcs-cipher", GAAOPTID_pkcs_cipher);
@@ -755,6 +773,7 @@ static int gaa_get_option_num(char *str, int status)
                        GAA_CHECKSTR("to-p12", GAAOPTID_to_p12);
                        GAA_CHECKSTR("v1", GAAOPTID_v1);
                        GAA_CHECKSTR("fix-key", GAAOPTID_fix_key);
+                       GAA_CHECKSTR("pubkey-info", GAAOPTID_pubkey_info);
                        GAA_CHECKSTR("pgp-key-info", GAAOPTID_pgp_key_info);
                        GAA_CHECKSTR("key-info", GAAOPTID_key_info);
                        GAA_CHECKSTR("smime-to-p7", GAAOPTID_smime_to_p7);
@@ -771,6 +790,7 @@ static int gaa_get_option_num(char *str, int status)
                        GAA_CHECKSTR("load-ca-privkey", 
GAAOPTID_load_ca_privkey);
                        GAA_CHECKSTR("load-certificate", 
GAAOPTID_load_certificate);
                        GAA_CHECKSTR("load-request", GAAOPTID_load_request);
+                       GAA_CHECKSTR("load-pubkey", GAAOPTID_load_pubkey);
                        GAA_CHECKSTR("load-privkey", GAAOPTID_load_privkey);
                        GAA_CHECKSTR("get-dh-params", GAAOPTID_get_dh_params);
                        GAA_CHECKSTR("generate-dh-params", 
GAAOPTID_generate_dh_params);
@@ -809,6 +829,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo 
*gaaval, char *opt_list)
        struct GAAOPTION_load_ca_privkey GAATMP_load_ca_privkey;
        struct GAAOPTION_load_certificate GAATMP_load_certificate;
        struct GAAOPTION_load_request GAATMP_load_request;
+       struct GAAOPTION_load_pubkey GAATMP_load_pubkey;
        struct GAAOPTION_load_privkey GAATMP_load_privkey;
 
 #line 393 "gaa.skel"
@@ -832,14 +853,14 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo 
*gaaval, char *opt_list)
     {
        case GAAOPTID_version:
        OK = 0;
-#line 148 "certtool.gaa"
+#line 154 "certtool.gaa"
 { certtool_version(); exit(0); ;};
 
                return GAA_OK;
                break;
        case GAAOPTID_help:
        OK = 0;
-#line 146 "certtool.gaa"
+#line 152 "certtool.gaa"
 { gaa_help(); exit(0); ;};
 
                return GAA_OK;
@@ -849,35 +870,42 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo 
*gaaval, char *opt_list)
                GAA_TESTMOREARGS;
                GAA_FILL(GAATMP_debug.arg1, gaa_getint, GAATMP_debug.size1);
                gaa_index++;
-#line 144 "certtool.gaa"
+#line 150 "certtool.gaa"
 { gaaval->debug = GAATMP_debug.arg1 ;};
 
                return GAA_OK;
                break;
        case GAAOPTID_pkcs11_list_tokens:
        OK = 0;
-#line 141 "certtool.gaa"
+#line 147 "certtool.gaa"
 { gaaval->action = ACTION_PKCS11_TOKENS; ;};
 
                return GAA_OK;
                break;
        case GAAOPTID_pkcs11_list_all:
        OK = 0;
-#line 140 "certtool.gaa"
+#line 146 "certtool.gaa"
 { gaaval->action = ACTION_PKCS11_LIST; gaaval->pkcs11_type=PKCS11_TYPE_ALL; ;};
 
                return GAA_OK;
                break;
+       case GAAOPTID_pkcs11_list_all_certs:
+       OK = 0;
+#line 145 "certtool.gaa"
+{ gaaval->action = ACTION_PKCS11_LIST; 
gaaval->pkcs11_type=PKCS11_TYPE_CRT_ALL; ;};
+
+               return GAA_OK;
+               break;
        case GAAOPTID_pkcs11_list_trusted:
        OK = 0;
-#line 139 "certtool.gaa"
+#line 144 "certtool.gaa"
 { gaaval->action = ACTION_PKCS11_LIST; 
gaaval->pkcs11_type=PKCS11_TYPE_TRUSTED; ;};
 
                return GAA_OK;
                break;
-       case GAAOPTID_pkcs11_list:
+       case GAAOPTID_pkcs11_list_certs:
        OK = 0;
-#line 138 "certtool.gaa"
+#line 143 "certtool.gaa"
 { gaaval->action = ACTION_PKCS11_LIST; gaaval->pkcs11_type=PKCS11_TYPE_PK; ;};
 
                return GAA_OK;
@@ -887,7 +915,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo 
*gaaval, char *opt_list)
                GAA_TESTMOREARGS;
                GAA_FILL(GAATMP_pkcs11_export_url.arg1, gaa_getstr, 
GAATMP_pkcs11_export_url.size1);
                gaa_index++;
-#line 135 "certtool.gaa"
+#line 140 "certtool.gaa"
 { gaaval->action = ACTION_PKCS11_EXPORT_URL; gaaval->pkcs11_url = 
GAATMP_pkcs11_export_url.arg1; ;};
 
                return GAA_OK;
@@ -897,7 +925,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo 
*gaaval, char *opt_list)
                GAA_TESTMOREARGS;
                GAA_FILL(GAATMP_pkcs11_provider.arg1, gaa_getstr, 
GAATMP_pkcs11_provider.size1);
                gaa_index++;
-#line 132 "certtool.gaa"
+#line 137 "certtool.gaa"
 { gaaval->pkcs11_provider = GAATMP_pkcs11_provider.arg1 ;};
 
                return GAA_OK;
@@ -907,7 +935,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo 
*gaaval, char *opt_list)
                GAA_TESTMOREARGS;
                GAA_FILL(GAATMP_pkcs_cipher.arg1, gaa_getstr, 
GAATMP_pkcs_cipher.size1);
                gaa_index++;
-#line 129 "certtool.gaa"
+#line 134 "certtool.gaa"
 { gaaval->pkcs_cipher = GAATMP_pkcs_cipher.arg1 ;};
 
                return GAA_OK;
@@ -917,7 +945,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo 
*gaaval, char *opt_list)
                GAA_TESTMOREARGS;
                GAA_FILL(GAATMP_template.arg1, gaa_getstr, 
GAATMP_template.size1);
                gaa_index++;
-#line 126 "certtool.gaa"
+#line 131 "certtool.gaa"
 { gaaval->template = GAATMP_template.arg1 ;};
 
                return GAA_OK;
@@ -927,7 +955,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo 
*gaaval, char *opt_list)
                GAA_TESTMOREARGS;
                GAA_FILL(GAATMP_infile.arg1, gaa_getstr, GAATMP_infile.size1);
                gaa_index++;
-#line 123 "certtool.gaa"
+#line 128 "certtool.gaa"
 { gaaval->infile = GAATMP_infile.arg1 ;};
 
                return GAA_OK;
@@ -937,14 +965,14 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo 
*gaaval, char *opt_list)
                GAA_TESTMOREARGS;
                GAA_FILL(GAATMP_outfile.arg1, gaa_getstr, GAATMP_outfile.size1);
                gaa_index++;
-#line 120 "certtool.gaa"
+#line 125 "certtool.gaa"
 { gaaval->outfile = GAATMP_outfile.arg1 ;};
 
                return GAA_OK;
                break;
        case GAAOPTID_disable_quick_random:
        OK = 0;
-#line 117 "certtool.gaa"
+#line 122 "certtool.gaa"
 { gaaval->quick_random = 0; ;};
 
                return GAA_OK;
@@ -954,42 +982,42 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo 
*gaaval, char *opt_list)
                GAA_TESTMOREARGS;
                GAA_FILL(GAATMP_bits.arg1, gaa_getint, GAATMP_bits.size1);
                gaa_index++;
-#line 114 "certtool.gaa"
+#line 119 "certtool.gaa"
 { gaaval->bits = GAATMP_bits.arg1 ;};
 
                return GAA_OK;
                break;
        case GAAOPTID_outraw:
        OK = 0;
-#line 111 "certtool.gaa"
+#line 116 "certtool.gaa"
 { gaaval->outcert_format=1 ;};
 
                return GAA_OK;
                break;
        case GAAOPTID_outder:
        OK = 0;
-#line 110 "certtool.gaa"
+#line 115 "certtool.gaa"
 { gaaval->outcert_format=1 ;};
 
                return GAA_OK;
                break;
        case GAAOPTID_inraw:
        OK = 0;
-#line 107 "certtool.gaa"
+#line 112 "certtool.gaa"
 { gaaval->incert_format=1 ;};
 
                return GAA_OK;
                break;
        case GAAOPTID_inder:
        OK = 0;
-#line 106 "certtool.gaa"
+#line 111 "certtool.gaa"
 { gaaval->incert_format=1 ;};
 
                return GAA_OK;
                break;
        case GAAOPTID_export_ciphers:
        OK = 0;
-#line 103 "certtool.gaa"
+#line 108 "certtool.gaa"
 { gaaval->export=1 ;};
 
                return GAA_OK;
@@ -999,126 +1027,133 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo 
*gaaval, char *opt_list)
                GAA_TESTMOREARGS;
                GAA_FILL(GAATMP_hash.arg1, gaa_getstr, GAATMP_hash.size1);
                gaa_index++;
-#line 100 "certtool.gaa"
+#line 105 "certtool.gaa"
 { gaaval->hash = GAATMP_hash.arg1 ;};
 
                return GAA_OK;
                break;
        case GAAOPTID_dsa:
        OK = 0;
-#line 97 "certtool.gaa"
+#line 102 "certtool.gaa"
 { gaaval->dsa=1 ;};
 
                return GAA_OK;
                break;
        case GAAOPTID_pkcs8:
        OK = 0;
-#line 94 "certtool.gaa"
+#line 99 "certtool.gaa"
 { gaaval->pkcs8=1 ;};
 
                return GAA_OK;
                break;
        case GAAOPTID_to_p8:
        OK = 0;
-#line 90 "certtool.gaa"
+#line 95 "certtool.gaa"
 { gaaval->action = ACTION_GENERATE_PKCS8; ;};
 
                return GAA_OK;
                break;
        case GAAOPTID_to_p12:
        OK = 0;
-#line 88 "certtool.gaa"
+#line 93 "certtool.gaa"
 { gaaval->action = ACTION_TO_PKCS12; ;};
 
                return GAA_OK;
                break;
        case GAAOPTID_v1:
        OK = 0;
-#line 86 "certtool.gaa"
+#line 91 "certtool.gaa"
 { gaaval->v1_cert = 1; ;};
 
                return GAA_OK;
                break;
        case GAAOPTID_fix_key:
        OK = 0;
-#line 83 "certtool.gaa"
+#line 88 "certtool.gaa"
 { gaaval->privkey_op=1; gaaval->fix_key = 1; ;};
 
                return GAA_OK;
                break;
+       case GAAOPTID_pubkey_info:
+       OK = 0;
+#line 85 "certtool.gaa"
+{ gaaval->action = ACTION_PUBKEY_INFO; ;};
+
+               return GAA_OK;
+               break;
        case GAAOPTID_pgp_key_info:
        OK = 0;
-#line 80 "certtool.gaa"
+#line 83 "certtool.gaa"
 { gaaval->privkey_op=1; gaaval->action = ACTION_PGP_PRIVKEY_INFO; ;};
 
                return GAA_OK;
                break;
        case GAAOPTID_key_info:
        OK = 0;
-#line 78 "certtool.gaa"
+#line 81 "certtool.gaa"
 { gaaval->privkey_op=1; gaaval->action = ACTION_PRIVKEY_INFO; ;};
 
                return GAA_OK;
                break;
        case GAAOPTID_smime_to_p7:
        OK = 0;
-#line 74 "certtool.gaa"
+#line 77 "certtool.gaa"
 { gaaval->action = ACTION_SMIME_TO_P7; ;};
 
                return GAA_OK;
                break;
        case GAAOPTID_p7_info:
        OK = 0;
-#line 72 "certtool.gaa"
+#line 75 "certtool.gaa"
 { gaaval->action = ACTION_P7_INFO; ;};
 
                return GAA_OK;
                break;
        case GAAOPTID_p12_info:
        OK = 0;
-#line 70 "certtool.gaa"
+#line 73 "certtool.gaa"
 { gaaval->action = ACTION_PKCS12_INFO; ;};
 
                return GAA_OK;
                break;
        case GAAOPTID_no_crq_extensions:
        OK = 0;
-#line 68 "certtool.gaa"
+#line 71 "certtool.gaa"
 { gaaval->crq_extensions = 0; ;};
 
                return GAA_OK;
                break;
        case GAAOPTID_crq_info:
        OK = 0;
-#line 65 "certtool.gaa"
+#line 68 "certtool.gaa"
 { gaaval->action = ACTION_REQUEST; ;};
 
                return GAA_OK;
                break;
        case GAAOPTID_crl_info:
        OK = 0;
-#line 63 "certtool.gaa"
+#line 66 "certtool.gaa"
 { gaaval->action = ACTION_CRL_INFO; ;};
 
                return GAA_OK;
                break;
        case GAAOPTID_pgp_ring_info:
        OK = 0;
-#line 61 "certtool.gaa"
+#line 64 "certtool.gaa"
 { gaaval->action = ACTION_RING_INFO; ;};
 
                return GAA_OK;
                break;
        case GAAOPTID_pgp_certificate_info:
        OK = 0;
-#line 59 "certtool.gaa"
+#line 62 "certtool.gaa"
 { gaaval->action = ACTION_PGP_INFO; ;};
 
                return GAA_OK;
                break;
        case GAAOPTID_certificate_info:
        OK = 0;
-#line 57 "certtool.gaa"
+#line 60 "certtool.gaa"
 { gaaval->action = ACTION_CERT_INFO; ;};
 
                return GAA_OK;
@@ -1128,7 +1163,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo 
*gaaval, char *opt_list)
                GAA_TESTMOREARGS;
                GAA_FILL(GAATMP_password.arg1, gaa_getstr, 
GAATMP_password.size1);
                gaa_index++;
-#line 55 "certtool.gaa"
+#line 58 "certtool.gaa"
 { gaaval->pass = GAATMP_password.arg1 ;};
 
                return GAA_OK;
@@ -1138,7 +1173,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo 
*gaaval, char *opt_list)
                GAA_TESTMOREARGS;
                GAA_FILL(GAATMP_load_ca_certificate.arg1, gaa_getstr, 
GAATMP_load_ca_certificate.size1);
                gaa_index++;
-#line 52 "certtool.gaa"
+#line 55 "certtool.gaa"
 { gaaval->ca = GAATMP_load_ca_certificate.arg1 ;};
 
                return GAA_OK;
@@ -1148,7 +1183,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo 
*gaaval, char *opt_list)
                GAA_TESTMOREARGS;
                GAA_FILL(GAATMP_load_ca_privkey.arg1, gaa_getstr, 
GAATMP_load_ca_privkey.size1);
                gaa_index++;
-#line 49 "certtool.gaa"
+#line 52 "certtool.gaa"
 { gaaval->ca_privkey = GAATMP_load_ca_privkey.arg1 ;};
 
                return GAA_OK;
@@ -1158,7 +1193,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo 
*gaaval, char *opt_list)
                GAA_TESTMOREARGS;
                GAA_FILL(GAATMP_load_certificate.arg1, gaa_getstr, 
GAATMP_load_certificate.size1);
                gaa_index++;
-#line 46 "certtool.gaa"
+#line 49 "certtool.gaa"
 { gaaval->cert = GAATMP_load_certificate.arg1 ;};
 
                return GAA_OK;
@@ -1168,11 +1203,21 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo 
*gaaval, char *opt_list)
                GAA_TESTMOREARGS;
                GAA_FILL(GAATMP_load_request.arg1, gaa_getstr, 
GAATMP_load_request.size1);
                gaa_index++;
-#line 43 "certtool.gaa"
+#line 46 "certtool.gaa"
 { gaaval->request = GAATMP_load_request.arg1 ;};
 
                return GAA_OK;
                break;
+       case GAAOPTID_load_pubkey:
+       OK = 0;
+               GAA_TESTMOREARGS;
+               GAA_FILL(GAATMP_load_pubkey.arg1, gaa_getstr, 
GAATMP_load_pubkey.size1);
+               gaa_index++;
+#line 43 "certtool.gaa"
+{ gaaval->pubkey = GAATMP_load_pubkey.arg1 ;};
+
+               return GAA_OK;
+               break;
        case GAAOPTID_load_privkey:
        OK = 0;
                GAA_TESTMOREARGS;
@@ -1284,13 +1329,13 @@ int gaa(int argc, char **argv, gaainfo *gaaval)
     if(inited == 0)
     {
 
-#line 150 "certtool.gaa"
+#line 156 "certtool.gaa"
 { gaaval->bits = 2048; gaaval->pkcs8 = 0; gaaval->privkey = NULL; 
gaaval->ca=NULL; gaaval->ca_privkey = NULL; 
        gaaval->debug=1; gaaval->request = NULL; gaaval->infile = NULL; 
gaaval->outfile = NULL; gaaval->cert = NULL; 
        gaaval->incert_format = 0; gaaval->outcert_format = 0; 
gaaval->action=-1; gaaval->pass = NULL; gaaval->v1_cert = 0;
        gaaval->export = 0; gaaval->template = NULL; gaaval->hash=NULL; 
gaaval->fix_key = 0; gaaval->quick_random=1; 
        gaaval->privkey_op = 0; gaaval->pkcs_cipher = "3des"; 
gaaval->crq_extensions=1; gaaval->pkcs11_provider= NULL;
-       gaaval->pkcs11_url = NULL; gaaval->pkcs11_type = PKCS11_TYPE_PK; ;};
+       gaaval->pkcs11_url = NULL; gaaval->pkcs11_type = PKCS11_TYPE_PK; 
gaaval->pubkey=NULL; ;};
 
     }
     inited = 1;
diff --git a/src/certtool-gaa.h b/src/certtool-gaa.h
index ded4286..80b022a 100644
--- a/src/certtool-gaa.h
+++ b/src/certtool-gaa.h
@@ -8,54 +8,56 @@ typedef struct _gaainfo gaainfo;
 
 struct _gaainfo
 {
-#line 143 "certtool.gaa"
+#line 149 "certtool.gaa"
        int debug;
-#line 137 "certtool.gaa"
+#line 142 "certtool.gaa"
        int pkcs11_type;
-#line 134 "certtool.gaa"
+#line 139 "certtool.gaa"
        char* pkcs11_url;
-#line 131 "certtool.gaa"
+#line 136 "certtool.gaa"
        char* pkcs11_provider;
-#line 128 "certtool.gaa"
+#line 133 "certtool.gaa"
        char *pkcs_cipher;
-#line 125 "certtool.gaa"
+#line 130 "certtool.gaa"
        char *template;
-#line 122 "certtool.gaa"
+#line 127 "certtool.gaa"
        char *infile;
-#line 119 "certtool.gaa"
+#line 124 "certtool.gaa"
        char *outfile;
-#line 116 "certtool.gaa"
+#line 121 "certtool.gaa"
        int quick_random;
-#line 113 "certtool.gaa"
+#line 118 "certtool.gaa"
        int bits;
-#line 109 "certtool.gaa"
+#line 114 "certtool.gaa"
        int outcert_format;
-#line 105 "certtool.gaa"
+#line 110 "certtool.gaa"
        int incert_format;
-#line 102 "certtool.gaa"
+#line 107 "certtool.gaa"
        int export;
-#line 99 "certtool.gaa"
+#line 104 "certtool.gaa"
        char *hash;
-#line 96 "certtool.gaa"
+#line 101 "certtool.gaa"
        int dsa;
-#line 93 "certtool.gaa"
+#line 98 "certtool.gaa"
        int pkcs8;
-#line 85 "certtool.gaa"
+#line 90 "certtool.gaa"
        int v1_cert;
-#line 82 "certtool.gaa"
+#line 87 "certtool.gaa"
        int fix_key;
-#line 67 "certtool.gaa"
+#line 70 "certtool.gaa"
        int crq_extensions;
-#line 54 "certtool.gaa"
+#line 57 "certtool.gaa"
        char *pass;
-#line 51 "certtool.gaa"
+#line 54 "certtool.gaa"
        char *ca;
-#line 48 "certtool.gaa"
+#line 51 "certtool.gaa"
        char *ca_privkey;
-#line 45 "certtool.gaa"
+#line 48 "certtool.gaa"
        char *cert;
-#line 42 "certtool.gaa"
+#line 45 "certtool.gaa"
        char *request;
+#line 42 "certtool.gaa"
+       char *pubkey;
 #line 39 "certtool.gaa"
        char *privkey;
 #line 17 "certtool.gaa"
diff --git a/src/certtool.c b/src/certtool.c
index dca3e3f..bf025c9 100644
--- a/src/certtool.c
+++ b/src/certtool.c
@@ -26,6 +26,7 @@
 #include <gnutls/openpgp.h>
 #include <gnutls/pkcs12.h>
 #include <gnutls/pkcs11.h>
+#include <gnutls/abstract.h>
 
 #include <gcrypt.h>
 
@@ -60,6 +61,7 @@ void generate_pkcs12 (void);
 void generate_pkcs8 (void);
 void verify_chain (void);
 void verify_crl (void);
+void pubkey_info (void);
 void pgp_privkey_info (void);
 void pgp_ring_info (void);
 gnutls_x509_privkey_t load_private_key (int mand);
@@ -67,6 +69,7 @@ gnutls_x509_crq_t load_request (void);
 gnutls_x509_privkey_t load_ca_private_key (void);
 gnutls_x509_crt_t load_ca_cert (void);
 gnutls_x509_crt_t load_cert (int mand);
+gnutls_pubkey_t load_pubkey (int mand);
 void certificate_info (void);
 void pgp_certificate_info (void);
 void crl_info (void);
@@ -133,8 +136,11 @@ static void
 print_dsa_pkey (gnutls_datum_t * x, gnutls_datum_t * y, gnutls_datum_t * p,
                gnutls_datum_t * q, gnutls_datum_t * g)
 {
-  fprintf (outfile, "private key:");
-  print_hex_datum (x);
+  if (x) 
+    {
+      fprintf (outfile, "private key:");
+      print_hex_datum (x);
+    }
   fprintf (outfile, "public key:");
   print_hex_datum (y);
   fprintf (outfile, "p:");
@@ -153,14 +159,17 @@ print_rsa_pkey (gnutls_datum_t * m, gnutls_datum_t * e, 
gnutls_datum_t * d,
   print_hex_datum (m);
   fprintf (outfile, "public exponent:");
   print_hex_datum (e);
-  fprintf (outfile, "private exponent:");
-  print_hex_datum (d);
-  fprintf (outfile, "prime1:");
-  print_hex_datum (p);
-  fprintf (outfile, "prime2:");
-  print_hex_datum (q);
-  fprintf (outfile, "coefficient:");
-  print_hex_datum (u);
+  if (d) 
+    {
+      fprintf (outfile, "private exponent:");
+      print_hex_datum (d);
+      fprintf (outfile, "prime1:");
+      print_hex_datum (p);
+      fprintf (outfile, "prime2:");
+      print_hex_datum (q);
+      fprintf (outfile, "coefficient:");
+      print_hex_datum (u);
+    }
 }
 
 static gnutls_x509_privkey_t
@@ -971,6 +980,9 @@ gaa_parser (int argc, char **argv)
     case ACTION_PRIVKEY_INFO:
       privkey_info ();
       break;
+    case ACTION_PUBKEY_INFO:
+      pubkey_info ();
+      break;
     case ACTION_UPDATE_CERTIFICATE:
       update_signed_certificate ();
       break;
@@ -1610,6 +1622,51 @@ privkey_info (void)
   gnutls_x509_privkey_deinit (key);
 }
 
+/* Load a public key.
+ * @mand should be non zero if it is required to read a public key.
+ */
+gnutls_pubkey_t
+load_pubkey (int mand)
+{
+  gnutls_pubkey_t key;
+  int ret;
+  gnutls_datum_t dat;
+  size_t size;
+
+  if (!info.pubkey && !mand)
+    return NULL;
+
+  if (info.pubkey == NULL)
+    error (EXIT_FAILURE, 0, "missing --load-pubkey");
+
+  ret = gnutls_pubkey_init (&key);
+  if (ret < 0)
+    error (EXIT_FAILURE, 0, "privkey_init: %s", gnutls_strerror (ret));
+
+  dat.data = read_binary_file (info.pubkey, &size);
+  dat.size = size;
+
+  if (!dat.data)
+    error (EXIT_FAILURE, errno, "reading --load-pubkey: %s", info.pubkey);
+
+  ret = gnutls_pubkey_import (key, &dat, info.incert_format);
+
+  free (dat.data);
+
+  if (ret == GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR)
+    {
+      error (EXIT_FAILURE, 0,
+            "import error: could not find a valid PEM header; "
+            "check if your key has the PUBLIC KEY header");
+    }
+
+  if (ret < 0)
+    error (EXIT_FAILURE, 0, "importing --load-pubkey: %s: %s",
+          info.pubkey, gnutls_strerror (ret));
+
+  return key;
+}
+
 
 /* Load the private key.
  * @mand should be non zero if it is required to read a private key.
@@ -2978,3 +3035,141 @@ certtool_version (void)
   version_etc (stdout, program_name, p, gnutls_check_version (NULL),
               "Nikos Mavrogiannopoulos", "Simon Josefsson", (char *) NULL);
 }
+
+static void print_key_usage(FILE* outfile, unsigned int usage)
+{
+  if (usage & GNUTLS_KEY_DIGITAL_SIGNATURE) {
+    fprintf(outfile, "\tDigital signature.\n");
+  }
+
+  if (usage & GNUTLS_KEY_NON_REPUDIATION) {
+    fprintf(outfile, "\tNon repudiation.\n");
+  }
+
+  if (usage & GNUTLS_KEY_KEY_ENCIPHERMENT) {
+    fprintf(outfile, "\tKey encipherment.\n");
+  }
+
+  if (usage & GNUTLS_KEY_DATA_ENCIPHERMENT) {
+    fprintf(outfile, "\tData encipherment.\n");
+  }
+
+  if (usage & GNUTLS_KEY_KEY_AGREEMENT) {
+    fprintf(outfile, "\tKey agreement.\n");
+  }
+
+  if (usage & GNUTLS_KEY_KEY_CERT_SIGN) {
+    fprintf(outfile, "\tCertificate signing.\n");
+  }
+
+  if (usage & GNUTLS_KEY_NON_REPUDIATION) {
+    fprintf(outfile, "\tCRL signing.\n");  
+  }
+
+  if (usage & GNUTLS_KEY_ENCIPHER_ONLY) {
+    fprintf(outfile, "\tKey encipher only.\n");
+  }
+
+  if (usage & GNUTLS_KEY_DECIPHER_ONLY) {
+    fprintf(outfile, "\tKey decipher only.\n");
+  }
+}
+
+void pubkey_info (void)
+{
+  gnutls_x509_crt_t crt;
+  gnutls_pubkey_t pubkey;
+  unsigned int bits, usage;
+  int ret;
+  size_t size;
+  const char* cprint;
+
+  ret = gnutls_pubkey_init(&pubkey);
+  if (ret < 0) {
+    error (EXIT_FAILURE, 0, "pubkey_init: %s", gnutls_strerror (ret));
+  }
+
+  crt = load_cert(0);
+  
+  if (crt != NULL) {
+    ret = gnutls_pubkey_import_x509(pubkey, crt, 0);
+    if (ret < 0) {
+      error (EXIT_FAILURE, 0, "pubkey_import_x509: %s", gnutls_strerror (ret));
+    }
+  } else {
+    pubkey = load_pubkey(1);
+  }
+
+  fprintf (outfile, "Public Key Info:\n\n");
+  ret = gnutls_pubkey_get_pk_algorithm (pubkey, &bits);
+  fprintf (outfile, "Public Key Algorithm: ");
+
+  cprint = gnutls_pk_algorithm_get_name (ret);
+  fprintf (outfile, "%s (%u bits)\n", cprint ? cprint : "Unknown", bits);
+
+
+  /* Print the raw public and private keys
+   */
+  if (ret == GNUTLS_PK_RSA)
+    {
+      gnutls_datum_t m, e;
+
+      ret = gnutls_pubkey_get_pk_rsa_raw (pubkey, &m, &e);
+      if (ret < 0)
+       fprintf (stderr, "Error in key RSA data export: %s\n",
+                gnutls_strerror (ret));
+      else
+       {
+         print_rsa_pkey (&m, &e, NULL, NULL, NULL, NULL);
+         gnutls_free (m.data);
+         gnutls_free (e.data);
+       }
+    }
+  else if (ret == GNUTLS_PK_DSA)
+    {
+      gnutls_datum_t p, q, g, y;
+
+      ret = gnutls_pubkey_get_pk_dsa_raw (pubkey, &p, &q, &g, &y);
+      if (ret < 0)
+       fprintf (stderr, "Error in key DSA data export: %s\n",
+                gnutls_strerror (ret));
+      else
+       {
+         print_dsa_pkey (NULL, &y, &p, &q, &g);
+         gnutls_free (y.data);
+         gnutls_free (p.data);
+         gnutls_free (q.data);
+         gnutls_free (g.data);
+       }
+    }
+
+  ret = gnutls_pubkey_get_key_usage (pubkey, &usage);
+  if (ret < 0) {
+    error (EXIT_FAILURE, 0, "pubkey_get_key_usage: %s", gnutls_strerror (ret));
+  }
+  
+  fprintf (outfile, "Public Key Usage:\n");
+  print_key_usage(outfile, usage);
+
+  fprintf (outfile, "\n");
+
+  size = sizeof (buffer);
+  if ((ret = gnutls_pubkey_get_key_id (pubkey, 0, buffer, &size)) < 0)
+    {
+      fprintf (stderr, "Error in key id calculation: %s\n",
+              gnutls_strerror (ret));
+    }
+  else
+    {
+      fprintf (outfile, "Public Key ID: %s\n", raw_to_string (buffer, size));
+    }
+
+  size = sizeof (buffer);
+  ret = gnutls_pubkey_export (pubkey, GNUTLS_X509_FMT_PEM, buffer, &size);
+  if (ret < 0)
+    error (EXIT_FAILURE, 0, "export error: %s", gnutls_strerror (ret));
+
+  fprintf (outfile, "\n%s\n", buffer);
+
+  gnutls_pubkey_deinit (pubkey);
+}
diff --git a/src/certtool.gaa b/src/certtool.gaa
index 0e9da9e..f84b6db 100644
--- a/src/certtool.gaa
+++ b/src/certtool.gaa
@@ -39,6 +39,9 @@ option (get-dh-params) { $action=ACTION_GET_DH; } "Get the 
included PKCS #3 enco
 #char *privkey;
 option (load-privkey) STR "FILE" { $privkey = $1 } "Private key file to use."
 
+#char *pubkey;
+option (load-pubkey) STR "FILE" { $pubkey = $1 } "Private key file to use."
+
 #char *request;
 option (load-request) STR "FILE" { $request = $1 } "Certificate request file 
to use."
 
@@ -79,6 +82,8 @@ option (k, key-info) { $privkey_op=1; $action = 
ACTION_PRIVKEY_INFO; } "Print in
 
 option (pgp-key-info) { $privkey_op=1; $action = ACTION_PGP_PRIVKEY_INFO; } 
"Print information on a OpenPGP private key."
 
+option (pubkey-info) { $action = ACTION_PUBKEY_INFO; } "Print information on a 
public key."
+
 #int fix_key;
 option (fix-key) { $privkey_op=1; $fix_key = 1; } "Regenerate the parameters 
in a private key."
 
@@ -135,8 +140,9 @@ option (pkcs11-provider) STR "Library" { $pkcs11_provider = 
$1 } "Specify the pk
 option (pkcs11-export-url) STR "URL" { $action = ACTION_PKCS11_EXPORT_URL; 
$pkcs11_url = $1; } "Export data specified a pkcs11 URL"
 
 #int pkcs11_type;
-option (pkcs11-list) { $action = ACTION_PKCS11_LIST; 
$pkcs11_type=PKCS11_TYPE_PK; } "List objects specified by a PKCS#11 URL"
-option (pkcs11-list-trusted) { $action = ACTION_PKCS11_LIST; 
$pkcs11_type=PKCS11_TYPE_TRUSTED; } "List objects marked as trusted, specified 
by a PKCS#11 URL"
+option (pkcs11-list-certs) { $action = ACTION_PKCS11_LIST; 
$pkcs11_type=PKCS11_TYPE_PK; } "List certificates specified by a PKCS#11 URL"
+option (pkcs11-list-trusted) { $action = ACTION_PKCS11_LIST; 
$pkcs11_type=PKCS11_TYPE_TRUSTED; } "List certificates marked as trusted, 
specified by a PKCS#11 URL"
+option (pkcs11-list-all-certs) { $action = ACTION_PKCS11_LIST; 
$pkcs11_type=PKCS11_TYPE_CRT_ALL; } "List all certificates specified by a 
PKCS#11 URL"
 option (pkcs11-list-all) { $action = ACTION_PKCS11_LIST; 
$pkcs11_type=PKCS11_TYPE_ALL; } "List all objects specified by a PKCS#11 URL"
 option (pkcs11-list-tokens) { $action = ACTION_PKCS11_TOKENS; } "List all 
available tokens"
 
@@ -152,4 +158,4 @@ init { $bits = 2048; $pkcs8 = 0; $privkey = NULL; $ca=NULL; 
$ca_privkey = NULL;
        $incert_format = 0; $outcert_format = 0; $action=-1; $pass = NULL; 
$v1_cert = 0;
        $export = 0; $template = NULL; $hash=NULL; $fix_key = 0; 
$quick_random=1; 
        $privkey_op = 0; $pkcs_cipher = "3des"; $crq_extensions=1; 
$pkcs11_provider= NULL;
-       $pkcs11_url = NULL; $pkcs11_type = PKCS11_TYPE_PK; }
+       $pkcs11_url = NULL; $pkcs11_type = PKCS11_TYPE_PK; $pubkey=NULL; }
diff --git a/src/pkcs11.c b/src/pkcs11.c
index f3d4824..a9f1605 100644
--- a/src/pkcs11.c
+++ b/src/pkcs11.c
@@ -46,7 +46,7 @@ static void pkcs11_common(void)
  */
 void pkcs11_list( FILE* outfile, const char* url, int type)
 {
-gnutls_pkcs11_crt_t *crt_list;
+gnutls_pkcs11_obj_t *crt_list;
 gnutls_x509_crt_t xcrt;
 unsigned int crt_list_size = 0;
 int ret;
@@ -58,35 +58,48 @@ int i, flags;
        if (url == NULL)
                url = "pkcs11:";
 
-       ret = gnutls_pkcs11_crt_list_import_url( NULL, &crt_list_size, url, 
GNUTLS_PKCS11_CRT_ATTR_ALL);
+       if (type == PKCS11_TYPE_TRUSTED) {
+               flags = GNUTLS_PKCS11_OBJ_ATTR_CRT_TRUSTED;
+       } else if (type == PKCS11_TYPE_PK) {
+               flags = GNUTLS_PKCS11_OBJ_ATTR_CRT_WITH_PRIVKEY;
+       } else if (type == PKCS11_TYPE_CRT_ALL) {
+               flags = GNUTLS_PKCS11_OBJ_ATTR_CRT_ALL;
+       } else {
+               flags = GNUTLS_PKCS11_OBJ_ATTR_ALL;
+       }
+               
+       /* give some initial value to avoid asking for the pkcs11 pin twice.
+        */
+       crt_list_size = 128;
+       crt_list = malloc(sizeof(*crt_list)*crt_list_size);
+       if (crt_list == NULL) {
+               fprintf(stderr, "Memory error\n");
+               exit(1);
+       }
+
+       ret = gnutls_pkcs11_obj_list_import_url( crt_list, &crt_list_size, url, 
flags);
        if (ret < 0 && ret != GNUTLS_E_SHORT_MEMORY_BUFFER) {
                fprintf(stderr, "Error in crt_list_import (1): %s\n", 
gnutls_strerror(ret));
                exit(1);
        }
        
        if (crt_list_size == 0) {
-               fprintf(stderr, "No matching certificates found\n");
+               fprintf(stderr, "No matching objects found\n");
                exit(0);
        }
        
-       crt_list = malloc(sizeof(*crt_list)*crt_list_size);
-       if (crt_list == NULL) {
-               fprintf(stderr, "Memory error\n");
-               exit(1);
-       }
-
-       if (type == PKCS11_TYPE_TRUSTED) {
-               flags = GNUTLS_PKCS11_CRT_ATTR_TRUSTED;
-       } else if (type == PKCS11_TYPE_PK) {
-               flags = GNUTLS_PKCS11_CRT_ATTR_WITH_PK;
-       } else {
-               flags = GNUTLS_PKCS11_CRT_ATTR_ALL;
-       }
+       if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER) {
+               crt_list = realloc(crt_list, sizeof(*crt_list)*crt_list_size);
+               if (crt_list == NULL) {
+                       fprintf(stderr, "Memory error\n");
+                       exit(1);
+               }
 
-       ret = gnutls_pkcs11_crt_list_import_url( crt_list, &crt_list_size, url, 
flags);
-       if (ret < 0) {
-               fprintf(stderr, "Error in crt_list_import: %s\n", 
gnutls_strerror(ret));
-               exit(1);
+               ret = gnutls_pkcs11_obj_list_import_url( crt_list, 
&crt_list_size, url, flags);
+               if (ret < 0) {
+                       fprintf(stderr, "Error in crt_list_import: %s\n", 
gnutls_strerror(ret));
+                       exit(1);
+               }
        }
        
        for (i=0;i<crt_list_size;i++) {
@@ -94,16 +107,18 @@ int i, flags;
                size_t size;
                
                
-               ret = gnutls_pkcs11_crt_export_url(crt_list[i], &output);
+               ret = gnutls_pkcs11_obj_export_url(crt_list[i], &output);
                if (ret < 0) {
                        fprintf(stderr, "Error in %s:%d: %s\n", __func__, 
__LINE__, gnutls_strerror(ret));
                        exit(1);
                }
 
-               fprintf(outfile, "Certificate %d:\n\tURL: %s\n", i, output);
+               fprintf(outfile, "Object %d:\n\tURL: %s\n", i, output);
+
+               fprintf(outfile, "\tType: %s\n", 
gnutls_pkcs11_type_get_name(gnutls_pkcs11_obj_get_type( crt_list[i])));
                
                size = sizeof(buf);
-               ret = gnutls_pkcs11_crt_get_info( crt_list[i], 
GNUTLS_PKCS11_CRT_LABEL, buf, &size);
+               ret = gnutls_pkcs11_obj_get_info( crt_list[i], 
GNUTLS_PKCS11_OBJ_LABEL, buf, &size);
                if (ret < 0) {
                        fprintf(stderr, "Error in %s:%d: %s\n", __func__, 
__LINE__, gnutls_strerror(ret));
                        exit(1);
@@ -111,13 +126,17 @@ int i, flags;
                fprintf(outfile, "\tLabel: %s\n", buf);
 
                size = sizeof(buf);
-               ret = gnutls_pkcs11_crt_get_info( crt_list[i], 
GNUTLS_PKCS11_CRT_ID_HEX, buf, &size);
+               ret = gnutls_pkcs11_obj_get_info( crt_list[i], 
GNUTLS_PKCS11_OBJ_ID_HEX, buf, &size);
                if (ret < 0) {
                        fprintf(stderr, "Error in %s:%d: %s\n", __func__, 
__LINE__, gnutls_strerror(ret));
                        exit(1);
                }
                fprintf(outfile, "\tID: %s\n\n", buf);
+               
+               
 
+               if (flags == GNUTLS_PKCS11_OBJ_ATTR_ALL)
+                       continue;
 
                ret = gnutls_x509_crt_init(&xcrt);
                if (ret < 0) {
@@ -153,7 +172,7 @@ int i, flags;
 
 void pkcs11_export(FILE* outfile, const char* url)
 {
-gnutls_pkcs11_crt_t crt;
+gnutls_pkcs11_obj_t crt;
 gnutls_x509_crt_t xcrt;
 int ret;
 size_t size;
@@ -163,13 +182,13 @@ size_t size;
        if (url == NULL)
                url = "pkcs11:";
 
-       ret = gnutls_pkcs11_crt_init(&crt);
+       ret = gnutls_pkcs11_obj_init(&crt);
        if (ret < 0) {
                fprintf(stderr, "Error in %s:%d: %s\n", __func__, __LINE__, 
gnutls_strerror(ret));
                exit(1);
        }
 
-       ret = gnutls_pkcs11_crt_import_url( crt, url);
+       ret = gnutls_pkcs11_obj_import_url( crt, url);
        if (ret < 0) {
                fprintf(stderr, "Error in %s:%d: %s\n", __func__, __LINE__, 
gnutls_strerror(ret));
                exit(1);
@@ -197,7 +216,7 @@ size_t size;
        fputs("\n\n", outfile);
 
        gnutls_x509_crt_deinit(xcrt);
-       gnutls_pkcs11_crt_deinit(crt);
+       gnutls_pkcs11_obj_deinit(crt);
        
        return;
 


hooks/post-receive
-- 
GNU gnutls



reply via email to

[Prev in Thread] Current Thread [Next in Thread]