summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLucas Fisher <lucas.fisher@gmail.com>2012-06-23 17:50:52 -0400
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2012-06-24 20:22:53 +0200
commit451680971317d571b6df8eb284b45655a445a83b (patch)
tree29b71718e91ba436cec5b5ae9c3d1747d34b4496
parent4fcc3470021eebb9faa5955963907d7ec112def7 (diff)
downloadgnutls-451680971317d571b6df8eb284b45655a445a83b.tar.gz
Certtool exports multiple keys in PKCS12 file
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>
-rw-r--r--src/certtool-common.c72
-rw-r--r--src/certtool-common.h2
-rw-r--r--src/certtool.c15
3 files changed, 82 insertions, 7 deletions
diff --git a/src/certtool-common.c b/src/certtool-common.c
index e2fdab9ace..a3fa0c7737 100644
--- a/src/certtool-common.c
+++ b/src/certtool-common.c
@@ -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.
diff --git a/src/certtool-common.h b/src/certtool-common.h
index dbd69e5a09..96bec5bff7 100644
--- a/src/certtool-common.h
+++ b/src/certtool-common.h
@@ -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);
diff --git a/src/certtool.c b/src/certtool.c
index 8876d0918b..62262b7592 100644
--- a/src/certtool.c
+++ b/src/certtool.c
@@ -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;