From a4ee5725b862544f9469119067a42bdcc667010c Mon Sep 17 00:00:00 2001 From: Klas Lindfors Date: Mon, 14 Dec 2015 10:55:32 +0100 Subject: [PATCH] add generic write and read object actions for the tool this take in/out hex dump of the data --- tool/cmdline.ggo | 4 +- tool/yubico-piv-tool.c | 95 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+), 1 deletion(-) diff --git a/tool/cmdline.ggo b/tool/cmdline.ggo index 5252868..33b968b 100644 --- a/tool/cmdline.ggo +++ b/tool/cmdline.ggo @@ -32,7 +32,8 @@ option "action" a "Action to take" values="version","generate","set-mgm-key", "reset","pin-retries","import-key","import-certificate","set-chuid", "request-certificate","verify-pin","change-pin","change-puk","unblock-pin", "selfsign-certificate","delete-certificate","read-certificate","status", - "test-signature","test-decipher","list-readers","set-ccc" enum multiple + "test-signature","test-decipher","list-readers","set-ccc","write-object", + "read-object" enum multiple text " Multiple actions may be given at once and will be executed in order for example --action=verify-pin --action=request-certificate\n" @@ -60,4 +61,5 @@ option "pin" P "Pin/puk code for verification" string optional option "new-pin" N "New pin/puk code for changing" string optional dependon="pin" option "pin-policy" - "Set pin policy for action generate or import-key" values="never","once","always" enum optional option "touch-policy" - "Set touch policy for action generate, import-key or set-mgm-key" values="never","always" enum optional +option "id" - "Id of object for write/get" int optional option "sign" - "Sign data" flag off hidden diff --git a/tool/yubico-piv-tool.c b/tool/yubico-piv-tool.c index 0c00a59..ab3caef 100644 --- a/tool/yubico-piv-tool.c +++ b/tool/yubico-piv-tool.c @@ -1644,6 +1644,82 @@ static bool list_readers(ykpiv_state *state) { return true; } +static bool write_object(ykpiv_state *state, int id, + const char *input_file_name, int verbosity) { + bool ret = false; + FILE *input_file = NULL; + unsigned char data[3072]; + char raw_data[3072 * 2]; + size_t len = sizeof(data); + size_t raw_len = sizeof(raw_data); + ykpiv_rc res; + + input_file = open_file(input_file_name, INPUT); + if(!input_file) { + return false; + } + + if(isatty(fileno(input_file))) { + fprintf(stderr, "Please paste the data...\n"); + } + + raw_len = fread(raw_data, 1, raw_len, input_file); + if(raw_len == 0) { + fprintf(stderr, "Failed reading data\n"); + goto write_out; + } + if(raw_data[raw_len - 1] == '\n') { + raw_len -= 1; + } + + if(ykpiv_hex_decode(raw_data, raw_len, data, &len) != YKPIV_OK) { + fprintf(stderr, "Failed decoding data\n"); + goto write_out; + } + + if(verbosity) { + fprintf(stderr, "Writing %lu bytes of data to object %x.\n", len, id); + } + + if((res = ykpiv_save_object(state, id, data, len)) != YKPIV_OK) { + fprintf(stderr, "Failed writing data to device: %s\n", ykpiv_strerror(res)); + } else { + ret = true; + } + +write_out: + if(input_file != stdin) { + fclose(input_file); + } + return ret; +} + +static bool read_object(ykpiv_state *state, int id, const char *output_file_name) { + FILE *output_file = NULL; + unsigned char data[3072]; + size_t len = sizeof(data); + bool ret = false; + + output_file = open_file(output_file_name, OUTPUT); + if(!output_file) { + return false; + } + + if(ykpiv_fetch_object(state, id, data, &len) != YKPIV_OK) { + fprintf(stderr, "Failed fetching object.\n"); + goto read_out; + } + + dump_hex(data, len, output_file, false); + ret = true; + +read_out: + if(output_file != stdout) { + fclose(output_file); + } + return ret; +} + int main(int argc, char *argv[]) { struct gengetopt_args_info args_info; ykpiv_state *state; @@ -1688,6 +1764,14 @@ int main(int argc, char *argv[]) { return EXIT_FAILURE; } break; + case action_arg_writeMINUS_object: + case action_arg_readMINUS_object: + if(!args_info.id_given) { + fprintf(stderr, "The '%s' action needs the --id argument.\n", + cmdline_parser_action_values[action]); + return EXIT_FAILURE; + } + break; case action_arg_changeMINUS_pin: case action_arg_changeMINUS_puk: case action_arg_unblockMINUS_pin: @@ -1727,6 +1811,7 @@ int main(int argc, char *argv[]) { case action_arg_setMINUS_chuid: case action_arg_setMINUS_ccc: case action_arg_deleteMINUS_certificate: + case action_arg_writeMINUS_object: if(verbosity) { fprintf(stderr, "Authenticating since action '%s' needs that.\n", cmdline_parser_action_values[action]); } @@ -1745,6 +1830,7 @@ int main(int argc, char *argv[]) { case action_arg_testMINUS_signature: case action_arg_testMINUS_decipher: case action_arg_listMINUS_readers: + case action_arg_readMINUS_object: case action__NULL: default: if(verbosity) { @@ -1945,6 +2031,15 @@ int main(int argc, char *argv[]) { if(list_readers(state) == false) { ret = EXIT_FAILURE; } + case action_arg_writeMINUS_object: + if(write_object(state, args_info.id_arg, args_info.input_arg, verbosity) == false) { + ret = EXIT_FAILURE; + } + break; + case action_arg_readMINUS_object: + if(read_object(state, args_info.id_arg, args_info.output_arg) == false) { + ret = EXIT_FAILURE; + } break; case action__NULL: default: