From 2972247cb4ae84ed660532cac426259a4f17c816 Mon Sep 17 00:00:00 2001 From: Qixiang Xu Date: Thu, 9 Nov 2017 13:51:58 +0800 Subject: [PATCH] tools: add an option -hash-alg for cert_create This option enables the user to select the secure hash algorithm to be used for generating the hash. It supports the following options: - sha256 (default) - sha384 - sha512 Change-Id: Icb093cec1b5715e248c3d1c3749a2479a7ab4b89 Signed-off-by: Qixiang Xu --- tools/cert_create/include/cert.h | 10 ++++-- tools/cert_create/include/key.h | 9 ++++- tools/cert_create/include/sha.h | 4 +-- tools/cert_create/src/cert.c | 25 ++++++++++++-- tools/cert_create/src/main.c | 58 +++++++++++++++++++++++++++----- tools/cert_create/src/sha.c | 29 ++++++++++++---- 6 files changed, 112 insertions(+), 23 deletions(-) diff --git a/tools/cert_create/include/cert.h b/tools/cert_create/include/cert.h index 256e7afd2..9b4ef5af6 100644 --- a/tools/cert_create/include/cert.h +++ b/tools/cert_create/include/cert.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -48,7 +48,13 @@ struct cert_s { int cert_init(void); cert_t *cert_get_by_opt(const char *opt); int cert_add_ext(X509 *issuer, X509 *subject, int nid, char *value); -int cert_new(int key_alg, cert_t *cert, int days, int ca, STACK_OF(X509_EXTENSION) * sk); +int cert_new( + int key_alg, + int md_alg, + cert_t *cert, + int days, + int ca, + STACK_OF(X509_EXTENSION) * sk); /* Macro to register the certificates used in the CoT */ #define REGISTER_COT(_certs) \ diff --git a/tools/cert_create/include/key.h b/tools/cert_create/include/key.h index 304fa6154..1a253cc71 100644 --- a/tools/cert_create/include/key.h +++ b/tools/cert_create/include/key.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -30,6 +30,13 @@ enum { KEY_ALG_MAX_NUM }; +/* Supported hash algorithms */ +enum{ + HASH_ALG_SHA256, + HASH_ALG_SHA384, + HASH_ALG_SHA512, +}; + /* * This structure contains the relevant information to create the keys * required to sign the certificates. diff --git a/tools/cert_create/include/sha.h b/tools/cert_create/include/sha.h index 6907fa196..4d07a1e72 100644 --- a/tools/cert_create/include/sha.h +++ b/tools/cert_create/include/sha.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -7,6 +7,6 @@ #ifndef SHA_H_ #define SHA_H_ -int sha_file(const char *filename, unsigned char *md); +int sha_file(int md_alg, const char *filename, unsigned char *md); #endif /* SHA_H_ */ diff --git a/tools/cert_create/src/cert.c b/tools/cert_create/src/cert.c index 3f0b4d363..8e8aee699 100644 --- a/tools/cert_create/src/cert.c +++ b/tools/cert_create/src/cert.c @@ -56,6 +56,19 @@ error: return ret; } +const EVP_MD *get_digest(int alg) +{ + switch (alg) { + case HASH_ALG_SHA256: + return EVP_sha256(); + case HASH_ALG_SHA384: + return EVP_sha384(); + case HASH_ALG_SHA512: + return EVP_sha512(); + default: + return NULL; + } +} int cert_add_ext(X509 *issuer, X509 *subject, int nid, char *value) { @@ -79,7 +92,13 @@ int cert_add_ext(X509 *issuer, X509 *subject, int nid, char *value) return 1; } -int cert_new(int key_alg, cert_t *cert, int days, int ca, STACK_OF(X509_EXTENSION) * sk) +int cert_new( + int key_alg, + int md_alg, + cert_t *cert, + int days, + int ca, + STACK_OF(X509_EXTENSION) * sk) { EVP_PKEY *pkey = keys[cert->key].key; cert_t *issuer_cert = &certs[cert->issuer]; @@ -118,7 +137,7 @@ int cert_new(int key_alg, cert_t *cert, int days, int ca, STACK_OF(X509_EXTENSIO } /* Sign the certificate with the issuer key */ - if (!EVP_DigestSignInit(mdCtx, &pKeyCtx, EVP_sha256(), NULL, ikey)) { + if (!EVP_DigestSignInit(mdCtx, &pKeyCtx, get_digest(md_alg), NULL, ikey)) { ERR_print_errors_fp(stdout); goto END; } @@ -138,7 +157,7 @@ int cert_new(int key_alg, cert_t *cert, int days, int ca, STACK_OF(X509_EXTENSIO goto END; } - if (!EVP_PKEY_CTX_set_rsa_mgf1_md(pKeyCtx, EVP_sha256())) { + if (!EVP_PKEY_CTX_set_rsa_mgf1_md(pKeyCtx, get_digest(md_alg))) { ERR_print_errors_fp(stdout); goto END; } diff --git a/tools/cert_create/src/main.c b/tools/cert_create/src/main.c index 741242f59..4abfe6dd7 100644 --- a/tools/cert_create/src/main.c +++ b/tools/cert_create/src/main.c @@ -68,6 +68,7 @@ /* Global options */ static int key_alg; +static int hash_alg; static int new_keys; static int save_keys; static int print_cert; @@ -95,6 +96,12 @@ static const char *key_algs_str[] = { #endif /* OPENSSL_NO_EC */ }; +static const char *hash_algs_str[] = { + [HASH_ALG_SHA256] = "sha256", + [HASH_ALG_SHA384] = "sha384", + [HASH_ALG_SHA512] = "sha512", +}; + static void print_help(const char *cmd, const struct option *long_opt) { int rem, i = 0; @@ -150,6 +157,19 @@ static int get_key_alg(const char *key_alg_str) return -1; } +static int get_hash_alg(const char *hash_alg_str) +{ + int i; + + for (i = 0 ; i < NUM_ELEM(hash_algs_str) ; i++) { + if (0 == strcmp(hash_alg_str, hash_algs_str[i])) { + return i; + } + } + + return -1; +} + static void check_cmd_params(void) { cert_t *cert; @@ -227,6 +247,10 @@ static const cmd_opt_t common_cmd_opt[] = { "Key algorithm: 'rsa' (default) - RSAPSS scheme as per \ PKCS#1 v2.1, 'rsa_1_5' - RSA PKCS#1 v1.5, 'ecdsa'" }, + { + { "hash-alg", required_argument, NULL, 's' }, + "Hash algorithm : 'sha256' (default), 'sha384', 'sha512'" + }, { { "save-keys", no_argument, NULL, 'k' }, "Save key pairs into files. Filenames must be provided" @@ -254,7 +278,8 @@ int main(int argc, char *argv[]) const struct option *cmd_opt; const char *cur_opt; unsigned int err_code; - unsigned char md[SHA256_DIGEST_LENGTH]; + unsigned char md[SHA512_DIGEST_LENGTH]; + unsigned int md_len; const EVP_MD *md_info; NOTICE("CoT Generation Tool: %s\n", build_msg); @@ -262,6 +287,7 @@ int main(int argc, char *argv[]) /* Set default options */ key_alg = KEY_ALG_RSA; + hash_alg = HASH_ALG_SHA256; /* Add common command line options */ for (i = 0; i < NUM_ELEM(common_cmd_opt); i++) { @@ -291,7 +317,7 @@ int main(int argc, char *argv[]) while (1) { /* getopt_long stores the option index here. */ - c = getopt_long(argc, argv, "a:hknp", cmd_opt, &opt_idx); + c = getopt_long(argc, argv, "a:hknps:", cmd_opt, &opt_idx); /* Detect the end of the options. */ if (c == -1) { @@ -318,6 +344,13 @@ int main(int argc, char *argv[]) case 'p': print_cert = 1; break; + case 's': + hash_alg = get_hash_alg(optarg); + if (hash_alg < 0) { + ERROR("Invalid hash algorithm '%s'\n", optarg); + exit(1); + } + break; case CMD_OPT_EXT: cur_opt = cmd_opt_get_name(opt_idx); ext = ext_get_by_opt(cur_opt); @@ -343,9 +376,18 @@ int main(int argc, char *argv[]) /* Check command line arguments */ check_cmd_params(); - /* Indicate SHA256 as image hash algorithm in the certificate + /* Indicate SHA as image hash algorithm in the certificate * extension */ - md_info = EVP_sha256(); + if (hash_alg == HASH_ALG_SHA384) { + md_info = EVP_sha384(); + md_len = SHA384_DIGEST_LENGTH; + } else if (hash_alg == HASH_ALG_SHA512) { + md_info = EVP_sha512(); + md_len = SHA512_DIGEST_LENGTH; + } else { + md_info = EVP_sha256(); + md_len = SHA256_DIGEST_LENGTH; + } /* Load private keys from files (or generate new ones) */ for (i = 0 ; i < num_keys ; i++) { @@ -421,14 +463,14 @@ int main(int argc, char *argv[]) if (ext->arg == NULL) { if (ext->optional) { /* Include a hash filled with zeros */ - memset(md, 0x0, SHA256_DIGEST_LENGTH); + memset(md, 0x0, SHA512_DIGEST_LENGTH); } else { /* Do not include this hash in the certificate */ break; } } else { /* Calculate the hash of the file */ - if (!sha_file(ext->arg, md)) { + if (!sha_file(hash_alg, ext->arg, md)) { ERROR("Cannot calculate hash of %s\n", ext->arg); exit(1); @@ -436,7 +478,7 @@ int main(int argc, char *argv[]) } CHECK_NULL(cert_ext, ext_new_hash(ext_nid, EXT_CRIT, md_info, md, - SHA256_DIGEST_LENGTH)); + md_len)); break; case EXT_TYPE_PKEY: CHECK_NULL(cert_ext, ext_new_key(ext_nid, @@ -453,7 +495,7 @@ int main(int argc, char *argv[]) } /* Create certificate. Signed with corresponding key */ - if (cert->fn && !cert_new(key_alg, cert, VAL_DAYS, 0, sk)) { + if (cert->fn && !cert_new(key_alg, hash_alg, cert, VAL_DAYS, 0, sk)) { ERROR("Cannot create %s\n", cert->cn); exit(1); } diff --git a/tools/cert_create/src/sha.c b/tools/cert_create/src/sha.c index 297159302..3d977fbfe 100644 --- a/tools/cert_create/src/sha.c +++ b/tools/cert_create/src/sha.c @@ -1,20 +1,21 @@ /* - * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ #include #include - #include "debug.h" +#include "key.h" #define BUFFER_SIZE 256 -int sha_file(const char *filename, unsigned char *md) +int sha_file(int md_alg, const char *filename, unsigned char *md) { FILE *inFile; SHA256_CTX shaContext; + SHA512_CTX sha512Context; int bytes; unsigned char data[BUFFER_SIZE]; @@ -29,11 +30,25 @@ int sha_file(const char *filename, unsigned char *md) return 0; } - SHA256_Init(&shaContext); - while ((bytes = fread(data, 1, BUFFER_SIZE, inFile)) != 0) { - SHA256_Update(&shaContext, data, bytes); + if (md_alg == HASH_ALG_SHA384) { + SHA384_Init(&sha512Context); + while ((bytes = fread(data, 1, BUFFER_SIZE, inFile)) != 0) { + SHA384_Update(&sha512Context, data, bytes); + } + SHA384_Final(md, &sha512Context); + } else if (md_alg == HASH_ALG_SHA512) { + SHA512_Init(&sha512Context); + while ((bytes = fread(data, 1, BUFFER_SIZE, inFile)) != 0) { + SHA512_Update(&sha512Context, data, bytes); + } + SHA512_Final(md, &sha512Context); + } else { + SHA256_Init(&shaContext); + while ((bytes = fread(data, 1, BUFFER_SIZE, inFile)) != 0) { + SHA256_Update(&shaContext, data, bytes); + } + SHA256_Final(md, &shaContext); } - SHA256_Final(md, &shaContext); fclose(inFile); return 1;