16f971622SJuan Castillo /* 2bb41eb7aSMasahiro Yamada * Copyright (c) 2015-2017, 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> 136f971622SJuan Castillo 146f971622SJuan Castillo #include <openssl/conf.h> 156f971622SJuan Castillo #include <openssl/engine.h> 166f971622SJuan Castillo #include <openssl/err.h> 176f971622SJuan Castillo #include <openssl/pem.h> 186f971622SJuan Castillo #include <openssl/sha.h> 196f971622SJuan Castillo #include <openssl/x509v3.h> 206f971622SJuan Castillo 21bb41eb7aSMasahiro Yamada #if USE_TBBR_DEFS 22bb41eb7aSMasahiro Yamada #include <tbbr_oid.h> 23bb41eb7aSMasahiro Yamada #else 24bb41eb7aSMasahiro Yamada #include <platform_oid.h> 25bb41eb7aSMasahiro Yamada #endif 26bb41eb7aSMasahiro Yamada 276f971622SJuan Castillo #include "cert.h" 28ad2c1a9aSJuan Castillo #include "cmd_opt.h" 296f971622SJuan Castillo #include "debug.h" 306f971622SJuan Castillo #include "ext.h" 316f971622SJuan Castillo #include "key.h" 326f971622SJuan Castillo #include "sha.h" 3355e291a4SJuan Castillo #include "tbbr/tbb_cert.h" 342a4b4b71SIsla Mitchell #include "tbbr/tbb_ext.h" 3555e291a4SJuan Castillo #include "tbbr/tbb_key.h" 366f971622SJuan Castillo 376f971622SJuan Castillo /* 386f971622SJuan Castillo * Helper macros to simplify the code. This macro assigns the return value of 396f971622SJuan Castillo * the 'fn' function to 'v' and exits if the value is NULL. 406f971622SJuan Castillo */ 416f971622SJuan Castillo #define CHECK_NULL(v, fn) \ 426f971622SJuan Castillo do { \ 436f971622SJuan Castillo v = fn; \ 446f971622SJuan Castillo if (v == NULL) { \ 456f971622SJuan Castillo ERROR("NULL object at %s:%d\n", __FILE__, __LINE__); \ 466f971622SJuan Castillo exit(1); \ 476f971622SJuan Castillo } \ 486f971622SJuan Castillo } while (0) 496f971622SJuan Castillo 506f971622SJuan Castillo /* 516f971622SJuan Castillo * This macro assigns the NID corresponding to 'oid' to 'v' and exits if the 526f971622SJuan Castillo * NID is undefined. 536f971622SJuan Castillo */ 546f971622SJuan Castillo #define CHECK_OID(v, oid) \ 556f971622SJuan Castillo do { \ 566f971622SJuan Castillo v = OBJ_txt2nid(oid); \ 576f971622SJuan Castillo if (v == NID_undef) { \ 586f971622SJuan Castillo ERROR("Cannot find TBB extension %s\n", oid); \ 596f971622SJuan Castillo exit(1); \ 606f971622SJuan Castillo } \ 616f971622SJuan Castillo } while (0) 626f971622SJuan Castillo 636f971622SJuan Castillo #define MAX_FILENAME_LEN 1024 646f971622SJuan Castillo #define VAL_DAYS 7300 656f971622SJuan Castillo #define ID_TO_BIT_MASK(id) (1 << id) 66ccbf890eSJuan Castillo #define NUM_ELEM(x) ((sizeof(x)) / (sizeof(x[0]))) 67159807e2SJuan Castillo #define HELP_OPT_MAX_LEN 128 686f971622SJuan Castillo 696f971622SJuan Castillo /* Global options */ 70ccbf890eSJuan Castillo static int key_alg; 71*2972247cSQixiang Xu static int hash_alg; 726f971622SJuan Castillo static int new_keys; 736f971622SJuan Castillo static int save_keys; 746f971622SJuan Castillo static int print_cert; 756f971622SJuan Castillo 766f971622SJuan Castillo /* Info messages created in the Makefile */ 776f971622SJuan Castillo extern const char build_msg[]; 786f971622SJuan Castillo extern const char platform_msg[]; 796f971622SJuan Castillo 806f971622SJuan Castillo 816f971622SJuan Castillo static char *strdup(const char *str) 826f971622SJuan Castillo { 836f971622SJuan Castillo int n = strlen(str) + 1; 846f971622SJuan Castillo char *dup = malloc(n); 856f971622SJuan Castillo if (dup) { 866f971622SJuan Castillo strcpy(dup, str); 876f971622SJuan Castillo } 886f971622SJuan Castillo return dup; 896f971622SJuan Castillo } 906f971622SJuan Castillo 91ccbf890eSJuan Castillo static const char *key_algs_str[] = { 92ccbf890eSJuan Castillo [KEY_ALG_RSA] = "rsa", 93a8eb286aSSoby Mathew [KEY_ALG_RSA_1_5] = "rsa_1_5", 94ed2a76eaSJuan Castillo #ifndef OPENSSL_NO_EC 95ccbf890eSJuan Castillo [KEY_ALG_ECDSA] = "ecdsa" 96ed2a76eaSJuan Castillo #endif /* OPENSSL_NO_EC */ 97ccbf890eSJuan Castillo }; 98ccbf890eSJuan Castillo 99*2972247cSQixiang Xu static const char *hash_algs_str[] = { 100*2972247cSQixiang Xu [HASH_ALG_SHA256] = "sha256", 101*2972247cSQixiang Xu [HASH_ALG_SHA384] = "sha384", 102*2972247cSQixiang Xu [HASH_ALG_SHA512] = "sha512", 103*2972247cSQixiang Xu }; 104*2972247cSQixiang Xu 105ad2c1a9aSJuan Castillo static void print_help(const char *cmd, const struct option *long_opt) 1066f971622SJuan Castillo { 107159807e2SJuan Castillo int rem, i = 0; 108159807e2SJuan Castillo const struct option *opt; 109159807e2SJuan Castillo char line[HELP_OPT_MAX_LEN]; 110159807e2SJuan Castillo char *p; 111159807e2SJuan Castillo 112159807e2SJuan Castillo assert(cmd != NULL); 113159807e2SJuan Castillo assert(long_opt != NULL); 114159807e2SJuan Castillo 1156f971622SJuan Castillo printf("\n\n"); 1166f971622SJuan Castillo printf("The certificate generation tool loads the binary images and\n" 1176f971622SJuan Castillo "optionally the RSA keys, and outputs the key and content\n" 1186f971622SJuan Castillo "certificates properly signed to implement the chain of trust.\n" 1196f971622SJuan Castillo "If keys are provided, they must be in PEM format.\n" 1206f971622SJuan Castillo "Certificates are generated in DER format.\n"); 1216f971622SJuan Castillo printf("\n"); 122159807e2SJuan Castillo printf("Usage:\n"); 123159807e2SJuan Castillo printf("\t%s [OPTIONS]\n\n", cmd); 124159807e2SJuan Castillo 125159807e2SJuan Castillo printf("Available options:\n"); 126159807e2SJuan Castillo opt = long_opt; 127159807e2SJuan Castillo while (opt->name) { 128159807e2SJuan Castillo p = line; 129159807e2SJuan Castillo rem = HELP_OPT_MAX_LEN; 130159807e2SJuan Castillo if (isalpha(opt->val)) { 131159807e2SJuan Castillo /* Short format */ 132159807e2SJuan Castillo sprintf(p, "-%c,", (char)opt->val); 133159807e2SJuan Castillo p += 3; 134159807e2SJuan Castillo rem -= 3; 1356f971622SJuan Castillo } 136159807e2SJuan Castillo snprintf(p, rem, "--%s %s", opt->name, 137159807e2SJuan Castillo (opt->has_arg == required_argument) ? "<arg>" : ""); 138159807e2SJuan Castillo printf("\t%-32s %s\n", line, cmd_opt_get_help_msg(i)); 139159807e2SJuan Castillo opt++; 140159807e2SJuan Castillo i++; 141159807e2SJuan Castillo } 1426f971622SJuan Castillo printf("\n"); 1436f971622SJuan Castillo 1446f971622SJuan Castillo exit(0); 1456f971622SJuan Castillo } 1466f971622SJuan Castillo 147ccbf890eSJuan Castillo static int get_key_alg(const char *key_alg_str) 148ccbf890eSJuan Castillo { 149ccbf890eSJuan Castillo int i; 150ccbf890eSJuan Castillo 151ccbf890eSJuan Castillo for (i = 0 ; i < NUM_ELEM(key_algs_str) ; i++) { 152ccbf890eSJuan Castillo if (0 == strcmp(key_alg_str, key_algs_str[i])) { 153ccbf890eSJuan Castillo return i; 154ccbf890eSJuan Castillo } 155ccbf890eSJuan Castillo } 156ccbf890eSJuan Castillo 157ccbf890eSJuan Castillo return -1; 158ccbf890eSJuan Castillo } 159ccbf890eSJuan Castillo 160*2972247cSQixiang Xu static int get_hash_alg(const char *hash_alg_str) 161*2972247cSQixiang Xu { 162*2972247cSQixiang Xu int i; 163*2972247cSQixiang Xu 164*2972247cSQixiang Xu for (i = 0 ; i < NUM_ELEM(hash_algs_str) ; i++) { 165*2972247cSQixiang Xu if (0 == strcmp(hash_alg_str, hash_algs_str[i])) { 166*2972247cSQixiang Xu return i; 167*2972247cSQixiang Xu } 168*2972247cSQixiang Xu } 169*2972247cSQixiang Xu 170*2972247cSQixiang Xu return -1; 171*2972247cSQixiang Xu } 172*2972247cSQixiang Xu 1736f971622SJuan Castillo static void check_cmd_params(void) 1746f971622SJuan Castillo { 175dfc90e26SJuan Castillo cert_t *cert; 176dfc90e26SJuan Castillo ext_t *ext; 177dfc90e26SJuan Castillo key_t *key; 178dfc90e26SJuan Castillo int i, j; 179dfc90e26SJuan Castillo 180ccbf890eSJuan Castillo /* Only save new keys */ 181ccbf890eSJuan Castillo if (save_keys && !new_keys) { 182ccbf890eSJuan Castillo ERROR("Only new keys can be saved to disk\n"); 183ccbf890eSJuan Castillo exit(1); 184ccbf890eSJuan Castillo } 185ccbf890eSJuan Castillo 186dfc90e26SJuan Castillo /* Check that all required options have been specified in the 187dfc90e26SJuan Castillo * command line */ 188dfc90e26SJuan Castillo for (i = 0; i < num_certs; i++) { 189dfc90e26SJuan Castillo cert = &certs[i]; 190dfc90e26SJuan Castillo if (cert->fn == NULL) { 191dfc90e26SJuan Castillo /* Certificate not requested. Skip to the next one */ 192dfc90e26SJuan Castillo continue; 193dfc90e26SJuan Castillo } 194dfc90e26SJuan Castillo 195dfc90e26SJuan Castillo /* Check that all parameters required to create this certificate 196dfc90e26SJuan Castillo * have been specified in the command line */ 197dfc90e26SJuan Castillo for (j = 0; j < cert->num_ext; j++) { 198dfc90e26SJuan Castillo ext = &extensions[cert->ext[j]]; 199dfc90e26SJuan Castillo switch (ext->type) { 20096103d5aSJuan Castillo case EXT_TYPE_NVCOUNTER: 20196103d5aSJuan Castillo /* Counter value must be specified */ 20296103d5aSJuan Castillo if ((!ext->optional) && (ext->arg == NULL)) { 20396103d5aSJuan Castillo ERROR("Value for '%s' not specified\n", 20496103d5aSJuan Castillo ext->ln); 20596103d5aSJuan Castillo exit(1); 20696103d5aSJuan Castillo } 20796103d5aSJuan Castillo break; 208dfc90e26SJuan Castillo case EXT_TYPE_PKEY: 209dfc90e26SJuan Castillo /* Key filename must be specified */ 21096103d5aSJuan Castillo key = &keys[ext->attr.key]; 211dfc90e26SJuan Castillo if (!new_keys && key->fn == NULL) { 212dfc90e26SJuan Castillo ERROR("Key '%s' required by '%s' not " 213dfc90e26SJuan Castillo "specified\n", key->desc, 214dfc90e26SJuan Castillo cert->cn); 2156f971622SJuan Castillo exit(1); 2166f971622SJuan Castillo } 217dfc90e26SJuan Castillo break; 218dfc90e26SJuan Castillo case EXT_TYPE_HASH: 219cebe1f23SYatharth Kochar /* 220cebe1f23SYatharth Kochar * Binary image must be specified 221cebe1f23SYatharth Kochar * unless it is explicitly made optional. 222cebe1f23SYatharth Kochar */ 22396103d5aSJuan Castillo if ((!ext->optional) && (ext->arg == NULL)) { 224dfc90e26SJuan Castillo ERROR("Image for '%s' not specified\n", 225dfc90e26SJuan Castillo ext->ln); 2266f971622SJuan Castillo exit(1); 2276f971622SJuan Castillo } 228dfc90e26SJuan Castillo break; 229dfc90e26SJuan Castillo default: 23096103d5aSJuan Castillo ERROR("Unknown extension type '%d' in '%s'\n", 23196103d5aSJuan Castillo ext->type, ext->ln); 2326f971622SJuan Castillo exit(1); 233dfc90e26SJuan Castillo break; 2346f971622SJuan Castillo } 2356f971622SJuan Castillo } 2366f971622SJuan Castillo } 2376f971622SJuan Castillo } 2386f971622SJuan Castillo 239159807e2SJuan Castillo /* Common command line options */ 240159807e2SJuan Castillo static const cmd_opt_t common_cmd_opt[] = { 241159807e2SJuan Castillo { 242159807e2SJuan Castillo { "help", no_argument, NULL, 'h' }, 243159807e2SJuan Castillo "Print this message and exit" 244159807e2SJuan Castillo }, 245159807e2SJuan Castillo { 246159807e2SJuan Castillo { "key-alg", required_argument, NULL, 'a' }, 247a8eb286aSSoby Mathew "Key algorithm: 'rsa' (default) - RSAPSS scheme as per \ 248a8eb286aSSoby Mathew PKCS#1 v2.1, 'rsa_1_5' - RSA PKCS#1 v1.5, 'ecdsa'" 249159807e2SJuan Castillo }, 250159807e2SJuan Castillo { 251*2972247cSQixiang Xu { "hash-alg", required_argument, NULL, 's' }, 252*2972247cSQixiang Xu "Hash algorithm : 'sha256' (default), 'sha384', 'sha512'" 253*2972247cSQixiang Xu }, 254*2972247cSQixiang Xu { 255159807e2SJuan Castillo { "save-keys", no_argument, NULL, 'k' }, 256159807e2SJuan Castillo "Save key pairs into files. Filenames must be provided" 257159807e2SJuan Castillo }, 258159807e2SJuan Castillo { 259159807e2SJuan Castillo { "new-keys", no_argument, NULL, 'n' }, 260159807e2SJuan Castillo "Generate new key pairs if no key files are provided" 261159807e2SJuan Castillo }, 262159807e2SJuan Castillo { 263159807e2SJuan Castillo { "print-cert", no_argument, NULL, 'p' }, 264159807e2SJuan Castillo "Print the certificates in the standard output" 265159807e2SJuan Castillo } 266159807e2SJuan Castillo }; 267159807e2SJuan Castillo 2686f971622SJuan Castillo int main(int argc, char *argv[]) 2696f971622SJuan Castillo { 270c893c733SMasahiro Yamada STACK_OF(X509_EXTENSION) * sk; 271742c4e14SMichalis Pappas X509_EXTENSION *cert_ext = NULL; 272c893c733SMasahiro Yamada ext_t *ext; 273c893c733SMasahiro Yamada key_t *key; 274c893c733SMasahiro Yamada cert_t *cert; 275c893c733SMasahiro Yamada FILE *file; 27696103d5aSJuan Castillo int i, j, ext_nid, nvctr; 2776f971622SJuan Castillo int c, opt_idx = 0; 278ad2c1a9aSJuan Castillo const struct option *cmd_opt; 279ad2c1a9aSJuan Castillo const char *cur_opt; 280ccbf890eSJuan Castillo unsigned int err_code; 281*2972247cSQixiang Xu unsigned char md[SHA512_DIGEST_LENGTH]; 282*2972247cSQixiang Xu unsigned int md_len; 283c3da66b1SJuan Castillo const EVP_MD *md_info; 2846f971622SJuan Castillo 2856f971622SJuan Castillo NOTICE("CoT Generation Tool: %s\n", build_msg); 2866f971622SJuan Castillo NOTICE("Target platform: %s\n", platform_msg); 2876f971622SJuan Castillo 288ccbf890eSJuan Castillo /* Set default options */ 289ccbf890eSJuan Castillo key_alg = KEY_ALG_RSA; 290*2972247cSQixiang Xu hash_alg = HASH_ALG_SHA256; 291ccbf890eSJuan Castillo 292ad2c1a9aSJuan Castillo /* Add common command line options */ 293159807e2SJuan Castillo for (i = 0; i < NUM_ELEM(common_cmd_opt); i++) { 294159807e2SJuan Castillo cmd_opt_add(&common_cmd_opt[i]); 295159807e2SJuan Castillo } 296ad2c1a9aSJuan Castillo 297ad2c1a9aSJuan Castillo /* Initialize the certificates */ 298ad2c1a9aSJuan Castillo if (cert_init() != 0) { 299ad2c1a9aSJuan Castillo ERROR("Cannot initialize certificates\n"); 300ad2c1a9aSJuan Castillo exit(1); 301ad2c1a9aSJuan Castillo } 302ad2c1a9aSJuan Castillo 303ad2c1a9aSJuan Castillo /* Initialize the keys */ 304ad2c1a9aSJuan Castillo if (key_init() != 0) { 305ad2c1a9aSJuan Castillo ERROR("Cannot initialize keys\n"); 306ad2c1a9aSJuan Castillo exit(1); 307ad2c1a9aSJuan Castillo } 308ad2c1a9aSJuan Castillo 309ad2c1a9aSJuan Castillo /* Initialize the new types and register OIDs for the extensions */ 310ad2c1a9aSJuan Castillo if (ext_init() != 0) { 311ad2c1a9aSJuan Castillo ERROR("Cannot initialize TBB extensions\n"); 312ad2c1a9aSJuan Castillo exit(1); 313ad2c1a9aSJuan Castillo } 314ad2c1a9aSJuan Castillo 315ad2c1a9aSJuan Castillo /* Get the command line options populated during the initialization */ 316ad2c1a9aSJuan Castillo cmd_opt = cmd_opt_get_array(); 317ad2c1a9aSJuan Castillo 3186f971622SJuan Castillo while (1) { 3196f971622SJuan Castillo /* getopt_long stores the option index here. */ 320*2972247cSQixiang Xu c = getopt_long(argc, argv, "a:hknps:", cmd_opt, &opt_idx); 3216f971622SJuan Castillo 3226f971622SJuan Castillo /* Detect the end of the options. */ 3236f971622SJuan Castillo if (c == -1) { 3246f971622SJuan Castillo break; 3256f971622SJuan Castillo } 3266f971622SJuan Castillo 3276f971622SJuan Castillo switch (c) { 328ccbf890eSJuan Castillo case 'a': 329ccbf890eSJuan Castillo key_alg = get_key_alg(optarg); 330ccbf890eSJuan Castillo if (key_alg < 0) { 331ccbf890eSJuan Castillo ERROR("Invalid key algorithm '%s'\n", optarg); 332ccbf890eSJuan Castillo exit(1); 333ccbf890eSJuan Castillo } 334ccbf890eSJuan Castillo break; 3356f971622SJuan Castillo case 'h': 336ad2c1a9aSJuan Castillo print_help(argv[0], cmd_opt); 3376f971622SJuan Castillo break; 3386f971622SJuan Castillo case 'k': 3396f971622SJuan Castillo save_keys = 1; 3406f971622SJuan Castillo break; 3416f971622SJuan Castillo case 'n': 3426f971622SJuan Castillo new_keys = 1; 3436f971622SJuan Castillo break; 3446f971622SJuan Castillo case 'p': 3456f971622SJuan Castillo print_cert = 1; 3466f971622SJuan Castillo break; 347*2972247cSQixiang Xu case 's': 348*2972247cSQixiang Xu hash_alg = get_hash_alg(optarg); 349*2972247cSQixiang Xu if (hash_alg < 0) { 350*2972247cSQixiang Xu ERROR("Invalid hash algorithm '%s'\n", optarg); 351*2972247cSQixiang Xu exit(1); 352*2972247cSQixiang Xu } 353*2972247cSQixiang Xu break; 354ad2c1a9aSJuan Castillo case CMD_OPT_EXT: 355ad2c1a9aSJuan Castillo cur_opt = cmd_opt_get_name(opt_idx); 356ad2c1a9aSJuan Castillo ext = ext_get_by_opt(cur_opt); 35796103d5aSJuan Castillo ext->arg = strdup(optarg); 3586f971622SJuan Castillo break; 359ad2c1a9aSJuan Castillo case CMD_OPT_KEY: 360ad2c1a9aSJuan Castillo cur_opt = cmd_opt_get_name(opt_idx); 361ad2c1a9aSJuan Castillo key = key_get_by_opt(cur_opt); 362ad2c1a9aSJuan Castillo key->fn = strdup(optarg); 3636f971622SJuan Castillo break; 364ad2c1a9aSJuan Castillo case CMD_OPT_CERT: 365ad2c1a9aSJuan Castillo cur_opt = cmd_opt_get_name(opt_idx); 366ad2c1a9aSJuan Castillo cert = cert_get_by_opt(cur_opt); 367ad2c1a9aSJuan Castillo cert->fn = strdup(optarg); 3686f971622SJuan Castillo break; 3696f971622SJuan Castillo case '?': 3706f971622SJuan Castillo default: 371159807e2SJuan Castillo print_help(argv[0], cmd_opt); 3726f971622SJuan Castillo exit(1); 3736f971622SJuan Castillo } 3746f971622SJuan Castillo } 3756f971622SJuan Castillo 3766f971622SJuan Castillo /* Check command line arguments */ 3776f971622SJuan Castillo check_cmd_params(); 3786f971622SJuan Castillo 379*2972247cSQixiang Xu /* Indicate SHA as image hash algorithm in the certificate 380c3da66b1SJuan Castillo * extension */ 381*2972247cSQixiang Xu if (hash_alg == HASH_ALG_SHA384) { 382*2972247cSQixiang Xu md_info = EVP_sha384(); 383*2972247cSQixiang Xu md_len = SHA384_DIGEST_LENGTH; 384*2972247cSQixiang Xu } else if (hash_alg == HASH_ALG_SHA512) { 385*2972247cSQixiang Xu md_info = EVP_sha512(); 386*2972247cSQixiang Xu md_len = SHA512_DIGEST_LENGTH; 387*2972247cSQixiang Xu } else { 388c3da66b1SJuan Castillo md_info = EVP_sha256(); 389*2972247cSQixiang Xu md_len = SHA256_DIGEST_LENGTH; 390*2972247cSQixiang Xu } 391c3da66b1SJuan Castillo 3926f971622SJuan Castillo /* Load private keys from files (or generate new ones) */ 39355e291a4SJuan Castillo for (i = 0 ; i < num_keys ; i++) { 394762f1ebeSMasahiro Yamada if (!key_new(&keys[i])) { 395762f1ebeSMasahiro Yamada ERROR("Failed to allocate key container\n"); 396762f1ebeSMasahiro Yamada exit(1); 397762f1ebeSMasahiro Yamada } 398762f1ebeSMasahiro Yamada 399ccbf890eSJuan Castillo /* First try to load the key from disk */ 400ccbf890eSJuan Castillo if (key_load(&keys[i], &err_code)) { 401ccbf890eSJuan Castillo /* Key loaded successfully */ 402ccbf890eSJuan Castillo continue; 403ccbf890eSJuan Castillo } 404ccbf890eSJuan Castillo 405ccbf890eSJuan Castillo /* Key not loaded. Check the error code */ 406762f1ebeSMasahiro Yamada if (err_code == KEY_ERR_LOAD) { 407ccbf890eSJuan Castillo /* File exists, but it does not contain a valid private 408ccbf890eSJuan Castillo * key. Abort. */ 409ccbf890eSJuan Castillo ERROR("Error loading '%s'\n", keys[i].fn); 4106f971622SJuan Castillo exit(1); 4116f971622SJuan Castillo } 412ccbf890eSJuan Castillo 413ccbf890eSJuan Castillo /* File does not exist, could not be opened or no filename was 414ccbf890eSJuan Castillo * given */ 415ccbf890eSJuan Castillo if (new_keys) { 416ccbf890eSJuan Castillo /* Try to create a new key */ 417ccbf890eSJuan Castillo NOTICE("Creating new key for '%s'\n", keys[i].desc); 418ccbf890eSJuan Castillo if (!key_create(&keys[i], key_alg)) { 419ccbf890eSJuan Castillo ERROR("Error creating key '%s'\n", keys[i].desc); 420ccbf890eSJuan Castillo exit(1); 4216f971622SJuan Castillo } 4226f971622SJuan Castillo } else { 423ccbf890eSJuan Castillo if (err_code == KEY_ERR_OPEN) { 424ccbf890eSJuan Castillo ERROR("Error opening '%s'\n", keys[i].fn); 425ccbf890eSJuan Castillo } else { 426ccbf890eSJuan Castillo ERROR("Key '%s' not specified\n", keys[i].desc); 4276f971622SJuan Castillo } 428ccbf890eSJuan Castillo exit(1); 4296f971622SJuan Castillo } 4306f971622SJuan Castillo } 4316f971622SJuan Castillo 43255e291a4SJuan Castillo /* Create the certificates */ 43355e291a4SJuan Castillo for (i = 0 ; i < num_certs ; i++) { 43455e291a4SJuan Castillo 43555e291a4SJuan Castillo cert = &certs[i]; 43655e291a4SJuan Castillo 43755e291a4SJuan Castillo /* Create a new stack of extensions. This stack will be used 43855e291a4SJuan Castillo * to create the certificate */ 4396f971622SJuan Castillo CHECK_NULL(sk, sk_X509_EXTENSION_new_null()); 4406f971622SJuan Castillo 44155e291a4SJuan Castillo for (j = 0 ; j < cert->num_ext ; j++) { 4426f971622SJuan Castillo 44355e291a4SJuan Castillo ext = &extensions[cert->ext[j]]; 44455e291a4SJuan Castillo 44555e291a4SJuan Castillo /* Get OpenSSL internal ID for this extension */ 44655e291a4SJuan Castillo CHECK_OID(ext_nid, ext->oid); 44755e291a4SJuan Castillo 44855e291a4SJuan Castillo /* 44955e291a4SJuan Castillo * Three types of extensions are currently supported: 45055e291a4SJuan Castillo * - EXT_TYPE_NVCOUNTER 45155e291a4SJuan Castillo * - EXT_TYPE_HASH 45255e291a4SJuan Castillo * - EXT_TYPE_PKEY 45355e291a4SJuan Castillo */ 45455e291a4SJuan Castillo switch (ext->type) { 45555e291a4SJuan Castillo case EXT_TYPE_NVCOUNTER: 456f16db56aSYatharth Kochar if (ext->arg) { 45796103d5aSJuan Castillo nvctr = atoi(ext->arg); 45855e291a4SJuan Castillo CHECK_NULL(cert_ext, ext_new_nvcounter(ext_nid, 45996103d5aSJuan Castillo EXT_CRIT, nvctr)); 460f16db56aSYatharth Kochar } 46155e291a4SJuan Castillo break; 46255e291a4SJuan Castillo case EXT_TYPE_HASH: 46396103d5aSJuan Castillo if (ext->arg == NULL) { 464cebe1f23SYatharth Kochar if (ext->optional) { 465cebe1f23SYatharth Kochar /* Include a hash filled with zeros */ 466*2972247cSQixiang Xu memset(md, 0x0, SHA512_DIGEST_LENGTH); 467cebe1f23SYatharth Kochar } else { 468cebe1f23SYatharth Kochar /* Do not include this hash in the certificate */ 46955e291a4SJuan Castillo break; 47055e291a4SJuan Castillo } 471cebe1f23SYatharth Kochar } else { 472cebe1f23SYatharth Kochar /* Calculate the hash of the file */ 473*2972247cSQixiang Xu if (!sha_file(hash_alg, ext->arg, md)) { 47455e291a4SJuan Castillo ERROR("Cannot calculate hash of %s\n", 47596103d5aSJuan Castillo ext->arg); 4766f971622SJuan Castillo exit(1); 4776f971622SJuan Castillo } 478cebe1f23SYatharth Kochar } 47955e291a4SJuan Castillo CHECK_NULL(cert_ext, ext_new_hash(ext_nid, 48055e291a4SJuan Castillo EXT_CRIT, md_info, md, 481*2972247cSQixiang Xu md_len)); 48255e291a4SJuan Castillo break; 48355e291a4SJuan Castillo case EXT_TYPE_PKEY: 48455e291a4SJuan Castillo CHECK_NULL(cert_ext, ext_new_key(ext_nid, 48596103d5aSJuan Castillo EXT_CRIT, keys[ext->attr.key].key)); 48655e291a4SJuan Castillo break; 48755e291a4SJuan Castillo default: 48896103d5aSJuan Castillo ERROR("Unknown extension type '%d' in %s\n", 48996103d5aSJuan Castillo ext->type, cert->cn); 49055e291a4SJuan Castillo exit(1); 49155e291a4SJuan Castillo } 49255e291a4SJuan Castillo 49355e291a4SJuan Castillo /* Push the extension into the stack */ 49455e291a4SJuan Castillo sk_X509_EXTENSION_push(sk, cert_ext); 49555e291a4SJuan Castillo } 4966f971622SJuan Castillo 497a8eb286aSSoby Mathew /* Create certificate. Signed with corresponding key */ 498*2972247cSQixiang Xu if (cert->fn && !cert_new(key_alg, hash_alg, cert, VAL_DAYS, 0, sk)) { 49955e291a4SJuan Castillo ERROR("Cannot create %s\n", cert->cn); 5006f971622SJuan Castillo exit(1); 5016f971622SJuan Castillo } 5026f971622SJuan Castillo 5036f971622SJuan Castillo sk_X509_EXTENSION_free(sk); 5046f971622SJuan Castillo } 5056f971622SJuan Castillo 5066f971622SJuan Castillo 5076f971622SJuan Castillo /* Print the certificates */ 5086f971622SJuan Castillo if (print_cert) { 50955e291a4SJuan Castillo for (i = 0 ; i < num_certs ; i++) { 5106f971622SJuan Castillo if (!certs[i].x) { 5116f971622SJuan Castillo continue; 5126f971622SJuan Castillo } 5136f971622SJuan Castillo printf("\n\n=====================================\n\n"); 5146f971622SJuan Castillo X509_print_fp(stdout, certs[i].x); 5156f971622SJuan Castillo } 5166f971622SJuan Castillo } 5176f971622SJuan Castillo 5186f971622SJuan Castillo /* Save created certificates to files */ 51955e291a4SJuan Castillo for (i = 0 ; i < num_certs ; i++) { 5206f971622SJuan Castillo if (certs[i].x && certs[i].fn) { 5216f971622SJuan Castillo file = fopen(certs[i].fn, "w"); 5226f971622SJuan Castillo if (file != NULL) { 5236f971622SJuan Castillo i2d_X509_fp(file, certs[i].x); 5246f971622SJuan Castillo fclose(file); 5256f971622SJuan Castillo } else { 5266f971622SJuan Castillo ERROR("Cannot create file %s\n", certs[i].fn); 5276f971622SJuan Castillo } 5286f971622SJuan Castillo } 5296f971622SJuan Castillo } 5306f971622SJuan Castillo 5316f971622SJuan Castillo /* Save keys */ 5326f971622SJuan Castillo if (save_keys) { 53355e291a4SJuan Castillo for (i = 0 ; i < num_keys ; i++) { 5346f971622SJuan Castillo if (!key_store(&keys[i])) { 5356f971622SJuan Castillo ERROR("Cannot save %s\n", keys[i].desc); 5366f971622SJuan Castillo } 5376f971622SJuan Castillo } 5386f971622SJuan Castillo } 5396f971622SJuan Castillo 5406f971622SJuan Castillo #ifndef OPENSSL_NO_ENGINE 5416f971622SJuan Castillo ENGINE_cleanup(); 5426f971622SJuan Castillo #endif 5436f971622SJuan Castillo CRYPTO_cleanup_all_ex_data(); 5446f971622SJuan Castillo 5456f971622SJuan Castillo return 0; 5466f971622SJuan Castillo } 547