On 08/27/2011 06:58 PM, Andreas Metzler wrote:

Hello,
I would not be surprised if upstream's response was "don't do this, this
was never supposed to work" but at a quick look I could not find
respective reference in the docs either.

It is a bug introduced in 2.12.x. Does the attached patch
fix the issue?

regards,
Nikos
>From c4a8f333fc118ac454906e6ef056789b4069e4d2 Mon Sep 17 00:00:00 2001
From: Nikos Mavrogiannopoulos <n...@gnutls.org>
Date: Sat, 27 Aug 2011 20:20:43 +0200
Subject: [PATCH] gnutls_certificate_set_x509_key() and
 gnutls_certificate_set_openpgp_key() operate as in gnutls
 2.10.x and do not require to hold the structures.

---
 NEWS                           |   11 +++++++++
 lib/gnutls_privkey.c           |   39 +++++++++++++++++++++++++++++--
 lib/gnutls_x509.c              |    2 +-
 lib/includes/gnutls/abstract.h |    3 +-
 lib/openpgp/gnutls_openpgp.c   |    3 +-
 lib/openpgp/gnutls_openpgp.h   |    3 ++
 lib/openpgp/privkey.c          |   49 ++++++++++++++++++++++++++++++++++++++++
 lib/x509/x509.c                |    3 +-
 8 files changed, 105 insertions(+), 8 deletions(-)

diff --git a/NEWS b/NEWS
index 66a1151..cfa076b 100644
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,17 @@ Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005,
               2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
 See the end for copying conditions.
 
+* Version 2.12.10 (unreleased)
+
+** libgnutls: gnutls_certificate_set_x509_key() and
+gnutls_certificate_set_openpgp_key() operate as in 2.10.x
+and allow the release of the private key during the
+lifetime of the certificate structure.
+
+** API and ABI modifications:
+GNUTLS_PRIVKEY_IMPORT_COPY: new gnutls_privkey_import() flag
+
+
 * Version 2.12.9 (released 2011-08-21)
 
 ** libgnutls-extra: Replaced enumeration with unsigned
diff --git a/lib/gnutls_privkey.c b/lib/gnutls_privkey.c
index 499640e..f61524f 100644
--- a/lib/gnutls_privkey.c
+++ b/lib/gnutls_privkey.c
@@ -271,7 +271,7 @@ gnutls_privkey_deinit (gnutls_privkey_t key)
 {
   if (key == NULL) return;
 
-  if (key->flags & GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE)
+  if (key->flags & GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE || key->flags & GNUTLS_PRIVKEY_IMPORT_COPY)
     switch (key->type)
       {
 #ifdef ENABLE_OPENPGP
@@ -331,6 +331,9 @@ int ret;
       return ret;
     }
 
+  if (flags & GNUTLS_PRIVKEY_IMPORT_COPY)
+    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
   pkey->key.pkcs11 = key;
   pkey->type = GNUTLS_PRIVKEY_PKCS11;
   pkey->pk_algorithm = gnutls_pkcs11_privkey_get_pk_algorithm (key, NULL);
@@ -369,7 +372,22 @@ int ret;
       return ret;
     }
 
-  pkey->key.x509 = key;
+  if (flags & GNUTLS_PRIVKEY_IMPORT_COPY)
+    {
+      ret = gnutls_x509_privkey_init(&pkey->key.x509);
+      if (ret < 0)
+        return gnutls_assert_val(ret);
+      
+      ret = gnutls_x509_privkey_cpy(pkey->key.x509, key);
+      if (ret < 0)
+        {
+          gnutls_x509_privkey_deinit(pkey->key.x509);
+          return gnutls_assert_val(ret);
+        }
+    }
+  else
+    pkey->key.x509 = key;
+
   pkey->type = GNUTLS_PRIVKEY_X509;
   pkey->pk_algorithm = gnutls_x509_privkey_get_pk_algorithm (key);
   pkey->flags = flags;
@@ -409,7 +427,22 @@ uint8_t keyid[GNUTLS_OPENPGP_KEYID_SIZE];
       return ret;
     }
 
-  pkey->key.openpgp = key;
+  if (flags & GNUTLS_PRIVKEY_IMPORT_COPY)
+    {
+      ret = gnutls_openpgp_privkey_init(&pkey->key.openpgp);
+      if (ret < 0)
+        return gnutls_assert_val(ret);
+      
+      ret = _gnutls_openpgp_privkey_cpy(pkey->key.openpgp, key);
+      if (ret < 0)
+        {
+          gnutls_openpgp_privkey_deinit(pkey->key.openpgp);
+          return gnutls_assert_val(ret);
+        }
+    }
+  else
+    pkey->key.openpgp = key;
+
   pkey->type = GNUTLS_PRIVKEY_OPENPGP;
   
   ret = gnutls_openpgp_privkey_get_preferred_key_id (key, keyid);
diff --git a/lib/gnutls_x509.c b/lib/gnutls_x509.c
index 9b74ef5..6f73c44 100644
--- a/lib/gnutls_x509.c
+++ b/lib/gnutls_x509.c
@@ -969,7 +969,7 @@ gnutls_certificate_set_x509_key (gnutls_certificate_credentials_t res,
       return ret;
     }
 
-  ret = gnutls_privkey_import_x509 (pkey, key, 0);
+  ret = gnutls_privkey_import_x509 (pkey, key, GNUTLS_PRIVKEY_IMPORT_COPY);
   if (ret < 0)
     {
       gnutls_assert ();
diff --git a/lib/includes/gnutls/abstract.h b/lib/includes/gnutls/abstract.h
index 73266df..0e2c226 100644
--- a/lib/includes/gnutls/abstract.h
+++ b/lib/includes/gnutls/abstract.h
@@ -101,7 +101,8 @@ gnutls_privkey_get_preferred_hash_algorithm (gnutls_privkey_t key,
 gnutls_privkey_type_t gnutls_privkey_get_type (gnutls_privkey_t key);
 
 
-#define GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE 1
+#define GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE (1<<0)
+#define GNUTLS_PRIVKEY_IMPORT_COPY (1<<1)
 int gnutls_privkey_import_pkcs11 (gnutls_privkey_t pkey,
                                   gnutls_pkcs11_privkey_t key,
                                   unsigned int flags);
diff --git a/lib/openpgp/gnutls_openpgp.c b/lib/openpgp/gnutls_openpgp.c
index 5e13fd4..9cff120 100644
--- a/lib/openpgp/gnutls_openpgp.c
+++ b/lib/openpgp/gnutls_openpgp.c
@@ -152,7 +152,7 @@ gnutls_certificate_set_openpgp_key (gnutls_certificate_credentials_t res,
   
   ret =
     gnutls_privkey_import_openpgp (privkey, pkey,
-                                   GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE);
+                                   GNUTLS_PRIVKEY_IMPORT_COPY);
   if (ret < 0)
     {
       gnutls_privkey_deinit (privkey);
@@ -431,6 +431,7 @@ gnutls_certificate_set_openpgp_key_mem2 (gnutls_certificate_credentials_t res,
   ret = gnutls_certificate_set_openpgp_key (res, crt, pkey);
 
   gnutls_openpgp_crt_deinit (crt);
+  gnutls_openpgp_privkey_deinit (pkey);
 
   return ret;
 }
diff --git a/lib/openpgp/gnutls_openpgp.h b/lib/openpgp/gnutls_openpgp.h
index 7816fcd..b7add60 100644
--- a/lib/openpgp/gnutls_openpgp.h
+++ b/lib/openpgp/gnutls_openpgp.h
@@ -34,6 +34,9 @@ _gnutls_openpgp_raw_privkey_to_gkey (gnutls_privkey_t * pkey,
                                      const gnutls_datum_t * raw_key);
 
 int
+_gnutls_openpgp_privkey_cpy (gnutls_openpgp_privkey_t dest, gnutls_openpgp_privkey_t src);
+
+int
 _gnutls_openpgp_request_key (gnutls_session_t,
                              gnutls_datum_t * ret,
                              const gnutls_certificate_credentials_t cred,
diff --git a/lib/openpgp/privkey.c b/lib/openpgp/privkey.c
index 0040922..61ae9aa 100644
--- a/lib/openpgp/privkey.c
+++ b/lib/openpgp/privkey.c
@@ -75,6 +75,55 @@ gnutls_openpgp_privkey_deinit (gnutls_openpgp_privkey_t key)
   gnutls_free (key);
 }
 
+/*-
+ * _gnutls_openpgp_privkey_cpy - This function copies a gnutls_openpgp_privkey_t structure
+ * @dest: The structure where to copy
+ * @src: The structure to be copied
+ *
+ * This function will copy an X.509 certificate structure.
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
+ *   negative error value.
+ -*/
+int
+_gnutls_openpgp_privkey_cpy (gnutls_openpgp_privkey_t dest, gnutls_openpgp_privkey_t src)
+{
+  int ret;
+  size_t der_size=0;
+  opaque *der;
+  gnutls_datum_t tmp;
+
+  ret = gnutls_openpgp_privkey_export (src, GNUTLS_OPENPGP_FMT_RAW, NULL, 0, NULL, &der_size);
+  if (ret != GNUTLS_E_SHORT_MEMORY_BUFFER)
+    return gnutls_assert_val(ret);
+
+  der = gnutls_malloc (der_size);
+  if (der == NULL)
+    return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+
+  ret = gnutls_openpgp_privkey_export (src, GNUTLS_OPENPGP_FMT_RAW, NULL, 0, der, &der_size);
+  if (ret < 0)
+    {
+      gnutls_assert ();
+      gnutls_free (der);
+      return ret;
+    }
+
+  tmp.data = der;
+  tmp.size = der_size;
+  ret = gnutls_openpgp_privkey_import (dest, &tmp, GNUTLS_OPENPGP_FMT_RAW, NULL, 0);
+
+  gnutls_free (der);
+
+  if (ret < 0)
+    return gnutls_assert_val(ret);
+
+  memcpy(dest->preferred_keyid, src->preferred_keyid, GNUTLS_OPENPGP_KEYID_SIZE);
+  dest->preferred_set = src->preferred_set;
+
+  return 0;
+}
+
 /**
  * gnutls_openpgp_privkey_sec_param:
  * @key: a key structure
diff --git a/lib/x509/x509.c b/lib/x509/x509.c
index 50a742e..8924ad6 100644
--- a/lib/x509/x509.c
+++ b/lib/x509/x509.c
@@ -84,7 +84,7 @@ int
 _gnutls_x509_crt_cpy (gnutls_x509_crt_t dest, gnutls_x509_crt_t src)
 {
   int ret;
-  size_t der_size;
+  size_t der_size = 0;
   opaque *der;
   gnutls_datum_t tmp;
 
@@ -123,7 +123,6 @@ _gnutls_x509_crt_cpy (gnutls_x509_crt_t dest, gnutls_x509_crt_t src)
     }
 
   return 0;
-
 }
 
 /**
-- 
1.7.5.4

Reply via email to