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_18-170-g43d5826


From: Nikos Mavrogiannopoulos
Subject: [SCM] GNU gnutls branch, master, updated. gnutls_3_0_18-170-g43d5826
Date: Thu, 28 Jun 2012 21:25:57 +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=43d5826b171937b9415501a5e227c8ec1d24bc71

The branch, master has been updated
       via  43d5826b171937b9415501a5e227c8ec1d24bc71 (commit)
       via  4e2e8a249e13edc606a72a8c3940ef47184dd24d (commit)
       via  a30f06fb5df93967c971a6ba8ab1b7925c01bfe6 (commit)
       via  0466d1f0afa365cd53643d0617d2d908de582b75 (commit)
      from  98e25bbadadeea2e03bd0d06b6c2812523924ff9 (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 43d5826b171937b9415501a5e227c8ec1d24bc71
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Thu Jun 28 23:25:31 2012 +0200

    Added functions gnutls_x509_privkey_import2 and 
gnutls_x509_privkey_import_openssl.
    
    The former imports keys in arbitrary formats and the latter imports openssl 
keys (unfinished).

commit 4e2e8a249e13edc606a72a8c3940ef47184dd24d
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Thu Jun 28 21:55:10 2012 +0200

    doc fixes

commit a30f06fb5df93967c971a6ba8ab1b7925c01bfe6
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Thu Jun 28 21:49:20 2012 +0200

    document the gnutls_pcert_st

commit 0466d1f0afa365cd53643d0617d2d908de582b75
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Thu Jun 28 21:44:25 2012 +0200

    use new functions.

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

Summary of changes:
 NEWS                          |    2 +
 doc/Makefile.am               |    2 +
 doc/cha-gtls-app.texi         |   22 +++-
 doc/examples/ex-cert-select.c |   71 ++--------
 lib/gnutls_privkey.c          |   21 +---
 lib/includes/gnutls/x509.h    |    9 ++
 lib/libgnutls.map             |    2 +
 lib/x509/Makefile.am          |    1 +
 lib/x509/privkey.c            |   64 +++++++++
 lib/x509/privkey_openssl.c    |  306 +++++++++++++++++++++++++++++++++++++++++
 lib/x509_b64.c                |  119 +++++++++--------
 lib/x509_b64.h                |    4 +
 src/certtool.c                |   15 +--
 13 files changed, 492 insertions(+), 146 deletions(-)
 create mode 100644 lib/x509/privkey_openssl.c

diff --git a/NEWS b/NEWS
index bbb2929..9fb936a 100644
--- a/NEWS
+++ b/NEWS
@@ -46,6 +46,8 @@ GNUTLS_CERT_SIGNATURE_FAILURE: Added
 gnutls_privkey_import_pkcs11_url: Added
 gnutls_privkey_import_openpgp_raw: Added
 gnutls_privkey_import_x509_raw: Added
+gnutls_x509_privkey_import2: Added
+gnutls_x509_privkey_import_openssl: Added
 gnutls_load_file: Added
 gnutls_pubkey_verify_hash2: Added
 gnutls_pkcs12_simple_parse: Added
diff --git a/doc/Makefile.am b/doc/Makefile.am
index 9b04117..174b624 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -1137,6 +1137,8 @@ FUNCS += functions/gnutls_x509_privkey_sec_param
 FUNCS += functions/gnutls_x509_privkey_cpy
 FUNCS += functions/gnutls_x509_privkey_import
 FUNCS += functions/gnutls_x509_privkey_import_pkcs8
+FUNCS += functions/gnutls_x509_privkey_import_openssl
+FUNCS += functions/gnutls_x509_privkey_import2
 FUNCS += functions/gnutls_x509_privkey_import_rsa_raw
 FUNCS += functions/gnutls_x509_privkey_import_rsa_raw2
 FUNCS += functions/gnutls_x509_privkey_import_ecc_raw
diff --git a/doc/cha-gtls-app.texi b/doc/cha-gtls-app.texi
index 52f6126..5a017e2 100644
--- a/doc/cha-gtls-app.texi
+++ b/doc/cha-gtls-app.texi
@@ -413,7 +413,13 @@ already.
 
 
@showfuncC{gnutls_certificate_set_x509_key_mem,gnutls_certificate_set_x509_key,gnutls_certificate_set_x509_key_file}
 
address@hidden,gnutls_certificate_set_openpgp_key,gnutls_certificate_set_openpgp_key_file,gnutls_certificate_set_key}
address@hidden,gnutls_certificate_set_openpgp_key,gnutls_certificate_set_openpgp_key_file}
+
+If the imported keys and certificates need to be accessed before any TLS 
session
+is established, it is convenient to use @funcref{gnutls_certificate_set_key}
+in combination with @funcref{gnutls_pcert_import_x509_raw} and 
@funcref{gnutls_privkey_import_x509_raw}.
+
address@hidden
 
 If multiple certificates are used with the functions above each
 client's request will be served with the certificate that matches the
@@ -430,7 +436,19 @@ algorithm preferences. To get those preferences use
 The functions above do not handle the requested server name automatically.
 A server would need to check the name requested by the client
 using @funcref{gnutls_server_name_get}, and serve the appropriate
-certificate.
+certificate. Note that some of these functions require the 
@code{gnutls_pcert_st} structure to be
+filled in. Helper functions to make the required structures are listed below.
+
address@hidden
+typedef struct gnutls_pcert_st
+{
+  gnutls_pubkey_t pubkey;
+  gnutls_datum_t cert;
+  gnutls_certificate_type_t type;
+} gnutls_pcert_st;
address@hidden verbatim
+
address@hidden,gnutls_pcert_import_openpgp,gnutls_pcert_import_x509_raw,gnutls_pcert_import_openpgp_raw,gnutls_pcert_deinit}
 
 In a handshake, the negotiated cipher suite depends on the
 certificate's parameters, so some key exchange methods might not be
diff --git a/doc/examples/ex-cert-select.c b/doc/examples/ex-cert-select.c
index e99baf4..49dfd8d 100644
--- a/doc/examples/ex-cert-select.c
+++ b/doc/examples/ex-cert-select.c
@@ -38,43 +38,9 @@ cert_callback (gnutls_session_t session,
                int sign_algos_length, gnutls_pcert_st ** pcert,
                unsigned int *pcert_length, gnutls_privkey_t * pkey);
 
-gnutls_pcert_st crt;
+gnutls_pcert_st pcrt;
 gnutls_privkey_t key;
 
-/* Helper functions to load a certificate and key
- * files into memory.
- */
-static gnutls_datum_t
-load_file (const char *file)
-{
-  FILE *f;
-  gnutls_datum_t loaded_file = { NULL, 0 };
-  long filelen;
-  void *ptr;
-
-  if (!(f = fopen (file, "r"))
-      || fseek (f, 0, SEEK_END) != 0
-      || (filelen = ftell (f)) < 0
-      || fseek (f, 0, SEEK_SET) != 0
-      || !(ptr = malloc ((size_t) filelen))
-      || fread (ptr, 1, (size_t) filelen, f) < (size_t) filelen)
-    {
-      if (f)
-        fclose (f);
-      return loaded_file;
-    }
-
-  loaded_file.data = ptr;
-  loaded_file.size = (unsigned int) filelen;
-  return loaded_file;
-}
-
-static void
-unload_file (gnutls_datum_t data)
-{
-  free (data.data);
-}
-
 /* Load the certificate and the private key.
  */
 static void
@@ -82,16 +48,15 @@ load_keys (void)
 {
   int ret;
   gnutls_datum_t data;
-  gnutls_x509_privkey_t x509_key;
 
-  data = load_file (CERT_FILE);
-  if (data.data == NULL)
+  ret = gnutls_load_file (CERT_FILE, &data);
+  if (ret < 0)
     {
       fprintf (stderr, "*** Error loading certificate file.\n");
       exit (1);
     }
 
-  ret = gnutls_pcert_import_x509_raw (&crt, &data, GNUTLS_X509_FMT_PEM, 0);
+  ret = gnutls_pcert_import_x509_raw (&pcrt, &data, GNUTLS_X509_FMT_PEM, 0);
   if (ret < 0)
     {
       fprintf (stderr, "*** Error loading certificate file: %s\n",
@@ -99,38 +64,26 @@ load_keys (void)
       exit (1);
     }
 
-  unload_file (data);
+  gnutls_free(data.data);
 
-  data = load_file (KEY_FILE);
-  if (data.data == NULL)
-    {
-      fprintf (stderr, "*** Error loading key file.\n");
-      exit (1);
-    }
-
-  gnutls_x509_privkey_init (&x509_key);
-
-  ret = gnutls_x509_privkey_import (x509_key, &data, GNUTLS_X509_FMT_PEM);
+  ret = gnutls_load_file (KEY_FILE, &data);
   if (ret < 0)
     {
-      fprintf (stderr, "*** Error loading key file: %s\n",
-               gnutls_strerror (ret));
+      fprintf (stderr, "*** Error loading key file.\n");
       exit (1);
     }
 
   gnutls_privkey_init (&key);
 
-  ret =
-    gnutls_privkey_import_x509 (key, x509_key,
-                                GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE);
+  ret = gnutls_privkey_import_x509_raw (key, &data, GNUTLS_X509_FMT_PEM, NULL);
   if (ret < 0)
     {
-      fprintf (stderr, "*** Error importing key: %s\n",
+      fprintf (stderr, "*** Error loading key file: %s\n",
                gnutls_strerror (ret));
       exit (1);
     }
-
-  unload_file (data);
+    
+  gnutls_free(data.data);
 }
 
 int
@@ -276,7 +229,7 @@ cert_callback (gnutls_session_t session,
   if (type == GNUTLS_CRT_X509)
     {
       *pcert_length = 1;
-      *pcert = &crt;
+      *pcert = &pcrt;
       *pkey = key;
     }
   else
diff --git a/lib/gnutls_privkey.c b/lib/gnutls_privkey.c
index dbca22b..346118d 100644
--- a/lib/gnutls_privkey.c
+++ b/lib/gnutls_privkey.c
@@ -788,24 +788,11 @@ int gnutls_privkey_import_x509_raw (gnutls_privkey_t pkey,
   if (ret < 0)
     return gnutls_assert_val(ret);
 
-  if (password == NULL)
-    {
-      ret = gnutls_x509_privkey_import(xpriv, data, format);
-      if (ret < 0)
-        {
-          gnutls_assert();
-          goto cleanup;
-        }
-    }
-  else
+  ret = gnutls_x509_privkey_import2(xpriv, data, format, password);
+  if (ret < 0)
     {
-      ret = gnutls_x509_privkey_import_pkcs8(xpriv, data, format, password, 0);
-      if (ret < 0)
-        {
-          gnutls_assert();
-          goto cleanup;
-        }
-    
+      gnutls_assert();
+      goto cleanup;
     }
 
   ret = gnutls_privkey_import_x509(pkey, xpriv, 
GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE);
diff --git a/lib/includes/gnutls/x509.h b/lib/includes/gnutls/x509.h
index a772bd3..a1947ff 100644
--- a/lib/includes/gnutls/x509.h
+++ b/lib/includes/gnutls/x509.h
@@ -718,6 +718,15 @@ extern "C"
                                         gnutls_x509_crt_fmt_t format,
                                         const char *password,
                                         unsigned int flags);
+  int gnutls_x509_privkey_import_openssl (gnutls_x509_privkey_t key,
+                                          const gnutls_datum_t *data, 
gnutls_x509_crt_fmt_t format, 
+                                          const char* password);
+
+  int gnutls_x509_privkey_import2 (gnutls_x509_privkey_t key,
+                                   const gnutls_datum_t * data,
+                                   gnutls_x509_crt_fmt_t format,
+                                   const char* password);
+
   int gnutls_x509_privkey_import_rsa_raw (gnutls_x509_privkey_t key,
                                           const gnutls_datum_t * m,
                                           const gnutls_datum_t * e,
diff --git a/lib/libgnutls.map b/lib/libgnutls.map
index c32fc0c..0629bbd 100644
--- a/lib/libgnutls.map
+++ b/lib/libgnutls.map
@@ -802,6 +802,8 @@ GNUTLS_3_1_0 {
        gnutls_privkey_import_x509_raw;
        gnutls_privkey_import_pkcs11_url;
        gnutls_load_file;
+       gnutls_x509_privkey_import_openssl;
+       gnutls_x509_privkey_import2;
 } GNUTLS_3_0_0;
 
 GNUTLS_PRIVATE {
diff --git a/lib/x509/Makefile.am b/lib/x509/Makefile.am
index dff0117..c80fc43 100644
--- a/lib/x509/Makefile.am
+++ b/lib/x509/Makefile.am
@@ -49,6 +49,7 @@ libgnutls_x509_la_SOURCES =   \
        pkcs7.c                 \
        privkey.c               \
        privkey_pkcs8.c         \
+       privkey_openssl.c       \
        rfc2818_hostname.c      \
        sign.c                  \
        verify.c                \
diff --git a/lib/x509/privkey.c b/lib/x509/privkey.c
index b777caa..51981ee 100644
--- a/lib/x509/privkey.c
+++ b/lib/x509/privkey.c
@@ -559,6 +559,70 @@ failover:
 }
 
 /**
+ * gnutls_x509_privkey_import2:
+ * @key: The structure to store the parsed key
+ * @data: The DER or PEM encoded certificate.
+ * @format: One of DER or PEM
+ * @password: A password (optional)
+ *
+ * This function will import the given DER or PEM encoded key, to 
+ * the native #gnutls_x509_privkey_t format, irrespective of the
+ * input format. The input format is auto-detected.
+ *
+ * The supported formats are typical X.509, PKCS #8 and the openssl
+ * format.
+ *
+ * If the provided key is encrypted but no password was given, then
+ * %GNUTLS_E_DECRYPTION_FAILED is returned.
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
+ *   negative error value.
+ **/
+int
+gnutls_x509_privkey_import2 (gnutls_x509_privkey_t key,
+                            const gnutls_datum_t * data,
+                            gnutls_x509_crt_fmt_t format,
+                            const char* password)
+{
+  int ret = 0;
+  
+  if (password == NULL)
+    {
+      ret = gnutls_x509_privkey_import(key, data, format);
+      if (ret < 0)
+        {
+          gnutls_assert();
+        }
+    }
+  
+  if (password != NULL || ret < 0)
+    {
+      ret = gnutls_x509_privkey_import_pkcs8(key, data, format, password, 0);
+      if (ret < 0)
+        {
+          if (format == GNUTLS_X509_FMT_PEM)
+            {
+              int err;
+              err = gnutls_x509_privkey_import_openssl(key, data, format, 
password);
+              if (err < 0)
+                {
+                  if (err == GNUTLS_E_DECRYPTION_FAILED) ret = err;
+                  gnutls_assert();
+                  goto cleanup;
+                }
+            }
+        }
+    
+    }
+
+  ret = 0;
+
+cleanup:  
+  return ret;
+}
+
+
+/**
  * gnutls_x509_privkey_import_rsa_raw:
  * @key: The structure to store the parsed key
  * @m: holds the modulus
diff --git a/lib/x509/privkey_openssl.c b/lib/x509/privkey_openssl.c
new file mode 100644
index 0000000..bbff8b2
--- /dev/null
+++ b/lib/x509/privkey_openssl.c
@@ -0,0 +1,306 @@
+/*
+ * Copyright (C) 2012 Free Software Foundation, Inc.
+ *
+ * Author: David Woodhouse
+ *
+ * This file is part of GnuTLS.
+ *
+ * The GnuTLS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 3 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include <gnutls_int.h>
+
+#include <gnutls_datum.h>
+#include <gnutls_global.h>
+#include <gnutls_errors.h>
+#include <gnutls_rsa_export.h>
+#include <common.h>
+#include <gnutls_x509.h>
+#include <x509_b64.h>
+#include "x509_int.h"
+#include <algorithms.h>
+#include <gnutls_num.h>
+#include <random.h>
+#include <pbkdf2-sha1.h>
+
+static int
+openssl_hash_password (const char *pass, gnutls_datum_t * key, gnutls_datum_t 
* salt)
+{
+  unsigned char md5[16];
+  gnutls_hash_hd_t hash;
+  unsigned int count = 0;
+  int err;
+
+  while (count < key->size)
+    {
+      err = gnutls_hash_init (&hash, GNUTLS_DIG_MD5);
+      if (err)
+        {
+          gnutls_assert ();
+          return err;
+        }
+      if (count)
+        {
+          err = gnutls_hash (hash, md5, sizeof (md5));
+          if (err)
+            {
+            hash_err:
+              gnutls_hash_deinit (hash, NULL);
+              gnutls_assert();
+              return err;
+            }
+        }
+      if (pass)
+        {
+          err = gnutls_hash (hash, pass, strlen (pass));
+          if (err)
+            goto hash_err;
+        }
+      err = gnutls_hash (hash, salt->data, salt->size);
+      if (err)
+        goto hash_err;
+
+      gnutls_hash_deinit (hash, md5);
+
+      if (key->size - count <= sizeof (md5))
+        {
+          memcpy (&key->data[count], md5, key->size - count);
+          break;
+        }
+
+      memcpy (&key->data[count], md5, sizeof (md5));
+      count += sizeof (md5);
+    }
+
+  return 0;
+}
+
+/**
+ * gnutls_x509_privkey_import_openssl:
+ * @key: The structure to store the parsed key
+ * @data: The DER or PEM encoded key.
+ * @format: Only PEM is supported
+ * @password: the password to decrypt the key (if it is encrypted).
+ *
+ * This function will convert the given PEM encrypted to 
+ * the native gnutls_x509_privkey_t format. The
+ * output will be stored in @key.  
+ *
+ * The @password should be in ASCII.
+ *
+ * If the Certificate is PEM encoded it should have a header of
+ * "PRIVATE KEY" and the "DEK-Info" header. 
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
+ *   negative error value.
+ **/
+int
+gnutls_x509_privkey_import_openssl (gnutls_x509_privkey_t key,
+                                    const gnutls_datum_t *data, 
gnutls_x509_crt_fmt_t format, const char* password)
+{
+  gnutls_cipher_hd_t handle;
+  gnutls_cipher_algorithm_t cipher;
+  gnutls_datum_t b64_data;
+  gnutls_datum_t salt, enc_key;
+  unsigned char *key_data;
+  const char *pem_header = (void*)data->data;
+  int ret, err;
+  unsigned int i, iv_size;
+
+  pem_header = memmem(pem_header, data->size, "DEK-Info: ", 10);
+  if (pem_header == NULL)
+    {
+      gnutls_assert();
+      return GNUTLS_E_PARSING_ERROR;
+    }
+  
+  pem_header += 10;
+
+  if (!strncmp (pem_header, "DES-EDE3-CBC,", 13))
+    {
+      pem_header += 13;
+      cipher = GNUTLS_CIPHER_3DES_CBC;
+    }
+  else if (!strncmp (pem_header, "AES-128-CBC,", 12))
+    {
+      pem_header += 12;
+      cipher = GNUTLS_CIPHER_AES_128_CBC;
+    }
+  else if (!strncmp (pem_header, "AES-256-CBC,", 12))
+    {
+      pem_header += 12;
+      cipher = GNUTLS_CIPHER_AES_256_CBC;
+    }
+  else
+    {
+      _gnutls_debug_log ("Unsupported PEM encryption type: %.10s\n", 
pem_header);
+      gnutls_assert();
+      return GNUTLS_E_INVALID_REQUEST;
+    }
+
+  iv_size = _gnutls_cipher_get_iv_size(cipher);
+  salt.size = iv_size;
+  salt.data = gnutls_malloc (salt.size);
+  if (!salt.data)
+    return GNUTLS_E_MEMORY_ERROR;
+    
+  for (i = 0; i < salt.size * 2; i++)
+    {
+      unsigned char x;
+      const char *c = &pem_header[i];
+
+      if (*c >= '0' && *c <= '9')
+        x = (*c) - '0';
+      else if (*c >= 'A' && *c <= 'F')
+        x = (*c) - 'A' + 10;
+      else
+        {
+          gnutls_assert();
+          /* Invalid salt in encrypted PEM file */
+          ret = GNUTLS_E_INVALID_REQUEST;
+          goto out_salt;
+        }
+      if (i & 1)
+        salt.data[i / 2] |= x;
+      else
+        salt.data[i / 2] = x << 4;
+    }
+
+  pem_header += salt.size * 2;
+  if (*pem_header != '\r' && *pem_header != '\n')
+    {
+      gnutls_assert();
+      ret = GNUTLS_E_INVALID_REQUEST;
+      goto out_salt;
+    }
+  while (*pem_header == '\n' || *pem_header == '\r')
+    pem_header++;
+
+  ret = _gnutls_base64_decode((const void*)pem_header, data->size, &b64_data);
+  if (ret < 0)
+    {
+      gnutls_assert();
+      goto out_salt;
+    }
+
+  if (b64_data.size < 16)
+    {
+      /* Just to be sure our parsing is OK */
+      gnutls_assert();
+      ret = GNUTLS_E_PARSING_ERROR;
+      goto out_b64;
+    }
+
+  ret = GNUTLS_E_MEMORY_ERROR;
+  enc_key.size = gnutls_cipher_get_key_size (cipher);
+  enc_key.data = gnutls_malloc (enc_key.size);
+  if (!enc_key.data)
+    goto out_b64;
+
+  key_data = gnutls_malloc (b64_data.size);
+  if (!key_data)
+    goto out_enc_key;
+
+  while (1)
+    {
+      memcpy (key_data, b64_data.data, b64_data.size);
+
+      ret = openssl_hash_password (password, &enc_key, &salt);
+      if (ret)
+        goto out;
+
+      err = gnutls_cipher_init (&handle, cipher, &enc_key, &salt);
+      if (err)
+        {
+          gnutls_assert();
+          gnutls_cipher_deinit (handle);
+          ret = err;
+          goto out;
+        }
+
+      err = gnutls_cipher_decrypt (handle, key_data, b64_data.size);
+      gnutls_cipher_deinit (handle);
+      if (err)
+        {
+          gnutls_assert();
+          ret = -err;
+          goto out;
+        }
+
+      /* We have to strip any padding for GnuTLS to accept it.
+         So a bit more ASN.1 parsing for us.
+         FIXME: Consolidate with similar code in gnutls_tpm.c */
+      if (key_data[0] == 0x30)
+        {
+          gnutls_datum_t key_datum;
+          unsigned int blocksize = gnutls_cipher_get_block_size (cipher);
+          unsigned int keylen = key_data[1];
+          unsigned int ofs = 2;
+
+          if (keylen & 0x80)
+            {
+              int lenlen = keylen & 0x7f;
+              keylen = 0;
+
+              if (lenlen > 3)
+                goto fail;
+
+              while (lenlen)
+                {
+                  keylen <<= 8;
+                  keylen |= key_data[ofs++];
+                  lenlen--;
+                }
+            }
+          keylen += ofs;
+
+          /* If there appears to be more padding than required, fail */
+          if (b64_data.size - keylen >= blocksize)
+            goto fail;
+
+          /* If the padding bytes aren't all equal to the amount of padding, 
fail */
+          ofs = keylen;
+          while (ofs < b64_data.size)
+            {
+              if (key_data[ofs] != b64_data.size - keylen)
+                goto fail;
+              ofs++;
+            }
+
+          key_datum.data = key_data;
+          key_datum.size = keylen;
+          err =
+              gnutls_x509_privkey_import (key, &key_datum,
+                                          GNUTLS_X509_FMT_DER);
+          if (!err)
+            {
+              ret = 0;
+              goto out;
+            }
+        }
+    fail:
+      ret = GNUTLS_E_DECRYPTION_FAILED;
+      goto out;
+    }
+out:
+  gnutls_free (key_data);
+out_enc_key:
+  gnutls_free (enc_key.data);
+out_b64:
+  gnutls_free (b64_data.data);
+out_salt:
+  gnutls_free (salt.data);
+  return ret;
+}
diff --git a/lib/x509_b64.c b/lib/x509_b64.c
index 6cb10c6..2b72ae8 100644
--- a/lib/x509_b64.c
+++ b/lib/x509_b64.c
@@ -195,69 +195,91 @@ gnutls_pem_base64_encode_alloc (const char *msg,
   return 0;
 }
 
+/* copies data to result but removes newlines and <CR>
+ * returns the size of the data copied.
+ */
+inline static int
+cpydata (const uint8_t * data, int data_size, gnutls_datum_t *result)
+{
+  int i, j;
+
+  result->data = gnutls_malloc (data_size);
+  if (result->data == NULL)
+    return GNUTLS_E_MEMORY_ERROR;
+
+  for (j = i = 0; i < data_size; i++)
+    {
+      if (data[i] == '\n' || data[i] == '\r' || data[i] == ' '
+          || data[i] == '\t')
+        continue;
+      else if (data[i] == '-') break;
+      result->data[j] = data[i];
+      j++;
+    }
+  
+  result->size = j;
+  result->data[j] = 0;
+  return j;
+}
 
 /* decodes data and puts the result into result (locally allocated)
  * The result_size is the return value
  */
-static int
+int
 _gnutls_base64_decode (const uint8_t * data, size_t data_size,
-                       uint8_t ** result)
+                       gnutls_datum_t * result)
 {
   unsigned int i;
-  int pos, tmp, est;
+  int pos, tmp, est, ret;
   uint8_t tmpres[48];
   size_t tmpres_size, decode_size;
+  gnutls_datum_t pdata;
+
+  ret = cpydata(data, data_size, &pdata);
+  if (ret < 0)
+    {
+      gnutls_assert();
+      return ret;
+    }
 
   est = ((data_size * 3) / 4) + 1;
-  (*result) = gnutls_malloc (est);
-  if ((*result) == NULL)
-    return GNUTLS_E_MEMORY_ERROR;
+  
+  result->data = gnutls_malloc (est);
+  if (result->data == NULL)
+    return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+
 
   pos = 0;
-  for (i = 0; i < data_size; i += 64)
+  for (i = 0; i < pdata.size; i += 64)
     {
-      if (data_size - i < 64)
-        decode_size = data_size - i;
+      if (pdata.size - i < 64)
+        decode_size = pdata.size - i;
       else
         decode_size = 64;
     
       tmpres_size = sizeof(tmpres);
-      tmp = base64_decode ((void*)&data[i], decode_size, (void*)tmpres, 
&tmpres_size);
+      tmp = base64_decode ((void*)&pdata.data[i], decode_size, (void*)tmpres, 
&tmpres_size);
       if (tmp == 0)
         {
-          gnutls_free (*result);
-          *result = NULL;
-          return tmp;
+          gnutls_assert();
+          gnutls_free (result->data);
+          result->data = NULL;
+          ret = GNUTLS_E_PARSING_ERROR;
+          goto cleanup;
         }
-      memcpy (&(*result)[pos], tmpres, tmpres_size);
+      memcpy (&(result->data)[pos], tmpres, tmpres_size);
       pos += tmpres_size;
     }
-  return pos;
-}
-
-/* copies data to result but removes newlines and <CR>
- * returns the size of the data copied.
- */
-inline static int
-cpydata (const uint8_t * data, int data_size, uint8_t ** result)
-{
-  int i, j;
 
-  (*result) = gnutls_malloc (data_size);
-  if (*result == NULL)
-    return GNUTLS_E_MEMORY_ERROR;
+  result->size = pos;
+  ret = pos;
 
-  for (j = i = 0; i < data_size; i++)
-    {
-      if (data[i] == '\n' || data[i] == '\r' || data[i] == ' '
-          || data[i] == '\t')
-        continue;
-      (*result)[j] = data[i];
-      j++;
-    }
-  return j;
+cleanup:
+  gnutls_free (pdata.data);
+  return ret;
 }
 
+
 /* Searches the given string for ONE PEM encoded certificate, and
  * stores it in the result.
  *
@@ -271,10 +293,9 @@ _gnutls_fbase64_decode (const char *header, const uint8_t 
* data,
   int ret;
   static const char top[] = "-----BEGIN ";
   static const char bottom[] = "-----END ";
-  uint8_t *rdata;
+  gnutls_datum_t res;
+  uint8_t *rdata, *kdata;
   int rdata_size;
-  uint8_t *kdata;
-  int kdata_size;
   char pem_header[128];
 
   _gnutls_str_cpy (pem_header, sizeof (pem_header), top);
@@ -331,28 +352,12 @@ _gnutls_fbase64_decode (const char *header, const uint8_t 
* data,
       return GNUTLS_E_BASE64_DECODING_ERROR;
     }
 
-  kdata_size = cpydata (rdata, rdata_size, &kdata);
-
-  if (kdata_size < 0)
-    {
-      gnutls_assert ();
-      return kdata_size;
-    }
-
-  if (kdata_size < 4)
-    {
-      gnutls_assert ();
-      gnutls_free (kdata);
-      return GNUTLS_E_BASE64_DECODING_ERROR;
-    }
-
-  if ((ret = _gnutls_base64_decode (kdata, kdata_size, result)) < 0)
+  if ((ret = _gnutls_base64_decode (rdata, rdata_size, &res)) < 0)
     {
-      gnutls_free (kdata);
       gnutls_assert ();
       return GNUTLS_E_BASE64_DECODING_ERROR;
     }
-  gnutls_free (kdata);
+  *result = res.data;
 
   return ret;
 }
diff --git a/lib/x509_b64.h b/lib/x509_b64.h
index e2835ed..a30f8f4 100644
--- a/lib/x509_b64.h
+++ b/lib/x509_b64.h
@@ -25,6 +25,10 @@ int _gnutls_fbase64_encode (const char *msg, const uint8_t * 
data,
 int _gnutls_fbase64_decode (const char *header, const uint8_t * data,
                             size_t data_size, uint8_t ** result);
 
+int
+_gnutls_base64_decode (const uint8_t * data, size_t data_size,
+                       gnutls_datum_t * result);
+
 #define B64SIZE( data_size) 
((data_size%3==0)?((data_size*4)/3):(4+((data_size/3)*4)))
 
 /* The size for B64 encoding + newlines plus header
diff --git a/src/certtool.c b/src/certtool.c
index 62262b7..8d3e393 100644
--- a/src/certtool.c
+++ b/src/certtool.c
@@ -1775,26 +1775,19 @@ privkey_info (common_info_st* cinfo)
   pem.data = buffer;
   pem.size = size;
 
-  ret = 0;
-  if (!cinfo->pkcs8)
-    ret = gnutls_x509_privkey_import (key, &pem, incert_format);
+  ret = gnutls_x509_privkey_import2 (key, &pem, incert_format, NULL);
 
   /* If we failed to import the certificate previously try PKCS #8 */
-  if (cinfo->pkcs8 || ret == GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR)
+  if (ret == GNUTLS_E_DECRYPTION_FAILED)
     {
-      ret = gnutls_x509_privkey_import_pkcs8 (key, &pem,
-                                              incert_format, NULL, 
GNUTLS_PKCS8_PLAIN);
-      if (ret == GNUTLS_E_DECRYPTION_FAILED)
-        {
           fprintf(stderr, "Encrypted structure detected...\n");
           if (cinfo->password)
             pass = cinfo->password;
           else
             pass = get_pass ();
 
-          ret = gnutls_x509_privkey_import_pkcs8 (key, &pem,
-                                                  incert_format, pass, 0);
-        }
+          ret = gnutls_x509_privkey_import2 (key, &pem,
+                                                  incert_format, pass);
     }
   if (ret < 0)
     error (EXIT_FAILURE, 0, "import error: %s", gnutls_strerror (ret));


hooks/post-receive
-- 
GNU gnutls



reply via email to

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