tools: add an option -hash-alg for cert_create
authorQixiang Xu <qixiang.xu@arm.com>
Thu, 9 Nov 2017 05:51:58 +0000 (13:51 +0800)
committerQixiang Xu <qixiang.xu@arm.com>
Tue, 21 Nov 2017 06:16:18 +0000 (14:16 +0800)
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 <qixiang.xu@arm.com>
tools/cert_create/include/cert.h
tools/cert_create/include/key.h
tools/cert_create/include/sha.h
tools/cert_create/src/cert.c
tools/cert_create/src/main.c
tools/cert_create/src/sha.c

index 256e7afd25b0cd6f5b23d1484a46995cac97c804..9b4ef5af6d1f9e35a9c579b044b86a71749c273e 100644 (file)
@@ -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) \
index 304fa6154f80fa8ca92342c3f44d12ffddce1ea2..1a253cc713cccee21352a1000fcd97f9469a65d9 100644 (file)
@@ -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.
index 6907fa196635b6e0d4f841621b552028d0991ad9..4d07a1e72d52816c1b0566773a0cd89a40f7dc65 100644 (file)
@@ -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_ */
index 3f0b4d363c12f4bef883af3c4ec21a48039b3fe2..8e8aee699c945d8854945b60a842c73af7213281 100644 (file)
@@ -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;
                }
index 741242f59f9bc1b900a8066e569623e0c92c016b..4abfe6dd766ce3aa3d73506b699175bf34b0f970 100644 (file)
@@ -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);
                }
index 2971593024a8f3ac62f6a100eb19ddc18c125c25..3d977fbfed7cb80e38a8d65381a549e35e6780d8 100644 (file)
@@ -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 <openssl/sha.h>
 #include <stdio.h>
-
 #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;