16f971622SJuan Castillo /* 2*a004ee8dSChris Kay * Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved. 36f971622SJuan Castillo * 482cb2c1aSdp-arm * SPDX-License-Identifier: BSD-3-Clause 56f971622SJuan Castillo */ 66f971622SJuan Castillo 7159807e2SJuan Castillo #include <assert.h> 8159807e2SJuan Castillo #include <ctype.h> 96f971622SJuan Castillo #include <getopt.h> 106f971622SJuan Castillo #include <stdio.h> 116f971622SJuan Castillo #include <stdlib.h> 126f971622SJuan Castillo #include <string.h> 13dfe0f4c2SJustin Chadwell #include <stdbool.h> 146f971622SJuan Castillo 156f971622SJuan Castillo #include <openssl/conf.h> 166f971622SJuan Castillo #include <openssl/engine.h> 176f971622SJuan Castillo #include <openssl/err.h> 186f971622SJuan Castillo #include <openssl/pem.h> 196f971622SJuan Castillo #include <openssl/sha.h> 206f971622SJuan Castillo #include <openssl/x509v3.h> 216f971622SJuan Castillo 226f971622SJuan Castillo #include "cert.h" 23ad2c1a9aSJuan Castillo #include "cmd_opt.h" 246f971622SJuan Castillo #include "debug.h" 256f971622SJuan Castillo #include "ext.h" 266f971622SJuan Castillo #include "key.h" 276f971622SJuan Castillo #include "sha.h" 286f971622SJuan Castillo 296f971622SJuan Castillo /* 306f971622SJuan Castillo * Helper macros to simplify the code. This macro assigns the return value of 316f971622SJuan Castillo * the 'fn' function to 'v' and exits if the value is NULL. 326f971622SJuan Castillo */ 336f971622SJuan Castillo #define CHECK_NULL(v, fn) \ 346f971622SJuan Castillo do { \ 356f971622SJuan Castillo v = fn; \ 366f971622SJuan Castillo if (v == NULL) { \ 376f971622SJuan Castillo ERROR("NULL object at %s:%d\n", __FILE__, __LINE__); \ 386f971622SJuan Castillo exit(1); \ 396f971622SJuan Castillo } \ 406f971622SJuan Castillo } while (0) 416f971622SJuan Castillo 426f971622SJuan Castillo /* 436f971622SJuan Castillo * This macro assigns the NID corresponding to 'oid' to 'v' and exits if the 446f971622SJuan Castillo * NID is undefined. 456f971622SJuan Castillo */ 466f971622SJuan Castillo #define CHECK_OID(v, oid) \ 476f971622SJuan Castillo do { \ 486f971622SJuan Castillo v = OBJ_txt2nid(oid); \ 496f971622SJuan Castillo if (v == NID_undef) { \ 50067f7e9cSSandrine Bailleux ERROR("Cannot find extension %s\n", oid); \ 516f971622SJuan Castillo exit(1); \ 526f971622SJuan Castillo } \ 536f971622SJuan Castillo } while (0) 546f971622SJuan Castillo 556f971622SJuan Castillo #define MAX_FILENAME_LEN 1024 566f971622SJuan Castillo #define VAL_DAYS 7300 576f971622SJuan Castillo #define ID_TO_BIT_MASK(id) (1 << id) 58ccbf890eSJuan Castillo #define NUM_ELEM(x) ((sizeof(x)) / (sizeof(x[0]))) 59159807e2SJuan Castillo #define HELP_OPT_MAX_LEN 128 606f971622SJuan Castillo 616f971622SJuan Castillo /* Global options */ 62ccbf890eSJuan Castillo static int key_alg; 632972247cSQixiang Xu static int hash_alg; 64dfe0f4c2SJustin Chadwell static int key_size; 656f971622SJuan Castillo static int new_keys; 666f971622SJuan Castillo static int save_keys; 676f971622SJuan Castillo static int print_cert; 686f971622SJuan Castillo 69*a004ee8dSChris Kay static const char build_msg[] = "Built : " __TIME__ ", " __DATE__; 70*a004ee8dSChris Kay static const char platform_msg[] = PLAT_MSG; 716f971622SJuan Castillo 726f971622SJuan Castillo static char *strdup(const char *str) 736f971622SJuan Castillo { 746f971622SJuan Castillo int n = strlen(str) + 1; 756f971622SJuan Castillo char *dup = malloc(n); 766f971622SJuan Castillo if (dup) { 776f971622SJuan Castillo strcpy(dup, str); 786f971622SJuan Castillo } 796f971622SJuan Castillo return dup; 806f971622SJuan Castillo } 816f971622SJuan Castillo 82ccbf890eSJuan Castillo static const char *key_algs_str[] = { 83ccbf890eSJuan Castillo [KEY_ALG_RSA] = "rsa", 84ed2a76eaSJuan Castillo #ifndef OPENSSL_NO_EC 85e78ba69eSLionel Debieve [KEY_ALG_ECDSA_NIST] = "ecdsa", 86c0c280dfSDonald Chan #if OPENSSL_VERSION_NUMBER >= 0x10100000L 87e78ba69eSLionel Debieve [KEY_ALG_ECDSA_BRAINPOOL_R] = "ecdsa-brainpool-regular", 88e78ba69eSLionel Debieve [KEY_ALG_ECDSA_BRAINPOOL_T] = "ecdsa-brainpool-twisted", 89c0c280dfSDonald Chan #endif 90ed2a76eaSJuan Castillo #endif /* OPENSSL_NO_EC */ 91ccbf890eSJuan Castillo }; 92ccbf890eSJuan Castillo 932972247cSQixiang Xu static const char *hash_algs_str[] = { 942972247cSQixiang Xu [HASH_ALG_SHA256] = "sha256", 952972247cSQixiang Xu [HASH_ALG_SHA384] = "sha384", 962972247cSQixiang Xu [HASH_ALG_SHA512] = "sha512", 972972247cSQixiang Xu }; 982972247cSQixiang Xu 99ad2c1a9aSJuan Castillo static void print_help(const char *cmd, const struct option *long_opt) 1006f971622SJuan Castillo { 101159807e2SJuan Castillo int rem, i = 0; 102159807e2SJuan Castillo const struct option *opt; 103159807e2SJuan Castillo char line[HELP_OPT_MAX_LEN]; 104159807e2SJuan Castillo char *p; 105159807e2SJuan Castillo 106159807e2SJuan Castillo assert(cmd != NULL); 107159807e2SJuan Castillo assert(long_opt != NULL); 108159807e2SJuan Castillo 1096f971622SJuan Castillo printf("\n\n"); 1106f971622SJuan Castillo printf("The certificate generation tool loads the binary images and\n" 111e78ba69eSLionel Debieve "optionally the RSA or ECC keys, and outputs the key and content\n" 1126f971622SJuan Castillo "certificates properly signed to implement the chain of trust.\n" 1136f971622SJuan Castillo "If keys are provided, they must be in PEM format.\n" 1146f971622SJuan Castillo "Certificates are generated in DER format.\n"); 1156f971622SJuan Castillo printf("\n"); 116159807e2SJuan Castillo printf("Usage:\n"); 117159807e2SJuan Castillo printf("\t%s [OPTIONS]\n\n", cmd); 118159807e2SJuan Castillo 119159807e2SJuan Castillo printf("Available options:\n"); 120159807e2SJuan Castillo opt = long_opt; 121159807e2SJuan Castillo while (opt->name) { 122159807e2SJuan Castillo p = line; 123159807e2SJuan Castillo rem = HELP_OPT_MAX_LEN; 124159807e2SJuan Castillo if (isalpha(opt->val)) { 125159807e2SJuan Castillo /* Short format */ 126159807e2SJuan Castillo sprintf(p, "-%c,", (char)opt->val); 127159807e2SJuan Castillo p += 3; 128159807e2SJuan Castillo rem -= 3; 1296f971622SJuan Castillo } 130159807e2SJuan Castillo snprintf(p, rem, "--%s %s", opt->name, 131159807e2SJuan Castillo (opt->has_arg == required_argument) ? "<arg>" : ""); 132159807e2SJuan Castillo printf("\t%-32s %s\n", line, cmd_opt_get_help_msg(i)); 133159807e2SJuan Castillo opt++; 134159807e2SJuan Castillo i++; 135159807e2SJuan Castillo } 1366f971622SJuan Castillo printf("\n"); 1376f971622SJuan Castillo } 1386f971622SJuan Castillo 139ccbf890eSJuan Castillo static int get_key_alg(const char *key_alg_str) 140ccbf890eSJuan Castillo { 141ccbf890eSJuan Castillo int i; 142ccbf890eSJuan Castillo 143ccbf890eSJuan Castillo for (i = 0 ; i < NUM_ELEM(key_algs_str) ; i++) { 144ccbf890eSJuan Castillo if (0 == strcmp(key_alg_str, key_algs_str[i])) { 145ccbf890eSJuan Castillo return i; 146ccbf890eSJuan Castillo } 147ccbf890eSJuan Castillo } 148ccbf890eSJuan Castillo 149ccbf890eSJuan Castillo return -1; 150ccbf890eSJuan Castillo } 151ccbf890eSJuan Castillo 152dfe0f4c2SJustin Chadwell static int get_key_size(const char *key_size_str) 153dfe0f4c2SJustin Chadwell { 154dfe0f4c2SJustin Chadwell char *end; 155dfe0f4c2SJustin Chadwell long key_size; 156dfe0f4c2SJustin Chadwell 157dfe0f4c2SJustin Chadwell key_size = strtol(key_size_str, &end, 10); 158dfe0f4c2SJustin Chadwell if (*end != '\0') 159dfe0f4c2SJustin Chadwell return -1; 160dfe0f4c2SJustin Chadwell 161dfe0f4c2SJustin Chadwell return key_size; 162dfe0f4c2SJustin Chadwell } 163dfe0f4c2SJustin Chadwell 1642972247cSQixiang Xu static int get_hash_alg(const char *hash_alg_str) 1652972247cSQixiang Xu { 1662972247cSQixiang Xu int i; 1672972247cSQixiang Xu 1682972247cSQixiang Xu for (i = 0 ; i < NUM_ELEM(hash_algs_str) ; i++) { 1692972247cSQixiang Xu if (0 == strcmp(hash_alg_str, hash_algs_str[i])) { 1702972247cSQixiang Xu return i; 1712972247cSQixiang Xu } 1722972247cSQixiang Xu } 1732972247cSQixiang Xu 1742972247cSQixiang Xu return -1; 1752972247cSQixiang Xu } 1762972247cSQixiang Xu 1776f971622SJuan Castillo static void check_cmd_params(void) 1786f971622SJuan Castillo { 179dfc90e26SJuan Castillo cert_t *cert; 180dfc90e26SJuan Castillo ext_t *ext; 181dfc90e26SJuan Castillo key_t *key; 182dfc90e26SJuan Castillo int i, j; 183dfe0f4c2SJustin Chadwell bool valid_size; 184dfc90e26SJuan Castillo 185ccbf890eSJuan Castillo /* Only save new keys */ 186ccbf890eSJuan Castillo if (save_keys && !new_keys) { 187ccbf890eSJuan Castillo ERROR("Only new keys can be saved to disk\n"); 188ccbf890eSJuan Castillo exit(1); 189ccbf890eSJuan Castillo } 190ccbf890eSJuan Castillo 191dfe0f4c2SJustin Chadwell /* Validate key-size */ 192dfe0f4c2SJustin Chadwell valid_size = false; 193dfe0f4c2SJustin Chadwell for (i = 0; i < KEY_SIZE_MAX_NUM; i++) { 194dfe0f4c2SJustin Chadwell if (key_size == KEY_SIZES[key_alg][i]) { 195dfe0f4c2SJustin Chadwell valid_size = true; 196dfe0f4c2SJustin Chadwell break; 197dfe0f4c2SJustin Chadwell } 198dfe0f4c2SJustin Chadwell } 199dfe0f4c2SJustin Chadwell if (!valid_size) { 200dfe0f4c2SJustin Chadwell ERROR("'%d' is not a valid key size for '%s'\n", 201dfe0f4c2SJustin Chadwell key_size, key_algs_str[key_alg]); 202dfe0f4c2SJustin Chadwell NOTICE("Valid sizes are: "); 203dfe0f4c2SJustin Chadwell for (i = 0; i < KEY_SIZE_MAX_NUM && 204dfe0f4c2SJustin Chadwell KEY_SIZES[key_alg][i] != 0; i++) { 205dfe0f4c2SJustin Chadwell printf("%d ", KEY_SIZES[key_alg][i]); 206dfe0f4c2SJustin Chadwell } 207dfe0f4c2SJustin Chadwell printf("\n"); 208dfe0f4c2SJustin Chadwell exit(1); 209dfe0f4c2SJustin Chadwell } 210dfe0f4c2SJustin Chadwell 211dfc90e26SJuan Castillo /* Check that all required options have been specified in the 212dfc90e26SJuan Castillo * command line */ 213dfc90e26SJuan Castillo for (i = 0; i < num_certs; i++) { 214dfc90e26SJuan Castillo cert = &certs[i]; 215dfc90e26SJuan Castillo if (cert->fn == NULL) { 216dfc90e26SJuan Castillo /* Certificate not requested. Skip to the next one */ 217dfc90e26SJuan Castillo continue; 218dfc90e26SJuan Castillo } 219dfc90e26SJuan Castillo 220dfc90e26SJuan Castillo /* Check that all parameters required to create this certificate 221dfc90e26SJuan Castillo * have been specified in the command line */ 222dfc90e26SJuan Castillo for (j = 0; j < cert->num_ext; j++) { 223dfc90e26SJuan Castillo ext = &extensions[cert->ext[j]]; 224dfc90e26SJuan Castillo switch (ext->type) { 22596103d5aSJuan Castillo case EXT_TYPE_NVCOUNTER: 22696103d5aSJuan Castillo /* Counter value must be specified */ 22796103d5aSJuan Castillo if ((!ext->optional) && (ext->arg == NULL)) { 22896103d5aSJuan Castillo ERROR("Value for '%s' not specified\n", 22996103d5aSJuan Castillo ext->ln); 23096103d5aSJuan Castillo exit(1); 23196103d5aSJuan Castillo } 23296103d5aSJuan Castillo break; 233dfc90e26SJuan Castillo case EXT_TYPE_PKEY: 234dfc90e26SJuan Castillo /* Key filename must be specified */ 23596103d5aSJuan Castillo key = &keys[ext->attr.key]; 236dfc90e26SJuan Castillo if (!new_keys && key->fn == NULL) { 237dfc90e26SJuan Castillo ERROR("Key '%s' required by '%s' not " 238dfc90e26SJuan Castillo "specified\n", key->desc, 239dfc90e26SJuan Castillo cert->cn); 2406f971622SJuan Castillo exit(1); 2416f971622SJuan Castillo } 242dfc90e26SJuan Castillo break; 243dfc90e26SJuan Castillo case EXT_TYPE_HASH: 244cebe1f23SYatharth Kochar /* 245cebe1f23SYatharth Kochar * Binary image must be specified 246cebe1f23SYatharth Kochar * unless it is explicitly made optional. 247cebe1f23SYatharth Kochar */ 24896103d5aSJuan Castillo if ((!ext->optional) && (ext->arg == NULL)) { 249dfc90e26SJuan Castillo ERROR("Image for '%s' not specified\n", 250dfc90e26SJuan Castillo ext->ln); 2516f971622SJuan Castillo exit(1); 2526f971622SJuan Castillo } 253dfc90e26SJuan Castillo break; 254dfc90e26SJuan Castillo default: 25596103d5aSJuan Castillo ERROR("Unknown extension type '%d' in '%s'\n", 25696103d5aSJuan Castillo ext->type, ext->ln); 2576f971622SJuan Castillo exit(1); 258dfc90e26SJuan Castillo break; 2596f971622SJuan Castillo } 2606f971622SJuan Castillo } 2616f971622SJuan Castillo } 2626f971622SJuan Castillo } 2636f971622SJuan Castillo 264159807e2SJuan Castillo /* Common command line options */ 265159807e2SJuan Castillo static const cmd_opt_t common_cmd_opt[] = { 266159807e2SJuan Castillo { 267159807e2SJuan Castillo { "help", no_argument, NULL, 'h' }, 268159807e2SJuan Castillo "Print this message and exit" 269159807e2SJuan Castillo }, 270159807e2SJuan Castillo { 271159807e2SJuan Castillo { "key-alg", required_argument, NULL, 'a' }, 272c0c280dfSDonald Chan "Key algorithm: 'rsa' (default)- RSAPSS scheme as per PKCS#1 v2.1, " 273c0c280dfSDonald Chan #if OPENSSL_VERSION_NUMBER >= 0x10100000L 274e78ba69eSLionel Debieve "'ecdsa', 'ecdsa-brainpool-regular', 'ecdsa-brainpool-twisted'" 275c0c280dfSDonald Chan #else 276c0c280dfSDonald Chan "'ecdsa'" 277c0c280dfSDonald Chan #endif 278159807e2SJuan Castillo }, 279159807e2SJuan Castillo { 280dfe0f4c2SJustin Chadwell { "key-size", required_argument, NULL, 'b' }, 281dfe0f4c2SJustin Chadwell "Key size (for supported algorithms)." 282dfe0f4c2SJustin Chadwell }, 283dfe0f4c2SJustin Chadwell { 2842972247cSQixiang Xu { "hash-alg", required_argument, NULL, 's' }, 2852972247cSQixiang Xu "Hash algorithm : 'sha256' (default), 'sha384', 'sha512'" 2862972247cSQixiang Xu }, 2872972247cSQixiang Xu { 288159807e2SJuan Castillo { "save-keys", no_argument, NULL, 'k' }, 289159807e2SJuan Castillo "Save key pairs into files. Filenames must be provided" 290159807e2SJuan Castillo }, 291159807e2SJuan Castillo { 292159807e2SJuan Castillo { "new-keys", no_argument, NULL, 'n' }, 293159807e2SJuan Castillo "Generate new key pairs if no key files are provided" 294159807e2SJuan Castillo }, 295159807e2SJuan Castillo { 296159807e2SJuan Castillo { "print-cert", no_argument, NULL, 'p' }, 297159807e2SJuan Castillo "Print the certificates in the standard output" 298159807e2SJuan Castillo } 299159807e2SJuan Castillo }; 300159807e2SJuan Castillo 3016f971622SJuan Castillo int main(int argc, char *argv[]) 3026f971622SJuan Castillo { 303c893c733SMasahiro Yamada STACK_OF(X509_EXTENSION) * sk; 304742c4e14SMichalis Pappas X509_EXTENSION *cert_ext = NULL; 305c893c733SMasahiro Yamada ext_t *ext; 306c893c733SMasahiro Yamada key_t *key; 307c893c733SMasahiro Yamada cert_t *cert; 308c893c733SMasahiro Yamada FILE *file; 30996103d5aSJuan Castillo int i, j, ext_nid, nvctr; 3106f971622SJuan Castillo int c, opt_idx = 0; 311ad2c1a9aSJuan Castillo const struct option *cmd_opt; 312ad2c1a9aSJuan Castillo const char *cur_opt; 313ccbf890eSJuan Castillo unsigned int err_code; 3142972247cSQixiang Xu unsigned char md[SHA512_DIGEST_LENGTH]; 3152972247cSQixiang Xu unsigned int md_len; 316c3da66b1SJuan Castillo const EVP_MD *md_info; 3176f971622SJuan Castillo 3186f971622SJuan Castillo NOTICE("CoT Generation Tool: %s\n", build_msg); 3196f971622SJuan Castillo NOTICE("Target platform: %s\n", platform_msg); 3206f971622SJuan Castillo 321ccbf890eSJuan Castillo /* Set default options */ 322ccbf890eSJuan Castillo key_alg = KEY_ALG_RSA; 3232972247cSQixiang Xu hash_alg = HASH_ALG_SHA256; 324dfe0f4c2SJustin Chadwell key_size = -1; 325ccbf890eSJuan Castillo 326ad2c1a9aSJuan Castillo /* Add common command line options */ 327159807e2SJuan Castillo for (i = 0; i < NUM_ELEM(common_cmd_opt); i++) { 328159807e2SJuan Castillo cmd_opt_add(&common_cmd_opt[i]); 329159807e2SJuan Castillo } 330ad2c1a9aSJuan Castillo 331ad2c1a9aSJuan Castillo /* Initialize the certificates */ 332ad2c1a9aSJuan Castillo if (cert_init() != 0) { 333ad2c1a9aSJuan Castillo ERROR("Cannot initialize certificates\n"); 334ad2c1a9aSJuan Castillo exit(1); 335ad2c1a9aSJuan Castillo } 336ad2c1a9aSJuan Castillo 337ad2c1a9aSJuan Castillo /* Initialize the keys */ 338ad2c1a9aSJuan Castillo if (key_init() != 0) { 339ad2c1a9aSJuan Castillo ERROR("Cannot initialize keys\n"); 340ad2c1a9aSJuan Castillo exit(1); 341ad2c1a9aSJuan Castillo } 342ad2c1a9aSJuan Castillo 343ad2c1a9aSJuan Castillo /* Initialize the new types and register OIDs for the extensions */ 344ad2c1a9aSJuan Castillo if (ext_init() != 0) { 345067f7e9cSSandrine Bailleux ERROR("Cannot initialize extensions\n"); 346ad2c1a9aSJuan Castillo exit(1); 347ad2c1a9aSJuan Castillo } 348ad2c1a9aSJuan Castillo 349ad2c1a9aSJuan Castillo /* Get the command line options populated during the initialization */ 350ad2c1a9aSJuan Castillo cmd_opt = cmd_opt_get_array(); 351ad2c1a9aSJuan Castillo 3526f971622SJuan Castillo while (1) { 3536f971622SJuan Castillo /* getopt_long stores the option index here. */ 354dfe0f4c2SJustin Chadwell c = getopt_long(argc, argv, "a:b:hknps:", cmd_opt, &opt_idx); 3556f971622SJuan Castillo 3566f971622SJuan Castillo /* Detect the end of the options. */ 3576f971622SJuan Castillo if (c == -1) { 3586f971622SJuan Castillo break; 3596f971622SJuan Castillo } 3606f971622SJuan Castillo 3616f971622SJuan Castillo switch (c) { 362ccbf890eSJuan Castillo case 'a': 363ccbf890eSJuan Castillo key_alg = get_key_alg(optarg); 364ccbf890eSJuan Castillo if (key_alg < 0) { 365ccbf890eSJuan Castillo ERROR("Invalid key algorithm '%s'\n", optarg); 366ccbf890eSJuan Castillo exit(1); 367ccbf890eSJuan Castillo } 368ccbf890eSJuan Castillo break; 369dfe0f4c2SJustin Chadwell case 'b': 370dfe0f4c2SJustin Chadwell key_size = get_key_size(optarg); 371dfe0f4c2SJustin Chadwell if (key_size <= 0) { 372dfe0f4c2SJustin Chadwell ERROR("Invalid key size '%s'\n", optarg); 373dfe0f4c2SJustin Chadwell exit(1); 374dfe0f4c2SJustin Chadwell } 375dfe0f4c2SJustin Chadwell break; 3766f971622SJuan Castillo case 'h': 377ad2c1a9aSJuan Castillo print_help(argv[0], cmd_opt); 378600835d0SRoberto Vargas exit(0); 3796f971622SJuan Castillo case 'k': 3806f971622SJuan Castillo save_keys = 1; 3816f971622SJuan Castillo break; 3826f971622SJuan Castillo case 'n': 3836f971622SJuan Castillo new_keys = 1; 3846f971622SJuan Castillo break; 3856f971622SJuan Castillo case 'p': 3866f971622SJuan Castillo print_cert = 1; 3876f971622SJuan Castillo break; 3882972247cSQixiang Xu case 's': 3892972247cSQixiang Xu hash_alg = get_hash_alg(optarg); 3902972247cSQixiang Xu if (hash_alg < 0) { 3912972247cSQixiang Xu ERROR("Invalid hash algorithm '%s'\n", optarg); 3922972247cSQixiang Xu exit(1); 3932972247cSQixiang Xu } 3942972247cSQixiang Xu break; 395ad2c1a9aSJuan Castillo case CMD_OPT_EXT: 396ad2c1a9aSJuan Castillo cur_opt = cmd_opt_get_name(opt_idx); 397ad2c1a9aSJuan Castillo ext = ext_get_by_opt(cur_opt); 39896103d5aSJuan Castillo ext->arg = strdup(optarg); 3996f971622SJuan Castillo break; 400ad2c1a9aSJuan Castillo case CMD_OPT_KEY: 401ad2c1a9aSJuan Castillo cur_opt = cmd_opt_get_name(opt_idx); 402ad2c1a9aSJuan Castillo key = key_get_by_opt(cur_opt); 403ad2c1a9aSJuan Castillo key->fn = strdup(optarg); 4046f971622SJuan Castillo break; 405ad2c1a9aSJuan Castillo case CMD_OPT_CERT: 406ad2c1a9aSJuan Castillo cur_opt = cmd_opt_get_name(opt_idx); 407ad2c1a9aSJuan Castillo cert = cert_get_by_opt(cur_opt); 408ad2c1a9aSJuan Castillo cert->fn = strdup(optarg); 4096f971622SJuan Castillo break; 4106f971622SJuan Castillo case '?': 4116f971622SJuan Castillo default: 412159807e2SJuan Castillo print_help(argv[0], cmd_opt); 4136f971622SJuan Castillo exit(1); 4146f971622SJuan Castillo } 4156f971622SJuan Castillo } 4166f971622SJuan Castillo 417dfe0f4c2SJustin Chadwell /* Select a reasonable default key-size */ 418dfe0f4c2SJustin Chadwell if (key_size == -1) { 419dfe0f4c2SJustin Chadwell key_size = KEY_SIZES[key_alg][0]; 420dfe0f4c2SJustin Chadwell } 421dfe0f4c2SJustin Chadwell 4226f971622SJuan Castillo /* Check command line arguments */ 4236f971622SJuan Castillo check_cmd_params(); 4246f971622SJuan Castillo 4252972247cSQixiang Xu /* Indicate SHA as image hash algorithm in the certificate 426c3da66b1SJuan Castillo * extension */ 4272972247cSQixiang Xu if (hash_alg == HASH_ALG_SHA384) { 4282972247cSQixiang Xu md_info = EVP_sha384(); 4292972247cSQixiang Xu md_len = SHA384_DIGEST_LENGTH; 4302972247cSQixiang Xu } else if (hash_alg == HASH_ALG_SHA512) { 4312972247cSQixiang Xu md_info = EVP_sha512(); 4322972247cSQixiang Xu md_len = SHA512_DIGEST_LENGTH; 4332972247cSQixiang Xu } else { 434c3da66b1SJuan Castillo md_info = EVP_sha256(); 4352972247cSQixiang Xu md_len = SHA256_DIGEST_LENGTH; 4362972247cSQixiang Xu } 437c3da66b1SJuan Castillo 4386f971622SJuan Castillo /* Load private keys from files (or generate new ones) */ 43955e291a4SJuan Castillo for (i = 0 ; i < num_keys ; i++) { 440cf2dd17dSJuan Pablo Conde #if !USING_OPENSSL3 441762f1ebeSMasahiro Yamada if (!key_new(&keys[i])) { 442762f1ebeSMasahiro Yamada ERROR("Failed to allocate key container\n"); 443762f1ebeSMasahiro Yamada exit(1); 444762f1ebeSMasahiro Yamada } 445cf2dd17dSJuan Pablo Conde #endif 446762f1ebeSMasahiro Yamada 447ccbf890eSJuan Castillo /* First try to load the key from disk */ 448bb3b0c0bSSandrine Bailleux err_code = key_load(&keys[i]); 449bb3b0c0bSSandrine Bailleux if (err_code == KEY_ERR_NONE) { 450ccbf890eSJuan Castillo /* Key loaded successfully */ 451ccbf890eSJuan Castillo continue; 452ccbf890eSJuan Castillo } 453ccbf890eSJuan Castillo 454ccbf890eSJuan Castillo /* Key not loaded. Check the error code */ 455762f1ebeSMasahiro Yamada if (err_code == KEY_ERR_LOAD) { 456ccbf890eSJuan Castillo /* File exists, but it does not contain a valid private 457ccbf890eSJuan Castillo * key. Abort. */ 458ccbf890eSJuan Castillo ERROR("Error loading '%s'\n", keys[i].fn); 4596f971622SJuan Castillo exit(1); 4606f971622SJuan Castillo } 461ccbf890eSJuan Castillo 462ccbf890eSJuan Castillo /* File does not exist, could not be opened or no filename was 463ccbf890eSJuan Castillo * given */ 464ccbf890eSJuan Castillo if (new_keys) { 465ccbf890eSJuan Castillo /* Try to create a new key */ 466ccbf890eSJuan Castillo NOTICE("Creating new key for '%s'\n", keys[i].desc); 467dfe0f4c2SJustin Chadwell if (!key_create(&keys[i], key_alg, key_size)) { 468ccbf890eSJuan Castillo ERROR("Error creating key '%s'\n", keys[i].desc); 469ccbf890eSJuan Castillo exit(1); 4706f971622SJuan Castillo } 4716f971622SJuan Castillo } else { 472ccbf890eSJuan Castillo if (err_code == KEY_ERR_OPEN) { 473ccbf890eSJuan Castillo ERROR("Error opening '%s'\n", keys[i].fn); 474ccbf890eSJuan Castillo } else { 475ccbf890eSJuan Castillo ERROR("Key '%s' not specified\n", keys[i].desc); 4766f971622SJuan Castillo } 477ccbf890eSJuan Castillo exit(1); 4786f971622SJuan Castillo } 4796f971622SJuan Castillo } 4806f971622SJuan Castillo 48155e291a4SJuan Castillo /* Create the certificates */ 48255e291a4SJuan Castillo for (i = 0 ; i < num_certs ; i++) { 48355e291a4SJuan Castillo 48455e291a4SJuan Castillo cert = &certs[i]; 48555e291a4SJuan Castillo 486294e2656SManish V Badarkhe if (cert->fn == NULL) { 487294e2656SManish V Badarkhe /* Certificate not requested. Skip to the next one */ 488294e2656SManish V Badarkhe continue; 489294e2656SManish V Badarkhe } 490294e2656SManish V Badarkhe 49155e291a4SJuan Castillo /* Create a new stack of extensions. This stack will be used 49255e291a4SJuan Castillo * to create the certificate */ 4936f971622SJuan Castillo CHECK_NULL(sk, sk_X509_EXTENSION_new_null()); 4946f971622SJuan Castillo 49555e291a4SJuan Castillo for (j = 0 ; j < cert->num_ext ; j++) { 4966f971622SJuan Castillo 49755e291a4SJuan Castillo ext = &extensions[cert->ext[j]]; 49855e291a4SJuan Castillo 49955e291a4SJuan Castillo /* Get OpenSSL internal ID for this extension */ 50055e291a4SJuan Castillo CHECK_OID(ext_nid, ext->oid); 50155e291a4SJuan Castillo 50255e291a4SJuan Castillo /* 50355e291a4SJuan Castillo * Three types of extensions are currently supported: 50455e291a4SJuan Castillo * - EXT_TYPE_NVCOUNTER 50555e291a4SJuan Castillo * - EXT_TYPE_HASH 50655e291a4SJuan Castillo * - EXT_TYPE_PKEY 50755e291a4SJuan Castillo */ 50855e291a4SJuan Castillo switch (ext->type) { 50955e291a4SJuan Castillo case EXT_TYPE_NVCOUNTER: 5101ed941c0SJimmy Brisson if (ext->optional && ext->arg == NULL) { 5111ed941c0SJimmy Brisson /* Skip this NVCounter */ 5121ed941c0SJimmy Brisson continue; 5131ed941c0SJimmy Brisson } else { 5141ed941c0SJimmy Brisson /* Checked by `check_cmd_params` */ 5151ed941c0SJimmy Brisson assert(ext->arg != NULL); 51696103d5aSJuan Castillo nvctr = atoi(ext->arg); 51755e291a4SJuan Castillo CHECK_NULL(cert_ext, ext_new_nvcounter(ext_nid, 51896103d5aSJuan Castillo EXT_CRIT, nvctr)); 519f16db56aSYatharth Kochar } 52055e291a4SJuan Castillo break; 52155e291a4SJuan Castillo case EXT_TYPE_HASH: 52296103d5aSJuan Castillo if (ext->arg == NULL) { 523cebe1f23SYatharth Kochar if (ext->optional) { 524cebe1f23SYatharth Kochar /* Include a hash filled with zeros */ 5252972247cSQixiang Xu memset(md, 0x0, SHA512_DIGEST_LENGTH); 526cebe1f23SYatharth Kochar } else { 527cebe1f23SYatharth Kochar /* Do not include this hash in the certificate */ 5281ed941c0SJimmy Brisson continue; 52955e291a4SJuan Castillo } 530cebe1f23SYatharth Kochar } else { 531cebe1f23SYatharth Kochar /* Calculate the hash of the file */ 5322972247cSQixiang Xu if (!sha_file(hash_alg, ext->arg, md)) { 53355e291a4SJuan Castillo ERROR("Cannot calculate hash of %s\n", 53496103d5aSJuan Castillo ext->arg); 5356f971622SJuan Castillo exit(1); 5366f971622SJuan Castillo } 537cebe1f23SYatharth Kochar } 53855e291a4SJuan Castillo CHECK_NULL(cert_ext, ext_new_hash(ext_nid, 53955e291a4SJuan Castillo EXT_CRIT, md_info, md, 5402972247cSQixiang Xu md_len)); 54155e291a4SJuan Castillo break; 54255e291a4SJuan Castillo case EXT_TYPE_PKEY: 54355e291a4SJuan Castillo CHECK_NULL(cert_ext, ext_new_key(ext_nid, 54496103d5aSJuan Castillo EXT_CRIT, keys[ext->attr.key].key)); 54555e291a4SJuan Castillo break; 54655e291a4SJuan Castillo default: 54796103d5aSJuan Castillo ERROR("Unknown extension type '%d' in %s\n", 54896103d5aSJuan Castillo ext->type, cert->cn); 54955e291a4SJuan Castillo exit(1); 55055e291a4SJuan Castillo } 55155e291a4SJuan Castillo 55255e291a4SJuan Castillo /* Push the extension into the stack */ 55355e291a4SJuan Castillo sk_X509_EXTENSION_push(sk, cert_ext); 55455e291a4SJuan Castillo } 5556f971622SJuan Castillo 556a8eb286aSSoby Mathew /* Create certificate. Signed with corresponding key */ 557294e2656SManish V Badarkhe if (!cert_new(hash_alg, cert, VAL_DAYS, 0, sk)) { 55855e291a4SJuan Castillo ERROR("Cannot create %s\n", cert->cn); 5596f971622SJuan Castillo exit(1); 5606f971622SJuan Castillo } 5616f971622SJuan Castillo 562bea80198SJimmy Brisson for (cert_ext = sk_X509_EXTENSION_pop(sk); cert_ext != NULL; 563bea80198SJimmy Brisson cert_ext = sk_X509_EXTENSION_pop(sk)) { 564bea80198SJimmy Brisson X509_EXTENSION_free(cert_ext); 565bea80198SJimmy Brisson } 566bea80198SJimmy Brisson 5676f971622SJuan Castillo sk_X509_EXTENSION_free(sk); 5686f971622SJuan Castillo } 5696f971622SJuan Castillo 5706f971622SJuan Castillo 5716f971622SJuan Castillo /* Print the certificates */ 5726f971622SJuan Castillo if (print_cert) { 57355e291a4SJuan Castillo for (i = 0 ; i < num_certs ; i++) { 5746f971622SJuan Castillo if (!certs[i].x) { 5756f971622SJuan Castillo continue; 5766f971622SJuan Castillo } 5776f971622SJuan Castillo printf("\n\n=====================================\n\n"); 5786f971622SJuan Castillo X509_print_fp(stdout, certs[i].x); 5796f971622SJuan Castillo } 5806f971622SJuan Castillo } 5816f971622SJuan Castillo 5826f971622SJuan Castillo /* Save created certificates to files */ 58355e291a4SJuan Castillo for (i = 0 ; i < num_certs ; i++) { 5846f971622SJuan Castillo if (certs[i].x && certs[i].fn) { 5856f971622SJuan Castillo file = fopen(certs[i].fn, "w"); 5866f971622SJuan Castillo if (file != NULL) { 5876f971622SJuan Castillo i2d_X509_fp(file, certs[i].x); 5886f971622SJuan Castillo fclose(file); 5896f971622SJuan Castillo } else { 5906f971622SJuan Castillo ERROR("Cannot create file %s\n", certs[i].fn); 5916f971622SJuan Castillo } 5926f971622SJuan Castillo } 5936f971622SJuan Castillo } 5946f971622SJuan Castillo 5956f971622SJuan Castillo /* Save keys */ 5966f971622SJuan Castillo if (save_keys) { 59755e291a4SJuan Castillo for (i = 0 ; i < num_keys ; i++) { 5986f971622SJuan Castillo if (!key_store(&keys[i])) { 5996f971622SJuan Castillo ERROR("Cannot save %s\n", keys[i].desc); 6006f971622SJuan Castillo } 6016f971622SJuan Castillo } 6026f971622SJuan Castillo } 6036f971622SJuan Castillo 6041f111f12SJimmy Brisson /* If we got here, then we must have filled the key array completely. 6051f111f12SJimmy Brisson * We can then safely call free on all of the keys in the array 6061f111f12SJimmy Brisson */ 607cf2dd17dSJuan Pablo Conde key_cleanup(); 6081f111f12SJimmy Brisson 6096f971622SJuan Castillo #ifndef OPENSSL_NO_ENGINE 6106f971622SJuan Castillo ENGINE_cleanup(); 6116f971622SJuan Castillo #endif 6126f971622SJuan Castillo CRYPTO_cleanup_all_ex_data(); 6136f971622SJuan Castillo 6144a34d18fSJimmy Brisson 6154a34d18fSJimmy Brisson /* We allocated strings through strdup, so now we have to free them */ 6164a34d18fSJimmy Brisson 617cf2dd17dSJuan Pablo Conde ext_cleanup(); 6184a34d18fSJimmy Brisson 619cf2dd17dSJuan Pablo Conde cert_cleanup(); 6204a34d18fSJimmy Brisson 6216f971622SJuan Castillo return 0; 6226f971622SJuan Castillo } 623