]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Certtool exports multiple keys in PKCS12 file
authorLucas Fisher <lucas.fisher@gmail.com>
Sat, 23 Jun 2012 21:50:52 +0000 (17:50 -0400)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Sun, 24 Jun 2012 18:22:53 +0000 (20:22 +0200)
Update certtool to export multiple keys in a PKCS12 file so multiple
certificate/key pairs may be included in one file.

- Add load_privkey_list() so that --load-privkey loads multiple keys

- Change generate_pkcs12() to add multiple keys to the PKCS12 file

Signed-off-by: Nikos Mavrogiannopoulos <nmav@gnutls.org>
src/certtool-common.c
src/certtool-common.h
src/certtool.c

index e2fdab9ace99c3da7ed562cbc1333ff4072ed5d0..a3fa0c77370fa3cee08ca8232448ed3b518de27d 100644 (file)
@@ -346,6 +346,78 @@ load_x509_private_key (int mand, common_info_st * info)
   return key;
 }
 
+#define MAX_KEYS 256
+
+/* Loads a x509 private key list
+ */
+gnutls_x509_privkey_t *
+load_privkey_list (int mand, size_t * privkey_size, common_info_st * info)
+{
+  FILE *fd;
+  static gnutls_x509_privkey_t key[MAX_KEYS];
+  char *ptr;
+  int ret, i;
+  gnutls_datum_t dat;
+  size_t size;
+  int ptr_size;
+
+  *privkey_size = 0;
+  fprintf (stderr, "Loading private key list...\n");
+
+  if (info->privkey == NULL)
+    {
+      if (mand)
+        error (EXIT_FAILURE, 0, "missing --load-privkey");
+      else
+        return NULL;
+    }
+
+  fd = fopen (info->privkey, "r");
+  if (fd == NULL)
+    error (EXIT_FAILURE, errno, "%s", info->privkey);
+
+  size = fread (buffer, 1, sizeof (buffer) - 1, fd);
+  buffer[size] = 0;
+
+  fclose (fd);
+
+  ptr = (void*)buffer;
+  ptr_size = size;
+
+  for (i = 0; i < MAX_KEYS; i++)
+    {
+      ret = gnutls_x509_privkey_init (&key[i]);
+      if (ret < 0)
+        error (EXIT_FAILURE, 0, "privkey_init: %s", gnutls_strerror (ret));
+
+      dat.data = (void*)ptr;
+      dat.size = ptr_size;
+
+      ret = gnutls_x509_privkey_import (key[i], &dat, info->incert_format);
+      if (ret < 0 && *privkey_size > 0)
+        break;
+      if (ret < 0)
+        error (EXIT_FAILURE, 0, "privkey_import: %s", gnutls_strerror (ret));
+
+      ptr = strstr (ptr, "---END");
+      if (ptr == NULL)
+        break;
+      ptr++;
+
+      ptr_size = size;
+      ptr_size -=
+        (unsigned int) ((unsigned char *) ptr - (unsigned char *) buffer);
+
+      if (ptr_size < 0)
+        break;
+
+      (*privkey_size)++;
+    }
+  fprintf (stderr, "Loaded %d private keys.\n", (int) *privkey_size);
+
+  return key;
+}
+
 /* Loads the certificate
  * If mand is non zero then a certificate is mandatory. Otherwise
  * null will be returned if the certificate loading fails.
index dbd69e5a09e3dca855da6b0438e07807a66d2741..96bec5bff768fe93b7e57fe6c19350ecffd843a1 100644 (file)
@@ -55,6 +55,8 @@ typedef struct common_info
 gnutls_pubkey_t load_public_key_or_import(int mand, gnutls_privkey_t privkey, common_info_st * info);
 gnutls_privkey_t load_private_key (int mand, common_info_st * info);
 gnutls_x509_privkey_t load_x509_private_key (int mand, common_info_st * info);
+gnutls_x509_privkey_t *load_privkey_list (int mand, size_t * privkey_size,
+                                           common_info_st * info);
 gnutls_x509_crq_t load_request (common_info_st * info);
 gnutls_privkey_t load_ca_private_key (common_info_st * info);
 gnutls_x509_crt_t load_ca_cert (common_info_st * info);
index 8876d0918beb728e2f101d95a36eed3fa7b60222..62262b759207a4fe228fedd009bc2bb1b9425544 100644 (file)
@@ -2406,7 +2406,7 @@ generate_pkcs12 (common_info_st * cinfo)
 {
   gnutls_pkcs12_t pkcs12;
   gnutls_x509_crt_t *crts;
-  gnutls_x509_privkey_t key;
+  gnutls_x509_privkey_t *keys;
   int result;
   size_t size;
   gnutls_datum_t data;
@@ -2417,10 +2417,11 @@ generate_pkcs12 (common_info_st * cinfo)
   unsigned char _key_id[32];
   int indx;
   size_t ncrts;
+  size_t nkeys;
 
   fprintf (stderr, "Generating a PKCS #12 structure...\n");
 
-  key = load_x509_private_key (0, cinfo);
+  keys = load_privkey_list (0, &nkeys, cinfo);
   crts = load_cert_list (0, &ncrts, cinfo);
 
   name = get_pkcs12_key_name ();
@@ -2489,7 +2490,7 @@ generate_pkcs12 (common_info_st * cinfo)
         error (EXIT_FAILURE, 0, "set_bag: %s", gnutls_strerror (result));
     }
 
-  if (key)
+  for (i = 0; i < nkeys; i++)
     {
       gnutls_pkcs12_bag_t kbag;
 
@@ -2501,10 +2502,10 @@ generate_pkcs12 (common_info_st * cinfo)
 
       size = buffer_size;
       result =
-        gnutls_x509_privkey_export_pkcs8 (key, GNUTLS_X509_FMT_DER,
+        gnutls_x509_privkey_export_pkcs8 (keys[i], GNUTLS_X509_FMT_DER,
                                           pass, flags, buffer, &size);
       if (result < 0)
-        error (EXIT_FAILURE, 0, "key_export: %s", gnutls_strerror (result));
+        error (EXIT_FAILURE, 0, "key_export[%d]: %s", i, gnutls_strerror (result));
 
       data.data = buffer;
       data.size = size;
@@ -2522,9 +2523,9 @@ generate_pkcs12 (common_info_st * cinfo)
                gnutls_strerror (result));
 
       size = sizeof (_key_id);
-      result = gnutls_x509_privkey_get_key_id (key, 0, _key_id, &size);
+      result = gnutls_x509_privkey_get_key_id (keys[i], 0, _key_id, &size);
       if (result < 0)
-        error (EXIT_FAILURE, 0, "key_id: %s", gnutls_strerror (result));
+        error (EXIT_FAILURE, 0, "key_id[%d]: %s", i, gnutls_strerror (result));
 
       key_id.data = _key_id;
       key_id.size = size;