From d06852959cf6fcb0d0fa496edead1de4cc716f40 Mon Sep 17 00:00:00 2001 From: Klas Lindfors Date: Wed, 27 May 2015 21:38:46 +0200 Subject: [PATCH] add sha384 hash and refactor some common patterns --- tool/cmdline.ggo | 2 +- tool/util.c | 105 +++++++++++++++++ tool/util.h | 3 + tool/yubico-piv-tool.c | 252 ++++++++--------------------------------- 4 files changed, 155 insertions(+), 207 deletions(-) diff --git a/tool/cmdline.ggo b/tool/cmdline.ggo index 2696b39..25b606f 100644 --- a/tool/cmdline.ggo +++ b/tool/cmdline.ggo @@ -42,7 +42,7 @@ text " 9d is for Key Management 9e is for Card Authentication (PIN never checked)\n" option "algorithm" A "What algorithm to use" values="RSA1024","RSA2048","ECCP256","ECCP384" enum optional default="RSA2048" -option "hash" H "Hash to use for signatures" values="SHA1","SHA256","SHA512" enum optional default="SHA256" +option "hash" H "Hash to use for signatures" values="SHA1","SHA256","SHA384","SHA512" enum optional default="SHA256" option "new-key" n "New authentication key to use" string optional option "pin-retries" - "Number of retries before the pin code is blocked" int optional dependon="puk-retries" option "puk-retries" - "Number of retries before the puk code is blocked" int optional dependon="pin-retries" diff --git a/tool/util.c b/tool/util.c index f46b27d..ac1654e 100644 --- a/tool/util.c +++ b/tool/util.c @@ -239,3 +239,108 @@ bool prepare_rsa_signature(const unsigned char *in, unsigned int in_len, unsigne *out_len = (unsigned int)i2d_X509_SIG(&digestInfo, &out); return true; } + +static unsigned const char sha1oid[] = { + 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, + 0x04, 0x14 +}; + +static unsigned const char sha256oid[] = { + 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, + 0x02, 0x01, 0x05, 0x00, 0x04, 0x20 +}; + +static unsigned const char sha384oid[] = { + 0x30, 0x41, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, + 0x02, 0x02, 0x05, 0x00, 0x04, 0x30 +}; + +static unsigned const char sha512oid[] = { + 0x30, 0x51, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, + 0x02, 0x03, 0x05, 0x00, 0x04, 0x40 +}; + +const EVP_MD *get_hash(enum enum_hash hash, const unsigned char **oid, size_t *oid_len) { + switch(hash) { + case hash_arg_SHA1: + if(oid) { + *oid = sha1oid; + *oid_len = sizeof(sha1oid); + } + return EVP_sha1(); + case hash_arg_SHA256: + if(oid) { + *oid = sha256oid; + *oid_len = sizeof(sha256oid); + } + return EVP_sha256(); + case hash_arg_SHA384: + if(oid) { + *oid = sha384oid; + *oid_len = sizeof(sha384oid); + } + return EVP_sha384(); + case hash_arg_SHA512: + if(oid) { + *oid = sha512oid; + *oid_len = sizeof(sha512oid); + } + return EVP_sha512(); + case hash__NULL: + default: + return NULL; + } +} + +int get_hashnid(enum enum_hash hash, unsigned char algorithm) { + switch(algorithm) { + case YKPIV_ALGO_RSA1024: + case YKPIV_ALGO_RSA2048: + switch(hash) { + case hash_arg_SHA1: + return NID_sha1WithRSAEncryption; + case hash_arg_SHA256: + return NID_sha256WithRSAEncryption; + case hash_arg_SHA384: + return NID_sha384WithRSAEncryption; + case hash_arg_SHA512: + return NID_sha512WithRSAEncryption; + case hash__NULL: + default: + return 0; + } + case YKPIV_ALGO_ECCP256: + case YKPIV_ALGO_ECCP384: + switch(hash) { + case hash_arg_SHA1: + return NID_ecdsa_with_SHA1; + case hash_arg_SHA256: + return NID_ecdsa_with_SHA256; + case hash_arg_SHA384: + return NID_ecdsa_with_SHA384; + case hash_arg_SHA512: + return NID_ecdsa_with_SHA512; + case hash__NULL: + default: + return 0; + } + default: + return 0; + } +} + +unsigned char get_piv_algorithm(enum enum_algorithm algorithm) { + switch(algorithm) { + case algorithm_arg_RSA2048: + return YKPIV_ALGO_RSA2048; + case algorithm_arg_RSA1024: + return YKPIV_ALGO_RSA1024; + case algorithm_arg_ECCP256: + return YKPIV_ALGO_ECCP256; + case algorithm_arg_ECCP384: + return YKPIV_ALGO_ECCP384; + case algorithm__NULL: + default: + return 0; + } +} diff --git a/tool/util.h b/tool/util.h index 2e619be..066d389 100644 --- a/tool/util.h +++ b/tool/util.h @@ -47,5 +47,8 @@ int get_object_id(enum enum_slot slot); bool set_component_with_len(unsigned char**, const BIGNUM*, int); bool prepare_rsa_signature(const unsigned char*, unsigned int, unsigned char*, unsigned int*, int); +const EVP_MD *get_hash(enum enum_hash, const unsigned char**, size_t*); +int get_hashnid(enum enum_hash, unsigned char); +unsigned char get_piv_algorithm(enum enum_algorithm); #endif diff --git a/tool/yubico-piv-tool.c b/tool/yubico-piv-tool.c index fd7036d..e781c75 100644 --- a/tool/yubico-piv-tool.c +++ b/tool/yubico-piv-tool.c @@ -62,20 +62,7 @@ unsigned const char chuid_tmpl[] = { }; #define CHUID_GUID_OFFS 29 -unsigned const char sha1oid[] = { - 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, - 0x04, 0x14 -}; - -unsigned const char sha256oid[] = { - 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, - 0x02, 0x01, 0x05, 0x00, 0x04, 0x20 -}; - -unsigned const char sha512oid[] = { - 0x30, 0x51, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, - 0x02, 0x03, 0x05, 0x00, 0x04, 0x40 -}; +#define MAX_OID_LEN 19 #define KEY_LEN 24 @@ -128,23 +115,10 @@ static bool generate_key(ykpiv_state *state, const char *slot, in_data[1] = 3; in_data[2] = 0x80; in_data[3] = 1; - switch(algorithm) { - case algorithm_arg_RSA2048: - in_data[4] = YKPIV_ALGO_RSA2048; - break; - case algorithm_arg_RSA1024: - in_data[4] = YKPIV_ALGO_RSA1024; - break; - case algorithm_arg_ECCP256: - in_data[4] = YKPIV_ALGO_ECCP256; - break; - case algorithm_arg_ECCP384: - in_data[4] = YKPIV_ALGO_ECCP384; - break; - case algorithm__NULL: - default: - fprintf(stderr, "Unexepcted algorithm.\n"); - goto generate_out; + in_data[4] = get_piv_algorithm(algorithm); + if(in_data[4] == 0) { + fprintf(stderr, "Unexepcted algorithm.\n"); + goto generate_out; } if(ykpiv_transfer_data(state, templ, in_data, sizeof(in_data), data, &recv_len, &sw) != YKPIV_OK) { @@ -574,7 +548,7 @@ static bool request_certificate(ykpiv_state *state, enum enum_key_format key_for EVP_PKEY *public_key = NULL; const EVP_MD *md; bool ret = false; - unsigned char digest[EVP_MAX_MD_SIZE + sizeof(sha512oid)]; // maximum.. + unsigned char digest[EVP_MAX_MD_SIZE + MAX_OID_LEN]; unsigned int digest_len; unsigned int md_len; unsigned char algorithm; @@ -612,25 +586,9 @@ static bool request_certificate(ykpiv_state *state, enum enum_key_format key_for goto request_out; } - switch(hash) { - case hash_arg_SHA1: - md = EVP_sha1(); - oid = sha1oid; - oid_len = sizeof(sha1oid); - break; - case hash_arg_SHA256: - md = EVP_sha256(); - oid = sha256oid; - oid_len = sizeof(sha256oid); - break; - case hash_arg_SHA512: - md = EVP_sha512(); - oid = sha512oid; - oid_len = sizeof(sha512oid); - break; - case hash__NULL: - default: - goto request_out; + md = get_hash(hash, &oid, &oid_len); + if(md == NULL) { + goto request_out; } md_len = (unsigned int)EVP_MD_size(md); @@ -666,49 +624,19 @@ static bool request_certificate(ykpiv_state *state, enum enum_key_format key_for goto request_out; } - switch(algorithm) { - case YKPIV_ALGO_RSA1024: - case YKPIV_ALGO_RSA2048: - signinput = digest; - len = oid_len + digest_len; - switch(hash) { - case hash_arg_SHA1: - nid = NID_sha1WithRSAEncryption; - break; - case hash_arg_SHA256: - nid = NID_sha256WithRSAEncryption; - break; - case hash_arg_SHA512: - nid = NID_sha512WithRSAEncryption; - break; - case hash__NULL: - default: - goto request_out; - } - break; - case YKPIV_ALGO_ECCP256: - case YKPIV_ALGO_ECCP384: + nid = get_hashnid(hash, algorithm); + if(nid == 0) { + fprintf(stderr, "Unsupported algorithm %x or hash %x\n", algorithm, hash); + goto request_out; + } + if(algorithm == YKPIV_ALGO_RSA1024 || algorithm == YKPIV_ALGO_RSA2048) { + signinput = digest; + len = oid_len + digest_len; + } else { signinput = digest + oid_len; len = digest_len; - switch(hash) { - case hash_arg_SHA1: - nid = NID_ecdsa_with_SHA1; - break; - case hash_arg_SHA256: - nid = NID_ecdsa_with_SHA256; - break; - case hash_arg_SHA512: - nid = NID_ecdsa_with_SHA512; - break; - case hash__NULL: - default: - goto request_out; - } - break; - default: - fprintf(stderr, "Unsupported algorithm %x.\n", algorithm); - goto request_out; } + req->sig_alg->algorithm = OBJ_nid2obj(nid); { unsigned char signature[1024]; @@ -759,7 +687,7 @@ static bool selfsign_certificate(ykpiv_state *state, enum enum_key_format key_fo X509 *x509 = NULL; X509_NAME *name = NULL; const EVP_MD *md; - unsigned char digest[EVP_MAX_MD_SIZE + sizeof(sha512oid)]; + unsigned char digest[EVP_MAX_MD_SIZE + MAX_OID_LEN]; unsigned int digest_len; unsigned char algorithm; int key = 0; @@ -797,27 +725,10 @@ static bool selfsign_certificate(ykpiv_state *state, enum enum_key_format key_fo goto selfsign_out; } - switch(hash) { - case hash_arg_SHA1: - md = EVP_sha1(); - oid = sha1oid; - oid_len = sizeof(sha1oid); - break; - case hash_arg_SHA256: - md = EVP_sha256(); - oid = sha256oid; - oid_len = sizeof(sha256oid); - break; - case hash_arg_SHA512: - md = EVP_sha512(); - oid = sha512oid; - oid_len = sizeof(sha512oid); - break; - case hash__NULL: - default: - goto selfsign_out; + md = get_hash(hash, &oid, &oid_len); + if(md == NULL) { + goto selfsign_out; } - md_len = (unsigned int)EVP_MD_size(md); digest_len = sizeof(digest) - md_len; @@ -859,49 +770,18 @@ static bool selfsign_certificate(ykpiv_state *state, enum enum_key_format key_fo fprintf(stderr, "Failed setting certificate issuer.\n"); goto selfsign_out; } - switch(algorithm) { - case YKPIV_ALGO_RSA1024: - case YKPIV_ALGO_RSA2048: - signinput = digest; - len = oid_len + md_len; - switch(hash) { - case hash_arg_SHA1: - nid = NID_sha1WithRSAEncryption; - break; - case hash_arg_SHA256: - nid = NID_sha256WithRSAEncryption; - break; - case hash_arg_SHA512: - nid = NID_sha512WithRSAEncryption; - break; - case hash__NULL: - default: - goto selfsign_out; - } - break; - case YKPIV_ALGO_ECCP256: - case YKPIV_ALGO_ECCP384: - signinput = digest + oid_len; - len = md_len; - switch(hash) { - case hash_arg_SHA1: - nid = NID_ecdsa_with_SHA1; - break; - case hash_arg_SHA256: - nid = NID_ecdsa_with_SHA256; - break; - case hash_arg_SHA512: - nid = NID_ecdsa_with_SHA512; - break; - case hash__NULL: - default: - goto selfsign_out; - } - break; - default: - fprintf(stderr, "Unsupported algorithm %x.\n", algorithm); - goto selfsign_out; + nid = get_hashnid(hash, algorithm); + if(nid == 0) { + goto selfsign_out; } + if(algorithm == YKPIV_ALGO_RSA1024 || algorithm == YKPIV_ALGO_RSA2048) { + signinput = digest; + len = oid_len + md_len; + } else { + signinput = digest + oid_len; + len = md_len; + } + x509->sig_alg->algorithm = OBJ_nid2obj(nid); x509->cert_info->signature->algorithm = x509->sig_alg->algorithm; memcpy(digest, oid, oid_len); @@ -1128,37 +1008,17 @@ static bool sign_file(ykpiv_state *state, const char *input, const char *output, return false; } - switch(algorithm) { - case algorithm_arg_RSA2048: - algo = YKPIV_ALGO_RSA2048; - break; - case algorithm_arg_RSA1024: - algo = YKPIV_ALGO_RSA1024; - break; - case algorithm_arg_ECCP256: - algo = YKPIV_ALGO_ECCP256; - break; - case algorithm__NULL: - default: - goto out; + algo = get_piv_algorithm(algorithm); + if(algo == 0) { + goto out; } { EVP_MD_CTX *mdctx; - switch(hash) { - case hash_arg_SHA1: - md = EVP_sha1(); - break; - case hash_arg_SHA256: - md = EVP_sha256(); - break; - case hash_arg_SHA512: - md = EVP_sha512(); - break; - case hash__NULL: - default: - goto out; + md = get_hash(hash, NULL, NULL); + if(md == NULL) { + goto out; } mdctx = EVP_MD_CTX_create(); @@ -1318,19 +1178,9 @@ static bool status(ykpiv_state *state, enum enum_hash hash, return false; } - switch(hash) { - case hash_arg_SHA1: - md = EVP_sha1(); - break; - case hash_arg_SHA256: - md = EVP_sha256(); - break; - case hash_arg_SHA512: - md = EVP_sha512(); - break; - case hash__NULL: - default: - return false; + md = get_hash(hash, NULL, NULL); + if(md == NULL) { + return false; } fprintf(output_file, "CHUID:\t"); @@ -1394,19 +1244,9 @@ static bool test_signature(ykpiv_state *state, enum enum_slot slot, goto test_out; } - switch(hash) { - case hash_arg_SHA1: - md = EVP_sha1(); - break; - case hash_arg_SHA256: - md = EVP_sha256(); - break; - case hash_arg_SHA512: - md = EVP_sha512(); - break; - case hash__NULL: - default: - return false; + md = get_hash(hash, NULL, NULL); + if(md == NULL) { + return false; } {