From 30cc13aaff789b11c7d166d061276d35877a9944 Mon Sep 17 00:00:00 2001 From: Klas Lindfors Date: Tue, 15 Dec 2015 10:22:11 +0100 Subject: [PATCH] add format for read/write object as hex/base64/binary relates #31 --- tool/cmdline.ggo | 3 +- tool/util.c | 76 +++++++++++++++++++++++++++++++++++++++--- tool/util.h | 2 ++ tool/yubico-piv-tool.c | 27 ++++++--------- 4 files changed, 85 insertions(+), 23 deletions(-) diff --git a/tool/cmdline.ggo b/tool/cmdline.ggo index 33b968b..03e61c9 100644 --- a/tool/cmdline.ggo +++ b/tool/cmdline.ggo @@ -61,5 +61,6 @@ 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 "id" - "Id of object for write/read object" int optional +option "format" f "Format of data for write/read object" values="hex","base64","binary" enum optional default="hex" option "sign" - "Sign data" flag off hidden diff --git a/tool/util.c b/tool/util.c index d330daa..56a9588 100644 --- a/tool/util.c +++ b/tool/util.c @@ -148,12 +148,78 @@ parse_err: return NULL; } -void dump_hex(const unsigned char *buf, unsigned int len, FILE *output, bool space) { - unsigned int i; - for (i = 0; i < len; i++) { - fprintf(output, "%02x%s", buf[i], space == true ? " " : ""); +size_t read_data(unsigned char *buf, size_t len, FILE* input, enum enum_format format) { + char raw_buf[3072 * 2]; + size_t raw_len = sizeof(raw_buf); + raw_len = fread(raw_buf, 1, raw_len, input); + switch(format) { + case format_arg_hex: + if(raw_buf[raw_len - 1] == '\n') { + raw_len -= 1; + } + if(ykpiv_hex_decode(raw_buf, raw_len, buf, &len) != YKPIV_OK) { + return 0; + } + return len; + case format_arg_base64: + { + int read; + BIO *b64 = BIO_new(BIO_f_base64()); + BIO *bio = BIO_new_mem_buf(raw_buf, raw_len); + BIO_push(b64, bio); + read = BIO_read(b64, buf, len); + BIO_free_all(b64); + if(read <= 0) { + return 0; + } else { + return (size_t)read; + } + } + break; + case format_arg_binary: + if(raw_len > len) { + return 0; + } + memcpy(buf, raw_buf, raw_len); + return raw_len; + case format__NULL: + default: + return 0; } - fprintf(output, "\n"); +} + +void dump_data(const unsigned char *buf, unsigned int len, FILE *output, bool space, enum enum_format format) { + switch(format) { + case format_arg_hex: + { + unsigned int i; + for (i = 0; i < len; i++) { + fprintf(output, "%02x%s", buf[i], space == true ? " " : ""); + } + fprintf(output, "\n"); + } + return; + case format_arg_base64: + { + BIO *b64 = BIO_new(BIO_f_base64()); + BIO *bio = BIO_new_fp(output, BIO_NOCLOSE); + BIO_push(b64, bio); + BIO_write(b64, buf, (int)len); + BIO_flush(b64); + BIO_free_all(b64); + } + return; + case format_arg_binary: + fwrite(buf, 1, len, output); + return; + case format__NULL: + default: + return; + } +} + +void dump_hex(const unsigned char *buf, unsigned int len, FILE *output, bool space) { + dump_data(buf, len, output, space, format_arg_hex); } int get_length(const unsigned char *buffer, int *len) { diff --git a/tool/util.h b/tool/util.h index 21bb843..8b2b728 100644 --- a/tool/util.h +++ b/tool/util.h @@ -38,6 +38,8 @@ #define INPUT 1 #define OUTPUT 2 +size_t read_data(unsigned char*, size_t, FILE*, enum enum_format); +void dump_data(unsigned const char*, unsigned int, FILE*, bool, enum enum_format); void dump_hex(unsigned const char*, unsigned int, FILE*, bool); int set_length(unsigned char*, int); int get_length(const unsigned char*, int*); diff --git a/tool/yubico-piv-tool.c b/tool/yubico-piv-tool.c index ab3caef..40b71c3 100644 --- a/tool/yubico-piv-tool.c +++ b/tool/yubico-piv-tool.c @@ -1645,13 +1645,11 @@ static bool list_readers(ykpiv_state *state) { } static bool write_object(ykpiv_state *state, int id, - const char *input_file_name, int verbosity) { + const char *input_file_name, int verbosity, enum enum_format format) { 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); @@ -1663,19 +1661,11 @@ static bool write_object(ykpiv_state *state, int id, fprintf(stderr, "Please paste the data...\n"); } - raw_len = fread(raw_data, 1, raw_len, input_file); - if(raw_len == 0) { + len = read_data(data, len, input_file, format); + if(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); @@ -1694,7 +1684,8 @@ write_out: return ret; } -static bool read_object(ykpiv_state *state, int id, const char *output_file_name) { +static bool read_object(ykpiv_state *state, int id, const char *output_file_name, + enum enum_format format) { FILE *output_file = NULL; unsigned char data[3072]; size_t len = sizeof(data); @@ -1710,7 +1701,7 @@ static bool read_object(ykpiv_state *state, int id, const char *output_file_name goto read_out; } - dump_hex(data, len, output_file, false); + dump_data(data, len, output_file, false, format); ret = true; read_out: @@ -2032,12 +2023,14 @@ int main(int argc, char *argv[]) { ret = EXIT_FAILURE; } case action_arg_writeMINUS_object: - if(write_object(state, args_info.id_arg, args_info.input_arg, verbosity) == false) { + if(write_object(state, args_info.id_arg, args_info.input_arg, verbosity, + args_info.format_arg) == false) { ret = EXIT_FAILURE; } break; case action_arg_readMINUS_object: - if(read_object(state, args_info.id_arg, args_info.output_arg) == false) { + if(read_object(state, args_info.id_arg, args_info.output_arg, + args_info.format_arg) == false) { ret = EXIT_FAILURE; } break;