From ab3083dc1b866cb06dccc3bad26d5077d133bc7b Mon Sep 17 00:00:00 2001 From: Klas Lindfors Date: Tue, 24 Jun 2014 09:37:03 +0200 Subject: [PATCH] split out util functions from yubico-piv-tool.c --- .gitignore | 3 + tool/Makefile.am | 7 +- tool/internal.h | 58 ++++++++++++ tool/util.c | 197 +++++++++++++++++++++++++++++++++++++++++ tool/yubico-piv-tool.c | 179 +------------------------------------ 5 files changed, 264 insertions(+), 180 deletions(-) create mode 100644 tool/internal.h create mode 100644 tool/util.c diff --git a/.gitignore b/.gitignore index 4c1cce0..9363123 100644 --- a/.gitignore +++ b/.gitignore @@ -65,4 +65,7 @@ tool/.libs/ tool/libpiv_cmd.la tool/libpiv_cmd_la-cmdline.lo tool/libpiv_cmd_la-cmdline.o +tool/libpiv_util.la +tool/util.lo +tool/util.o diff --git a/tool/Makefile.am b/tool/Makefile.am index 60f13f4..657f09e 100644 --- a/tool/Makefile.am +++ b/tool/Makefile.am @@ -30,12 +30,15 @@ AM_CPPFLAGS += -I$(top_srcdir)/lib -I$(top_builddir)/lib bin_PROGRAMS = yubico-piv-tool yubico_piv_tool_SOURCES = yubico-piv-tool.c yubico-piv-tool.h2m -yubico_piv_tool_LDADD = $(OPENSSL_LIBS) ../lib/libykpiv.la libpiv_cmd.la +yubico_piv_tool_LDADD = $(OPENSSL_LIBS) ../lib/libykpiv.la +yubico_piv_tool_LDADD += libpiv_cmd.la libpiv_util.la -noinst_LTLIBRARIES = libpiv_cmd.la +noinst_LTLIBRARIES = libpiv_cmd.la libpiv_util.la libpiv_cmd_la_SOURCES = cmdline.ggo cmdline.c cmdline.h libpiv_cmd_la_CFLAGS = +libpiv_util_la_SOURCES = util.c internal.h + cmdline.c cmdline.h: cmdline.ggo Makefile.am $(GENGETOPT) --input $^ diff --git a/tool/internal.h b/tool/internal.h new file mode 100644 index 0000000..03e2ca2 --- /dev/null +++ b/tool/internal.h @@ -0,0 +1,58 @@ + /* + * Copyright (c) 2014 Yubico AB + * All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Additional permission under GNU GPL version 3 section 7 + * + * If you modify this program, or any covered work, by linking or + * combining it with the OpenSSL project's OpenSSL library (or a + * modified version of that library), containing parts covered by the + * terms of the OpenSSL or SSLeay licenses, We grant you additional + * permission to convey the resulting work. Corresponding Source for a + * non-source form of such a combination shall include the source code + * for the parts of OpenSSL used as well as that of the covered work. + * + */ + +#ifndef YUBICO_PIV_TOOL_INTERNAL_H +#define YUBICO_PIV_TOOL_INTERNAL_H + +#define INPUT 1 +#define OUTPUT 2 + +union u_APDU { + struct { + unsigned char cla; + unsigned char ins; + unsigned char p1; + unsigned char p2; + unsigned char lc; + unsigned char data[0xff]; + } st; + unsigned char raw[0xff + 5]; +}; + +typedef union u_APDU APDU; + +void dump_hex(unsigned const char*, unsigned int); +int set_length(unsigned char*, int); +int get_length(unsigned char*, int*); +X509_NAME *parse_name(char*); +unsigned char get_algorithm(EVP_PKEY*); +FILE *open_file(const char*, int); +int get_object_id(enum enum_slot slot); + +#endif diff --git a/tool/util.c b/tool/util.c new file mode 100644 index 0000000..6c99119 --- /dev/null +++ b/tool/util.c @@ -0,0 +1,197 @@ + /* + * Copyright (c) 2014 Yubico AB + * All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Additional permission under GNU GPL version 3 section 7 + * + * If you modify this program, or any covered work, by linking or + * combining it with the OpenSSL project's OpenSSL library (or a + * modified version of that library), containing parts covered by the + * terms of the OpenSSL or SSLeay licenses, We grant you additional + * permission to convey the resulting work. Corresponding Source for a + * non-source form of such a combination shall include the source code + * for the parts of OpenSSL used as well as that of the covered work. + * + */ + +#include +#include +#include +#include + +#ifdef _WIN32 +#include +#endif + +#include + +#include + +#include "cmdline.h" +#include "internal.h" + +FILE *open_file(const char *file_name, int mode) { + FILE *file; + if(!strcmp(file_name, "-")) { + file = mode == INPUT ? stdin : stdout; + } else { + file = fopen(file_name, mode == INPUT ? "r" : "w"); + if(!file) { + fprintf(stderr, "Failed opening '%s'!\n", file_name); + return NULL; + } + } + return file; +} + +unsigned char get_algorithm(EVP_PKEY *key) { + int type = EVP_PKEY_type(key->type); + switch(type) { + case EVP_PKEY_RSA: + { + RSA *rsa = EVP_PKEY_get1_RSA(key); + int size = RSA_size(rsa); + if(size == 256) { + return YKPIV_ALGO_RSA2048; + } else if(size == 128) { + return YKPIV_ALGO_RSA1024; + } else { + fprintf(stderr, "Unuseable key of %d bits, only 1024 and 2048 is supported.\n", size * 8); + return 0; + } + } + case EVP_PKEY_EC: + { + EC_KEY *ec = EVP_PKEY_get1_EC_KEY(key); + const EC_GROUP *group = EC_KEY_get0_group(ec); + int curve = EC_GROUP_get_curve_name(group); + if(curve == NID_X9_62_prime256v1) { + return YKPIV_ALGO_ECCP256; + } else { + fprintf(stderr, "Unknown EC curve %d\n", curve); + return 0; + } + } + default: + fprintf(stderr, "Unknown algorithm %d.\n", type); + return 0; + } +} + +X509_NAME *parse_name(char *name) { + X509_NAME *parsed = NULL; + char *ptr = name; + char *part; + if(*name != '/') { + fprintf(stderr, "Name does not start with '/'!\n"); + return NULL; + } + parsed = X509_NAME_new(); + if(!parsed) { + fprintf(stderr, "Failed to allocate memory\n"); + return NULL; + } + while((part = strtok(ptr, "/"))) { + char *key; + char *value; + char *equals = strchr(part, '='); + if(!equals) { + fprintf(stderr, "The part '%s' doesn't seem to contain a =.\n", part); + goto parse_err; + } + *equals++ = '\0'; + value = equals; + key = part; + + ptr = NULL; + if(!key) { + fprintf(stderr, "Malformed name (%s)\n", part); + goto parse_err; + } + if(!value) { + fprintf(stderr, "Malformed name (%s)\n", part); + goto parse_err; + } + if(!X509_NAME_add_entry_by_txt(parsed, key, MBSTRING_UTF8, (unsigned char*)value, -1, -1, 0)) { + fprintf(stderr, "Failed adding %s=%s to name.\n", key, value); + goto parse_err; + } + } + return parsed; +parse_err: + X509_NAME_free(parsed); + return NULL; +} + +void dump_hex(const unsigned char *buf, unsigned int len) { + unsigned int i; + for (i = 0; i < len; i++) { + fprintf(stderr, "%02x ", buf[i]); + } +} + +int get_length(unsigned char *buffer, int *len) { + if(buffer[0] < 0x81) { + *len = buffer[0]; + return 1; + } else if((*buffer & 0x7f) == 1) { + *len = buffer[1]; + return 2; + } else if((*buffer & 0x7f) == 2) { + *len = (buffer[1] << 8) + buffer[2]; + return 3; + } + return 0; +} + +int set_length(unsigned char *buffer, int length) { + if(length < 0x80) { + *buffer++ = length; + return 1; + } else if(length < 0xff) { + *buffer++ = 0x81; + *buffer++ = length; + return 2; + } else { + *buffer++ = 0x82; + *buffer++ = (length >> 8) & 0xff; + *buffer++ = length & 0xff; + return 3; + } +} + +int get_object_id(enum enum_slot slot) { + int object; + + switch(slot) { + case slot_arg_9a: + object = 0x5fc105; + break; + case slot_arg_9c: + object = 0x5fc10a; + break; + case slot_arg_9d: + object = 0x5fc10b; + break; + case slot_arg_9e: + object = 0x5fc101; + break; + case slot__NULL: + default: + object = 0; + } + return object; +} diff --git a/tool/yubico-piv-tool.c b/tool/yubico-piv-tool.c index d15c672..15e04e5 100644 --- a/tool/yubico-piv-tool.c +++ b/tool/yubico-piv-tool.c @@ -44,6 +44,7 @@ #include #include "cmdline.h" +#include "internal.h" /* FASC-N containing S9999F9999F999999F0F1F0000000000300001E encoded in * 4-bit BCD with 1 bit parity. run through the tools/fasc.pl script to get @@ -67,31 +68,6 @@ unsigned const char sha256oid[] = { #define KEY_LEN 24 -#define INPUT 1 -#define OUTPUT 2 - -union u_APDU { - struct { - unsigned char cla; - unsigned char ins; - unsigned char p1; - unsigned char p2; - unsigned char lc; - unsigned char data[0xff]; - } st; - unsigned char raw[0xff + 5]; -}; - -typedef union u_APDU APDU; - -static void dump_hex(unsigned const char*, unsigned int); -static int set_length(unsigned char*, int); -static int get_length(unsigned char*, int*); -static X509_NAME *parse_name(char*); -static unsigned char get_algorithm(EVP_PKEY*); -static FILE *open_file(const char*, int); -static int get_object_id(enum enum_slot slot); - static void print_version(ykpiv_state *state) { char version[7]; if(ykpiv_get_version(state, version, sizeof(version)) == YKPIV_OK) { @@ -905,159 +881,6 @@ static bool delete_certificate(ykpiv_state *state, enum enum_slot slot) { return ret; } -static FILE *open_file(const char *file_name, int mode) { - FILE *file; - if(!strcmp(file_name, "-")) { - file = mode == INPUT ? stdin : stdout; - } else { - file = fopen(file_name, mode == INPUT ? "r" : "w"); - if(!file) { - fprintf(stderr, "Failed opening '%s'!\n", file_name); - return NULL; - } - } - return file; -} - -static unsigned char get_algorithm(EVP_PKEY *key) { - int type = EVP_PKEY_type(key->type); - switch(type) { - case EVP_PKEY_RSA: - { - RSA *rsa = EVP_PKEY_get1_RSA(key); - int size = RSA_size(rsa); - if(size == 256) { - return YKPIV_ALGO_RSA2048; - } else if(size == 128) { - return YKPIV_ALGO_RSA1024; - } else { - fprintf(stderr, "Unuseable key of %d bits, only 1024 and 2048 is supported.\n", size * 8); - return 0; - } - } - case EVP_PKEY_EC: - { - EC_KEY *ec = EVP_PKEY_get1_EC_KEY(key); - const EC_GROUP *group = EC_KEY_get0_group(ec); - int curve = EC_GROUP_get_curve_name(group); - if(curve == NID_X9_62_prime256v1) { - return YKPIV_ALGO_ECCP256; - } else { - fprintf(stderr, "Unknown EC curve %d\n", curve); - return 0; - } - } - default: - fprintf(stderr, "Unknown algorithm %d.\n", type); - return 0; - } -} - -static X509_NAME *parse_name(char *name) { - X509_NAME *parsed = NULL; - char *ptr = name; - char *part; - if(*name != '/') { - fprintf(stderr, "Name does not start with '/'!\n"); - return NULL; - } - parsed = X509_NAME_new(); - if(!parsed) { - fprintf(stderr, "Failed to allocate memory\n"); - return NULL; - } - while((part = strtok(ptr, "/"))) { - char *key; - char *value; - char *equals = strchr(part, '='); - if(!equals) { - fprintf(stderr, "The part '%s' doesn't seem to contain a =.\n", part); - goto parse_err; - } - *equals++ = '\0'; - value = equals; - key = part; - - ptr = NULL; - if(!key) { - fprintf(stderr, "Malformed name (%s)\n", part); - goto parse_err; - } - if(!value) { - fprintf(stderr, "Malformed name (%s)\n", part); - goto parse_err; - } - if(!X509_NAME_add_entry_by_txt(parsed, key, MBSTRING_UTF8, (unsigned char*)value, -1, -1, 0)) { - fprintf(stderr, "Failed adding %s=%s to name.\n", key, value); - goto parse_err; - } - } - return parsed; -parse_err: - X509_NAME_free(parsed); - return NULL; -} - -static void dump_hex(const unsigned char *buf, unsigned int len) { - unsigned int i; - for (i = 0; i < len; i++) { - fprintf(stderr, "%02x ", buf[i]); - } -} - -static int get_length(unsigned char *buffer, int *len) { - if(buffer[0] < 0x81) { - *len = buffer[0]; - return 1; - } else if((*buffer & 0x7f) == 1) { - *len = buffer[1]; - return 2; - } else if((*buffer & 0x7f) == 2) { - *len = (buffer[1] << 8) + buffer[2]; - return 3; - } - return 0; -} - -static int set_length(unsigned char *buffer, int length) { - if(length < 0x80) { - *buffer++ = length; - return 1; - } else if(length < 0xff) { - *buffer++ = 0x81; - *buffer++ = length; - return 2; - } else { - *buffer++ = 0x82; - *buffer++ = (length >> 8) & 0xff; - *buffer++ = length & 0xff; - return 3; - } -} - -static int get_object_id(enum enum_slot slot) { - int object; - - switch(slot) { - case slot_arg_9a: - object = 0x5fc105; - break; - case slot_arg_9c: - object = 0x5fc10a; - break; - case slot_arg_9d: - object = 0x5fc10b; - break; - case slot_arg_9e: - object = 0x5fc101; - break; - case slot__NULL: - default: - object = 0; - } - return object; -} - int main(int argc, char *argv[]) { struct gengetopt_args_info args_info; ykpiv_state *state;