From 9db6d3d45a5e8c34c3b3cbfa8d12d8f9efcab759 Mon Sep 17 00:00:00 2001 From: Klas Lindfors Date: Fri, 20 Mar 2015 14:02:24 +0100 Subject: [PATCH] replace EVP_MD_CTX_verify() stuff with RSA_verify()/ECDSA_verify() since the EVP_MD_CTX stuff doesn't seem to exist on osx at all. --- tool/util.c | 23 +++++++++- tool/util.h | 2 + tool/yubico-piv-tool.c | 96 ++++++++++++++++++++++-------------------- 3 files changed, 75 insertions(+), 46 deletions(-) diff --git a/tool/util.c b/tool/util.c index cc57814..f08af50 100644 --- a/tool/util.c +++ b/tool/util.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 Yubico AB + * Copyright (c) 2014-2015 Yubico AB * All rights reserved. * * This program is free software: you can redistribute it and/or modify @@ -216,3 +216,24 @@ bool set_component_with_len(unsigned char **in_ptr, const BIGNUM *bn, int elemen *in_ptr += BN_bn2bin(bn, *in_ptr); return true; } + +bool prepare_rsa_signature(const unsigned char *in, unsigned int in_len, unsigned char *out, unsigned int *out_len, int nid) { + X509_SIG digestInfo; + X509_ALGOR algor; + ASN1_TYPE parameter; + ASN1_OCTET_STRING digest; + unsigned char data[1024]; + + memcpy(data, in, in_len); + + digestInfo.algor = &algor; + digestInfo.algor->algorithm = OBJ_nid2obj(nid); + digestInfo.algor->parameter = ¶meter; + digestInfo.algor->parameter->type = V_ASN1_NULL; + digestInfo.algor->parameter->value.ptr = NULL; + digestInfo.digest = &digest; + digestInfo.digest->data = data; + digestInfo.digest->length = (int)in_len; + *out_len = (unsigned int)i2d_X509_SIG(&digestInfo, &out); + return true; +} diff --git a/tool/util.h b/tool/util.h index 4a30fe9..2e619be 100644 --- a/tool/util.h +++ b/tool/util.h @@ -45,5 +45,7 @@ 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); +bool prepare_rsa_signature(const unsigned char*, unsigned int, unsigned char*, + unsigned int*, int); #endif diff --git a/tool/yubico-piv-tool.c b/tool/yubico-piv-tool.c index 7d421d8..b9706e2 100644 --- a/tool/yubico-piv-tool.c +++ b/tool/yubico-piv-tool.c @@ -45,6 +45,7 @@ #include #include #include +#include #include "cmdline.h" #include "util.h" @@ -1087,7 +1088,7 @@ static bool sign_file(ykpiv_state *state, const char *input, const char *output, unsigned char hashed[EVP_MAX_MD_SIZE]; bool ret = false; int algo; - int nid; + const EVP_MD *md; sscanf(slot, "%2x", &key); @@ -1121,21 +1122,17 @@ static bool sign_file(ykpiv_state *state, const char *input, const char *output, } { - const EVP_MD *md; EVP_MD_CTX *mdctx; switch(hash) { case hash_arg_SHA1: md = EVP_sha1(); - nid = NID_sha1; break; case hash_arg_SHA256: md = EVP_sha256(); - nid = NID_sha256; break; case hash_arg_SHA512: md = EVP_sha512(); - nid = NID_sha512; break; case hash__NULL: default: @@ -1159,24 +1156,7 @@ static bool sign_file(ykpiv_state *state, const char *input, const char *output, } if(algo == YKPIV_ALGO_RSA1024 || algo == YKPIV_ALGO_RSA2048) { - X509_SIG digestInfo; - X509_ALGOR algor; - ASN1_TYPE parameter; - ASN1_OCTET_STRING digest; - unsigned char buf[1024]; - unsigned char *ptr = hashed; - - memcpy(buf, hashed, hash_len); - - digestInfo.algor = &algor; - digestInfo.algor->algorithm = OBJ_nid2obj(nid); - digestInfo.algor->parameter = ¶meter; - digestInfo.algor->parameter->type = V_ASN1_NULL; - digestInfo.algor->parameter->value.ptr = NULL; - digestInfo.digest = &digest; - digestInfo.digest->data = buf; - digestInfo.digest->length = (int)hash_len; - hash_len = (unsigned int)i2d_X509_SIG(&digestInfo, &ptr); + prepare_rsa_signature(hashed, hash_len, hashed, &hash_len, EVP_MD_type(md)); } { @@ -1364,11 +1344,10 @@ static bool test_signature(ykpiv_state *state, enum enum_slot slot, enum enum_key_format cert_format, int verbose) { const EVP_MD *md; bool ret = false; - unsigned char data[EVP_MAX_MD_SIZE]; + unsigned char data[1024]; unsigned int data_len; X509 *x509 = NULL; EVP_PKEY *pubkey; - EVP_PKEY_CTX *verify_ctx = NULL; FILE *input_file = open_file(input_file_name, INPUT); if(!input_file) { @@ -1428,6 +1407,9 @@ static bool test_signature(ykpiv_state *state, enum enum_slot slot, { unsigned char signature[1024]; + unsigned char encoded[1024]; + unsigned char *ptr = data; + unsigned int enc_len; size_t sig_len = sizeof(signature); int key = 0; unsigned char algorithm; @@ -1439,31 +1421,58 @@ static bool test_signature(ykpiv_state *state, enum enum_slot slot, } algorithm = get_algorithm(pubkey); if(algorithm == 0) { - return false; + goto test_out; } sscanf(cmdline_parser_slot_values[slot], "%2x", &key); - if(ykpiv_sign_data(state, data, data_len, signature, &sig_len, algorithm, key) + if(algorithm == YKPIV_ALGO_RSA1024 || algorithm == YKPIV_ALGO_RSA2048) { + prepare_rsa_signature(data, data_len, encoded, &enc_len, EVP_MD_type(md)); + ptr = encoded; + } else { + enc_len = data_len; + } + if(ykpiv_sign_data(state, ptr, enc_len, signature, &sig_len, algorithm, key) != YKPIV_OK) { fprintf(stderr, "Failed signing test data.\n"); goto test_out; } - { - verify_ctx = EVP_PKEY_CTX_new(pubkey, NULL); - if(!verify_ctx) { - fprintf(stderr, "Allocation failure.\n"); + switch(algorithm) { + case YKPIV_ALGO_RSA1024: + case YKPIV_ALGO_RSA2048: + { + RSA *rsa = EVP_PKEY_get1_RSA(pubkey); + if(!rsa) { + fprintf(stderr, "Failed getting RSA pubkey.\n"); + goto test_out; + } + + if(RSA_verify(EVP_MD_type(md), data, data_len, signature, sig_len, rsa) == 1) { + fprintf(stderr, "Successful RSA verification.\n"); + ret = true; + goto test_out; + } else { + fprintf(stderr, "Failed RSA verification.\n"); + goto test_out; + } + } + + break; + case YKPIV_ALGO_ECCP256: + { + EC_KEY *ec = EVP_PKEY_get1_EC_KEY(pubkey); + if(ECDSA_verify(0, data, (int)data_len, signature, (int)sig_len, ec) == 1) { + fprintf(stderr, "Successful ECDSA verification.\n"); + ret = true; + goto test_out; + } else { + fprintf(stderr, "Failed ECDSA verification.\n"); + goto test_out; + } + } + break; + default: + fprintf(stderr, "Unknown algorithm.\n"); goto test_out; - } - if(EVP_PKEY_verify_init(verify_ctx) == 0) { - fprintf(stderr, "Failed initializing verify context.\n"); - goto test_out; - } - if(EVP_PKEY_verify(verify_ctx, signature, sig_len, data, data_len) == 1) { - fprintf(stderr, "Successfully verified signature.\n"); - ret = true; - } else { - fprintf(stderr, "Signature verification failed.\n"); - } } } test_out: @@ -1473,9 +1482,6 @@ test_out: if(input_file != stdin) { fclose(input_file); } - if(verify_ctx) { - EVP_PKEY_CTX_free(verify_ctx); - } return ret; }