diff options
Diffstat (limited to 'tools/cert_create/src/main.c')
-rw-r--r-- | tools/cert_create/src/main.c | 813 |
1 files changed, 299 insertions, 514 deletions
diff --git a/tools/cert_create/src/main.c b/tools/cert_create/src/main.c index 6df367a2..741242f5 100644 --- a/tools/cert_create/src/main.c +++ b/tools/cert_create/src/main.c @@ -1,33 +1,11 @@ /* - * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of ARM nor the names of its contributors may be used - * to endorse or promote products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * SPDX-License-Identifier: BSD-3-Clause */ +#include <assert.h> +#include <ctype.h> #include <getopt.h> #include <stdio.h> #include <stdlib.h> @@ -40,15 +18,21 @@ #include <openssl/sha.h> #include <openssl/x509v3.h> +#if USE_TBBR_DEFS +#include <tbbr_oid.h> +#else +#include <platform_oid.h> +#endif + #include "cert.h" +#include "cmd_opt.h" #include "debug.h" #include "ext.h" #include "key.h" -#include "platform_oid.h" #include "sha.h" -#include "tbb_ext.h" -#include "tbb_cert.h" -#include "tbb_key.h" +#include "tbbr/tbb_cert.h" +#include "tbbr/tbb_ext.h" +#include "tbbr/tbb_key.h" /* * Helper macros to simplify the code. This macro assigns the return value of @@ -79,49 +63,14 @@ #define MAX_FILENAME_LEN 1024 #define VAL_DAYS 7300 #define ID_TO_BIT_MASK(id) (1 << id) -#define NVCOUNTER_VALUE 0 - -/* Files */ -enum { - /* Image file names (inputs) */ - BL2_ID = 0, - BL30_ID, - BL31_ID, - BL32_ID, - BL33_ID, - /* Certificate file names (outputs) */ - BL2_CERT_ID, - TRUSTED_KEY_CERT_ID, - BL30_KEY_CERT_ID, - BL30_CERT_ID, - BL31_KEY_CERT_ID, - BL31_CERT_ID, - BL32_KEY_CERT_ID, - BL32_CERT_ID, - BL33_KEY_CERT_ID, - BL33_CERT_ID, - /* Key file names (input/output) */ - ROT_KEY_ID, - TRUSTED_WORLD_KEY_ID, - NON_TRUSTED_WORLD_KEY_ID, - BL30_KEY_ID, - BL31_KEY_ID, - BL32_KEY_ID, - BL33_KEY_ID, - NUM_OPTS -}; +#define NUM_ELEM(x) ((sizeof(x)) / (sizeof(x[0]))) +#define HELP_OPT_MAX_LEN 128 /* Global options */ +static int key_alg; static int new_keys; static int save_keys; static int print_cert; -static int bl30_present; -static int bl32_present; - -/* We are not checking nvcounters in TF. Include them in the certificates but - * the value will be set to 0 */ -static int tf_nvcounter; -static int non_tf_nvcounter; /* Info messages created in the Makefile */ extern const char build_msg[]; @@ -138,44 +87,24 @@ static char *strdup(const char *str) return dup; } -/* Command line options */ -static const struct option long_opt[] = { - /* Binary images */ - {"bl2", required_argument, 0, BL2_ID}, - {"bl30", required_argument, 0, BL30_ID}, - {"bl31", required_argument, 0, BL31_ID}, - {"bl32", required_argument, 0, BL32_ID}, - {"bl33", required_argument, 0, BL33_ID}, - /* Certificate files */ - {"bl2-cert", required_argument, 0, BL2_CERT_ID}, - {"trusted-key-cert", required_argument, 0, TRUSTED_KEY_CERT_ID}, - {"bl30-key-cert", required_argument, 0, BL30_KEY_CERT_ID}, - {"bl30-cert", required_argument, 0, BL30_CERT_ID}, - {"bl31-key-cert", required_argument, 0, BL31_KEY_CERT_ID}, - {"bl31-cert", required_argument, 0, BL31_CERT_ID}, - {"bl32-key-cert", required_argument, 0, BL32_KEY_CERT_ID}, - {"bl32-cert", required_argument, 0, BL32_CERT_ID}, - {"bl33-key-cert", required_argument, 0, BL33_KEY_CERT_ID}, - {"bl33-cert", required_argument, 0, BL33_CERT_ID}, - /* Private key files */ - {"rot-key", required_argument, 0, ROT_KEY_ID}, - {"trusted-world-key", required_argument, 0, TRUSTED_WORLD_KEY_ID}, - {"non-trusted-world-key", required_argument, 0, NON_TRUSTED_WORLD_KEY_ID}, - {"bl30-key", required_argument, 0, BL30_KEY_ID}, - {"bl31-key", required_argument, 0, BL31_KEY_ID}, - {"bl32-key", required_argument, 0, BL32_KEY_ID}, - {"bl33-key", required_argument, 0, BL33_KEY_ID}, - /* Common options */ - {"help", no_argument, 0, 'h'}, - {"save-keys", no_argument, 0, 'k'}, - {"new-chain", no_argument, 0, 'n'}, - {"print-cert", no_argument, 0, 'p'}, - {0, 0, 0, 0} +static const char *key_algs_str[] = { + [KEY_ALG_RSA] = "rsa", + [KEY_ALG_RSA_1_5] = "rsa_1_5", +#ifndef OPENSSL_NO_EC + [KEY_ALG_ECDSA] = "ecdsa" +#endif /* OPENSSL_NO_EC */ }; -static void print_help(const char *cmd) +static void print_help(const char *cmd, const struct option *long_opt) { - int i = 0; + int rem, i = 0; + const struct option *opt; + char line[HELP_OPT_MAX_LEN]; + char *p; + + assert(cmd != NULL); + assert(long_opt != NULL); + printf("\n\n"); printf("The certificate generation tool loads the binary images and\n" "optionally the RSA keys, and outputs the key and content\n" @@ -183,107 +112,186 @@ static void print_help(const char *cmd) "If keys are provided, they must be in PEM format.\n" "Certificates are generated in DER format.\n"); printf("\n"); - printf("Usage:\n\n"); - printf(" %s [-hknp] \\\n", cmd); - for (i = 0; i < NUM_OPTS; i++) { - printf(" --%s <file> \\\n", long_opt[i].name); + printf("Usage:\n"); + printf("\t%s [OPTIONS]\n\n", cmd); + + printf("Available options:\n"); + opt = long_opt; + while (opt->name) { + p = line; + rem = HELP_OPT_MAX_LEN; + if (isalpha(opt->val)) { + /* Short format */ + sprintf(p, "-%c,", (char)opt->val); + p += 3; + rem -= 3; + } + snprintf(p, rem, "--%s %s", opt->name, + (opt->has_arg == required_argument) ? "<arg>" : ""); + printf("\t%-32s %s\n", line, cmd_opt_get_help_msg(i)); + opt++; + i++; } printf("\n"); - printf("-h Print help and exit\n"); - printf("-k Save key pairs into files. Filenames must be provided\n"); - printf("-n Generate new key pairs if no key files are provided\n"); - printf("-p Print the certificates in the standard output\n"); - printf("\n"); exit(0); } -static void check_cmd_params(void) +static int get_key_alg(const char *key_alg_str) { - /* BL2, BL31 and BL33 are mandatory */ - if (certs[BL2_CERT].bin == NULL) { - ERROR("BL2 image not specified\n"); - exit(1); - } - - if (certs[BL31_CERT].bin == NULL) { - ERROR("BL31 image not specified\n"); - exit(1); - } + int i; - if (certs[BL33_CERT].bin == NULL) { - ERROR("BL33 image not specified\n"); - exit(1); + for (i = 0 ; i < NUM_ELEM(key_algs_str) ; i++) { + if (0 == strcmp(key_alg_str, key_algs_str[i])) { + return i; + } } - /* BL30 and BL32 are optional */ - if (certs[BL30_CERT].bin != NULL) { - bl30_present = 1; - } + return -1; +} - if (certs[BL32_CERT].bin != NULL) { - bl32_present = 1; +static void check_cmd_params(void) +{ + cert_t *cert; + ext_t *ext; + key_t *key; + int i, j; + + /* Only save new keys */ + if (save_keys && !new_keys) { + ERROR("Only new keys can be saved to disk\n"); + exit(1); } - /* TODO: Certificate filenames */ - - /* Filenames to store keys must be specified */ - if (save_keys || !new_keys) { - if (keys[ROT_KEY].fn == NULL) { - ERROR("ROT key not specified\n"); - exit(1); + /* Check that all required options have been specified in the + * command line */ + for (i = 0; i < num_certs; i++) { + cert = &certs[i]; + if (cert->fn == NULL) { + /* Certificate not requested. Skip to the next one */ + continue; } - if (keys[TRUSTED_WORLD_KEY].fn == NULL) { - ERROR("Trusted World key not specified\n"); - exit(1); - } - - if (keys[NON_TRUSTED_WORLD_KEY].fn == NULL) { - ERROR("Non-trusted World key not specified\n"); - exit(1); - } - - if (keys[BL31_KEY].fn == NULL) { - ERROR("BL31 key not specified\n"); - exit(1); - } - - if (keys[BL33_KEY].fn == NULL) { - ERROR("BL33 key not specified\n"); - exit(1); - } - - if (bl30_present && (keys[BL30_KEY].fn == NULL)) { - ERROR("BL30 key not specified\n"); - exit(1); - } - - if (bl32_present && (keys[BL32_KEY].fn == NULL)) { - ERROR("BL32 key not specified\n"); - exit(1); + /* Check that all parameters required to create this certificate + * have been specified in the command line */ + for (j = 0; j < cert->num_ext; j++) { + ext = &extensions[cert->ext[j]]; + switch (ext->type) { + case EXT_TYPE_NVCOUNTER: + /* Counter value must be specified */ + if ((!ext->optional) && (ext->arg == NULL)) { + ERROR("Value for '%s' not specified\n", + ext->ln); + exit(1); + } + break; + case EXT_TYPE_PKEY: + /* Key filename must be specified */ + key = &keys[ext->attr.key]; + if (!new_keys && key->fn == NULL) { + ERROR("Key '%s' required by '%s' not " + "specified\n", key->desc, + cert->cn); + exit(1); + } + break; + case EXT_TYPE_HASH: + /* + * Binary image must be specified + * unless it is explicitly made optional. + */ + if ((!ext->optional) && (ext->arg == NULL)) { + ERROR("Image for '%s' not specified\n", + ext->ln); + exit(1); + } + break; + default: + ERROR("Unknown extension type '%d' in '%s'\n", + ext->type, ext->ln); + exit(1); + break; + } } } } +/* Common command line options */ +static const cmd_opt_t common_cmd_opt[] = { + { + { "help", no_argument, NULL, 'h' }, + "Print this message and exit" + }, + { + { "key-alg", required_argument, NULL, 'a' }, + "Key algorithm: 'rsa' (default) - RSAPSS scheme as per \ +PKCS#1 v2.1, 'rsa_1_5' - RSA PKCS#1 v1.5, 'ecdsa'" + }, + { + { "save-keys", no_argument, NULL, 'k' }, + "Save key pairs into files. Filenames must be provided" + }, + { + { "new-keys", no_argument, NULL, 'n' }, + "Generate new key pairs if no key files are provided" + }, + { + { "print-cert", no_argument, NULL, 'p' }, + "Print the certificates in the standard output" + } +}; + int main(int argc, char *argv[]) { - STACK_OF(X509_EXTENSION) * sk = NULL; - X509_EXTENSION *hash_ext = NULL; - X509_EXTENSION *nvctr_ext = NULL; - X509_EXTENSION *trusted_key_ext = NULL; - X509_EXTENSION *non_trusted_key_ext = NULL; - FILE *file = NULL; - int i, tz_nvctr_nid, ntz_nvctr_nid, hash_nid, pk_nid; + STACK_OF(X509_EXTENSION) * sk; + X509_EXTENSION *cert_ext = NULL; + ext_t *ext; + key_t *key; + cert_t *cert; + FILE *file; + int i, j, ext_nid, nvctr; int c, opt_idx = 0; + const struct option *cmd_opt; + const char *cur_opt; + unsigned int err_code; unsigned char md[SHA256_DIGEST_LENGTH]; + const EVP_MD *md_info; NOTICE("CoT Generation Tool: %s\n", build_msg); NOTICE("Target platform: %s\n", platform_msg); + /* Set default options */ + key_alg = KEY_ALG_RSA; + + /* Add common command line options */ + for (i = 0; i < NUM_ELEM(common_cmd_opt); i++) { + cmd_opt_add(&common_cmd_opt[i]); + } + + /* Initialize the certificates */ + if (cert_init() != 0) { + ERROR("Cannot initialize certificates\n"); + exit(1); + } + + /* Initialize the keys */ + if (key_init() != 0) { + ERROR("Cannot initialize keys\n"); + exit(1); + } + + /* Initialize the new types and register OIDs for the extensions */ + if (ext_init() != 0) { + ERROR("Cannot initialize TBB extensions\n"); + exit(1); + } + + /* Get the command line options populated during the initialization */ + cmd_opt = cmd_opt_get_array(); + while (1) { /* getopt_long stores the option index here. */ - c = getopt_long(argc, argv, "hknp", long_opt, &opt_idx); + c = getopt_long(argc, argv, "a:hknp", cmd_opt, &opt_idx); /* Detect the end of the options. */ if (c == -1) { @@ -291,8 +299,15 @@ int main(int argc, char *argv[]) } switch (c) { + case 'a': + key_alg = get_key_alg(optarg); + if (key_alg < 0) { + ERROR("Invalid key algorithm '%s'\n", optarg); + exit(1); + } + break; case 'h': - print_help(argv[0]); + print_help(argv[0], cmd_opt); break; case 'k': save_keys = 1; @@ -303,378 +318,153 @@ int main(int argc, char *argv[]) case 'p': print_cert = 1; break; - case BL2_ID: - certs[BL2_CERT].bin = strdup(optarg); - break; - case BL30_ID: - certs[BL30_CERT].bin = strdup(optarg); - break; - case BL31_ID: - certs[BL31_CERT].bin = strdup(optarg); - break; - case BL32_ID: - certs[BL32_CERT].bin = strdup(optarg); - break; - case BL33_ID: - certs[BL33_CERT].bin = strdup(optarg); + case CMD_OPT_EXT: + cur_opt = cmd_opt_get_name(opt_idx); + ext = ext_get_by_opt(cur_opt); + ext->arg = strdup(optarg); break; - case BL2_CERT_ID: - certs[BL2_CERT].fn = strdup(optarg); + case CMD_OPT_KEY: + cur_opt = cmd_opt_get_name(opt_idx); + key = key_get_by_opt(cur_opt); + key->fn = strdup(optarg); break; - case TRUSTED_KEY_CERT_ID: - certs[TRUSTED_KEY_CERT].fn = strdup(optarg); - break; - case BL30_KEY_CERT_ID: - certs[BL30_KEY_CERT].fn = strdup(optarg); - break; - case BL30_CERT_ID: - certs[BL30_CERT].fn = strdup(optarg); - break; - case BL31_KEY_CERT_ID: - certs[BL31_KEY_CERT].fn = strdup(optarg); - break; - case BL31_CERT_ID: - certs[BL31_CERT].fn = strdup(optarg); - break; - case BL32_KEY_CERT_ID: - certs[BL32_KEY_CERT].fn = strdup(optarg); - break; - case BL32_CERT_ID: - certs[BL32_CERT].fn = strdup(optarg); - break; - case BL33_KEY_CERT_ID: - certs[BL33_KEY_CERT].fn = strdup(optarg); - break; - case BL33_CERT_ID: - certs[BL33_CERT].fn = strdup(optarg); - break; - case ROT_KEY_ID: - keys[ROT_KEY].fn = strdup(optarg); - break; - case TRUSTED_WORLD_KEY_ID: - keys[TRUSTED_WORLD_KEY].fn = strdup(optarg); - break; - case NON_TRUSTED_WORLD_KEY_ID: - keys[NON_TRUSTED_WORLD_KEY].fn = strdup(optarg); - break; - case BL30_KEY_ID: - keys[BL30_KEY].fn = strdup(optarg); - break; - case BL31_KEY_ID: - keys[BL31_KEY].fn = strdup(optarg); - break; - case BL32_KEY_ID: - keys[BL32_KEY].fn = strdup(optarg); - break; - case BL33_KEY_ID: - keys[BL33_KEY].fn = strdup(optarg); + case CMD_OPT_CERT: + cur_opt = cmd_opt_get_name(opt_idx); + cert = cert_get_by_opt(cur_opt); + cert->fn = strdup(optarg); break; case '?': default: - printf("%s\n", optarg); + print_help(argv[0], cmd_opt); exit(1); } } - /* Set the value of the NVCounters */ - tf_nvcounter = NVCOUNTER_VALUE; - non_tf_nvcounter = NVCOUNTER_VALUE; - /* Check command line arguments */ check_cmd_params(); - /* Register the new types and OIDs for the extensions */ - if (ext_init(tbb_ext) != 0) { - ERROR("Cannot initialize TBB extensions\n"); - exit(1); - } - - /* Get non-volatile counters NIDs */ - CHECK_OID(tz_nvctr_nid, TZ_FW_NVCOUNTER_OID); - CHECK_OID(ntz_nvctr_nid, NTZ_FW_NVCOUNTER_OID); + /* Indicate SHA256 as image hash algorithm in the certificate + * extension */ + md_info = EVP_sha256(); /* Load private keys from files (or generate new ones) */ - if (new_keys) { - for (i = 0 ; i < NUM_KEYS ; i++) { - if (!key_new(&keys[i])) { - ERROR("Error creating %s\n", keys[i].desc); - exit(1); - } - } - } else { - for (i = 0 ; i < NUM_KEYS ; i++) { - if (!key_load(&keys[i])) { - ERROR("Error loading %s\n", keys[i].desc); - exit(1); - } - } - } - - /* ********************************************************************* - * BL2 certificate (Trusted Boot Firmware certificate): - * - Self-signed with OEM ROT private key - * - Extensions: - * - TrustedFirmwareNVCounter (TODO) - * - BL2 hash - **********************************************************************/ - CHECK_NULL(sk, sk_X509_EXTENSION_new_null()); - - /* Add the NVCounter as a critical extension */ - CHECK_NULL(nvctr_ext, ext_new_nvcounter(tz_nvctr_nid, EXT_CRIT, - tf_nvcounter)); - sk_X509_EXTENSION_push(sk, nvctr_ext); - - /* Add hash of BL2 as an extension */ - if (!sha_file(certs[BL2_CERT].bin, md)) { - ERROR("Cannot calculate the hash of %s\n", certs[BL2_CERT].bin); - exit(1); - } - CHECK_OID(hash_nid, BL2_HASH_OID); - CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md, - SHA256_DIGEST_LENGTH)); - sk_X509_EXTENSION_push(sk, hash_ext); - - /* Create certificate. Signed with ROT key */ - if (!cert_new(&certs[BL2_CERT], VAL_DAYS, 0, sk)) { - ERROR("Cannot create %s\n", certs[BL2_CERT].cn); - exit(1); - } - sk_X509_EXTENSION_free(sk); - - /* ********************************************************************* - * Trusted Key certificate: - * - Self-signed with OEM ROT private key - * - Extensions: - * - TrustedFirmwareNVCounter (TODO) - * - TrustedWorldPK - * - NonTrustedWorldPK - **********************************************************************/ - CHECK_NULL(sk, sk_X509_EXTENSION_new_null()); - CHECK_NULL(nvctr_ext, ext_new_nvcounter(tz_nvctr_nid, EXT_CRIT, - tf_nvcounter)); - sk_X509_EXTENSION_push(sk, nvctr_ext); - CHECK_OID(pk_nid, TZ_WORLD_PK_OID); - CHECK_NULL(trusted_key_ext, ext_new_key(pk_nid, EXT_CRIT, - keys[TRUSTED_WORLD_KEY].key)); - sk_X509_EXTENSION_push(sk, trusted_key_ext); - CHECK_OID(pk_nid, NTZ_WORLD_PK_OID); - CHECK_NULL(non_trusted_key_ext, ext_new_key(pk_nid, EXT_CRIT, - keys[NON_TRUSTED_WORLD_KEY].key)); - sk_X509_EXTENSION_push(sk, non_trusted_key_ext); - if (!cert_new(&certs[TRUSTED_KEY_CERT], VAL_DAYS, 0, sk)) { - ERROR("Cannot create %s\n", certs[TRUSTED_KEY_CERT].cn); - exit(1); - } - sk_X509_EXTENSION_free(sk); - - /* ********************************************************************* - * BL30 Key certificate (Trusted SCP Firmware Key certificate): - * - Self-signed with Trusted World key - * - Extensions: - * - TrustedFirmwareNVCounter (TODO) - * - SCPFirmwareContentCertPK - **********************************************************************/ - if (bl30_present) { - CHECK_NULL(sk, sk_X509_EXTENSION_new_null()); - CHECK_NULL(nvctr_ext, ext_new_nvcounter(tz_nvctr_nid, EXT_CRIT, - tf_nvcounter)); - sk_X509_EXTENSION_push(sk, nvctr_ext); - CHECK_OID(pk_nid, BL30_CONTENT_CERT_PK_OID); - CHECK_NULL(trusted_key_ext, ext_new_key(pk_nid, EXT_CRIT, - keys[BL30_KEY].key)); - sk_X509_EXTENSION_push(sk, trusted_key_ext); - if (!cert_new(&certs[BL30_KEY_CERT], VAL_DAYS, 0, sk)) { - ERROR("Cannot create %s\n", certs[BL30_KEY_CERT].cn); + for (i = 0 ; i < num_keys ; i++) { + if (!key_new(&keys[i])) { + ERROR("Failed to allocate key container\n"); exit(1); } - sk_X509_EXTENSION_free(sk); - } - /* ********************************************************************* - * BL30 certificate (SCP Firmware Content certificate): - * - Signed with Trusted World Key - * - Extensions: - * - TrustedFirmwareNVCounter (TODO) - * - SCPFirmwareHash - **********************************************************************/ - if (bl30_present) { - CHECK_NULL(sk, sk_X509_EXTENSION_new_null()); - CHECK_NULL(nvctr_ext, ext_new_nvcounter(tz_nvctr_nid, EXT_CRIT, - tf_nvcounter)); - sk_X509_EXTENSION_push(sk, nvctr_ext); + /* First try to load the key from disk */ + if (key_load(&keys[i], &err_code)) { + /* Key loaded successfully */ + continue; + } - if (!sha_file(certs[BL30_CERT].bin, md)) { - ERROR("Cannot calculate the hash of %s\n", - certs[BL30_CERT].bin); + /* Key not loaded. Check the error code */ + if (err_code == KEY_ERR_LOAD) { + /* File exists, but it does not contain a valid private + * key. Abort. */ + ERROR("Error loading '%s'\n", keys[i].fn); exit(1); } - CHECK_OID(hash_nid, BL30_HASH_OID); - CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md, - SHA256_DIGEST_LENGTH)); - sk_X509_EXTENSION_push(sk, hash_ext); - if (!cert_new(&certs[BL30_CERT], VAL_DAYS, 0, sk)) { - ERROR("Cannot create %s\n", certs[BL30_CERT].cn); + /* File does not exist, could not be opened or no filename was + * given */ + if (new_keys) { + /* Try to create a new key */ + NOTICE("Creating new key for '%s'\n", keys[i].desc); + if (!key_create(&keys[i], key_alg)) { + ERROR("Error creating key '%s'\n", keys[i].desc); + exit(1); + } + } else { + if (err_code == KEY_ERR_OPEN) { + ERROR("Error opening '%s'\n", keys[i].fn); + } else { + ERROR("Key '%s' not specified\n", keys[i].desc); + } exit(1); } - - sk_X509_EXTENSION_free(sk); - } - - /* ********************************************************************* - * BL31 Key certificate (Trusted SoC Firmware Key certificate): - * - Self-signed with Trusted World key - * - Extensions: - * - TrustedFirmwareNVCounter (TODO) - * - SoCFirmwareContentCertPK - **********************************************************************/ - CHECK_NULL(sk, sk_X509_EXTENSION_new_null()); - CHECK_NULL(nvctr_ext, ext_new_nvcounter(tz_nvctr_nid, EXT_CRIT, - tf_nvcounter)); - sk_X509_EXTENSION_push(sk, nvctr_ext); - CHECK_OID(pk_nid, BL31_CONTENT_CERT_PK_OID); - CHECK_NULL(trusted_key_ext, ext_new_key(pk_nid, EXT_CRIT, - keys[BL31_KEY].key)); - sk_X509_EXTENSION_push(sk, trusted_key_ext); - if (!cert_new(&certs[BL31_KEY_CERT], VAL_DAYS, 0, sk)) { - ERROR("Cannot create %s\n", certs[BL31_KEY_CERT].cn); - exit(1); - } - sk_X509_EXTENSION_free(sk); - - /* ********************************************************************* - * BL31 certificate (SOC Firmware Content certificate): - * - Signed with Trusted World Key - * - Extensions: - * - TrustedFirmwareNVCounter (TODO) - * - BL31 hash - **********************************************************************/ - CHECK_NULL(sk, sk_X509_EXTENSION_new_null()); - CHECK_NULL(nvctr_ext, ext_new_nvcounter(tz_nvctr_nid, EXT_CRIT, - tf_nvcounter)); - sk_X509_EXTENSION_push(sk, nvctr_ext); - - if (!sha_file(certs[BL31_CERT].bin, md)) { - ERROR("Cannot calculate the hash of %s\n", certs[BL31_CERT].bin); - exit(1); } - CHECK_OID(hash_nid, BL31_HASH_OID); - CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md, - SHA256_DIGEST_LENGTH)); - sk_X509_EXTENSION_push(sk, hash_ext); - if (!cert_new(&certs[BL31_CERT], VAL_DAYS, 0, sk)) { - ERROR("Cannot create %s\n", certs[BL31_CERT].cn); - exit(1); - } + /* Create the certificates */ + for (i = 0 ; i < num_certs ; i++) { - sk_X509_EXTENSION_free(sk); + cert = &certs[i]; - /* ********************************************************************* - * BL32 Key certificate (Trusted OS Firmware Key certificate): - * - Self-signed with Trusted World key - * - Extensions: - * - TrustedFirmwareNVCounter (TODO) - * - TrustedOSFirmwareContentCertPK - **********************************************************************/ - if (bl32_present) { + /* Create a new stack of extensions. This stack will be used + * to create the certificate */ CHECK_NULL(sk, sk_X509_EXTENSION_new_null()); - CHECK_NULL(nvctr_ext, ext_new_nvcounter(tz_nvctr_nid, EXT_CRIT, - tf_nvcounter)); - sk_X509_EXTENSION_push(sk, nvctr_ext); - CHECK_OID(pk_nid, BL32_CONTENT_CERT_PK_OID); - CHECK_NULL(trusted_key_ext, ext_new_key(pk_nid, EXT_CRIT, - keys[BL32_KEY].key)); - sk_X509_EXTENSION_push(sk, trusted_key_ext); - if (!cert_new(&certs[BL32_KEY_CERT], VAL_DAYS, 0, sk)) { - ERROR("Cannot create %s\n", certs[BL32_KEY_CERT].cn); - exit(1); - } - sk_X509_EXTENSION_free(sk); - } - /* ********************************************************************* - * BL32 certificate (TrustedOS Firmware Content certificate): - * - Signed with Trusted World Key - * - Extensions: - * - TrustedFirmwareNVCounter (TODO) - * - BL32 hash - **********************************************************************/ - if (bl32_present) { - CHECK_NULL(sk, sk_X509_EXTENSION_new_null()); - CHECK_NULL(nvctr_ext, ext_new_nvcounter(tz_nvctr_nid, EXT_CRIT, - tf_nvcounter)); - sk_X509_EXTENSION_push(sk, nvctr_ext); + for (j = 0 ; j < cert->num_ext ; j++) { + + ext = &extensions[cert->ext[j]]; + + /* Get OpenSSL internal ID for this extension */ + CHECK_OID(ext_nid, ext->oid); + + /* + * Three types of extensions are currently supported: + * - EXT_TYPE_NVCOUNTER + * - EXT_TYPE_HASH + * - EXT_TYPE_PKEY + */ + switch (ext->type) { + case EXT_TYPE_NVCOUNTER: + if (ext->arg) { + nvctr = atoi(ext->arg); + CHECK_NULL(cert_ext, ext_new_nvcounter(ext_nid, + EXT_CRIT, nvctr)); + } + break; + case EXT_TYPE_HASH: + if (ext->arg == NULL) { + if (ext->optional) { + /* Include a hash filled with zeros */ + memset(md, 0x0, SHA256_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)) { + ERROR("Cannot calculate hash of %s\n", + ext->arg); + exit(1); + } + } + CHECK_NULL(cert_ext, ext_new_hash(ext_nid, + EXT_CRIT, md_info, md, + SHA256_DIGEST_LENGTH)); + break; + case EXT_TYPE_PKEY: + CHECK_NULL(cert_ext, ext_new_key(ext_nid, + EXT_CRIT, keys[ext->attr.key].key)); + break; + default: + ERROR("Unknown extension type '%d' in %s\n", + ext->type, cert->cn); + exit(1); + } - if (!sha_file(certs[BL32_CERT].bin, md)) { - ERROR("Cannot calculate the hash of %s\n", - certs[BL32_CERT].bin); - exit(1); + /* Push the extension into the stack */ + sk_X509_EXTENSION_push(sk, cert_ext); } - CHECK_OID(hash_nid, BL32_HASH_OID); - CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md, - SHA256_DIGEST_LENGTH)); - sk_X509_EXTENSION_push(sk, hash_ext); - if (!cert_new(&certs[BL32_CERT], VAL_DAYS, 0, sk)) { - ERROR("Cannot create %s\n", certs[BL32_CERT].cn); + /* Create certificate. Signed with corresponding key */ + if (cert->fn && !cert_new(key_alg, cert, VAL_DAYS, 0, sk)) { + ERROR("Cannot create %s\n", cert->cn); exit(1); } sk_X509_EXTENSION_free(sk); } - /* ********************************************************************* - * BL33 Key certificate (Non Trusted Firmware Key certificate): - * - Self-signed with Non Trusted World key - * - Extensions: - * - NonTrustedFirmwareNVCounter (TODO) - * - NonTrustedFirmwareContentCertPK - **********************************************************************/ - CHECK_NULL(sk, sk_X509_EXTENSION_new_null()); - CHECK_NULL(nvctr_ext, ext_new_nvcounter(ntz_nvctr_nid, EXT_CRIT, - non_tf_nvcounter)); - sk_X509_EXTENSION_push(sk, nvctr_ext); - CHECK_OID(pk_nid, BL33_CONTENT_CERT_PK_OID); - CHECK_NULL(non_trusted_key_ext, ext_new_key(pk_nid, EXT_CRIT, - keys[BL33_KEY].key)); - sk_X509_EXTENSION_push(sk, non_trusted_key_ext); - if (!cert_new(&certs[BL33_KEY_CERT], VAL_DAYS, 0, sk)) { - ERROR("Cannot create %s\n", certs[BL33_KEY_CERT].cn); - exit(1); - } - sk_X509_EXTENSION_free(sk); - - /* ********************************************************************* - * BL33 certificate (Non-Trusted World Content certificate): - * - Signed with Non-Trusted World Key - * - Extensions: - * - NonTrustedFirmwareNVCounter (TODO) - * - BL33 hash - **********************************************************************/ - CHECK_NULL(sk, sk_X509_EXTENSION_new_null()); - CHECK_NULL(nvctr_ext, ext_new_nvcounter(ntz_nvctr_nid, EXT_CRIT, - non_tf_nvcounter)); - sk_X509_EXTENSION_push(sk, nvctr_ext); - - if (!sha_file(certs[BL33_CERT].bin, md)) { - ERROR("Cannot calculate the hash of %s\n", certs[BL33_CERT].bin); - exit(1); - } - CHECK_OID(hash_nid, BL33_HASH_OID); - CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md, - SHA256_DIGEST_LENGTH)); - sk_X509_EXTENSION_push(sk, hash_ext); - - if (!cert_new(&certs[BL33_CERT], VAL_DAYS, 0, sk)) { - ERROR("Cannot create %s\n", certs[BL33_CERT].cn); - exit(1); - } - sk_X509_EXTENSION_free(sk); /* Print the certificates */ if (print_cert) { - for (i = 0 ; i < NUM_CERTIFICATES ; i++) { + for (i = 0 ; i < num_certs ; i++) { if (!certs[i].x) { continue; } @@ -684,7 +474,7 @@ int main(int argc, char *argv[]) } /* Save created certificates to files */ - for (i = 0 ; i < NUM_CERTIFICATES ; i++) { + for (i = 0 ; i < num_certs ; i++) { if (certs[i].x && certs[i].fn) { file = fopen(certs[i].fn, "w"); if (file != NULL) { @@ -698,18 +488,13 @@ int main(int argc, char *argv[]) /* Save keys */ if (save_keys) { - for (i = 0 ; i < NUM_KEYS ; i++) { + for (i = 0 ; i < num_keys ; i++) { if (!key_store(&keys[i])) { ERROR("Cannot save %s\n", keys[i].desc); } } } - X509_EXTENSION_free(hash_ext); - X509_EXTENSION_free(nvctr_ext); - X509_EXTENSION_free(trusted_key_ext); - X509_EXTENSION_free(non_trusted_key_ext); - #ifndef OPENSSL_NO_ENGINE ENGINE_cleanup(); #endif |