From 88ec461bc5b6041e0417df569de74875253f05d3 Mon Sep 17 00:00:00 2001 From: Dirk-Willem van Gulik Date: Tue, 17 Mar 2015 12:42:01 +0100 Subject: [PATCH] tool: RFC4716 compliant key output Add a comment field to the ssh key output if a label is set on the key. Add RFC4716 compliant key output for the new breed of modern (mobile) SSH clients. VTA: use short form of log call in iso7816 --- doc/tools/pkcs15-tool.1.xml | 16 ++++++++++- src/libopensc/iso7816.c | 3 +- src/tools/pkcs15-tool.c | 55 ++++++++++++++++++++++++++++--------- 3 files changed, 58 insertions(+), 16 deletions(-) diff --git a/doc/tools/pkcs15-tool.1.xml b/doc/tools/pkcs15-tool.1.xml index 9c588726..82ad7b91 100644 --- a/doc/tools/pkcs15-tool.1.xml +++ b/doc/tools/pkcs15-tool.1.xml @@ -185,7 +185,21 @@ Reads the public key with id id, writing the output in format suitable for - $HOME/.ssh/authorized_keys. + $HOME/.ssh/authorized_keys. + + The key label, if any will be shown in the 'Comment' field. + + + + + + + When used in conjunction with option the + output format of the public key follows rfc4716. + + + The default output format is a single line (openssh). + diff --git a/src/libopensc/iso7816.c b/src/libopensc/iso7816.c index 5ed0f17d..37abd177 100644 --- a/src/libopensc/iso7816.c +++ b/src/libopensc/iso7816.c @@ -1016,8 +1016,7 @@ iso7816_build_pin_apdu(struct sc_card *card, struct sc_apdu *apdu, * but expect the new one to be entered on the keypad. */ if (data->pin1.len && data->pin2.len == 0) { - sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, - "Special case - initial pin provided - but new pin asked on keypad"); + sc_log(card->ctx, "Special case - initial pin provided - but new pin asked on keypad"); data->flags |= SC_PIN_CMD_IMPLICIT_CHANGE; }; len += r; diff --git a/src/tools/pkcs15-tool.c b/src/tools/pkcs15-tool.c index 409d9847..abc64f43 100644 --- a/src/tools/pkcs15-tool.c +++ b/src/tools/pkcs15-tool.c @@ -57,6 +57,9 @@ static const char * opt_pin = NULL; static const char * opt_puk = NULL; static int verbose = 0; static int opt_no_prompt = 0; +#if defined(ENABLE_OPENSSL) && (defined(_WIN32) || defined(HAVE_INTTYPES_H)) +static int opt_rfc4716 = 0; +#endif enum { OPT_CHANGE_PIN = 0x100, @@ -68,6 +71,7 @@ enum { OPT_READ_PUB, #if defined(ENABLE_OPENSSL) && (defined(_WIN32) || defined(HAVE_INTTYPES_H)) OPT_READ_SSH, + OPT_RFC4716, #endif OPT_PIN, OPT_NEWPIN, @@ -76,7 +80,7 @@ enum { OPT_BIND_TO_AID, OPT_LIST_APPLICATIONS, OPT_LIST_SKEYS, - OPT_NO_PROMPT + OPT_NO_PROMPT, }; #define NELEMENTS(x) (sizeof(x)/sizeof((x)[0])) @@ -100,6 +104,7 @@ static const struct option options[] = { { "read-public-key", required_argument, NULL, OPT_READ_PUB }, #if defined(ENABLE_OPENSSL) && (defined(_WIN32) || defined(HAVE_INTTYPES_H)) { "read-ssh-key", required_argument, NULL, OPT_READ_SSH }, + { "rfc4716", no_argument, NULL, OPT_RFC4716 }, #endif { "test-update", no_argument, NULL, 'T' }, { "update", no_argument, NULL, 'U' }, @@ -786,6 +791,36 @@ static int list_skeys(void) #if defined(ENABLE_OPENSSL) && (defined(_WIN32) || defined(HAVE_INTTYPES_H)) + +static void print_ssh_key(FILE *outf, const char * alg, struct sc_pkcs15_object *obj, unsigned char * buf, uint32_t len) { + unsigned char *uu; + int r; + + uu = malloc(len*2); // Way over - even if we have extra LFs; as each 6 bits take one byte. + + if (opt_rfc4716) { + r = sc_base64_encode(buf, len, uu, 2*len, 64); + + fprintf(outf,"---- BEGIN SSH2 PUBLIC KEY ----\n"); + + if (obj->label && strlen(obj->label)) + fprintf(outf,"Comment: \"%s\"\n", obj->label); + + fprintf(outf,"%s", uu); + fprintf(outf,"---- END SSH2 PUBLIC KEY ----\n"); + } else { + // Old style openssh - [ [ anything else] + // + r = sc_base64_encode(buf, len, uu, 2*len, 0); + if (obj->label && strlen(obj->label)) + fprintf(outf,"ssh-%s %s %s\n", alg, uu, obj->label); + else + fprintf(outf,"ssh-%s %s\n", alg, uu); + } + free(uu); + return; +} + static int read_ssh_key(void) { int r; @@ -844,7 +879,6 @@ static int read_ssh_key(void) if (pubkey->algorithm == SC_ALGORITHM_RSA) { unsigned char buf[2048]; - unsigned char *uu; uint32_t len, n; if (!pubkey->u.rsa.modulus.data || !pubkey->u.rsa.modulus.len || @@ -895,16 +929,11 @@ static int read_ssh_key(void) memcpy(buf+len,pubkey->u.rsa.modulus.data, pubkey->u.rsa.modulus.len); len += pubkey->u.rsa.modulus.len; - uu = malloc(len*2); - r = sc_base64_encode(buf, len, uu, 2*len, 2*len); - - fprintf(outf,"ssh-rsa %s", uu); - free(uu); + print_ssh_key(outf, "rsa", obj, buf, len); } if (pubkey->algorithm == SC_ALGORITHM_DSA) { unsigned char buf[2048]; - unsigned char *uu; uint32_t len; uint32_t n; @@ -991,11 +1020,7 @@ static int read_ssh_key(void) memcpy(buf+len,pubkey->u.dsa.pub.data, pubkey->u.dsa.pub.len); len += pubkey->u.dsa.pub.len; - uu = malloc(len*2); - r = sc_base64_encode(buf, len, uu, 2*len, 2*len); - - fprintf(outf,"ssh-dss %s", uu); - free(uu); + print_ssh_key(outf, "dss", obj, buf, len); } if (outf != stdout) @@ -1016,6 +1041,7 @@ fail2: sc_pkcs15_free_pubkey(pubkey); return SC_ERROR_OUT_OF_MEMORY; } + #endif static sc_pkcs15_object_t * @@ -1900,6 +1926,9 @@ int main(int argc, char * const argv[]) do_read_sshkey = 1; action_count++; break; + case OPT_RFC4716: + opt_rfc4716 = 1; + break; #endif case 'L': do_learn_card = 1;