diff options
author | Lucas Fisher <lucas.fisher@gmail.com> | 2012-06-23 17:50:52 -0400 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2012-06-24 20:22:53 +0200 |
commit | 451680971317d571b6df8eb284b45655a445a83b (patch) | |
tree | 29b71718e91ba436cec5b5ae9c3d1747d34b4496 | |
parent | 4fcc3470021eebb9faa5955963907d7ec112def7 (diff) | |
download | gnutls-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.c | 72 | ||||
-rw-r--r-- | src/certtool-common.h | 2 | ||||
-rw-r--r-- | src/certtool.c | 15 |
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; |