From 36468219c240a7f41660514d08de91fff1709d29 Mon Sep 17 00:00:00 2001 From: Klas Lindfors Date: Wed, 12 Nov 2014 14:08:11 +0100 Subject: [PATCH] check length of private key components before setting the card functions only accepts key components of correct size so here we add 0 before if they're shorter (usually one byte shorter) thus fixing the issue where the card returned 6f00 --- tool/util.c | 12 ++++++++++++ tool/util.h | 1 + tool/yubico-piv-tool.c | 40 ++++++++++++++++++++++++++++------------ 3 files changed, 41 insertions(+), 12 deletions(-) diff --git a/tool/util.c b/tool/util.c index 618cad2..1bdc184 100644 --- a/tool/util.c +++ b/tool/util.c @@ -203,3 +203,15 @@ int get_object_id(enum enum_slot slot) { } return object; } + +bool set_component_with_len(unsigned char **in_ptr, const BIGNUM *bn, int element_len) { + int real_len = BN_num_bytes(bn); + *in_ptr += set_length(*in_ptr, element_len); + if(real_len > element_len) { + return false; + } + memset(*in_ptr, 0, (size_t)(element_len - real_len)); + *in_ptr += element_len - real_len; + *in_ptr += BN_bn2bin(bn, *in_ptr); + return true; +} diff --git a/tool/util.h b/tool/util.h index a20ed34..d03f8ad 100644 --- a/tool/util.h +++ b/tool/util.h @@ -42,5 +42,6 @@ X509_NAME *parse_name(const char*); unsigned char get_algorithm(EVP_PKEY*); FILE *open_file(const char*, int); int get_object_id(enum enum_slot slot); +bool set_component_with_len(unsigned char**, const BIGNUM*, int); #endif diff --git a/tool/yubico-piv-tool.c b/tool/yubico-piv-tool.c index b5dabb0..655f0ab 100644 --- a/tool/yubico-piv-tool.c +++ b/tool/yubico-piv-tool.c @@ -326,33 +326,49 @@ static bool import_key(ykpiv_state *state, enum enum_key_format key_format, int sw; if(algorithm == YKPIV_ALGO_RSA1024 || algorithm == YKPIV_ALGO_RSA2048) { RSA *rsa_private_key = EVP_PKEY_get1_RSA(private_key); + int element_len = 128; + if(algorithm == YKPIV_ALGO_RSA1024) { + element_len = 64; + } *in_ptr++ = 0x01; - in_ptr += set_length(in_ptr, BN_num_bytes(rsa_private_key->p)); - in_ptr += BN_bn2bin(rsa_private_key->p, in_ptr); + if(set_component_with_len(&in_ptr, rsa_private_key->p, element_len) == false) { + fprintf(stderr, "Failed setting p component.\n"); + goto import_out; + } *in_ptr++ = 0x02; - in_ptr += set_length(in_ptr, BN_num_bytes(rsa_private_key->q)); - in_ptr += BN_bn2bin(rsa_private_key->q, in_ptr); + if(set_component_with_len(&in_ptr, rsa_private_key->q, element_len) == false) { + fprintf(stderr, "Failed setting q component.\n"); + goto import_out; + } *in_ptr++ = 0x03; - in_ptr += set_length(in_ptr, BN_num_bytes(rsa_private_key->dmp1)); - in_ptr += BN_bn2bin(rsa_private_key->dmp1, in_ptr); + if(set_component_with_len(&in_ptr, rsa_private_key->dmp1, element_len) == false) { + fprintf(stderr, "Failed setting dmp1 component.\n"); + goto import_out; + } *in_ptr++ = 0x04; - in_ptr += set_length(in_ptr, BN_num_bytes(rsa_private_key->dmq1)); - in_ptr += BN_bn2bin(rsa_private_key->dmq1, in_ptr); + if(set_component_with_len(&in_ptr, rsa_private_key->dmq1, element_len) == false) { + fprintf(stderr, "Failed setting dmq1 component.\n"); + goto import_out; + } *in_ptr++ = 0x05; - in_ptr += set_length(in_ptr, BN_num_bytes(rsa_private_key->iqmp)); - in_ptr += BN_bn2bin(rsa_private_key->iqmp, in_ptr); + if(set_component_with_len(&in_ptr, rsa_private_key->iqmp, element_len) == false) { + fprintf(stderr, "Failed setting iqmp component.\n"); + goto import_out; + } } else if(algorithm == YKPIV_ALGO_ECCP256) { EC_KEY *ec = EVP_PKEY_get1_EC_KEY(private_key); const BIGNUM *s = EC_KEY_get0_private_key(ec); *in_ptr++ = 0x06; - in_ptr += set_length(in_ptr, BN_num_bytes(s)); - in_ptr += BN_bn2bin(s, in_ptr); + if(set_component_with_len(&in_ptr, s, 32) == false) { + fprintf(stderr, "Failed setting ec private key.\n"); + goto import_out; + } } if(ykpiv_transfer_data(state, templ, in_data, in_ptr - in_data, data,