gnutls-commit
[Top][All Lists]
Advanced

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

[SCM] GNU gnutls branch, master, updated. gnutls_3_0_21-9-g60a19ba


From: Nikos Mavrogiannopoulos
Subject: [SCM] GNU gnutls branch, master, updated. gnutls_3_0_21-9-g60a19ba
Date: Sun, 08 Jul 2012 12:21:31 +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=60a19bacc312dc7190c65ef449505abbb09a947a

The branch, master has been updated
       via  60a19bacc312dc7190c65ef449505abbb09a947a (commit)
       via  1c218b507acfc62d6af742bac192113fef119284 (commit)
      from  54c1e5d81ec42547b1c8d15e50d7263497089d07 (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 60a19bacc312dc7190c65ef449505abbb09a947a
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Sun Jul 8 14:08:38 2012 +0200

    Added functionality to extract the pubkey key from a TPM key.
    
    Added new function gnutls_pubkey_import_tpm_raw(). tpmtool can now
    print the pubkey key from a TPM key.

commit 1c218b507acfc62d6af742bac192113fef119284
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Sun Jul 8 13:13:40 2012 +0200

    simplified base64 encoding/decoding functions by using a datum.

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

Summary of changes:
 NEWS                           |    1 +
 doc/Makefile.am                |    2 +
 lib/gnutls_dh_primes.c         |   28 ++---
 lib/gnutls_pubkey.c            |   11 +--
 lib/includes/gnutls/abstract.h |    5 +
 lib/libgnutls.map              |    1 +
 lib/tpm.c                      |  253 ++++++++++++++++++++++++++++++++++------
 lib/x509/common.c              |   20 +--
 lib/x509/crl.c                 |   11 +--
 lib/x509/crq.c                 |   15 +--
 lib/x509/pkcs12.c              |   11 +--
 lib/x509/pkcs7.c               |    9 +--
 lib/x509/privkey.c             |   11 +--
 lib/x509/privkey_pkcs8.c       |   13 +--
 lib/x509/x509.c                |   13 +--
 lib/x509_b64.c                 |  101 ++++++++---------
 lib/x509_b64.h                 |    4 +-
 src/certtool-common.c          |  244 ++++++++++++++++++++++++++++++++++++++
 src/certtool-common.h          |   14 +++
 src/certtool.c                 |  250 +--------------------------------------
 src/tpmtool-args.c             |  176 +++++++++++++++++++---------
 src/tpmtool-args.def           |   14 ++-
 src/tpmtool-args.h             |   26 +++--
 src/tpmtool.c                  |   46 +++++++
 24 files changed, 771 insertions(+), 508 deletions(-)

diff --git a/NEWS b/NEWS
index 04e8a72..ba0f658 100644
--- a/NEWS
+++ b/NEWS
@@ -47,6 +47,7 @@ by Alexandre Bique.
 ** API and ABI modifications:
 GNUTLS_CERT_SIGNATURE_FAILURE: Added
 GNUTLS_CAMELLIA_192_CBC: Added
+gnutls_pubkey_import_tpm_raw: Added
 gnutls_privkey_import_tpm_raw: Added
 gnutls_privkey_import_pkcs11_url: Added
 gnutls_privkey_import_openpgp_raw: Added
diff --git a/doc/Makefile.am b/doc/Makefile.am
index ce3e25b..59b2a0d 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -483,6 +483,7 @@ FUNCS += functions/gnutls_pubkey_import_x509
 FUNCS += functions/gnutls_pubkey_import_pkcs11
 FUNCS += functions/gnutls_pubkey_import_openpgp
 FUNCS += functions/gnutls_pubkey_import_privkey
+FUNCS += functions/gnutls_pubkey_import_tpm_raw
 FUNCS += functions/gnutls_pubkey_get_preferred_hash_algorithm
 FUNCS += functions/gnutls_pubkey_get_pk_rsa_raw
 FUNCS += functions/gnutls_pubkey_get_pk_dsa_raw
@@ -995,6 +996,7 @@ FUNCS += functions/gnutls_pkcs12_bag_get_key_id
 FUNCS += functions/gnutls_pkcs12_bag_set_key_id
 FUNCS += functions/gnutls_pkcs12_bag_get_friendly_name
 FUNCS += functions/gnutls_pkcs12_bag_set_friendly_name
+FUNCS += functions/gnutls_tpm_privkey_generate
 FUNCS += functions/gnutls_x509_crt_init
 FUNCS += functions/gnutls_x509_crt_deinit
 FUNCS += functions/gnutls_x509_crt_import
diff --git a/lib/gnutls_dh_primes.c b/lib/gnutls_dh_primes.c
index 70d73d2..caa9fe8 100644
--- a/lib/gnutls_dh_primes.c
+++ b/lib/gnutls_dh_primes.c
@@ -229,11 +229,10 @@ gnutls_dh_params_import_pkcs3 (gnutls_dh_params_t params,
 
   if (format == GNUTLS_X509_FMT_PEM)
     {
-      uint8_t *out;
 
       result = _gnutls_fbase64_decode ("DH PARAMETERS",
                                        pkcs3_params->data,
-                                       pkcs3_params->size, &out);
+                                       pkcs3_params->size, &_params);
 
       if (result <= 0)
         {
@@ -243,11 +242,7 @@ gnutls_dh_params_import_pkcs3 (gnutls_dh_params_t params,
           return result;
         }
 
-      _params.data = out;
-      _params.size = result;
-
       need_free = 1;
-
     }
   else
     {
@@ -442,7 +437,7 @@ gnutls_dh_params_export_pkcs3 (gnutls_dh_params_t params,
   else
     {                           /* PEM */
       uint8_t *tmp;
-      uint8_t *out;
+      gnutls_datum_t out;
       int len;
 
       len = 0;
@@ -477,27 +472,20 @@ gnutls_dh_params_export_pkcs3 (gnutls_dh_params_t params,
           return result;
         }
 
-      if (result == 0)
-        {                       /* oooops */
-          gnutls_assert ();
-          gnutls_free (out);
-          return GNUTLS_E_INTERNAL_ERROR;
-        }
-
-      if ((unsigned) result > *params_data_size)
+      if ((unsigned) out.size > *params_data_size)
         {
           gnutls_assert ();
-          gnutls_free (out);
-          *params_data_size = result;
+          gnutls_free (out.data);
+          *params_data_size = out.size + 1;
           return GNUTLS_E_SHORT_MEMORY_BUFFER;
         }
 
-      *params_data_size = result - 1;
+      *params_data_size = out.size;
 
       if (params_data)
-        memcpy (params_data, out, result);
+        memcpy (params_data, out.data, out.size);
 
-      gnutls_free (out);
+      gnutls_free (out.data);
 
     }
 
diff --git a/lib/gnutls_pubkey.c b/lib/gnutls_pubkey.c
index aaae702..c8cc319 100644
--- a/lib/gnutls_pubkey.c
+++ b/lib/gnutls_pubkey.c
@@ -836,23 +836,16 @@ gnutls_pubkey_import (gnutls_pubkey_t key,
    */
   if (format == GNUTLS_X509_FMT_PEM)
     {
-      uint8_t *out;
-
       /* Try the first header */
       result =
-        _gnutls_fbase64_decode (PK_PEM_HEADER, data->data, data->size, &out);
+        _gnutls_fbase64_decode (PK_PEM_HEADER, data->data, data->size, &_data);
 
-      if (result <= 0)
+      if (result < 0)
         {
-          if (result == 0)
-            result = GNUTLS_E_INTERNAL_ERROR;
           gnutls_assert ();
           return result;
         }
 
-      _data.data = out;
-      _data.size = result;
-
       need_free = 1;
     }
 
diff --git a/lib/includes/gnutls/abstract.h b/lib/includes/gnutls/abstract.h
index 69dde11..623c774 100644
--- a/lib/includes/gnutls/abstract.h
+++ b/lib/includes/gnutls/abstract.h
@@ -68,6 +68,11 @@ int
 gnutls_pubkey_import_privkey (gnutls_pubkey_t key, gnutls_privkey_t pkey,
                               unsigned int usage, unsigned int flags);
 
+int
+gnutls_pubkey_import_tpm_raw (gnutls_pubkey_t pkey,
+                              const gnutls_datum_t * fdata,
+                              gnutls_x509_crt_fmt_t format,
+                              const char *srk_password);
 
 int gnutls_pubkey_get_preferred_hash_algorithm (gnutls_pubkey_t key,
                                                 gnutls_digest_algorithm_t *
diff --git a/lib/libgnutls.map b/lib/libgnutls.map
index 5403415..d7579aa 100644
--- a/lib/libgnutls.map
+++ b/lib/libgnutls.map
@@ -808,6 +808,7 @@ GNUTLS_3_1_0 {
        gnutls_privkey_import_ext2;
        gnutls_privkey_import_tpm_raw;
         gnutls_tpm_privkey_generate;
+       gnutls_pubkey_import_tpm_raw;
 } GNUTLS_3_0_0;
 
 GNUTLS_PRIVATE {
diff --git a/lib/tpm.c b/lib/tpm.c
index 2218364..c6f37a8 100644
--- a/lib/tpm.c
+++ b/lib/tpm.c
@@ -111,6 +111,7 @@ tpm_sign_fn (gnutls_privkey_t key, void *_s,
 }
 
 static const unsigned char nullpass[20];
+const TSS_UUID srk_uuid = TSS_UUID_SRK;
 
 /**
  * gnutls_privkey_import_tpm_raw:
@@ -140,7 +141,6 @@ gnutls_privkey_import_tpm_raw (gnutls_privkey_t pkey,
                               const char *srk_password,
                               const char *key_password)
 {
-  static const TSS_UUID SRK_UUID = TSS_UUID_SRK;
   gnutls_datum_t asn1;
   size_t slen;
   int err, ret;
@@ -193,7 +193,7 @@ gnutls_privkey_import_tpm_raw (gnutls_privkey_t pkey,
     }
   err =
       Tspi_Context_LoadKeyByUUID (s->tpm_context, TSS_PS_TYPE_SYSTEM,
-                                 SRK_UUID, &s->srk);
+                                 srk_uuid, &s->srk);
   if (err)
     {
       gnutls_assert ();
@@ -339,7 +339,213 @@ out_blob:
   return ret;
 }
 
-const TSS_UUID srk_uuid = TSS_UUID_SRK;
+/* reads the RSA public key from the given TSS key.
+ * If psize is non-null it contains the total size of the parameters
+ * in bytes */
+static int read_pubkey(gnutls_pubkey_t pub, TSS_HKEY key_ctx, size_t *psize)
+{
+void* tdata;
+UINT32 tint;
+TSS_RESULT tssret;
+gnutls_datum_t m, e;
+int ret;
+
+  /* read the public key */
+
+  tssret = Tspi_GetAttribData(key_ctx, TSS_TSPATTRIB_RSAKEY_INFO,
+                                TSS_TSPATTRIB_KEYINFO_RSA_MODULUS, &tint, 
(void*)&tdata);
+  if (tssret != 0)
+    {
+      gnutls_assert();
+      return GNUTLS_E_TPM_ERROR;
+    }
+    
+  m.data = tdata;
+  m.size = tint;
+
+  tssret = Tspi_GetAttribData(key_ctx, TSS_TSPATTRIB_RSAKEY_INFO,
+                                TSS_TSPATTRIB_KEYINFO_RSA_EXPONENT, &tint, 
(void*)&tdata);
+  if (tssret != 0)
+    {
+      gnutls_assert();
+      Tspi_Context_FreeMemory(key_ctx, m.data);
+      return GNUTLS_E_TPM_ERROR;
+    }
+    
+  e.data = tdata;
+  e.size = tint;
+    
+  ret = gnutls_pubkey_import_rsa_raw(pub, &m, &e);
+
+  Tspi_Context_FreeMemory(key_ctx, m.data);
+  Tspi_Context_FreeMemory(key_ctx, e.data);
+
+  if (ret < 0)
+    return gnutls_assert_val(ret);
+  
+  if (psize)
+    *psize = e.size + m.size;
+
+  return 0;
+}
+
+
+/**
+ * gnutls_pubkey_import_tpm_raw:
+ * @pkey: The public key
+ * @fdata: The TPM key to be imported
+ * @format: The format of the private key
+ * @srk_password: The password for the SRK key (optional)
+ * @key_password: A password for the key (optional)
+ *
+ * This function will import the public key from the provided
+ * TPM key structure. If a password is needed to decrypt
+ * the provided key or the provided password is wrong, then 
+ * %GNUTLS_E_TPM_SRK_PASSWORD_ERROR is returned. If the TPM password
+ * is wrong or not provided then %GNUTLS_E_TPM_KEY_PASSWORD_ERROR
+ * is returned. 
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
+ *   negative error value.
+ *
+ * Since: 3.1.0
+ *
+ **/
+int
+gnutls_pubkey_import_tpm_raw (gnutls_pubkey_t pkey,
+                              const gnutls_datum_t * fdata,
+                              gnutls_x509_crt_fmt_t format,
+                              const char *srk_password)
+{
+gnutls_datum_t asn1;
+size_t slen;
+int err, ret;
+struct tpm_ctx_st s;
+
+  ret = gnutls_pem_base64_decode_alloc ("TSS KEY BLOB", fdata, &asn1);
+  if (ret)
+    {
+      gnutls_assert ();
+      _gnutls_debug_log ("Error decoding TSS key blob: %s\n",
+                        gnutls_strerror (ret));
+      return ret;
+    }
+
+  slen = asn1.size;
+  ret = _gnutls_x509_decode_octet_string(NULL, asn1.data, asn1.size, 
asn1.data, &slen);
+  if (ret < 0)
+    {
+      gnutls_assert();
+      goto out_blob;
+    }
+  asn1.size = slen;
+
+  err = Tspi_Context_Create (&s.tpm_context);
+  if (err)
+    {
+      gnutls_assert ();
+      _gnutls_debug_log ("Failed to create TPM context: %s\n",
+                        Trspi_Error_String (err));
+      ret = GNUTLS_E_TPM_ERROR;
+      goto out_blob;
+    }
+  err = Tspi_Context_Connect (s.tpm_context, NULL);
+  if (err)
+    {
+      gnutls_assert ();
+      _gnutls_debug_log ("Failed to connect TPM context: %s\n",
+                        Trspi_Error_String (err));
+      ret = GNUTLS_E_TPM_ERROR;
+      goto out_tspi_ctx;
+    }
+  err =
+      Tspi_Context_LoadKeyByUUID (s.tpm_context, TSS_PS_TYPE_SYSTEM,
+                                 srk_uuid, &s.srk);
+  if (err)
+    {
+      gnutls_assert ();
+      _gnutls_debug_log
+         ("Failed to load TPM SRK key: %s\n", Trspi_Error_String (err));
+      ret = GNUTLS_E_TPM_ERROR;
+      goto out_tspi_ctx;
+    }
+  err = Tspi_GetPolicyObject (s.srk, TSS_POLICY_USAGE, &s.srk_policy);
+  if (err)
+    {
+      gnutls_assert ();
+      _gnutls_debug_log ("Failed to load TPM SRK policy object: %s\n",
+                        Trspi_Error_String (err));
+      ret = GNUTLS_E_TPM_ERROR;
+      goto out_srk;
+    }
+
+  /* We don't seem to get the error here... */
+  if (srk_password)
+    err = Tspi_Policy_SetSecret (s.srk_policy,
+                                TSS_SECRET_MODE_PLAIN,
+                                strlen (srk_password), (BYTE *) srk_password);
+  else                         /* Well-known NULL key */
+    err = Tspi_Policy_SetSecret (s.srk_policy,
+                                TSS_SECRET_MODE_SHA1,
+                                sizeof (nullpass), (BYTE *) nullpass);
+  if (err)
+    {
+      gnutls_assert ();
+      _gnutls_debug_log ("Failed to set TPM PIN: %s\n",
+                        Trspi_Error_String (err));
+      ret = GNUTLS_E_TPM_ERROR;
+      goto out_srkpol;
+    }
+
+  /* ... we get it here instead. */
+  err = Tspi_Context_LoadKeyByBlob (s.tpm_context, s.srk,
+                                   asn1.size, asn1.data, &s.tpm_key);
+  if (err != 0)
+    {
+      if (srk_password)
+       {
+         gnutls_assert ();
+         _gnutls_debug_log
+             ("Failed to load TPM key blob: %s\n",
+              Trspi_Error_String (err));
+       }
+
+      if (err != TPM_E_AUTHFAIL)
+       {
+         gnutls_assert ();
+         ret = GNUTLS_E_TPM_ERROR;
+         goto out_srkpol;
+       }
+      else
+       {
+         ret = gnutls_assert_val (GNUTLS_E_TPM_SRK_PASSWORD_ERROR);
+         goto out_srkpol;
+       }
+    }
+
+  ret = read_pubkey(pkey, s.tpm_key, NULL);
+  if (ret < 0)
+    {
+      gnutls_assert();
+      goto out_srkpol;
+    }
+
+  gnutls_free (asn1.data);
+  return 0;
+out_srkpol:
+  Tspi_Context_CloseObject (s.tpm_context, s.srk_policy);
+  s.srk_policy = 0;
+out_srk:
+  Tspi_Context_CloseObject (s.tpm_context, s.srk);
+  s.srk = 0;
+out_tspi_ctx:
+  Tspi_Context_Close (s.tpm_context);
+  s.tpm_context = 0;
+out_blob:
+  gnutls_free (asn1.data);
+  return ret;
+}
+
 
 /**
  * gnutls_tpm_privkey_generate:
@@ -357,6 +563,9 @@ const TSS_UUID srk_uuid = TSS_UUID_SRK;
  * form. Furthermore the wrapped key can be protected with
  * the provided @password.
  *
+ * Note that bits in TPM is quantized value. Allowed values are 512,
+ * 1024, 2048, 4096, 8192 and 16384.
+ *
  * Allowed flags are %GNUTLS_TPM_SIG_PKCS1V15 and 
%GNUTLS_TPM_SIG_PKCS1V15_SHA1.
  *
  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
@@ -408,7 +617,7 @@ gnutls_pubkey_t pub;
     default:
       return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
   }
-  
+
   tssret = Tspi_Context_Create(&ctx);
   if (tssret != 0)
     {
@@ -532,13 +741,12 @@ gnutls_pubkey_t pub;
   
   if (format == GNUTLS_X509_FMT_PEM)
     {
-      ret = _gnutls_fbase64_encode ("TSS KEY BLOB", tmpkey.data, tmpkey.size, 
&privkey->data);
+      ret = _gnutls_fbase64_encode ("TSS KEY BLOB", tmpkey.data, tmpkey.size, 
privkey);
       if (ret < 0)
         {
           gnutls_assert();
           goto cleanup;
         }
-      privkey->size = ret;
     }
   else
     {
@@ -547,8 +755,8 @@ gnutls_pubkey_t pub;
       tmpkey.data = NULL;
     }
 
+  /* read the public key */
   {
-    gnutls_datum_t m, e;
     size_t psize;
 
     ret = gnutls_pubkey_init(&pub);
@@ -557,40 +765,15 @@ gnutls_pubkey_t pub;
         gnutls_assert();
         goto privkey_cleanup;
       }
-    
-    tssret = Tspi_GetAttribData(key_ctx, TSS_TSPATTRIB_RSAKEY_INFO,
-                                TSS_TSPATTRIB_KEYINFO_RSA_MODULUS, &tint, 
(void*)&tdata);
-    if (tssret != 0)
-      {
-        gnutls_assert();
-        ret = GNUTLS_E_TPM_ERROR;
-        goto pubkey_cleanup;
-      }
-    
-    m.data = tdata;
-    m.size = tint;
 
-    tssret = Tspi_GetAttribData(key_ctx, TSS_TSPATTRIB_RSAKEY_INFO,
-                                TSS_TSPATTRIB_KEYINFO_RSA_EXPONENT, &tint, 
(void*)&tdata);
-    if (tssret != 0)
-      {
-        gnutls_assert();
-        Tspi_Context_FreeMemory(key_ctx, m.data);
-        ret = GNUTLS_E_TPM_ERROR;
-        goto pubkey_cleanup;
-      }
-    
-    e.data = tdata;
-    e.size = tint;
-    
-    ret = gnutls_pubkey_import_rsa_raw(pub, &m, &e);
+    ret = read_pubkey(pub, key_ctx, &psize);
     if (ret < 0)
       {
         gnutls_assert();
-        goto pubkey_cleanup;
+        goto privkey_cleanup;
       }
+    psize+=512;
     
-    psize = e.size+m.size+512;
     pubkey->data = gnutls_malloc(psize);
     if (pubkey->data == NULL)
       {
diff --git a/lib/x509/common.c b/lib/x509/common.c
index 2e4ff2e..9409141 100644
--- a/lib/x509/common.c
+++ b/lib/x509/common.c
@@ -805,7 +805,7 @@ _gnutls_x509_export_int_named (ASN1_TYPE asn1_data, const 
char *name,
     }
   else
     {                           /* PEM */
-      uint8_t *out;
+      gnutls_datum_t out;
       gnutls_datum_t tmp;
 
       result = _gnutls_x509_der_encode (asn1_data, name, &tmp, 0);
@@ -825,31 +825,25 @@ _gnutls_x509_export_int_named (ASN1_TYPE asn1_data, const 
char *name,
           return result;
         }
 
-      if (result == 0)
-        {                       /* oooops */
-          gnutls_assert ();
-          return GNUTLS_E_INTERNAL_ERROR;
-        }
-
-      if ((size_t) result > *output_data_size)
+      if ((size_t) out.size > *output_data_size)
         {
           gnutls_assert ();
-          gnutls_free (out);
-          *output_data_size = (size_t)result;
+          gnutls_free (out.data);
+          *output_data_size = (size_t)out.size+1;
           return GNUTLS_E_SHORT_MEMORY_BUFFER;
         }
 
-      *output_data_size = (size_t)result;
+      *output_data_size = (size_t)out.size;
 
       if (output_data)
         {
-          memcpy (output_data, out, (size_t)result);
+          memcpy (output_data, out.data, (size_t)out.size);
 
           /* do not include the null character into output size.
            */
           *output_data_size = (size_t)result - 1;
         }
-      gnutls_free (out);
+      gnutls_free (out.data);
 
     }
 
diff --git a/lib/x509/crl.c b/lib/x509/crl.c
index cfd4b93..b0e1fd8 100644
--- a/lib/x509/crl.c
+++ b/lib/x509/crl.c
@@ -118,21 +118,14 @@ gnutls_x509_crl_import (gnutls_x509_crl_t crl,
    */
   if (format == GNUTLS_X509_FMT_PEM)
     {
-      uint8_t *out;
+      result = _gnutls_fbase64_decode (PEM_CRL, data->data, data->size, 
&_data);
 
-      result = _gnutls_fbase64_decode (PEM_CRL, data->data, data->size, &out);
-
-      if (result <= 0)
+      if (result < 0)
         {
-          if (result == 0)
-            result = GNUTLS_E_INTERNAL_ERROR;
           gnutls_assert ();
           return result;
         }
 
-      _data.data = out;
-      _data.size = result;
-
       need_free = 1;
     }
 
diff --git a/lib/x509/crq.c b/lib/x509/crq.c
index 0a2e13d..956229b 100644
--- a/lib/x509/crq.c
+++ b/lib/x509/crq.c
@@ -126,26 +126,19 @@ gnutls_x509_crq_import (gnutls_x509_crq_t crq,
    */
   if (format == GNUTLS_X509_FMT_PEM)
     {
-      uint8_t *out;
-
       /* Try the first header */
-      result = _gnutls_fbase64_decode (PEM_CRQ, data->data, data->size, &out);
+      result = _gnutls_fbase64_decode (PEM_CRQ, data->data, data->size, 
&_data);
 
-      if (result <= 0)          /* Go for the second header */
+      if (result < 0)          /* Go for the second header */
         result =
-          _gnutls_fbase64_decode (PEM_CRQ2, data->data, data->size, &out);
+          _gnutls_fbase64_decode (PEM_CRQ2, data->data, data->size, &_data);
 
-      if (result <= 0)
+      if (result < 0)
         {
-          if (result == 0)
-            result = GNUTLS_E_INTERNAL_ERROR;
           gnutls_assert ();
           return result;
         }
 
-      _data.data = out;
-      _data.size = result;
-
       need_free = 1;
     }
 
diff --git a/lib/x509/pkcs12.c b/lib/x509/pkcs12.c
index b1240a5..d66f91a 100644
--- a/lib/x509/pkcs12.c
+++ b/lib/x509/pkcs12.c
@@ -207,22 +207,15 @@ gnutls_pkcs12_import (gnutls_pkcs12_t pkcs12,
    */
   if (format == GNUTLS_X509_FMT_PEM)
     {
-      uint8_t *out;
-
       result = _gnutls_fbase64_decode (PEM_PKCS12, data->data, data->size,
-                                       &out);
+                                       &_data);
 
-      if (result <= 0)
+      if (result < 0)
         {
-          if (result == 0)
-            result = GNUTLS_E_INTERNAL_ERROR;
           gnutls_assert ();
           return result;
         }
 
-      _data.data = out;
-      _data.size = result;
-
       need_free = 1;
     }
 
diff --git a/lib/x509/pkcs7.c b/lib/x509/pkcs7.c
index ff6da72..16e4d3b 100644
--- a/lib/x509/pkcs7.c
+++ b/lib/x509/pkcs7.c
@@ -215,22 +215,15 @@ gnutls_pkcs7_import (gnutls_pkcs7_t pkcs7, const 
gnutls_datum_t * data,
    */
   if (format == GNUTLS_X509_FMT_PEM)
     {
-      uint8_t *out;
-
       result = _gnutls_fbase64_decode (PEM_PKCS7, data->data, data->size,
-                                       &out);
+                                       &_data);
 
       if (result <= 0)
         {
-          if (result == 0)
-            result = GNUTLS_E_INTERNAL_ERROR;
           gnutls_assert ();
           return result;
         }
 
-      _data.data = out;
-      _data.size = result;
-
       need_free = 1;
     }
 
diff --git a/lib/x509/privkey.c b/lib/x509/privkey.c
index 26e1332..9d32025 100644
--- a/lib/x509/privkey.c
+++ b/lib/x509/privkey.c
@@ -451,11 +451,9 @@ gnutls_x509_privkey_import (gnutls_x509_privkey_t key,
    */
   if (format == GNUTLS_X509_FMT_PEM)
     {
-      uint8_t *out;
-
       /* Try the first header */
       result =
-        _gnutls_fbase64_decode (PEM_KEY_RSA, data->data, data->size, &out);
+        _gnutls_fbase64_decode (PEM_KEY_RSA, data->data, data->size, &_data);
 
       if (result >= 0)
         key->pk_algorithm = GNUTLS_PK_RSA;
@@ -465,7 +463,7 @@ gnutls_x509_privkey_import (gnutls_x509_privkey_t key,
           /* try for the second header */
           result =
             _gnutls_fbase64_decode (PEM_KEY_DSA, data->data, data->size,
-                                    &out);
+                                    &_data);
 
           if (result >= 0)
             key->pk_algorithm = GNUTLS_PK_DSA;
@@ -475,7 +473,7 @@ gnutls_x509_privkey_import (gnutls_x509_privkey_t key,
               /* try for the second header */
               result =
                 _gnutls_fbase64_decode (PEM_KEY_ECC, data->data, data->size,
-                                    &out);
+                                    &_data);
               if (result >= 0)
                 key->pk_algorithm = GNUTLS_PK_EC;
              }
@@ -487,9 +485,6 @@ gnutls_x509_privkey_import (gnutls_x509_privkey_t key,
           goto failover;
         }
 
-      _data.data = out;
-      _data.size = result;
-
       need_free = 1;
     }
 
diff --git a/lib/x509/privkey_pkcs8.c b/lib/x509/privkey_pkcs8.c
index 0d90f29..95711ce 100644
--- a/lib/x509/privkey_pkcs8.c
+++ b/lib/x509/privkey_pkcs8.c
@@ -1215,24 +1215,20 @@ gnutls_x509_privkey_import_pkcs8 (gnutls_x509_privkey_t 
key,
    */
   if (format == GNUTLS_X509_FMT_PEM)
     {
-      uint8_t *out;
-
       /* Try the first header 
        */
       result =
         _gnutls_fbase64_decode (PEM_UNENCRYPTED_PKCS8,
-                                data->data, data->size, &out);
+                                data->data, data->size, &_data);
 
       if (result < 0)
         {                       /* Try the encrypted header 
                                  */
           result =
-            _gnutls_fbase64_decode (PEM_PKCS8, data->data, data->size, &out);
+            _gnutls_fbase64_decode (PEM_PKCS8, data->data, data->size, &_data);
 
-          if (result <= 0)
+          if (result < 0)
             {
-              if (result == 0)
-                result = GNUTLS_E_INTERNAL_ERROR;
               gnutls_assert ();
               return result;
             }
@@ -1240,9 +1236,6 @@ gnutls_x509_privkey_import_pkcs8 (gnutls_x509_privkey_t 
key,
       else if (flags == 0)
         flags |= GNUTLS_PKCS_PLAIN;
 
-      _data.data = out;
-      _data.size = result;
-
       need_free = 1;
     }
 
diff --git a/lib/x509/x509.c b/lib/x509/x509.c
index acb3cec..ab8bac0 100644
--- a/lib/x509/x509.c
+++ b/lib/x509/x509.c
@@ -178,31 +178,24 @@ gnutls_x509_crt_import (gnutls_x509_crt_t cert,
    */
   if (format == GNUTLS_X509_FMT_PEM)
     {
-      uint8_t *out;
-
       /* Try the first header */
       result =
-        _gnutls_fbase64_decode (PEM_X509_CERT2, data->data, data->size, &out);
+        _gnutls_fbase64_decode (PEM_X509_CERT2, data->data, data->size, 
&_data);
 
       if (result <= 0)
         {
           /* try for the second header */
           result =
             _gnutls_fbase64_decode (PEM_X509_CERT, data->data,
-                                    data->size, &out);
+                                    data->size, &_data);
 
-          if (result <= 0)
+          if (result < 0)
             {
-              if (result == 0)
-                result = GNUTLS_E_INTERNAL_ERROR;
               gnutls_assert ();
               return result;
             }
         }
 
-      _data.data = out;
-      _data.size = result;
-
       need_free = 1;
     }
 
diff --git a/lib/x509_b64.c b/lib/x509_b64.c
index 2b72ae8..8b43011 100644
--- a/lib/x509_b64.c
+++ b/lib/x509_b64.c
@@ -34,7 +34,7 @@
        what+=size; \
        if (what > max_len) { \
                gnutls_assert(); \
-               gnutls_free( (*result)); *result = NULL; \
+               gnutls_free( result->data); result->data = NULL; \
                return GNUTLS_E_INTERNAL_ERROR; \
        } \
        } while(0)
@@ -44,7 +44,7 @@
  */
 int
 _gnutls_fbase64_encode (const char *msg, const uint8_t * data,
-                        size_t data_size, uint8_t ** result)
+                        size_t data_size, gnutls_datum_t * result)
 {
   int tmp;
   unsigned int i;
@@ -74,8 +74,8 @@ _gnutls_fbase64_encode (const char *msg, const uint8_t * data,
 
   max = B64FSIZE (top_len+bottom_len, data_size);
 
-  (*result) = gnutls_calloc (1, max + 1);
-  if ((*result) == NULL)
+  result->data = gnutls_malloc (max + 1);
+  if (result->data == NULL)
     {
       gnutls_assert ();
       return GNUTLS_E_MEMORY_ERROR;
@@ -85,7 +85,7 @@ _gnutls_fbase64_encode (const char *msg, const uint8_t * data,
   INCR (bytes, top_len, max);
   pos = top_len;
 
-  memcpy (*result, top, top_len);
+  memcpy (result->data, top, top_len);
 
   for (i = 0; i < data_size; i += 48)
     {
@@ -98,7 +98,7 @@ _gnutls_fbase64_encode (const char *msg, const uint8_t * data,
       size = strlen(tmpres);
 
       INCR (bytes, size+1, max);
-      ptr = &(*result)[pos];
+      ptr = &result->data[pos];
 
       memcpy(ptr, tmpres, size);
       ptr += size;
@@ -109,8 +109,9 @@ _gnutls_fbase64_encode (const char *msg, const uint8_t * 
data,
 
   INCR (bytes, bottom_len, max);
 
-  memcpy (&(*result)[bytes - bottom_len], bottom, bottom_len);
-  (*result)[bytes] = 0;
+  memcpy (&result->data[bytes - bottom_len], bottom, bottom_len);
+  result->data[bytes] = 0;
+  result->size = bytes;
 
   return max + 1;
 }
@@ -136,24 +137,24 @@ int
 gnutls_pem_base64_encode (const char *msg, const gnutls_datum_t * data,
                           char *result, size_t * result_size)
 {
-  uint8_t *ret;
-  int size;
+  gnutls_datum_t res;
+  int ret;
 
-  size = _gnutls_fbase64_encode (msg, data->data, data->size, &ret);
-  if (size < 0)
-    return size;
+  ret = _gnutls_fbase64_encode (msg, data->data, data->size, &res);
+  if (ret < 0)
+    return ret;
 
-  if (result == NULL || *result_size < (unsigned) size)
+  if (result == NULL || *result_size < (unsigned) res.size)
     {
-      gnutls_free (ret);
-      *result_size = size;
+      gnutls_free (res.data);
+      *result_size = res.size + 1;
       return GNUTLS_E_SHORT_MEMORY_BUFFER;
     }
   else
     {
-      memcpy (result, ret, size);
-      gnutls_free (ret);
-      *result_size = size - 1;
+      memcpy (result, res.data, res.size);
+      gnutls_free (res.data);
+      *result_size = res.size;
     }
 
   return 0;
@@ -180,18 +181,15 @@ gnutls_pem_base64_encode_alloc (const char *msg,
                                 const gnutls_datum_t * data,
                                 gnutls_datum_t * result)
 {
-  uint8_t *ret;
-  int size;
+  int ret;
 
   if (result == NULL)
-    return GNUTLS_E_INVALID_REQUEST;
+    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
 
-  size = _gnutls_fbase64_encode (msg, data->data, data->size, &ret);
-  if (size < 0)
-    return size;
+  ret = _gnutls_fbase64_encode (msg, data->data, data->size, result);
+  if (ret < 0)
+    return gnutls_assert_val(ret);
 
-  result->data = ret;
-  result->size = size - 1;
   return 0;
 }
 
@@ -248,7 +246,6 @@ _gnutls_base64_decode (const uint8_t * data, size_t 
data_size,
   if (result->data == NULL)
     return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
 
-
   pos = 0;
   for (i = 0; i < pdata.size; i += 64)
     {
@@ -267,11 +264,12 @@ _gnutls_base64_decode (const uint8_t * data, size_t 
data_size,
           ret = GNUTLS_E_PARSING_ERROR;
           goto cleanup;
         }
-      memcpy (&(result->data)[pos], tmpres, tmpres_size);
+      memcpy (&result->data[pos], tmpres, tmpres_size);
       pos += tmpres_size;
     }
 
   result->size = pos;
+
   ret = pos;
 
 cleanup:
@@ -288,12 +286,11 @@ cleanup:
 #define ENDSTR "-----"
 int
 _gnutls_fbase64_decode (const char *header, const uint8_t * data,
-                        size_t data_size, uint8_t ** result)
+                        size_t data_size, gnutls_datum_t* result)
 {
   int ret;
   static const char top[] = "-----BEGIN ";
   static const char bottom[] = "-----END ";
-  gnutls_datum_t res;
   uint8_t *rdata, *kdata;
   int rdata_size;
   char pem_header[128];
@@ -352,12 +349,11 @@ _gnutls_fbase64_decode (const char *header, const uint8_t 
* data,
       return GNUTLS_E_BASE64_DECODING_ERROR;
     }
 
-  if ((ret = _gnutls_base64_decode (rdata, rdata_size, &res)) < 0)
+  if ((ret = _gnutls_base64_decode (rdata, rdata_size, result)) < 0)
     {
       gnutls_assert ();
       return GNUTLS_E_BASE64_DECODING_ERROR;
     }
-  *result = res.data;
 
   return ret;
 }
@@ -383,25 +379,25 @@ gnutls_pem_base64_decode (const char *header,
                           const gnutls_datum_t * b64_data,
                           unsigned char *result, size_t * result_size)
 {
-  uint8_t *ret;
-  int size;
+  gnutls_datum_t res;
+  int ret;
 
-  size =
-    _gnutls_fbase64_decode (header, b64_data->data, b64_data->size, &ret);
-  if (size < 0)
-    return size;
+  ret =
+    _gnutls_fbase64_decode (header, b64_data->data, b64_data->size, &res);
+  if (ret < 0)
+    return gnutls_assert_val(ret);
 
-  if (result == NULL || *result_size < (unsigned) size)
+  if (result == NULL || *result_size < (unsigned) res.size)
     {
-      gnutls_free (ret);
-      *result_size = size;
+      gnutls_free (res.data);
+      *result_size = res.size;
       return GNUTLS_E_SHORT_MEMORY_BUFFER;
     }
   else
     {
-      memcpy (result, ret, size);
-      gnutls_free (ret);
-      *result_size = size;
+      memcpy (result, res.data, res.size);
+      gnutls_free (res.data);
+      *result_size = res.size;
     }
 
   return 0;
@@ -429,18 +425,15 @@ gnutls_pem_base64_decode_alloc (const char *header,
                                 const gnutls_datum_t * b64_data,
                                 gnutls_datum_t * result)
 {
-  uint8_t *ret;
-  int size;
+  int ret;
 
   if (result == NULL)
-    return GNUTLS_E_INVALID_REQUEST;
+    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
 
-  size =
-    _gnutls_fbase64_decode (header, b64_data->data, b64_data->size, &ret);
-  if (size < 0)
-    return size;
+  ret =
+    _gnutls_fbase64_decode (header, b64_data->data, b64_data->size, result);
+  if (ret < 0)
+    return gnutls_assert_val(ret);
 
-  result->data = ret;
-  result->size = size;
   return 0;
 }
diff --git a/lib/x509_b64.h b/lib/x509_b64.h
index a30f8f4..d110c57 100644
--- a/lib/x509_b64.h
+++ b/lib/x509_b64.h
@@ -21,9 +21,9 @@
  */
 
 int _gnutls_fbase64_encode (const char *msg, const uint8_t * data,
-                            size_t data_size, uint8_t ** result);
+                            size_t data_size, gnutls_datum_t* result);
 int _gnutls_fbase64_decode (const char *header, const uint8_t * data,
-                            size_t data_size, uint8_t ** result);
+                            size_t data_size, gnutls_datum_t* result);
 
 int
 _gnutls_base64_decode (const uint8_t * data, size_t data_size,
diff --git a/src/certtool-common.c b/src/certtool-common.c
index 13aee71..e8e2f1c 100644
--- a/src/certtool-common.c
+++ b/src/certtool-common.c
@@ -664,3 +664,247 @@ gnutls_sec_param_t str_to_sec_param (const char *str)
     }
 
 }
+
+static void
+print_hex_datum (FILE* outfile, gnutls_datum_t * dat)
+{
+  unsigned int j;
+#define SPACE "\t"
+  fprintf (outfile, "\n" SPACE);
+  for (j = 0; j < dat->size; j++)
+    {
+      fprintf (outfile, "%.2x:", (unsigned char) dat->data[j]);
+      if ((j + 1) % 15 == 0)
+        fprintf (outfile, "\n" SPACE);
+    }
+  fprintf (outfile, "\n");
+}
+
+void
+print_dsa_pkey (FILE* outfile, gnutls_datum_t * x, gnutls_datum_t * y, 
gnutls_datum_t * p,
+                gnutls_datum_t * q, gnutls_datum_t * g)
+{
+  if (x)
+    {
+      fprintf (outfile, "private key:");
+      print_hex_datum (outfile, x);
+    }
+  fprintf (outfile, "public key:");
+  print_hex_datum (outfile, y);
+  fprintf (outfile, "p:");
+  print_hex_datum (outfile, p);
+  fprintf (outfile, "q:");
+  print_hex_datum (outfile, q);
+  fprintf (outfile, "g:");
+  print_hex_datum (outfile, g);
+}
+
+void
+print_ecc_pkey (FILE* outfile, gnutls_ecc_curve_t curve, gnutls_datum_t* k, 
gnutls_datum_t * x, gnutls_datum_t * y)
+{
+  fprintf (outfile, "curve:\t%s\n", gnutls_ecc_curve_get_name(curve));
+  if (k)
+    {
+      fprintf (outfile, "private key:");
+      print_hex_datum (outfile, k);
+    }
+  fprintf (outfile, "x:");
+  print_hex_datum (outfile, x);
+  fprintf (outfile, "y:");
+  print_hex_datum (outfile, y);
+}
+
+void
+print_rsa_pkey (FILE* outfile, gnutls_datum_t * m, gnutls_datum_t * e, 
gnutls_datum_t * d,
+                gnutls_datum_t * p, gnutls_datum_t * q, gnutls_datum_t * u,
+                gnutls_datum_t * exp1, gnutls_datum_t * exp2)
+{
+  fprintf (outfile, "modulus:");
+  print_hex_datum (outfile, m);
+  fprintf (outfile, "public exponent:");
+  print_hex_datum (outfile, e);
+  if (d)
+    {
+      fprintf (outfile, "private exponent:");
+      print_hex_datum (outfile, d);
+      fprintf (outfile, "prime1:");
+      print_hex_datum (outfile, p);
+      fprintf (outfile, "prime2:");
+      print_hex_datum (outfile, q);
+      fprintf (outfile, "coefficient:");
+      print_hex_datum (outfile, u);
+      if (exp1 && exp2)
+        {
+          fprintf (outfile, "exp1:");
+          print_hex_datum (outfile, exp1);
+          fprintf (outfile, "exp2:");
+          print_hex_datum (outfile, exp2);
+        }
+    }
+}
+
+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");
+    }
+}
+
+const char *
+raw_to_string (const unsigned char *raw, size_t raw_size)
+{
+  static char buf[1024];
+  size_t i;
+  if (raw_size == 0)
+    return NULL;
+
+  if (raw_size * 3 + 1 >= sizeof (buf))
+    return NULL;
+
+  for (i = 0; i < raw_size; i++)
+    {
+      sprintf (&(buf[i * 3]), "%02X%s", raw[i],
+               (i == raw_size - 1) ? "" : ":");
+    }
+  buf[sizeof (buf) - 1] = '\0';
+
+  return buf;
+}
+
+void _pubkey_info(FILE* outfile, gnutls_pubkey_t pubkey)
+{
+unsigned int usage;
+int ret;
+size_t size;
+unsigned int bits;
+const char *cprint;
+
+  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 (outfile, &m, &e, NULL, NULL, 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 (outfile, NULL, &y, &p, &q, &g);
+          gnutls_free (y.data);
+          gnutls_free (p.data);
+          gnutls_free (q.data);
+          gnutls_free (g.data);
+        }
+    }
+  else if (ret == GNUTLS_PK_EC)
+    {
+      gnutls_datum_t x, y;
+      gnutls_ecc_curve_t curve;
+
+      ret = gnutls_pubkey_get_pk_ecc_raw (pubkey, &curve, &x, &y);
+      if (ret < 0)
+        fprintf (stderr, "Error in key ECC data export: %s\n",
+                 gnutls_strerror (ret));
+      else
+        {
+          print_ecc_pkey (outfile, curve, NULL, &y, &x);
+          gnutls_free (y.data);
+          gnutls_free (x.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 = buffer_size;
+  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 = buffer_size;
+  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);
+}
diff --git a/src/certtool-common.h b/src/certtool-common.h
index deb3853..7bedfb5 100644
--- a/src/certtool-common.h
+++ b/src/certtool-common.h
@@ -74,8 +74,22 @@ void dh_info (common_info_st * ci);
 
 gnutls_x509_privkey_t * load_privkey_list (int mand, size_t * privkey_size, 
common_info_st * info);
 
+void _pubkey_info(FILE* outfile, gnutls_pubkey_t pubkey);
+void
+print_ecc_pkey (FILE* outfile, gnutls_ecc_curve_t curve, gnutls_datum_t* k, 
gnutls_datum_t * x, gnutls_datum_t * y);
+void
+print_rsa_pkey (FILE* outfile, gnutls_datum_t * m, gnutls_datum_t * e, 
gnutls_datum_t * d,
+                gnutls_datum_t * p, gnutls_datum_t * q, gnutls_datum_t * u,
+                gnutls_datum_t * exp1, gnutls_datum_t * exp2);
+void
+print_dsa_pkey (FILE* outfile, gnutls_datum_t * x, gnutls_datum_t * y, 
gnutls_datum_t * p,
+                gnutls_datum_t * q, gnutls_datum_t * g);
+
 FILE *safe_open_rw (const char *file, int privkey_op);
 
+const char *
+raw_to_string (const unsigned char *raw, size_t raw_size);
+
 extern unsigned char buffer[];
 extern const int buffer_size;
 
diff --git a/src/certtool.c b/src/certtool.c
index 8d3e393..7078d24 100644
--- a/src/certtool.c
+++ b/src/certtool.c
@@ -75,8 +75,6 @@ static void print_certificate_info (gnutls_x509_crt_t crt, 
FILE * out,
                                     unsigned int all);
 static void verify_certificate (common_info_st * cinfo);
 
-static void print_hex_datum (gnutls_datum_t * dat);
-
 FILE *outfile;
 FILE *infile;
 static gnutls_digest_algorithm_t default_dig;
@@ -104,90 +102,6 @@ main (int argc, char **argv)
   return 0;
 }
 
-static const char *
-raw_to_string (const unsigned char *raw, size_t raw_size)
-{
-  static char buf[1024];
-  size_t i;
-  if (raw_size == 0)
-    return NULL;
-
-  if (raw_size * 3 + 1 >= sizeof (buf))
-    return NULL;
-
-  for (i = 0; i < raw_size; i++)
-    {
-      sprintf (&(buf[i * 3]), "%02X%s", raw[i],
-               (i == raw_size - 1) ? "" : ":");
-    }
-  buf[sizeof (buf) - 1] = '\0';
-
-  return buf;
-}
-
-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)
-{
-  if (x)
-    {
-      fprintf (outfile, "private key:");
-      print_hex_datum (x);
-    }
-  fprintf (outfile, "public key:");
-  print_hex_datum (y);
-  fprintf (outfile, "p:");
-  print_hex_datum (p);
-  fprintf (outfile, "q:");
-  print_hex_datum (q);
-  fprintf (outfile, "g:");
-  print_hex_datum (g);
-}
-
-static void
-print_ecc_pkey (gnutls_ecc_curve_t curve, gnutls_datum_t* k, gnutls_datum_t * 
x, gnutls_datum_t * y)
-{
-  fprintf (outfile, "curve:\t%s\n", gnutls_ecc_curve_get_name(curve));
-  if (k)
-    {
-      fprintf (outfile, "private key:");
-      print_hex_datum (k);
-    }
-  fprintf (outfile, "x:");
-  print_hex_datum (x);
-  fprintf (outfile, "y:");
-  print_hex_datum (y);
-}
-
-static void
-print_rsa_pkey (gnutls_datum_t * m, gnutls_datum_t * e, gnutls_datum_t * d,
-                gnutls_datum_t * p, gnutls_datum_t * q, gnutls_datum_t * u,
-                gnutls_datum_t * exp1, gnutls_datum_t * exp2)
-{
-  fprintf (outfile, "modulus:");
-  print_hex_datum (m);
-  fprintf (outfile, "public exponent:");
-  print_hex_datum (e);
-  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);
-      if (exp1 && exp2)
-        {
-          fprintf (outfile, "exp1:");
-          print_hex_datum (exp1);
-          fprintf (outfile, "exp2:");
-          print_hex_datum (exp2);
-        }
-    }
-}
-
 static gnutls_x509_privkey_t
 generate_private_key_int (common_info_st * cinfo)
 {
@@ -1354,7 +1268,7 @@ pgp_privkey_info (void)
             fprintf (stderr, "Error in key RSA data export: %s\n",
                      gnutls_strerror (ret));
           else
-            print_rsa_pkey (&m, &e, &d, &p, &q, &u, NULL, NULL);
+            print_rsa_pkey (outfile, &m, &e, &d, &p, &q, &u, NULL, NULL);
 
           bits = m.size * 8;
         }
@@ -1373,7 +1287,7 @@ pgp_privkey_info (void)
             fprintf (stderr, "Error in key DSA data export: %s\n",
                      gnutls_strerror (ret));
           else
-            print_dsa_pkey (&x, &y, &p, &q, &g);
+            print_dsa_pkey (outfile, &x, &y, &p, &q, &g);
             
           bits = y.size * 8;
         }
@@ -1489,20 +1403,6 @@ pgp_ring_info (void)
 
 #endif
 
-static void
-print_hex_datum (gnutls_datum_t * dat)
-{
-  unsigned int j;
-#define SPACE "\t"
-  fprintf (outfile, "\n" SPACE);
-  for (j = 0; j < dat->size; j++)
-    {
-      fprintf (outfile, "%.2x:", (unsigned char) dat->data[j]);
-      if ((j + 1) % 15 == 0)
-        fprintf (outfile, "\n" SPACE);
-    }
-  fprintf (outfile, "\n");
-}
 
 
 static void
@@ -1680,7 +1580,7 @@ const char *cprint;
                  gnutls_strerror (ret));
       else
         {
-          print_rsa_pkey (&m, &e, &d, &p, &q, &u, &exp1, &exp2);
+          print_rsa_pkey (outfile, &m, &e, &d, &p, &q, &u, &exp1, &exp2);
           bits = m.size * 8;
 
           gnutls_free (m.data);
@@ -1703,7 +1603,7 @@ const char *cprint;
                  gnutls_strerror (ret));
       else
         {
-          print_dsa_pkey (&x, &y, &p, &q, &g);
+          print_dsa_pkey (outfile, &x, &y, &p, &q, &g);
           bits = y.size * 8;
 
           gnutls_free (x.data);
@@ -1724,7 +1624,7 @@ const char *cprint;
                  gnutls_strerror (ret));
       else
         {
-          print_ecc_pkey (curve, &k, &x, &y);
+          print_ecc_pkey (outfile, curve, &k, &x, &y);
           bits = gnutls_ecc_curve_get_size(curve) * 8;
 
           gnutls_free (x.data);
@@ -2848,63 +2748,13 @@ smime_to_pkcs7 (void)
   free (lineptr);
 }
 
-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 (gnutls_x509_crt_t crt, common_info_st * cinfo)
 {
   gnutls_pubkey_t pubkey;
-  unsigned int bits, usage;
   int ret;
   size_t size;
-  const char *cprint;
 
   ret = gnutls_pubkey_init (&pubkey);
   if (ret < 0)
@@ -2947,94 +2797,6 @@ pubkey_info (gnutls_x509_crt_t crt, common_info_st * 
cinfo)
     
   /* PEM */
 
-  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, 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);
-        }
-    }
-  else if (ret == GNUTLS_PK_EC)
-    {
-      gnutls_datum_t x, y;
-      gnutls_ecc_curve_t curve;
-
-      ret = gnutls_pubkey_get_pk_ecc_raw (pubkey, &curve, &x, &y);
-      if (ret < 0)
-        fprintf (stderr, "Error in key ECC data export: %s\n",
-                 gnutls_strerror (ret));
-      else
-        {
-          print_ecc_pkey (curve, NULL, &y, &x);
-          gnutls_free (y.data);
-          gnutls_free (x.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 = buffer_size;
-  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 = buffer_size;
-  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);
-
+  _pubkey_info(outfile, pubkey);
   gnutls_pubkey_deinit (pubkey);
 }
diff --git a/src/tpmtool-args.c b/src/tpmtool-args.c
index f4dcd20..1202179 100644
--- a/src/tpmtool-args.c
+++ b/src/tpmtool-args.c
@@ -2,7 +2,7 @@
  *  
  *  DO NOT EDIT THIS FILE   (tpmtool-args.c)
  *  
- *  It has been AutoGen-ed  July  6, 2012 at 10:34:04 PM by AutoGen 5.16
+ *  It has been AutoGen-ed  July  8, 2012 at 01:42:38 PM by AutoGen 5.16
  *  From the definitions    tpmtool-args.def
  *  and the template file   options
  *
@@ -67,7 +67,7 @@ extern FILE * option_usage_fp;
 /*
  *  tpmtool option static const strings
  */
-static char const tpmtool_opt_strs[1483] =
+static char const tpmtool_opt_strs[1564] =
 /*     0 */ "tpmtool @address@hidden"
             "Copyright (C) 2000-2012 Free Software Foundation, all rights 
reserved.\n"
             "This is free software. It is licensed for use, modification and\n"
@@ -87,30 +87,36 @@ static char const tpmtool_opt_strs[1483] =
 /*   881 */ "Enable debugging.\0"
 /*   899 */ "DEBUG\0"
 /*   905 */ "debug\0"
-/*   911 */ "Output file\0"
-/*   923 */ "OUTFILE\0"
-/*   931 */ "outfile\0"
-/*   939 */ "Generate an RSA private-public key pair\0"
-/*   979 */ "GENERATE_RSA\0"
-/*   992 */ "generate-rsa\0"
-/*  1005 */ "Specify the number of bits for key generate\0"
-/*  1049 */ "BITS\0"
-/*  1054 */ "bits\0"
-/*  1059 */ "Display extended usage information and exit\0"
-/*  1103 */ "help\0"
-/*  1108 */ "Extended usage information passed thru pager\0"
-/*  1153 */ "more-help\0"
-/*  1163 */ "Output version information and exit\0"
-/*  1199 */ "version\0"
-/*  1207 */ "TPMTOOL\0"
-/*  1215 */ "tpmtool - GnuTLS TPM tool - Ver. @address@hidden"
+/*   911 */ "Input file\0"
+/*   922 */ "INFILE\0"
+/*   929 */ "infile\0"
+/*   936 */ "Output file\0"
+/*   948 */ "OUTFILE\0"
+/*   956 */ "outfile\0"
+/*   964 */ "Generate an RSA private-public key pair\0"
+/*  1004 */ "GENERATE_RSA\0"
+/*  1017 */ "generate-rsa\0"
+/*  1030 */ "Prints the public key of the provided key\0"
+/*  1072 */ "PUBKEY\0"
+/*  1079 */ "pubkey\0"
+/*  1086 */ "Specify the number of bits for key generate\0"
+/*  1130 */ "BITS\0"
+/*  1135 */ "bits\0"
+/*  1140 */ "Display extended usage information and exit\0"
+/*  1184 */ "help\0"
+/*  1189 */ "Extended usage information passed thru pager\0"
+/*  1234 */ "more-help\0"
+/*  1244 */ "Output version information and exit\0"
+/*  1280 */ "version\0"
+/*  1288 */ "TPMTOOL\0"
+/*  1296 */ "tpmtool - GnuTLS TPM tool - Ver. @address@hidden"
             "USAGE:  %s [ -<flag> [<val>] | --<name>[{=| }<val>] ]...\n\0"
-/*  1316 */ "address@hidden"
-/*  1335 */ "\n\n\0"
-/*  1338 */ "\n"
+/*  1397 */ "address@hidden"
+/*  1416 */ "\n\n\0"
+/*  1419 */ "\n"
             "Program that allows handling cryptographic data from the TPM 
chip.\n\0"
-/*  1407 */ "tpmtool @address@hidden"
-/*  1425 */ "tpmtool [options]\n"
+/*  1488 */ "tpmtool @address@hidden"
+/*  1506 */ "tpmtool [options]\n"
             "tpmtool --help for usage instructions.\n";
 
 /*
@@ -123,39 +129,56 @@ static char const tpmtool_opt_strs[1483] =
         | OPTST_SET_ARGTYPE(OPARG_TYPE_NUMERIC))
 
 /*
+ *  infile option description:
+ */
+#define INFILE_DESC      (tpmtool_opt_strs+911)
+#define INFILE_NAME      (tpmtool_opt_strs+922)
+#define INFILE_name      (tpmtool_opt_strs+929)
+#define INFILE_FLAGS     (OPTST_DISABLED \
+        | OPTST_SET_ARGTYPE(OPARG_TYPE_FILE))
+
+/*
  *  outfile option description:
  */
-#define OUTFILE_DESC      (tpmtool_opt_strs+911)
-#define OUTFILE_NAME      (tpmtool_opt_strs+923)
-#define OUTFILE_name      (tpmtool_opt_strs+931)
+#define OUTFILE_DESC      (tpmtool_opt_strs+936)
+#define OUTFILE_NAME      (tpmtool_opt_strs+948)
+#define OUTFILE_name      (tpmtool_opt_strs+956)
 #define OUTFILE_FLAGS     (OPTST_DISABLED \
         | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
 
 /*
  *  generate-rsa option description:
  */
-#define GENERATE_RSA_DESC      (tpmtool_opt_strs+939)
-#define GENERATE_RSA_NAME      (tpmtool_opt_strs+979)
-#define GENERATE_RSA_name      (tpmtool_opt_strs+992)
+#define GENERATE_RSA_DESC      (tpmtool_opt_strs+964)
+#define GENERATE_RSA_NAME      (tpmtool_opt_strs+1004)
+#define GENERATE_RSA_name      (tpmtool_opt_strs+1017)
 #define GENERATE_RSA_FLAGS     (OPTST_DISABLED)
 
 /*
+ *  pubkey option description:
+ */
+#define PUBKEY_DESC      (tpmtool_opt_strs+1030)
+#define PUBKEY_NAME      (tpmtool_opt_strs+1072)
+#define PUBKEY_name      (tpmtool_opt_strs+1079)
+#define PUBKEY_FLAGS     (OPTST_DISABLED)
+
+/*
  *  bits option description:
  */
-#define BITS_DESC      (tpmtool_opt_strs+1005)
-#define BITS_NAME      (tpmtool_opt_strs+1049)
-#define BITS_name      (tpmtool_opt_strs+1054)
+#define BITS_DESC      (tpmtool_opt_strs+1086)
+#define BITS_NAME      (tpmtool_opt_strs+1130)
+#define BITS_name      (tpmtool_opt_strs+1135)
 #define BITS_FLAGS     (OPTST_DISABLED \
         | OPTST_SET_ARGTYPE(OPARG_TYPE_NUMERIC))
 
 /*
  *  Help/More_Help/Version option descriptions:
  */
-#define HELP_DESC       (tpmtool_opt_strs+1059)
-#define HELP_name       (tpmtool_opt_strs+1103)
+#define HELP_DESC       (tpmtool_opt_strs+1140)
+#define HELP_name       (tpmtool_opt_strs+1184)
 #ifdef HAVE_WORKING_FORK
-#define MORE_HELP_DESC  (tpmtool_opt_strs+1108)
-#define MORE_HELP_name  (tpmtool_opt_strs+1153)
+#define MORE_HELP_DESC  (tpmtool_opt_strs+1189)
+#define MORE_HELP_name  (tpmtool_opt_strs+1234)
 #define MORE_HELP_FLAGS (OPTST_IMM | OPTST_NO_INIT)
 #else
 #define MORE_HELP_DESC  NULL
@@ -168,8 +191,8 @@ static char const tpmtool_opt_strs[1483] =
 #  define VER_FLAGS     (OPTST_SET_ARGTYPE(OPARG_TYPE_STRING) | \
                          OPTST_ARG_OPTIONAL | OPTST_IMM | OPTST_NO_INIT)
 #endif
-#define VER_DESC        (tpmtool_opt_strs+1163)
-#define VER_name        (tpmtool_opt_strs+1199)
+#define VER_DESC        (tpmtool_opt_strs+1244)
+#define VER_name        (tpmtool_opt_strs+1280)
 /*
  *  Declare option callback procedures
  */
@@ -179,7 +202,7 @@ extern tOptProc
     optionStackArg,     optionTimeDate,     optionTimeVal,
     optionUnstackArg,   optionVendorOption;
 static tOptProc
-    doOptDebug, doUsageOpt;
+    doOptDebug, doOptInfile, doUsageOpt;
 #define VER_PROC        optionPrintVersion
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
@@ -201,8 +224,20 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ DEBUG_DESC, DEBUG_NAME, DEBUG_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 1, VALUE_OPT_OUTFILE,
-     /* equiv idx, value */ 1, VALUE_OPT_OUTFILE,
+  {  /* entry idx, value */ 1, VALUE_OPT_INFILE,
+     /* equiv idx, value */ 1, VALUE_OPT_INFILE,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ INFILE_FLAGS, 0,
+     /* last opt argumnt */ { NULL }, /* --infile */
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ doOptInfile,
+     /* desc, NAME, name */ INFILE_DESC, INFILE_NAME, INFILE_name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 2, VALUE_OPT_OUTFILE,
+     /* equiv idx, value */ 2, VALUE_OPT_OUTFILE,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ OUTFILE_FLAGS, 0,
@@ -213,8 +248,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ OUTFILE_DESC, OUTFILE_NAME, OUTFILE_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 2, VALUE_OPT_GENERATE_RSA,
-     /* equiv idx, value */ 2, VALUE_OPT_GENERATE_RSA,
+  {  /* entry idx, value */ 3, VALUE_OPT_GENERATE_RSA,
+     /* equiv idx, value */ 3, VALUE_OPT_GENERATE_RSA,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ GENERATE_RSA_FLAGS, 0,
@@ -225,8 +260,20 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ GENERATE_RSA_DESC, GENERATE_RSA_NAME, 
GENERATE_RSA_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 3, VALUE_OPT_BITS,
-     /* equiv idx, value */ 3, VALUE_OPT_BITS,
+  {  /* entry idx, value */ 4, VALUE_OPT_PUBKEY,
+     /* equiv idx, value */ 4, VALUE_OPT_PUBKEY,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ PUBKEY_FLAGS, 0,
+     /* last opt argumnt */ { NULL }, /* --pubkey */
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ PUBKEY_DESC, PUBKEY_NAME, PUBKEY_name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 5, VALUE_OPT_BITS,
+     /* equiv idx, value */ 5, VALUE_OPT_BITS,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ BITS_FLAGS, 0,
@@ -281,14 +328,14 @@ static tOptDesc optDesc[OPTION_CT] = {
  *
  *  Define the tpmtool Option Environment
  */
-#define zPROGNAME       (tpmtool_opt_strs+1207)
-#define zUsageTitle     (tpmtool_opt_strs+1215)
+#define zPROGNAME       (tpmtool_opt_strs+1288)
+#define zUsageTitle     (tpmtool_opt_strs+1296)
 #define zRcName         NULL
 #define apzHomeList     NULL
-#define zBugsAddr       (tpmtool_opt_strs+1316)
-#define zExplain        (tpmtool_opt_strs+1335)
-#define zDetail         (tpmtool_opt_strs+1338)
-#define zFullVersion    (tpmtool_opt_strs+1407)
+#define zBugsAddr       (tpmtool_opt_strs+1397)
+#define zExplain        (tpmtool_opt_strs+1416)
+#define zDetail         (tpmtool_opt_strs+1419)
+#define zFullVersion    (tpmtool_opt_strs+1488)
 /* extracted from optcode.tlib near line 350 */
 
 #if defined(ENABLE_NLS)
@@ -302,7 +349,7 @@ static tOptDesc optDesc[OPTION_CT] = {
 
 #define tpmtool_full_usage (NULL)
 
-#define tpmtool_short_usage (tpmtool_opt_strs+1425)
+#define tpmtool_short_usage (tpmtool_opt_strs+1506)
 
 #endif /* not defined __doxygen__ */
 
@@ -360,6 +407,27 @@ emit_ranges:
 
     optionShowRange(pOptions, pOptDesc, (void *)rng, 1);
 }
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+/**
+ * Code to handle the infile option.
+ *
+ * @param pOptions the tpmtool options data structure
+ * @param pOptDesc the option descriptor for this option.
+ */
+static void
+doOptInfile(tOptions* pOptions, tOptDesc* pOptDesc)
+{
+    static teOptFileType const  type =
+        FTYPE_MODE_MUST_EXIST + FTYPE_MODE_NO_OPEN;
+    static tuFileMode           mode;
+#ifndef O_CLOEXEC
+#  define O_CLOEXEC 0
+#endif
+    mode.file_flags = O_CLOEXEC;
+
+    optionFileCheck(pOptions, pOptDesc, type, mode);
+}
 /* extracted from optmain.tlib near line 1113 */
 
 /**
@@ -423,7 +491,7 @@ tOptions tpmtoolOptions = {
       NO_EQUIVALENT, /* '-#' option index */
       NO_EQUIVALENT /* index of default opt */
     },
-    7 /* full option count */, 4 /* user option count */,
+    9 /* full option count */, 6 /* user option count */,
     tpmtool_full_usage, tpmtool_short_usage,
     NULL, NULL,
     PKGDATADIR, tpmtool_packager_info
diff --git a/src/tpmtool-args.def b/src/tpmtool-args.def
index a72a921..e933dcf 100644
--- a/src/tpmtool-args.def
+++ b/src/tpmtool-args.def
@@ -7,6 +7,7 @@ short-usage   = "tpmtool [options]\ntpmtool --help for usage 
instructions.\n";
 explain       = "";
 
 #define  OUTFILE_OPT   1
+#define  INFILE_OPT   1
 #include args-std.def
 
 flag = {
@@ -16,6 +17,12 @@ flag = {
 };
 
 flag = {
+    name      = pubkey;
+    descrip   = "Prints the public key of the provided key";
+    doc = "";
+};
+
+flag = {
     name      = bits;
     arg-type  = number;
     descrip   = "Specify the number of bits for key generate";
@@ -36,7 +43,12 @@ doc-section = {
   ds-text   = <<-_EOT_
 To generate a public key use:
 @example
-$ tpmtool --generate-rsa --bits 1024
+$ tpmtool --generate-rsa --bits 1024 --outfile tpmkey.pem
address@hidden example
+
+To get the public key of a TPM key use:
address@hidden
+$ tpmtool --pubkey --infile tpmkey.tpm --outfile pubkey.pem
 @end example
 _EOT_;
 };
diff --git a/src/tpmtool-args.h b/src/tpmtool-args.h
index 134e364..e9f7a58 100644
--- a/src/tpmtool-args.h
+++ b/src/tpmtool-args.h
@@ -2,7 +2,7 @@
  *  
  *  DO NOT EDIT THIS FILE   (tpmtool-args.h)
  *  
- *  It has been AutoGen-ed  July  6, 2012 at 10:34:04 PM by AutoGen 5.16
+ *  It has been AutoGen-ed  July  8, 2012 at 01:42:38 PM by AutoGen 5.16
  *  From the definitions    tpmtool-args.def
  *  and the template file   options
  *
@@ -68,15 +68,17 @@
  */
 typedef enum {
     INDEX_OPT_DEBUG         =  0,
-    INDEX_OPT_OUTFILE       =  1,
-    INDEX_OPT_GENERATE_RSA  =  2,
-    INDEX_OPT_BITS          =  3,
-    INDEX_OPT_VERSION       =  4,
-    INDEX_OPT_HELP          =  5,
-    INDEX_OPT_MORE_HELP     =  6
+    INDEX_OPT_INFILE        =  1,
+    INDEX_OPT_OUTFILE       =  2,
+    INDEX_OPT_GENERATE_RSA  =  3,
+    INDEX_OPT_PUBKEY        =  4,
+    INDEX_OPT_BITS          =  5,
+    INDEX_OPT_VERSION       =  6,
+    INDEX_OPT_HELP          =  7,
+    INDEX_OPT_MORE_HELP     =  8
 } teOptIndex;
 
-#define OPTION_CT    7
+#define OPTION_CT    9
 #define TPMTOOL_VERSION       "@VERSION@"
 #define TPMTOOL_FULL_VERSION  "tpmtool @VERSION@"
 
@@ -117,9 +119,11 @@ typedef enum {
 #define VALUE_OPT_DEBUG          'd'
 
 #define OPT_VALUE_DEBUG          (DESC(DEBUG).optArg.argInt)
-#define VALUE_OPT_OUTFILE        1
-#define VALUE_OPT_GENERATE_RSA   2
-#define VALUE_OPT_BITS           3
+#define VALUE_OPT_INFILE         1
+#define VALUE_OPT_OUTFILE        2
+#define VALUE_OPT_GENERATE_RSA   3
+#define VALUE_OPT_PUBKEY         4
+#define VALUE_OPT_BITS           5
 
 #define OPT_VALUE_BITS           (DESC(BITS).optArg.argInt)
 #define VALUE_OPT_HELP          'h'
diff --git a/src/tpmtool.c b/src/tpmtool.c
index bc26e2c..3370480 100644
--- a/src/tpmtool.c
+++ b/src/tpmtool.c
@@ -51,8 +51,10 @@
 
 static void cmd_parser (int argc, char **argv);
 static void tpm_generate(FILE* outfile, unsigned int key_type, unsigned int 
bits);
+static void tpm_pubkey(FILE* infile, FILE* outfile);
 
 static FILE *outfile;
+static FILE *infile;
 int batch = 0;
 
 static void
@@ -103,6 +105,15 @@ cmd_parser (int argc, char **argv)
   else
     outfile = stdout;
 
+  if (HAVE_OPT(INFILE))
+    {
+      infile = fopen (OPT_ARG(INFILE), "rb");
+      if (infile == NULL)
+        error (EXIT_FAILURE, errno, "%s", OPT_ARG(INFILE));
+    }
+  else
+    infile = stdin;
+
   if (HAVE_OPT(BITS))
     bits = OPT_VALUE_BITS;
   else
@@ -113,6 +124,10 @@ cmd_parser (int argc, char **argv)
       key_type = GNUTLS_PK_RSA;
       tpm_generate (outfile, key_type, bits);
     }
+  else if (HAVE_OPT(PUBKEY))
+    {
+      tpm_pubkey (infile, outfile);
+    }
   else 
     {
       USAGE(1);
@@ -150,4 +165,35 @@ static void tpm_generate(FILE* outfile, unsigned int 
key_type, unsigned int bits
   fwrite (pubkey.data, 1, pubkey.size, outfile);
   fputs ("\n", outfile);
   fwrite (privkey.data, 1, privkey.size, outfile);
+  fputs ("\n", outfile);
+}
+
+static void tpm_pubkey(FILE* infile, FILE* outfile)
+{
+  int ret;
+  char* srk_pass;
+  gnutls_datum_t data;
+  gnutls_pubkey_t pubkey;
+  size_t size;
+  
+  srk_pass = getpass ("Enter SRK password: ");
+  if (srk_pass != NULL)
+    srk_pass = strdup(srk_pass);
+
+  data.data = (void*)fread_file (infile, &size);
+  data.size = size;
+  
+  gnutls_pubkey_init(&pubkey);
+
+  ret = gnutls_pubkey_import_tpm_raw(pubkey, &data, GNUTLS_X509_FMT_PEM,
+                                     srk_pass);
+
+  free(srk_pass);
+
+  if (ret < 0)
+    error (EXIT_FAILURE, 0, "gnutls_pubkey_import_tpm_raw: %s", 
gnutls_strerror (ret));
+
+  _pubkey_info(outfile, pubkey);
+
+  gnutls_pubkey_deinit(pubkey);
 }


hooks/post-receive
-- 
GNU gnutls



reply via email to

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