16f971622SJuan Castillo /* 2ba1eaabfSSandrine Bailleux * Copyright (c) 2015-2020, 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 696f971622SJuan Castillo /* Info messages created in the Makefile */ 706f971622SJuan Castillo extern const char build_msg[]; 716f971622SJuan Castillo extern const char platform_msg[]; 726f971622SJuan Castillo 736f971622SJuan Castillo 746f971622SJuan Castillo static char *strdup(const char *str) 756f971622SJuan Castillo { 766f971622SJuan Castillo int n = strlen(str) + 1; 776f971622SJuan Castillo char *dup = malloc(n); 786f971622SJuan Castillo if (dup) { 796f971622SJuan Castillo strcpy(dup, str); 806f971622SJuan Castillo } 816f971622SJuan Castillo return dup; 826f971622SJuan Castillo } 836f971622SJuan Castillo 84ccbf890eSJuan Castillo static const char *key_algs_str[] = { 85ccbf890eSJuan Castillo [KEY_ALG_RSA] = "rsa", 86ed2a76eaSJuan Castillo #ifndef OPENSSL_NO_EC 87ccbf890eSJuan Castillo [KEY_ALG_ECDSA] = "ecdsa" 88ed2a76eaSJuan Castillo #endif /* OPENSSL_NO_EC */ 89ccbf890eSJuan Castillo }; 90ccbf890eSJuan Castillo 912972247cSQixiang Xu static const char *hash_algs_str[] = { 922972247cSQixiang Xu [HASH_ALG_SHA256] = "sha256", 932972247cSQixiang Xu [HASH_ALG_SHA384] = "sha384", 942972247cSQixiang Xu [HASH_ALG_SHA512] = "sha512", 952972247cSQixiang Xu }; 962972247cSQixiang Xu 97ad2c1a9aSJuan Castillo static void print_help(const char *cmd, const struct option *long_opt) 986f971622SJuan Castillo { 99159807e2SJuan Castillo int rem, i = 0; 100159807e2SJuan Castillo const struct option *opt; 101159807e2SJuan Castillo char line[HELP_OPT_MAX_LEN]; 102159807e2SJuan Castillo char *p; 103159807e2SJuan Castillo 104159807e2SJuan Castillo assert(cmd != NULL); 105159807e2SJuan Castillo assert(long_opt != NULL); 106159807e2SJuan Castillo 1076f971622SJuan Castillo printf("\n\n"); 1086f971622SJuan Castillo printf("The certificate generation tool loads the binary images and\n" 1096f971622SJuan Castillo "optionally the RSA keys, and outputs the key and content\n" 1106f971622SJuan Castillo "certificates properly signed to implement the chain of trust.\n" 1116f971622SJuan Castillo "If keys are provided, they must be in PEM format.\n" 1126f971622SJuan Castillo "Certificates are generated in DER format.\n"); 1136f971622SJuan Castillo printf("\n"); 114159807e2SJuan Castillo printf("Usage:\n"); 115159807e2SJuan Castillo printf("\t%s [OPTIONS]\n\n", cmd); 116159807e2SJuan Castillo 117159807e2SJuan Castillo printf("Available options:\n"); 118159807e2SJuan Castillo opt = long_opt; 119159807e2SJuan Castillo while (opt->name) { 120159807e2SJuan Castillo p = line; 121159807e2SJuan Castillo rem = HELP_OPT_MAX_LEN; 122159807e2SJuan Castillo if (isalpha(opt->val)) { 123159807e2SJuan Castillo /* Short format */ 124159807e2SJuan Castillo sprintf(p, "-%c,", (char)opt->val); 125159807e2SJuan Castillo p += 3; 126159807e2SJuan Castillo rem -= 3; 1276f971622SJuan Castillo } 128159807e2SJuan Castillo snprintf(p, rem, "--%s %s", opt->name, 129159807e2SJuan Castillo (opt->has_arg == required_argument) ? "<arg>" : ""); 130159807e2SJuan Castillo printf("\t%-32s %s\n", line, cmd_opt_get_help_msg(i)); 131159807e2SJuan Castillo opt++; 132159807e2SJuan Castillo i++; 133159807e2SJuan Castillo } 1346f971622SJuan Castillo printf("\n"); 1356f971622SJuan Castillo } 1366f971622SJuan Castillo 137ccbf890eSJuan Castillo static int get_key_alg(const char *key_alg_str) 138ccbf890eSJuan Castillo { 139ccbf890eSJuan Castillo int i; 140ccbf890eSJuan Castillo 141ccbf890eSJuan Castillo for (i = 0 ; i < NUM_ELEM(key_algs_str) ; i++) { 142ccbf890eSJuan Castillo if (0 == strcmp(key_alg_str, key_algs_str[i])) { 143ccbf890eSJuan Castillo return i; 144ccbf890eSJuan Castillo } 145ccbf890eSJuan Castillo } 146ccbf890eSJuan Castillo 147ccbf890eSJuan Castillo return -1; 148ccbf890eSJuan Castillo } 149ccbf890eSJuan Castillo 150dfe0f4c2SJustin Chadwell static int get_key_size(const char *key_size_str) 151dfe0f4c2SJustin Chadwell { 152dfe0f4c2SJustin Chadwell char *end; 153dfe0f4c2SJustin Chadwell long key_size; 154dfe0f4c2SJustin Chadwell 155dfe0f4c2SJustin Chadwell key_size = strtol(key_size_str, &end, 10); 156dfe0f4c2SJustin Chadwell if (*end != '\0') 157dfe0f4c2SJustin Chadwell return -1; 158dfe0f4c2SJustin Chadwell 159dfe0f4c2SJustin Chadwell return key_size; 160dfe0f4c2SJustin Chadwell } 161dfe0f4c2SJustin Chadwell 1622972247cSQixiang Xu static int get_hash_alg(const char *hash_alg_str) 1632972247cSQixiang Xu { 1642972247cSQixiang Xu int i; 1652972247cSQixiang Xu 1662972247cSQixiang Xu for (i = 0 ; i < NUM_ELEM(hash_algs_str) ; i++) { 1672972247cSQixiang Xu if (0 == strcmp(hash_alg_str, hash_algs_str[i])) { 1682972247cSQixiang Xu return i; 1692972247cSQixiang Xu } 1702972247cSQixiang Xu } 1712972247cSQixiang Xu 1722972247cSQixiang Xu return -1; 1732972247cSQixiang Xu } 1742972247cSQixiang Xu 1756f971622SJuan Castillo static void check_cmd_params(void) 1766f971622SJuan Castillo { 177dfc90e26SJuan Castillo cert_t *cert; 178dfc90e26SJuan Castillo ext_t *ext; 179dfc90e26SJuan Castillo key_t *key; 180dfc90e26SJuan Castillo int i, j; 181dfe0f4c2SJustin Chadwell bool valid_size; 182dfc90e26SJuan Castillo 183ccbf890eSJuan Castillo /* Only save new keys */ 184ccbf890eSJuan Castillo if (save_keys && !new_keys) { 185ccbf890eSJuan Castillo ERROR("Only new keys can be saved to disk\n"); 186ccbf890eSJuan Castillo exit(1); 187ccbf890eSJuan Castillo } 188ccbf890eSJuan Castillo 189dfe0f4c2SJustin Chadwell /* Validate key-size */ 190dfe0f4c2SJustin Chadwell valid_size = false; 191dfe0f4c2SJustin Chadwell for (i = 0; i < KEY_SIZE_MAX_NUM; i++) { 192dfe0f4c2SJustin Chadwell if (key_size == KEY_SIZES[key_alg][i]) { 193dfe0f4c2SJustin Chadwell valid_size = true; 194dfe0f4c2SJustin Chadwell break; 195dfe0f4c2SJustin Chadwell } 196dfe0f4c2SJustin Chadwell } 197dfe0f4c2SJustin Chadwell if (!valid_size) { 198dfe0f4c2SJustin Chadwell ERROR("'%d' is not a valid key size for '%s'\n", 199dfe0f4c2SJustin Chadwell key_size, key_algs_str[key_alg]); 200dfe0f4c2SJustin Chadwell NOTICE("Valid sizes are: "); 201dfe0f4c2SJustin Chadwell for (i = 0; i < KEY_SIZE_MAX_NUM && 202dfe0f4c2SJustin Chadwell KEY_SIZES[key_alg][i] != 0; i++) { 203dfe0f4c2SJustin Chadwell printf("%d ", KEY_SIZES[key_alg][i]); 204dfe0f4c2SJustin Chadwell } 205dfe0f4c2SJustin Chadwell printf("\n"); 206dfe0f4c2SJustin Chadwell exit(1); 207dfe0f4c2SJustin Chadwell } 208dfe0f4c2SJustin Chadwell 209dfc90e26SJuan Castillo /* Check that all required options have been specified in the 210dfc90e26SJuan Castillo * command line */ 211dfc90e26SJuan Castillo for (i = 0; i < num_certs; i++) { 212dfc90e26SJuan Castillo cert = &certs[i]; 213dfc90e26SJuan Castillo if (cert->fn == NULL) { 214dfc90e26SJuan Castillo /* Certificate not requested. Skip to the next one */ 215dfc90e26SJuan Castillo continue; 216dfc90e26SJuan Castillo } 217dfc90e26SJuan Castillo 218dfc90e26SJuan Castillo /* Check that all parameters required to create this certificate 219dfc90e26SJuan Castillo * have been specified in the command line */ 220dfc90e26SJuan Castillo for (j = 0; j < cert->num_ext; j++) { 221dfc90e26SJuan Castillo ext = &extensions[cert->ext[j]]; 222dfc90e26SJuan Castillo switch (ext->type) { 22396103d5aSJuan Castillo case EXT_TYPE_NVCOUNTER: 22496103d5aSJuan Castillo /* Counter value must be specified */ 22596103d5aSJuan Castillo if ((!ext->optional) && (ext->arg == NULL)) { 22696103d5aSJuan Castillo ERROR("Value for '%s' not specified\n", 22796103d5aSJuan Castillo ext->ln); 22896103d5aSJuan Castillo exit(1); 22996103d5aSJuan Castillo } 23096103d5aSJuan Castillo break; 231dfc90e26SJuan Castillo case EXT_TYPE_PKEY: 232dfc90e26SJuan Castillo /* Key filename must be specified */ 23396103d5aSJuan Castillo key = &keys[ext->attr.key]; 234dfc90e26SJuan Castillo if (!new_keys && key->fn == NULL) { 235dfc90e26SJuan Castillo ERROR("Key '%s' required by '%s' not " 236dfc90e26SJuan Castillo "specified\n", key->desc, 237dfc90e26SJuan Castillo cert->cn); 2386f971622SJuan Castillo exit(1); 2396f971622SJuan Castillo } 240dfc90e26SJuan Castillo break; 241dfc90e26SJuan Castillo case EXT_TYPE_HASH: 242cebe1f23SYatharth Kochar /* 243cebe1f23SYatharth Kochar * Binary image must be specified 244cebe1f23SYatharth Kochar * unless it is explicitly made optional. 245cebe1f23SYatharth Kochar */ 24696103d5aSJuan Castillo if ((!ext->optional) && (ext->arg == NULL)) { 247dfc90e26SJuan Castillo ERROR("Image for '%s' not specified\n", 248dfc90e26SJuan Castillo ext->ln); 2496f971622SJuan Castillo exit(1); 2506f971622SJuan Castillo } 251dfc90e26SJuan Castillo break; 252dfc90e26SJuan Castillo default: 25396103d5aSJuan Castillo ERROR("Unknown extension type '%d' in '%s'\n", 25496103d5aSJuan Castillo ext->type, ext->ln); 2556f971622SJuan Castillo exit(1); 256dfc90e26SJuan Castillo break; 2576f971622SJuan Castillo } 2586f971622SJuan Castillo } 2596f971622SJuan Castillo } 2606f971622SJuan Castillo } 2616f971622SJuan Castillo 262159807e2SJuan Castillo /* Common command line options */ 263159807e2SJuan Castillo static const cmd_opt_t common_cmd_opt[] = { 264159807e2SJuan Castillo { 265159807e2SJuan Castillo { "help", no_argument, NULL, 'h' }, 266159807e2SJuan Castillo "Print this message and exit" 267159807e2SJuan Castillo }, 268159807e2SJuan Castillo { 269159807e2SJuan Castillo { "key-alg", required_argument, NULL, 'a' }, 2706a415a50SJustin Chadwell "Key algorithm: 'rsa' (default)- RSAPSS scheme as per PKCS#1 v2.1, 'ecdsa'" 271159807e2SJuan Castillo }, 272159807e2SJuan Castillo { 273dfe0f4c2SJustin Chadwell { "key-size", required_argument, NULL, 'b' }, 274dfe0f4c2SJustin Chadwell "Key size (for supported algorithms)." 275dfe0f4c2SJustin Chadwell }, 276dfe0f4c2SJustin Chadwell { 2772972247cSQixiang Xu { "hash-alg", required_argument, NULL, 's' }, 2782972247cSQixiang Xu "Hash algorithm : 'sha256' (default), 'sha384', 'sha512'" 2792972247cSQixiang Xu }, 2802972247cSQixiang Xu { 281159807e2SJuan Castillo { "save-keys", no_argument, NULL, 'k' }, 282159807e2SJuan Castillo "Save key pairs into files. Filenames must be provided" 283159807e2SJuan Castillo }, 284159807e2SJuan Castillo { 285159807e2SJuan Castillo { "new-keys", no_argument, NULL, 'n' }, 286159807e2SJuan Castillo "Generate new key pairs if no key files are provided" 287159807e2SJuan Castillo }, 288159807e2SJuan Castillo { 289159807e2SJuan Castillo { "print-cert", no_argument, NULL, 'p' }, 290159807e2SJuan Castillo "Print the certificates in the standard output" 291159807e2SJuan Castillo } 292159807e2SJuan Castillo }; 293159807e2SJuan Castillo 2946f971622SJuan Castillo int main(int argc, char *argv[]) 2956f971622SJuan Castillo { 296c893c733SMasahiro Yamada STACK_OF(X509_EXTENSION) * sk; 297742c4e14SMichalis Pappas X509_EXTENSION *cert_ext = NULL; 298c893c733SMasahiro Yamada ext_t *ext; 299c893c733SMasahiro Yamada key_t *key; 300c893c733SMasahiro Yamada cert_t *cert; 301c893c733SMasahiro Yamada FILE *file; 30296103d5aSJuan Castillo int i, j, ext_nid, nvctr; 3036f971622SJuan Castillo int c, opt_idx = 0; 304ad2c1a9aSJuan Castillo const struct option *cmd_opt; 305ad2c1a9aSJuan Castillo const char *cur_opt; 306ccbf890eSJuan Castillo unsigned int err_code; 3072972247cSQixiang Xu unsigned char md[SHA512_DIGEST_LENGTH]; 3082972247cSQixiang Xu unsigned int md_len; 309c3da66b1SJuan Castillo const EVP_MD *md_info; 3106f971622SJuan Castillo 3116f971622SJuan Castillo NOTICE("CoT Generation Tool: %s\n", build_msg); 3126f971622SJuan Castillo NOTICE("Target platform: %s\n", platform_msg); 3136f971622SJuan Castillo 314ccbf890eSJuan Castillo /* Set default options */ 315ccbf890eSJuan Castillo key_alg = KEY_ALG_RSA; 3162972247cSQixiang Xu hash_alg = HASH_ALG_SHA256; 317dfe0f4c2SJustin Chadwell key_size = -1; 318ccbf890eSJuan Castillo 319ad2c1a9aSJuan Castillo /* Add common command line options */ 320159807e2SJuan Castillo for (i = 0; i < NUM_ELEM(common_cmd_opt); i++) { 321159807e2SJuan Castillo cmd_opt_add(&common_cmd_opt[i]); 322159807e2SJuan Castillo } 323ad2c1a9aSJuan Castillo 324ad2c1a9aSJuan Castillo /* Initialize the certificates */ 325ad2c1a9aSJuan Castillo if (cert_init() != 0) { 326ad2c1a9aSJuan Castillo ERROR("Cannot initialize certificates\n"); 327ad2c1a9aSJuan Castillo exit(1); 328ad2c1a9aSJuan Castillo } 329ad2c1a9aSJuan Castillo 330ad2c1a9aSJuan Castillo /* Initialize the keys */ 331ad2c1a9aSJuan Castillo if (key_init() != 0) { 332ad2c1a9aSJuan Castillo ERROR("Cannot initialize keys\n"); 333ad2c1a9aSJuan Castillo exit(1); 334ad2c1a9aSJuan Castillo } 335ad2c1a9aSJuan Castillo 336ad2c1a9aSJuan Castillo /* Initialize the new types and register OIDs for the extensions */ 337ad2c1a9aSJuan Castillo if (ext_init() != 0) { 338067f7e9cSSandrine Bailleux ERROR("Cannot initialize extensions\n"); 339ad2c1a9aSJuan Castillo exit(1); 340ad2c1a9aSJuan Castillo } 341ad2c1a9aSJuan Castillo 342ad2c1a9aSJuan Castillo /* Get the command line options populated during the initialization */ 343ad2c1a9aSJuan Castillo cmd_opt = cmd_opt_get_array(); 344ad2c1a9aSJuan Castillo 3456f971622SJuan Castillo while (1) { 3466f971622SJuan Castillo /* getopt_long stores the option index here. */ 347dfe0f4c2SJustin Chadwell c = getopt_long(argc, argv, "a:b:hknps:", cmd_opt, &opt_idx); 3486f971622SJuan Castillo 3496f971622SJuan Castillo /* Detect the end of the options. */ 3506f971622SJuan Castillo if (c == -1) { 3516f971622SJuan Castillo break; 3526f971622SJuan Castillo } 3536f971622SJuan Castillo 3546f971622SJuan Castillo switch (c) { 355ccbf890eSJuan Castillo case 'a': 356ccbf890eSJuan Castillo key_alg = get_key_alg(optarg); 357ccbf890eSJuan Castillo if (key_alg < 0) { 358ccbf890eSJuan Castillo ERROR("Invalid key algorithm '%s'\n", optarg); 359ccbf890eSJuan Castillo exit(1); 360ccbf890eSJuan Castillo } 361ccbf890eSJuan Castillo break; 362dfe0f4c2SJustin Chadwell case 'b': 363dfe0f4c2SJustin Chadwell key_size = get_key_size(optarg); 364dfe0f4c2SJustin Chadwell if (key_size <= 0) { 365dfe0f4c2SJustin Chadwell ERROR("Invalid key size '%s'\n", optarg); 366dfe0f4c2SJustin Chadwell exit(1); 367dfe0f4c2SJustin Chadwell } 368dfe0f4c2SJustin Chadwell break; 3696f971622SJuan Castillo case 'h': 370ad2c1a9aSJuan Castillo print_help(argv[0], cmd_opt); 371600835d0SRoberto Vargas exit(0); 3726f971622SJuan Castillo case 'k': 3736f971622SJuan Castillo save_keys = 1; 3746f971622SJuan Castillo break; 3756f971622SJuan Castillo case 'n': 3766f971622SJuan Castillo new_keys = 1; 3776f971622SJuan Castillo break; 3786f971622SJuan Castillo case 'p': 3796f971622SJuan Castillo print_cert = 1; 3806f971622SJuan Castillo break; 3812972247cSQixiang Xu case 's': 3822972247cSQixiang Xu hash_alg = get_hash_alg(optarg); 3832972247cSQixiang Xu if (hash_alg < 0) { 3842972247cSQixiang Xu ERROR("Invalid hash algorithm '%s'\n", optarg); 3852972247cSQixiang Xu exit(1); 3862972247cSQixiang Xu } 3872972247cSQixiang Xu break; 388ad2c1a9aSJuan Castillo case CMD_OPT_EXT: 389ad2c1a9aSJuan Castillo cur_opt = cmd_opt_get_name(opt_idx); 390ad2c1a9aSJuan Castillo ext = ext_get_by_opt(cur_opt); 39196103d5aSJuan Castillo ext->arg = strdup(optarg); 3926f971622SJuan Castillo break; 393ad2c1a9aSJuan Castillo case CMD_OPT_KEY: 394ad2c1a9aSJuan Castillo cur_opt = cmd_opt_get_name(opt_idx); 395ad2c1a9aSJuan Castillo key = key_get_by_opt(cur_opt); 396ad2c1a9aSJuan Castillo key->fn = strdup(optarg); 3976f971622SJuan Castillo break; 398ad2c1a9aSJuan Castillo case CMD_OPT_CERT: 399ad2c1a9aSJuan Castillo cur_opt = cmd_opt_get_name(opt_idx); 400ad2c1a9aSJuan Castillo cert = cert_get_by_opt(cur_opt); 401ad2c1a9aSJuan Castillo cert->fn = strdup(optarg); 4026f971622SJuan Castillo break; 4036f971622SJuan Castillo case '?': 4046f971622SJuan Castillo default: 405159807e2SJuan Castillo print_help(argv[0], cmd_opt); 4066f971622SJuan Castillo exit(1); 4076f971622SJuan Castillo } 4086f971622SJuan Castillo } 4096f971622SJuan Castillo 410dfe0f4c2SJustin Chadwell /* Select a reasonable default key-size */ 411dfe0f4c2SJustin Chadwell if (key_size == -1) { 412dfe0f4c2SJustin Chadwell key_size = KEY_SIZES[key_alg][0]; 413dfe0f4c2SJustin Chadwell } 414dfe0f4c2SJustin Chadwell 4156f971622SJuan Castillo /* Check command line arguments */ 4166f971622SJuan Castillo check_cmd_params(); 4176f971622SJuan Castillo 4182972247cSQixiang Xu /* Indicate SHA as image hash algorithm in the certificate 419c3da66b1SJuan Castillo * extension */ 4202972247cSQixiang Xu if (hash_alg == HASH_ALG_SHA384) { 4212972247cSQixiang Xu md_info = EVP_sha384(); 4222972247cSQixiang Xu md_len = SHA384_DIGEST_LENGTH; 4232972247cSQixiang Xu } else if (hash_alg == HASH_ALG_SHA512) { 4242972247cSQixiang Xu md_info = EVP_sha512(); 4252972247cSQixiang Xu md_len = SHA512_DIGEST_LENGTH; 4262972247cSQixiang Xu } else { 427c3da66b1SJuan Castillo md_info = EVP_sha256(); 4282972247cSQixiang Xu md_len = SHA256_DIGEST_LENGTH; 4292972247cSQixiang Xu } 430c3da66b1SJuan Castillo 4316f971622SJuan Castillo /* Load private keys from files (or generate new ones) */ 43255e291a4SJuan Castillo for (i = 0 ; i < num_keys ; i++) { 433762f1ebeSMasahiro Yamada if (!key_new(&keys[i])) { 434762f1ebeSMasahiro Yamada ERROR("Failed to allocate key container\n"); 435762f1ebeSMasahiro Yamada exit(1); 436762f1ebeSMasahiro Yamada } 437762f1ebeSMasahiro Yamada 438ccbf890eSJuan Castillo /* First try to load the key from disk */ 439ccbf890eSJuan Castillo if (key_load(&keys[i], &err_code)) { 440ccbf890eSJuan Castillo /* Key loaded successfully */ 441ccbf890eSJuan Castillo continue; 442ccbf890eSJuan Castillo } 443ccbf890eSJuan Castillo 444ccbf890eSJuan Castillo /* Key not loaded. Check the error code */ 445762f1ebeSMasahiro Yamada if (err_code == KEY_ERR_LOAD) { 446ccbf890eSJuan Castillo /* File exists, but it does not contain a valid private 447ccbf890eSJuan Castillo * key. Abort. */ 448ccbf890eSJuan Castillo ERROR("Error loading '%s'\n", keys[i].fn); 4496f971622SJuan Castillo exit(1); 4506f971622SJuan Castillo } 451ccbf890eSJuan Castillo 452ccbf890eSJuan Castillo /* File does not exist, could not be opened or no filename was 453ccbf890eSJuan Castillo * given */ 454ccbf890eSJuan Castillo if (new_keys) { 455ccbf890eSJuan Castillo /* Try to create a new key */ 456ccbf890eSJuan Castillo NOTICE("Creating new key for '%s'\n", keys[i].desc); 457dfe0f4c2SJustin Chadwell if (!key_create(&keys[i], key_alg, key_size)) { 458ccbf890eSJuan Castillo ERROR("Error creating key '%s'\n", keys[i].desc); 459ccbf890eSJuan Castillo exit(1); 4606f971622SJuan Castillo } 4616f971622SJuan Castillo } else { 462ccbf890eSJuan Castillo if (err_code == KEY_ERR_OPEN) { 463ccbf890eSJuan Castillo ERROR("Error opening '%s'\n", keys[i].fn); 464ccbf890eSJuan Castillo } else { 465ccbf890eSJuan Castillo ERROR("Key '%s' not specified\n", keys[i].desc); 4666f971622SJuan Castillo } 467ccbf890eSJuan Castillo exit(1); 4686f971622SJuan Castillo } 4696f971622SJuan Castillo } 4706f971622SJuan Castillo 47155e291a4SJuan Castillo /* Create the certificates */ 47255e291a4SJuan Castillo for (i = 0 ; i < num_certs ; i++) { 47355e291a4SJuan Castillo 47455e291a4SJuan Castillo cert = &certs[i]; 47555e291a4SJuan Castillo 47655e291a4SJuan Castillo /* Create a new stack of extensions. This stack will be used 47755e291a4SJuan Castillo * to create the certificate */ 4786f971622SJuan Castillo CHECK_NULL(sk, sk_X509_EXTENSION_new_null()); 4796f971622SJuan Castillo 48055e291a4SJuan Castillo for (j = 0 ; j < cert->num_ext ; j++) { 4816f971622SJuan Castillo 48255e291a4SJuan Castillo ext = &extensions[cert->ext[j]]; 48355e291a4SJuan Castillo 48455e291a4SJuan Castillo /* Get OpenSSL internal ID for this extension */ 48555e291a4SJuan Castillo CHECK_OID(ext_nid, ext->oid); 48655e291a4SJuan Castillo 48755e291a4SJuan Castillo /* 48855e291a4SJuan Castillo * Three types of extensions are currently supported: 48955e291a4SJuan Castillo * - EXT_TYPE_NVCOUNTER 49055e291a4SJuan Castillo * - EXT_TYPE_HASH 49155e291a4SJuan Castillo * - EXT_TYPE_PKEY 49255e291a4SJuan Castillo */ 49355e291a4SJuan Castillo switch (ext->type) { 49455e291a4SJuan Castillo case EXT_TYPE_NVCOUNTER: 495f16db56aSYatharth Kochar if (ext->arg) { 49696103d5aSJuan Castillo nvctr = atoi(ext->arg); 49755e291a4SJuan Castillo CHECK_NULL(cert_ext, ext_new_nvcounter(ext_nid, 49896103d5aSJuan Castillo EXT_CRIT, nvctr)); 499f16db56aSYatharth Kochar } 50055e291a4SJuan Castillo break; 50155e291a4SJuan Castillo case EXT_TYPE_HASH: 50296103d5aSJuan Castillo if (ext->arg == NULL) { 503cebe1f23SYatharth Kochar if (ext->optional) { 504cebe1f23SYatharth Kochar /* Include a hash filled with zeros */ 5052972247cSQixiang Xu memset(md, 0x0, SHA512_DIGEST_LENGTH); 506cebe1f23SYatharth Kochar } else { 507cebe1f23SYatharth Kochar /* Do not include this hash in the certificate */ 50855e291a4SJuan Castillo break; 50955e291a4SJuan Castillo } 510cebe1f23SYatharth Kochar } else { 511cebe1f23SYatharth Kochar /* Calculate the hash of the file */ 5122972247cSQixiang Xu if (!sha_file(hash_alg, ext->arg, md)) { 51355e291a4SJuan Castillo ERROR("Cannot calculate hash of %s\n", 51496103d5aSJuan Castillo ext->arg); 5156f971622SJuan Castillo exit(1); 5166f971622SJuan Castillo } 517cebe1f23SYatharth Kochar } 51855e291a4SJuan Castillo CHECK_NULL(cert_ext, ext_new_hash(ext_nid, 51955e291a4SJuan Castillo EXT_CRIT, md_info, md, 5202972247cSQixiang Xu md_len)); 52155e291a4SJuan Castillo break; 52255e291a4SJuan Castillo case EXT_TYPE_PKEY: 52355e291a4SJuan Castillo CHECK_NULL(cert_ext, ext_new_key(ext_nid, 52496103d5aSJuan Castillo EXT_CRIT, keys[ext->attr.key].key)); 52555e291a4SJuan Castillo break; 52655e291a4SJuan Castillo default: 52796103d5aSJuan Castillo ERROR("Unknown extension type '%d' in %s\n", 52896103d5aSJuan Castillo ext->type, cert->cn); 52955e291a4SJuan Castillo exit(1); 53055e291a4SJuan Castillo } 53155e291a4SJuan Castillo 53255e291a4SJuan Castillo /* Push the extension into the stack */ 53355e291a4SJuan Castillo sk_X509_EXTENSION_push(sk, cert_ext); 53455e291a4SJuan Castillo } 5356f971622SJuan Castillo 536a8eb286aSSoby Mathew /* Create certificate. Signed with corresponding key */ 5376a415a50SJustin Chadwell if (cert->fn && !cert_new(hash_alg, cert, VAL_DAYS, 0, sk)) { 53855e291a4SJuan Castillo ERROR("Cannot create %s\n", cert->cn); 5396f971622SJuan Castillo exit(1); 5406f971622SJuan Castillo } 5416f971622SJuan Castillo 542bea80198SJimmy Brisson for (cert_ext = sk_X509_EXTENSION_pop(sk); cert_ext != NULL; 543bea80198SJimmy Brisson cert_ext = sk_X509_EXTENSION_pop(sk)) { 544bea80198SJimmy Brisson X509_EXTENSION_free(cert_ext); 545bea80198SJimmy Brisson } 546bea80198SJimmy Brisson 5476f971622SJuan Castillo sk_X509_EXTENSION_free(sk); 5486f971622SJuan Castillo } 5496f971622SJuan Castillo 5506f971622SJuan Castillo 5516f971622SJuan Castillo /* Print the certificates */ 5526f971622SJuan Castillo if (print_cert) { 55355e291a4SJuan Castillo for (i = 0 ; i < num_certs ; i++) { 5546f971622SJuan Castillo if (!certs[i].x) { 5556f971622SJuan Castillo continue; 5566f971622SJuan Castillo } 5576f971622SJuan Castillo printf("\n\n=====================================\n\n"); 5586f971622SJuan Castillo X509_print_fp(stdout, certs[i].x); 5596f971622SJuan Castillo } 5606f971622SJuan Castillo } 5616f971622SJuan Castillo 5626f971622SJuan Castillo /* Save created certificates to files */ 56355e291a4SJuan Castillo for (i = 0 ; i < num_certs ; i++) { 5646f971622SJuan Castillo if (certs[i].x && certs[i].fn) { 5656f971622SJuan Castillo file = fopen(certs[i].fn, "w"); 5666f971622SJuan Castillo if (file != NULL) { 5676f971622SJuan Castillo i2d_X509_fp(file, certs[i].x); 5686f971622SJuan Castillo fclose(file); 5696f971622SJuan Castillo } else { 5706f971622SJuan Castillo ERROR("Cannot create file %s\n", certs[i].fn); 5716f971622SJuan Castillo } 5726f971622SJuan Castillo } 5736f971622SJuan Castillo } 5746f971622SJuan Castillo 5756f971622SJuan Castillo /* Save keys */ 5766f971622SJuan Castillo if (save_keys) { 57755e291a4SJuan Castillo for (i = 0 ; i < num_keys ; i++) { 5786f971622SJuan Castillo if (!key_store(&keys[i])) { 5796f971622SJuan Castillo ERROR("Cannot save %s\n", keys[i].desc); 5806f971622SJuan Castillo } 5816f971622SJuan Castillo } 5826f971622SJuan Castillo } 5836f971622SJuan Castillo 5841f111f12SJimmy Brisson /* If we got here, then we must have filled the key array completely. 5851f111f12SJimmy Brisson * We can then safely call free on all of the keys in the array 5861f111f12SJimmy Brisson */ 5871f111f12SJimmy Brisson for (i = 0; i < num_keys; i++) { 5881f111f12SJimmy Brisson EVP_PKEY_free(keys[i].key); 5891f111f12SJimmy Brisson } 5901f111f12SJimmy Brisson 5916f971622SJuan Castillo #ifndef OPENSSL_NO_ENGINE 5926f971622SJuan Castillo ENGINE_cleanup(); 5936f971622SJuan Castillo #endif 5946f971622SJuan Castillo CRYPTO_cleanup_all_ex_data(); 5956f971622SJuan Castillo 596*4a34d18fSJimmy Brisson 597*4a34d18fSJimmy Brisson /* We allocated strings through strdup, so now we have to free them */ 598*4a34d18fSJimmy Brisson for (i = 0; i < num_keys; i++) { 599*4a34d18fSJimmy Brisson if (keys[i].fn != NULL) { 600*4a34d18fSJimmy Brisson void *ptr = keys[i].fn; 601*4a34d18fSJimmy Brisson 602*4a34d18fSJimmy Brisson keys[i].fn = NULL; 603*4a34d18fSJimmy Brisson free(ptr); 604*4a34d18fSJimmy Brisson } 605*4a34d18fSJimmy Brisson } 606*4a34d18fSJimmy Brisson for (i = 0; i < num_extensions; i++) { 607*4a34d18fSJimmy Brisson if (extensions[i].arg != NULL) { 608*4a34d18fSJimmy Brisson void *ptr = (void *)extensions[i].arg; 609*4a34d18fSJimmy Brisson 610*4a34d18fSJimmy Brisson extensions[i].arg = NULL; 611*4a34d18fSJimmy Brisson free(ptr); 612*4a34d18fSJimmy Brisson } 613*4a34d18fSJimmy Brisson } 614*4a34d18fSJimmy Brisson for (i = 0; i < num_certs; i++) { 615*4a34d18fSJimmy Brisson if (certs[i].fn != NULL) { 616*4a34d18fSJimmy Brisson void *ptr = (void *)certs[i].fn; 617*4a34d18fSJimmy Brisson 618*4a34d18fSJimmy Brisson certs[i].fn = NULL; 619*4a34d18fSJimmy Brisson free(ptr); 620*4a34d18fSJimmy Brisson } 621*4a34d18fSJimmy Brisson } 622*4a34d18fSJimmy Brisson 6236f971622SJuan Castillo return 0; 6246f971622SJuan Castillo } 625