16f971622SJuan Castillo /* 265ec13bcSJustin Chadwell * Copyright (c) 2015-2019, 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 22bb41eb7aSMasahiro Yamada #if USE_TBBR_DEFS 23bb41eb7aSMasahiro Yamada #include <tbbr_oid.h> 24bb41eb7aSMasahiro Yamada #else 25bb41eb7aSMasahiro Yamada #include <platform_oid.h> 26bb41eb7aSMasahiro Yamada #endif 27bb41eb7aSMasahiro Yamada 286f971622SJuan Castillo #include "cert.h" 29ad2c1a9aSJuan Castillo #include "cmd_opt.h" 306f971622SJuan Castillo #include "debug.h" 316f971622SJuan Castillo #include "ext.h" 326f971622SJuan Castillo #include "key.h" 336f971622SJuan Castillo #include "sha.h" 3455e291a4SJuan Castillo #include "tbbr/tbb_cert.h" 352a4b4b71SIsla Mitchell #include "tbbr/tbb_ext.h" 3655e291a4SJuan Castillo #include "tbbr/tbb_key.h" 376f971622SJuan Castillo 386f971622SJuan Castillo /* 396f971622SJuan Castillo * Helper macros to simplify the code. This macro assigns the return value of 406f971622SJuan Castillo * the 'fn' function to 'v' and exits if the value is NULL. 416f971622SJuan Castillo */ 426f971622SJuan Castillo #define CHECK_NULL(v, fn) \ 436f971622SJuan Castillo do { \ 446f971622SJuan Castillo v = fn; \ 456f971622SJuan Castillo if (v == NULL) { \ 466f971622SJuan Castillo ERROR("NULL object at %s:%d\n", __FILE__, __LINE__); \ 476f971622SJuan Castillo exit(1); \ 486f971622SJuan Castillo } \ 496f971622SJuan Castillo } while (0) 506f971622SJuan Castillo 516f971622SJuan Castillo /* 526f971622SJuan Castillo * This macro assigns the NID corresponding to 'oid' to 'v' and exits if the 536f971622SJuan Castillo * NID is undefined. 546f971622SJuan Castillo */ 556f971622SJuan Castillo #define CHECK_OID(v, oid) \ 566f971622SJuan Castillo do { \ 576f971622SJuan Castillo v = OBJ_txt2nid(oid); \ 586f971622SJuan Castillo if (v == NID_undef) { \ 596f971622SJuan Castillo ERROR("Cannot find TBB extension %s\n", oid); \ 606f971622SJuan Castillo exit(1); \ 616f971622SJuan Castillo } \ 626f971622SJuan Castillo } while (0) 636f971622SJuan Castillo 646f971622SJuan Castillo #define MAX_FILENAME_LEN 1024 656f971622SJuan Castillo #define VAL_DAYS 7300 666f971622SJuan Castillo #define ID_TO_BIT_MASK(id) (1 << id) 67ccbf890eSJuan Castillo #define NUM_ELEM(x) ((sizeof(x)) / (sizeof(x[0]))) 68159807e2SJuan Castillo #define HELP_OPT_MAX_LEN 128 696f971622SJuan Castillo 706f971622SJuan Castillo /* Global options */ 71ccbf890eSJuan Castillo static int key_alg; 722972247cSQixiang Xu static int hash_alg; 73dfe0f4c2SJustin Chadwell static int key_size; 746f971622SJuan Castillo static int new_keys; 756f971622SJuan Castillo static int save_keys; 766f971622SJuan Castillo static int print_cert; 776f971622SJuan Castillo 786f971622SJuan Castillo /* Info messages created in the Makefile */ 796f971622SJuan Castillo extern const char build_msg[]; 806f971622SJuan Castillo extern const char platform_msg[]; 816f971622SJuan Castillo 826f971622SJuan Castillo 836f971622SJuan Castillo static char *strdup(const char *str) 846f971622SJuan Castillo { 856f971622SJuan Castillo int n = strlen(str) + 1; 866f971622SJuan Castillo char *dup = malloc(n); 876f971622SJuan Castillo if (dup) { 886f971622SJuan Castillo strcpy(dup, str); 896f971622SJuan Castillo } 906f971622SJuan Castillo return dup; 916f971622SJuan Castillo } 926f971622SJuan Castillo 93ccbf890eSJuan Castillo static const char *key_algs_str[] = { 94ccbf890eSJuan Castillo [KEY_ALG_RSA] = "rsa", 95ed2a76eaSJuan Castillo #ifndef OPENSSL_NO_EC 96ccbf890eSJuan Castillo [KEY_ALG_ECDSA] = "ecdsa" 97ed2a76eaSJuan Castillo #endif /* OPENSSL_NO_EC */ 98ccbf890eSJuan Castillo }; 99ccbf890eSJuan Castillo 1002972247cSQixiang Xu static const char *hash_algs_str[] = { 1012972247cSQixiang Xu [HASH_ALG_SHA256] = "sha256", 1022972247cSQixiang Xu [HASH_ALG_SHA384] = "sha384", 1032972247cSQixiang Xu [HASH_ALG_SHA512] = "sha512", 1042972247cSQixiang Xu }; 1052972247cSQixiang Xu 106ad2c1a9aSJuan Castillo static void print_help(const char *cmd, const struct option *long_opt) 1076f971622SJuan Castillo { 108159807e2SJuan Castillo int rem, i = 0; 109159807e2SJuan Castillo const struct option *opt; 110159807e2SJuan Castillo char line[HELP_OPT_MAX_LEN]; 111159807e2SJuan Castillo char *p; 112159807e2SJuan Castillo 113159807e2SJuan Castillo assert(cmd != NULL); 114159807e2SJuan Castillo assert(long_opt != NULL); 115159807e2SJuan Castillo 1166f971622SJuan Castillo printf("\n\n"); 1176f971622SJuan Castillo printf("The certificate generation tool loads the binary images and\n" 1186f971622SJuan Castillo "optionally the RSA keys, and outputs the key and content\n" 1196f971622SJuan Castillo "certificates properly signed to implement the chain of trust.\n" 1206f971622SJuan Castillo "If keys are provided, they must be in PEM format.\n" 1216f971622SJuan Castillo "Certificates are generated in DER format.\n"); 1226f971622SJuan Castillo printf("\n"); 123159807e2SJuan Castillo printf("Usage:\n"); 124159807e2SJuan Castillo printf("\t%s [OPTIONS]\n\n", cmd); 125159807e2SJuan Castillo 126159807e2SJuan Castillo printf("Available options:\n"); 127159807e2SJuan Castillo opt = long_opt; 128159807e2SJuan Castillo while (opt->name) { 129159807e2SJuan Castillo p = line; 130159807e2SJuan Castillo rem = HELP_OPT_MAX_LEN; 131159807e2SJuan Castillo if (isalpha(opt->val)) { 132159807e2SJuan Castillo /* Short format */ 133159807e2SJuan Castillo sprintf(p, "-%c,", (char)opt->val); 134159807e2SJuan Castillo p += 3; 135159807e2SJuan Castillo rem -= 3; 1366f971622SJuan Castillo } 137159807e2SJuan Castillo snprintf(p, rem, "--%s %s", opt->name, 138159807e2SJuan Castillo (opt->has_arg == required_argument) ? "<arg>" : ""); 139159807e2SJuan Castillo printf("\t%-32s %s\n", line, cmd_opt_get_help_msg(i)); 140159807e2SJuan Castillo opt++; 141159807e2SJuan Castillo i++; 142159807e2SJuan Castillo } 1436f971622SJuan Castillo printf("\n"); 1446f971622SJuan Castillo } 1456f971622SJuan Castillo 146ccbf890eSJuan Castillo static int get_key_alg(const char *key_alg_str) 147ccbf890eSJuan Castillo { 148ccbf890eSJuan Castillo int i; 149ccbf890eSJuan Castillo 150ccbf890eSJuan Castillo for (i = 0 ; i < NUM_ELEM(key_algs_str) ; i++) { 151ccbf890eSJuan Castillo if (0 == strcmp(key_alg_str, key_algs_str[i])) { 152ccbf890eSJuan Castillo return i; 153ccbf890eSJuan Castillo } 154ccbf890eSJuan Castillo } 155ccbf890eSJuan Castillo 156ccbf890eSJuan Castillo return -1; 157ccbf890eSJuan Castillo } 158ccbf890eSJuan Castillo 159dfe0f4c2SJustin Chadwell static int get_key_size(const char *key_size_str) 160dfe0f4c2SJustin Chadwell { 161dfe0f4c2SJustin Chadwell char *end; 162dfe0f4c2SJustin Chadwell long key_size; 163dfe0f4c2SJustin Chadwell 164dfe0f4c2SJustin Chadwell key_size = strtol(key_size_str, &end, 10); 165dfe0f4c2SJustin Chadwell if (*end != '\0') 166dfe0f4c2SJustin Chadwell return -1; 167dfe0f4c2SJustin Chadwell 168dfe0f4c2SJustin Chadwell return key_size; 169dfe0f4c2SJustin Chadwell } 170dfe0f4c2SJustin Chadwell 1712972247cSQixiang Xu static int get_hash_alg(const char *hash_alg_str) 1722972247cSQixiang Xu { 1732972247cSQixiang Xu int i; 1742972247cSQixiang Xu 1752972247cSQixiang Xu for (i = 0 ; i < NUM_ELEM(hash_algs_str) ; i++) { 1762972247cSQixiang Xu if (0 == strcmp(hash_alg_str, hash_algs_str[i])) { 1772972247cSQixiang Xu return i; 1782972247cSQixiang Xu } 1792972247cSQixiang Xu } 1802972247cSQixiang Xu 1812972247cSQixiang Xu return -1; 1822972247cSQixiang Xu } 1832972247cSQixiang Xu 1846f971622SJuan Castillo static void check_cmd_params(void) 1856f971622SJuan Castillo { 186dfc90e26SJuan Castillo cert_t *cert; 187dfc90e26SJuan Castillo ext_t *ext; 188dfc90e26SJuan Castillo key_t *key; 189dfc90e26SJuan Castillo int i, j; 190dfe0f4c2SJustin Chadwell bool valid_size; 191dfc90e26SJuan Castillo 192ccbf890eSJuan Castillo /* Only save new keys */ 193ccbf890eSJuan Castillo if (save_keys && !new_keys) { 194ccbf890eSJuan Castillo ERROR("Only new keys can be saved to disk\n"); 195ccbf890eSJuan Castillo exit(1); 196ccbf890eSJuan Castillo } 197ccbf890eSJuan Castillo 198dfe0f4c2SJustin Chadwell /* Validate key-size */ 199dfe0f4c2SJustin Chadwell valid_size = false; 200dfe0f4c2SJustin Chadwell for (i = 0; i < KEY_SIZE_MAX_NUM; i++) { 201dfe0f4c2SJustin Chadwell if (key_size == KEY_SIZES[key_alg][i]) { 202dfe0f4c2SJustin Chadwell valid_size = true; 203dfe0f4c2SJustin Chadwell break; 204dfe0f4c2SJustin Chadwell } 205dfe0f4c2SJustin Chadwell } 206dfe0f4c2SJustin Chadwell if (!valid_size) { 207dfe0f4c2SJustin Chadwell ERROR("'%d' is not a valid key size for '%s'\n", 208dfe0f4c2SJustin Chadwell key_size, key_algs_str[key_alg]); 209dfe0f4c2SJustin Chadwell NOTICE("Valid sizes are: "); 210dfe0f4c2SJustin Chadwell for (i = 0; i < KEY_SIZE_MAX_NUM && 211dfe0f4c2SJustin Chadwell KEY_SIZES[key_alg][i] != 0; i++) { 212dfe0f4c2SJustin Chadwell printf("%d ", KEY_SIZES[key_alg][i]); 213dfe0f4c2SJustin Chadwell } 214dfe0f4c2SJustin Chadwell printf("\n"); 215dfe0f4c2SJustin Chadwell exit(1); 216dfe0f4c2SJustin Chadwell } 217dfe0f4c2SJustin Chadwell 218dfc90e26SJuan Castillo /* Check that all required options have been specified in the 219dfc90e26SJuan Castillo * command line */ 220dfc90e26SJuan Castillo for (i = 0; i < num_certs; i++) { 221dfc90e26SJuan Castillo cert = &certs[i]; 222dfc90e26SJuan Castillo if (cert->fn == NULL) { 223dfc90e26SJuan Castillo /* Certificate not requested. Skip to the next one */ 224dfc90e26SJuan Castillo continue; 225dfc90e26SJuan Castillo } 226dfc90e26SJuan Castillo 227dfc90e26SJuan Castillo /* Check that all parameters required to create this certificate 228dfc90e26SJuan Castillo * have been specified in the command line */ 229dfc90e26SJuan Castillo for (j = 0; j < cert->num_ext; j++) { 230dfc90e26SJuan Castillo ext = &extensions[cert->ext[j]]; 231dfc90e26SJuan Castillo switch (ext->type) { 23296103d5aSJuan Castillo case EXT_TYPE_NVCOUNTER: 23396103d5aSJuan Castillo /* Counter value must be specified */ 23496103d5aSJuan Castillo if ((!ext->optional) && (ext->arg == NULL)) { 23596103d5aSJuan Castillo ERROR("Value for '%s' not specified\n", 23696103d5aSJuan Castillo ext->ln); 23796103d5aSJuan Castillo exit(1); 23896103d5aSJuan Castillo } 23996103d5aSJuan Castillo break; 240dfc90e26SJuan Castillo case EXT_TYPE_PKEY: 241dfc90e26SJuan Castillo /* Key filename must be specified */ 24296103d5aSJuan Castillo key = &keys[ext->attr.key]; 243dfc90e26SJuan Castillo if (!new_keys && key->fn == NULL) { 244dfc90e26SJuan Castillo ERROR("Key '%s' required by '%s' not " 245dfc90e26SJuan Castillo "specified\n", key->desc, 246dfc90e26SJuan Castillo cert->cn); 2476f971622SJuan Castillo exit(1); 2486f971622SJuan Castillo } 249dfc90e26SJuan Castillo break; 250dfc90e26SJuan Castillo case EXT_TYPE_HASH: 251cebe1f23SYatharth Kochar /* 252cebe1f23SYatharth Kochar * Binary image must be specified 253cebe1f23SYatharth Kochar * unless it is explicitly made optional. 254cebe1f23SYatharth Kochar */ 25596103d5aSJuan Castillo if ((!ext->optional) && (ext->arg == NULL)) { 256dfc90e26SJuan Castillo ERROR("Image for '%s' not specified\n", 257dfc90e26SJuan Castillo ext->ln); 2586f971622SJuan Castillo exit(1); 2596f971622SJuan Castillo } 260dfc90e26SJuan Castillo break; 261dfc90e26SJuan Castillo default: 26296103d5aSJuan Castillo ERROR("Unknown extension type '%d' in '%s'\n", 26396103d5aSJuan Castillo ext->type, ext->ln); 2646f971622SJuan Castillo exit(1); 265dfc90e26SJuan Castillo break; 2666f971622SJuan Castillo } 2676f971622SJuan Castillo } 2686f971622SJuan Castillo } 2696f971622SJuan Castillo } 2706f971622SJuan Castillo 271159807e2SJuan Castillo /* Common command line options */ 272159807e2SJuan Castillo static const cmd_opt_t common_cmd_opt[] = { 273159807e2SJuan Castillo { 274159807e2SJuan Castillo { "help", no_argument, NULL, 'h' }, 275159807e2SJuan Castillo "Print this message and exit" 276159807e2SJuan Castillo }, 277159807e2SJuan Castillo { 278159807e2SJuan Castillo { "key-alg", required_argument, NULL, 'a' }, 279*6a415a50SJustin Chadwell "Key algorithm: 'rsa' (default)- RSAPSS scheme as per PKCS#1 v2.1, 'ecdsa'" 280159807e2SJuan Castillo }, 281159807e2SJuan Castillo { 282dfe0f4c2SJustin Chadwell { "key-size", required_argument, NULL, 'b' }, 283dfe0f4c2SJustin Chadwell "Key size (for supported algorithms)." 284dfe0f4c2SJustin Chadwell }, 285dfe0f4c2SJustin Chadwell { 2862972247cSQixiang Xu { "hash-alg", required_argument, NULL, 's' }, 2872972247cSQixiang Xu "Hash algorithm : 'sha256' (default), 'sha384', 'sha512'" 2882972247cSQixiang Xu }, 2892972247cSQixiang Xu { 290159807e2SJuan Castillo { "save-keys", no_argument, NULL, 'k' }, 291159807e2SJuan Castillo "Save key pairs into files. Filenames must be provided" 292159807e2SJuan Castillo }, 293159807e2SJuan Castillo { 294159807e2SJuan Castillo { "new-keys", no_argument, NULL, 'n' }, 295159807e2SJuan Castillo "Generate new key pairs if no key files are provided" 296159807e2SJuan Castillo }, 297159807e2SJuan Castillo { 298159807e2SJuan Castillo { "print-cert", no_argument, NULL, 'p' }, 299159807e2SJuan Castillo "Print the certificates in the standard output" 300159807e2SJuan Castillo } 301159807e2SJuan Castillo }; 302159807e2SJuan Castillo 3036f971622SJuan Castillo int main(int argc, char *argv[]) 3046f971622SJuan Castillo { 305c893c733SMasahiro Yamada STACK_OF(X509_EXTENSION) * sk; 306742c4e14SMichalis Pappas X509_EXTENSION *cert_ext = NULL; 307c893c733SMasahiro Yamada ext_t *ext; 308c893c733SMasahiro Yamada key_t *key; 309c893c733SMasahiro Yamada cert_t *cert; 310c893c733SMasahiro Yamada FILE *file; 31196103d5aSJuan Castillo int i, j, ext_nid, nvctr; 3126f971622SJuan Castillo int c, opt_idx = 0; 313ad2c1a9aSJuan Castillo const struct option *cmd_opt; 314ad2c1a9aSJuan Castillo const char *cur_opt; 315ccbf890eSJuan Castillo unsigned int err_code; 3162972247cSQixiang Xu unsigned char md[SHA512_DIGEST_LENGTH]; 3172972247cSQixiang Xu unsigned int md_len; 318c3da66b1SJuan Castillo const EVP_MD *md_info; 3196f971622SJuan Castillo 3206f971622SJuan Castillo NOTICE("CoT Generation Tool: %s\n", build_msg); 3216f971622SJuan Castillo NOTICE("Target platform: %s\n", platform_msg); 3226f971622SJuan Castillo 323ccbf890eSJuan Castillo /* Set default options */ 324ccbf890eSJuan Castillo key_alg = KEY_ALG_RSA; 3252972247cSQixiang Xu hash_alg = HASH_ALG_SHA256; 326dfe0f4c2SJustin Chadwell key_size = -1; 327ccbf890eSJuan Castillo 328ad2c1a9aSJuan Castillo /* Add common command line options */ 329159807e2SJuan Castillo for (i = 0; i < NUM_ELEM(common_cmd_opt); i++) { 330159807e2SJuan Castillo cmd_opt_add(&common_cmd_opt[i]); 331159807e2SJuan Castillo } 332ad2c1a9aSJuan Castillo 333ad2c1a9aSJuan Castillo /* Initialize the certificates */ 334ad2c1a9aSJuan Castillo if (cert_init() != 0) { 335ad2c1a9aSJuan Castillo ERROR("Cannot initialize certificates\n"); 336ad2c1a9aSJuan Castillo exit(1); 337ad2c1a9aSJuan Castillo } 338ad2c1a9aSJuan Castillo 339ad2c1a9aSJuan Castillo /* Initialize the keys */ 340ad2c1a9aSJuan Castillo if (key_init() != 0) { 341ad2c1a9aSJuan Castillo ERROR("Cannot initialize keys\n"); 342ad2c1a9aSJuan Castillo exit(1); 343ad2c1a9aSJuan Castillo } 344ad2c1a9aSJuan Castillo 345ad2c1a9aSJuan Castillo /* Initialize the new types and register OIDs for the extensions */ 346ad2c1a9aSJuan Castillo if (ext_init() != 0) { 347ad2c1a9aSJuan Castillo ERROR("Cannot initialize TBB extensions\n"); 348ad2c1a9aSJuan Castillo exit(1); 349ad2c1a9aSJuan Castillo } 350ad2c1a9aSJuan Castillo 351ad2c1a9aSJuan Castillo /* Get the command line options populated during the initialization */ 352ad2c1a9aSJuan Castillo cmd_opt = cmd_opt_get_array(); 353ad2c1a9aSJuan Castillo 3546f971622SJuan Castillo while (1) { 3556f971622SJuan Castillo /* getopt_long stores the option index here. */ 356dfe0f4c2SJustin Chadwell c = getopt_long(argc, argv, "a:b:hknps:", cmd_opt, &opt_idx); 3576f971622SJuan Castillo 3586f971622SJuan Castillo /* Detect the end of the options. */ 3596f971622SJuan Castillo if (c == -1) { 3606f971622SJuan Castillo break; 3616f971622SJuan Castillo } 3626f971622SJuan Castillo 3636f971622SJuan Castillo switch (c) { 364ccbf890eSJuan Castillo case 'a': 365ccbf890eSJuan Castillo key_alg = get_key_alg(optarg); 366ccbf890eSJuan Castillo if (key_alg < 0) { 367ccbf890eSJuan Castillo ERROR("Invalid key algorithm '%s'\n", optarg); 368ccbf890eSJuan Castillo exit(1); 369ccbf890eSJuan Castillo } 370ccbf890eSJuan Castillo break; 371dfe0f4c2SJustin Chadwell case 'b': 372dfe0f4c2SJustin Chadwell key_size = get_key_size(optarg); 373dfe0f4c2SJustin Chadwell if (key_size <= 0) { 374dfe0f4c2SJustin Chadwell ERROR("Invalid key size '%s'\n", optarg); 375dfe0f4c2SJustin Chadwell exit(1); 376dfe0f4c2SJustin Chadwell } 377dfe0f4c2SJustin Chadwell break; 3786f971622SJuan Castillo case 'h': 379ad2c1a9aSJuan Castillo print_help(argv[0], cmd_opt); 380600835d0SRoberto Vargas exit(0); 3816f971622SJuan Castillo case 'k': 3826f971622SJuan Castillo save_keys = 1; 3836f971622SJuan Castillo break; 3846f971622SJuan Castillo case 'n': 3856f971622SJuan Castillo new_keys = 1; 3866f971622SJuan Castillo break; 3876f971622SJuan Castillo case 'p': 3886f971622SJuan Castillo print_cert = 1; 3896f971622SJuan Castillo break; 3902972247cSQixiang Xu case 's': 3912972247cSQixiang Xu hash_alg = get_hash_alg(optarg); 3922972247cSQixiang Xu if (hash_alg < 0) { 3932972247cSQixiang Xu ERROR("Invalid hash algorithm '%s'\n", optarg); 3942972247cSQixiang Xu exit(1); 3952972247cSQixiang Xu } 3962972247cSQixiang Xu break; 397ad2c1a9aSJuan Castillo case CMD_OPT_EXT: 398ad2c1a9aSJuan Castillo cur_opt = cmd_opt_get_name(opt_idx); 399ad2c1a9aSJuan Castillo ext = ext_get_by_opt(cur_opt); 40096103d5aSJuan Castillo ext->arg = strdup(optarg); 4016f971622SJuan Castillo break; 402ad2c1a9aSJuan Castillo case CMD_OPT_KEY: 403ad2c1a9aSJuan Castillo cur_opt = cmd_opt_get_name(opt_idx); 404ad2c1a9aSJuan Castillo key = key_get_by_opt(cur_opt); 405ad2c1a9aSJuan Castillo key->fn = strdup(optarg); 4066f971622SJuan Castillo break; 407ad2c1a9aSJuan Castillo case CMD_OPT_CERT: 408ad2c1a9aSJuan Castillo cur_opt = cmd_opt_get_name(opt_idx); 409ad2c1a9aSJuan Castillo cert = cert_get_by_opt(cur_opt); 410ad2c1a9aSJuan Castillo cert->fn = strdup(optarg); 4116f971622SJuan Castillo break; 4126f971622SJuan Castillo case '?': 4136f971622SJuan Castillo default: 414159807e2SJuan Castillo print_help(argv[0], cmd_opt); 4156f971622SJuan Castillo exit(1); 4166f971622SJuan Castillo } 4176f971622SJuan Castillo } 4186f971622SJuan Castillo 419dfe0f4c2SJustin Chadwell /* Select a reasonable default key-size */ 420dfe0f4c2SJustin Chadwell if (key_size == -1) { 421dfe0f4c2SJustin Chadwell key_size = KEY_SIZES[key_alg][0]; 422dfe0f4c2SJustin Chadwell } 423dfe0f4c2SJustin Chadwell 4246f971622SJuan Castillo /* Check command line arguments */ 4256f971622SJuan Castillo check_cmd_params(); 4266f971622SJuan Castillo 4272972247cSQixiang Xu /* Indicate SHA as image hash algorithm in the certificate 428c3da66b1SJuan Castillo * extension */ 4292972247cSQixiang Xu if (hash_alg == HASH_ALG_SHA384) { 4302972247cSQixiang Xu md_info = EVP_sha384(); 4312972247cSQixiang Xu md_len = SHA384_DIGEST_LENGTH; 4322972247cSQixiang Xu } else if (hash_alg == HASH_ALG_SHA512) { 4332972247cSQixiang Xu md_info = EVP_sha512(); 4342972247cSQixiang Xu md_len = SHA512_DIGEST_LENGTH; 4352972247cSQixiang Xu } else { 436c3da66b1SJuan Castillo md_info = EVP_sha256(); 4372972247cSQixiang Xu md_len = SHA256_DIGEST_LENGTH; 4382972247cSQixiang Xu } 439c3da66b1SJuan Castillo 4406f971622SJuan Castillo /* Load private keys from files (or generate new ones) */ 44155e291a4SJuan Castillo for (i = 0 ; i < num_keys ; i++) { 442762f1ebeSMasahiro Yamada if (!key_new(&keys[i])) { 443762f1ebeSMasahiro Yamada ERROR("Failed to allocate key container\n"); 444762f1ebeSMasahiro Yamada exit(1); 445762f1ebeSMasahiro Yamada } 446762f1ebeSMasahiro Yamada 447ccbf890eSJuan Castillo /* First try to load the key from disk */ 448ccbf890eSJuan Castillo if (key_load(&keys[i], &err_code)) { 449ccbf890eSJuan Castillo /* Key loaded successfully */ 450ccbf890eSJuan Castillo continue; 451ccbf890eSJuan Castillo } 452ccbf890eSJuan Castillo 453ccbf890eSJuan Castillo /* Key not loaded. Check the error code */ 454762f1ebeSMasahiro Yamada if (err_code == KEY_ERR_LOAD) { 455ccbf890eSJuan Castillo /* File exists, but it does not contain a valid private 456ccbf890eSJuan Castillo * key. Abort. */ 457ccbf890eSJuan Castillo ERROR("Error loading '%s'\n", keys[i].fn); 4586f971622SJuan Castillo exit(1); 4596f971622SJuan Castillo } 460ccbf890eSJuan Castillo 461ccbf890eSJuan Castillo /* File does not exist, could not be opened or no filename was 462ccbf890eSJuan Castillo * given */ 463ccbf890eSJuan Castillo if (new_keys) { 464ccbf890eSJuan Castillo /* Try to create a new key */ 465ccbf890eSJuan Castillo NOTICE("Creating new key for '%s'\n", keys[i].desc); 466dfe0f4c2SJustin Chadwell if (!key_create(&keys[i], key_alg, key_size)) { 467ccbf890eSJuan Castillo ERROR("Error creating key '%s'\n", keys[i].desc); 468ccbf890eSJuan Castillo exit(1); 4696f971622SJuan Castillo } 4706f971622SJuan Castillo } else { 471ccbf890eSJuan Castillo if (err_code == KEY_ERR_OPEN) { 472ccbf890eSJuan Castillo ERROR("Error opening '%s'\n", keys[i].fn); 473ccbf890eSJuan Castillo } else { 474ccbf890eSJuan Castillo ERROR("Key '%s' not specified\n", keys[i].desc); 4756f971622SJuan Castillo } 476ccbf890eSJuan Castillo exit(1); 4776f971622SJuan Castillo } 4786f971622SJuan Castillo } 4796f971622SJuan Castillo 48055e291a4SJuan Castillo /* Create the certificates */ 48155e291a4SJuan Castillo for (i = 0 ; i < num_certs ; i++) { 48255e291a4SJuan Castillo 48355e291a4SJuan Castillo cert = &certs[i]; 48455e291a4SJuan Castillo 48555e291a4SJuan Castillo /* Create a new stack of extensions. This stack will be used 48655e291a4SJuan Castillo * to create the certificate */ 4876f971622SJuan Castillo CHECK_NULL(sk, sk_X509_EXTENSION_new_null()); 4886f971622SJuan Castillo 48955e291a4SJuan Castillo for (j = 0 ; j < cert->num_ext ; j++) { 4906f971622SJuan Castillo 49155e291a4SJuan Castillo ext = &extensions[cert->ext[j]]; 49255e291a4SJuan Castillo 49355e291a4SJuan Castillo /* Get OpenSSL internal ID for this extension */ 49455e291a4SJuan Castillo CHECK_OID(ext_nid, ext->oid); 49555e291a4SJuan Castillo 49655e291a4SJuan Castillo /* 49755e291a4SJuan Castillo * Three types of extensions are currently supported: 49855e291a4SJuan Castillo * - EXT_TYPE_NVCOUNTER 49955e291a4SJuan Castillo * - EXT_TYPE_HASH 50055e291a4SJuan Castillo * - EXT_TYPE_PKEY 50155e291a4SJuan Castillo */ 50255e291a4SJuan Castillo switch (ext->type) { 50355e291a4SJuan Castillo case EXT_TYPE_NVCOUNTER: 504f16db56aSYatharth Kochar if (ext->arg) { 50596103d5aSJuan Castillo nvctr = atoi(ext->arg); 50655e291a4SJuan Castillo CHECK_NULL(cert_ext, ext_new_nvcounter(ext_nid, 50796103d5aSJuan Castillo EXT_CRIT, nvctr)); 508f16db56aSYatharth Kochar } 50955e291a4SJuan Castillo break; 51055e291a4SJuan Castillo case EXT_TYPE_HASH: 51196103d5aSJuan Castillo if (ext->arg == NULL) { 512cebe1f23SYatharth Kochar if (ext->optional) { 513cebe1f23SYatharth Kochar /* Include a hash filled with zeros */ 5142972247cSQixiang Xu memset(md, 0x0, SHA512_DIGEST_LENGTH); 515cebe1f23SYatharth Kochar } else { 516cebe1f23SYatharth Kochar /* Do not include this hash in the certificate */ 51755e291a4SJuan Castillo break; 51855e291a4SJuan Castillo } 519cebe1f23SYatharth Kochar } else { 520cebe1f23SYatharth Kochar /* Calculate the hash of the file */ 5212972247cSQixiang Xu if (!sha_file(hash_alg, ext->arg, md)) { 52255e291a4SJuan Castillo ERROR("Cannot calculate hash of %s\n", 52396103d5aSJuan Castillo ext->arg); 5246f971622SJuan Castillo exit(1); 5256f971622SJuan Castillo } 526cebe1f23SYatharth Kochar } 52755e291a4SJuan Castillo CHECK_NULL(cert_ext, ext_new_hash(ext_nid, 52855e291a4SJuan Castillo EXT_CRIT, md_info, md, 5292972247cSQixiang Xu md_len)); 53055e291a4SJuan Castillo break; 53155e291a4SJuan Castillo case EXT_TYPE_PKEY: 53255e291a4SJuan Castillo CHECK_NULL(cert_ext, ext_new_key(ext_nid, 53396103d5aSJuan Castillo EXT_CRIT, keys[ext->attr.key].key)); 53455e291a4SJuan Castillo break; 53555e291a4SJuan Castillo default: 53696103d5aSJuan Castillo ERROR("Unknown extension type '%d' in %s\n", 53796103d5aSJuan Castillo ext->type, cert->cn); 53855e291a4SJuan Castillo exit(1); 53955e291a4SJuan Castillo } 54055e291a4SJuan Castillo 54155e291a4SJuan Castillo /* Push the extension into the stack */ 54255e291a4SJuan Castillo sk_X509_EXTENSION_push(sk, cert_ext); 54355e291a4SJuan Castillo } 5446f971622SJuan Castillo 545a8eb286aSSoby Mathew /* Create certificate. Signed with corresponding key */ 546*6a415a50SJustin Chadwell if (cert->fn && !cert_new(hash_alg, cert, VAL_DAYS, 0, sk)) { 54755e291a4SJuan Castillo ERROR("Cannot create %s\n", cert->cn); 5486f971622SJuan Castillo exit(1); 5496f971622SJuan Castillo } 5506f971622SJuan Castillo 5516f971622SJuan Castillo sk_X509_EXTENSION_free(sk); 5526f971622SJuan Castillo } 5536f971622SJuan Castillo 5546f971622SJuan Castillo 5556f971622SJuan Castillo /* Print the certificates */ 5566f971622SJuan Castillo if (print_cert) { 55755e291a4SJuan Castillo for (i = 0 ; i < num_certs ; i++) { 5586f971622SJuan Castillo if (!certs[i].x) { 5596f971622SJuan Castillo continue; 5606f971622SJuan Castillo } 5616f971622SJuan Castillo printf("\n\n=====================================\n\n"); 5626f971622SJuan Castillo X509_print_fp(stdout, certs[i].x); 5636f971622SJuan Castillo } 5646f971622SJuan Castillo } 5656f971622SJuan Castillo 5666f971622SJuan Castillo /* Save created certificates to files */ 56755e291a4SJuan Castillo for (i = 0 ; i < num_certs ; i++) { 5686f971622SJuan Castillo if (certs[i].x && certs[i].fn) { 5696f971622SJuan Castillo file = fopen(certs[i].fn, "w"); 5706f971622SJuan Castillo if (file != NULL) { 5716f971622SJuan Castillo i2d_X509_fp(file, certs[i].x); 5726f971622SJuan Castillo fclose(file); 5736f971622SJuan Castillo } else { 5746f971622SJuan Castillo ERROR("Cannot create file %s\n", certs[i].fn); 5756f971622SJuan Castillo } 5766f971622SJuan Castillo } 5776f971622SJuan Castillo } 5786f971622SJuan Castillo 5796f971622SJuan Castillo /* Save keys */ 5806f971622SJuan Castillo if (save_keys) { 58155e291a4SJuan Castillo for (i = 0 ; i < num_keys ; i++) { 5826f971622SJuan Castillo if (!key_store(&keys[i])) { 5836f971622SJuan Castillo ERROR("Cannot save %s\n", keys[i].desc); 5846f971622SJuan Castillo } 5856f971622SJuan Castillo } 5866f971622SJuan Castillo } 5876f971622SJuan Castillo 5886f971622SJuan Castillo #ifndef OPENSSL_NO_ENGINE 5896f971622SJuan Castillo ENGINE_cleanup(); 5906f971622SJuan Castillo #endif 5916f971622SJuan Castillo CRYPTO_cleanup_all_ex_data(); 5926f971622SJuan Castillo 5936f971622SJuan Castillo return 0; 5946f971622SJuan Castillo } 595