From 987e3cb9cdd20f212063c5508acdc1710b986947 Mon Sep 17 00:00:00 2001 From: Klas Lindfors Date: Tue, 4 Feb 2014 11:41:55 +0100 Subject: [PATCH] PKCS12 support for import --- cmdline.ggo | 2 +- yubico-piv-tool.c | 42 +++++++++++++++++++++++++++++++++++++----- 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/cmdline.ggo b/cmdline.ggo index ba70f45..4993b8a 100644 --- a/cmdline.ggo +++ b/cmdline.ggo @@ -35,4 +35,4 @@ option "pin-retries" p "Number of retries before the pin code is blocked" int op option "puk-retries" P "Number of retries before the puk code is blocked" int optional option "input" i "Filename to use as input, - for stdin" string optional default="-" option "output" o "Filename to use as output, - for stdout" string optional default="-" -option "key-format" K "Format of the private key being read" values="PEM" enum optional default="PEM" +option "key-format" K "Format of the private key being read" values="PEM","PKCS12" enum optional default="PEM" diff --git a/yubico-piv-tool.c b/yubico-piv-tool.c index 5eb1d40..6a3abcb 100644 --- a/yubico-piv-tool.c +++ b/yubico-piv-tool.c @@ -34,6 +34,7 @@ #include #include +#include #ifdef __APPLE__ #include @@ -348,12 +349,17 @@ static bool set_pin_retries(SCARDHANDLE *card, int pin_retries, int puk_retries, static bool import_key(SCARDHANDLE *card, enum enum_key_format key_format, const char *input_file_name, const char *slot, int verbose) { int key = 0; FILE *input_file; - EVP_PKEY *private_key; + EVP_PKEY *private_key = NULL; + PKCS12 *p12 = NULL; + X509 *cert = NULL; + bool in_stdin = false; + bool ret = true; sscanf(slot, "%x", &key); if(!strcmp(input_file_name, "-")) { input_file = stdin; + in_stdin = true; } else { input_file = fopen(input_file_name, "r"); if(!input_file) { @@ -368,6 +374,17 @@ static bool import_key(SCARDHANDLE *card, enum enum_key_format key_format, const fprintf(stderr, "Failed loading private key for import.\n"); return false; } + } else if(key_format == key_format_arg_PKCS12) { + p12 = d2i_PKCS12_fp(input_file, NULL); + if(!p12) { + fprintf(stderr, "Failed to load PKCS12 from file.\n"); + return false; + } + if(!PKCS12_parse(p12, NULL, &private_key, &cert, NULL)) { + fprintf(stderr, "Failed to parse PKCS12 structure.\n"); + ret = false; + goto import_out; + } } else { /* TODO: more formats go here */ fprintf(stderr, "Unknown key format.\n"); @@ -386,7 +403,8 @@ static bool import_key(SCARDHANDLE *card, enum enum_key_format key_format, const algorithm = 6; } else { fprintf(stderr, "Unuseable key of %d bits, only 1024 and 2048 is supported.\n", size * 8); - return false; + ret = false; + goto import_out; } { APDU apdu; @@ -439,7 +457,8 @@ static bool import_key(SCARDHANDLE *card, enum enum_key_format key_format, const sw = send_data(card, apdu, this_size + 5, data, &recv_len, verbose); if(sw != 0x9000) { fprintf(stderr, "Failed import command with code %x.", sw); - return false; + ret = false; + goto import_out; } in_ptr += this_size; } @@ -448,10 +467,23 @@ static bool import_key(SCARDHANDLE *card, enum enum_key_format key_format, const } else { /* TODO: ECC */ fprintf(stderr, "Unknown type: %d\n", type); - return false; + ret = false; } } - return true; +import_out: + if(private_key) { + EVP_PKEY_free(private_key); + } + if(p12) { + PKCS12_free(p12); + } + if(cert) { + X509_free(cert); + } + if(!in_stdin) { + fclose(input_file); + } + return ret; } static int send_data(SCARDHANDLE *card, APDU apdu, unsigned int send_len, unsigned char *data, unsigned long *recv_len, int verbose) {