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; 712972247cSQixiang 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 992972247cSQixiang Xu static const char *hash_algs_str[] = { 1002972247cSQixiang Xu [HASH_ALG_SHA256] = "sha256", 1012972247cSQixiang Xu [HASH_ALG_SHA384] = "sha384", 1022972247cSQixiang Xu [HASH_ALG_SHA512] = "sha512", 1032972247cSQixiang Xu }; 1042972247cSQixiang 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 145ccbf890eSJuan Castillo static int get_key_alg(const char *key_alg_str) 146ccbf890eSJuan Castillo { 147ccbf890eSJuan Castillo int i; 148ccbf890eSJuan Castillo 149ccbf890eSJuan Castillo for (i = 0 ; i < NUM_ELEM(key_algs_str) ; i++) { 150ccbf890eSJuan Castillo if (0 == strcmp(key_alg_str, key_algs_str[i])) { 151ccbf890eSJuan Castillo return i; 152ccbf890eSJuan Castillo } 153ccbf890eSJuan Castillo } 154ccbf890eSJuan Castillo 155ccbf890eSJuan Castillo return -1; 156ccbf890eSJuan Castillo } 157ccbf890eSJuan Castillo 1582972247cSQixiang Xu static int get_hash_alg(const char *hash_alg_str) 1592972247cSQixiang Xu { 1602972247cSQixiang Xu int i; 1612972247cSQixiang Xu 1622972247cSQixiang Xu for (i = 0 ; i < NUM_ELEM(hash_algs_str) ; i++) { 1632972247cSQixiang Xu if (0 == strcmp(hash_alg_str, hash_algs_str[i])) { 1642972247cSQixiang Xu return i; 1652972247cSQixiang Xu } 1662972247cSQixiang Xu } 1672972247cSQixiang Xu 1682972247cSQixiang Xu return -1; 1692972247cSQixiang Xu } 1702972247cSQixiang Xu 1716f971622SJuan Castillo static void check_cmd_params(void) 1726f971622SJuan Castillo { 173dfc90e26SJuan Castillo cert_t *cert; 174dfc90e26SJuan Castillo ext_t *ext; 175dfc90e26SJuan Castillo key_t *key; 176dfc90e26SJuan Castillo int i, j; 177dfc90e26SJuan Castillo 178ccbf890eSJuan Castillo /* Only save new keys */ 179ccbf890eSJuan Castillo if (save_keys && !new_keys) { 180ccbf890eSJuan Castillo ERROR("Only new keys can be saved to disk\n"); 181ccbf890eSJuan Castillo exit(1); 182ccbf890eSJuan Castillo } 183ccbf890eSJuan Castillo 184dfc90e26SJuan Castillo /* Check that all required options have been specified in the 185dfc90e26SJuan Castillo * command line */ 186dfc90e26SJuan Castillo for (i = 0; i < num_certs; i++) { 187dfc90e26SJuan Castillo cert = &certs[i]; 188dfc90e26SJuan Castillo if (cert->fn == NULL) { 189dfc90e26SJuan Castillo /* Certificate not requested. Skip to the next one */ 190dfc90e26SJuan Castillo continue; 191dfc90e26SJuan Castillo } 192dfc90e26SJuan Castillo 193dfc90e26SJuan Castillo /* Check that all parameters required to create this certificate 194dfc90e26SJuan Castillo * have been specified in the command line */ 195dfc90e26SJuan Castillo for (j = 0; j < cert->num_ext; j++) { 196dfc90e26SJuan Castillo ext = &extensions[cert->ext[j]]; 197dfc90e26SJuan Castillo switch (ext->type) { 19896103d5aSJuan Castillo case EXT_TYPE_NVCOUNTER: 19996103d5aSJuan Castillo /* Counter value must be specified */ 20096103d5aSJuan Castillo if ((!ext->optional) && (ext->arg == NULL)) { 20196103d5aSJuan Castillo ERROR("Value for '%s' not specified\n", 20296103d5aSJuan Castillo ext->ln); 20396103d5aSJuan Castillo exit(1); 20496103d5aSJuan Castillo } 20596103d5aSJuan Castillo break; 206dfc90e26SJuan Castillo case EXT_TYPE_PKEY: 207dfc90e26SJuan Castillo /* Key filename must be specified */ 20896103d5aSJuan Castillo key = &keys[ext->attr.key]; 209dfc90e26SJuan Castillo if (!new_keys && key->fn == NULL) { 210dfc90e26SJuan Castillo ERROR("Key '%s' required by '%s' not " 211dfc90e26SJuan Castillo "specified\n", key->desc, 212dfc90e26SJuan Castillo cert->cn); 2136f971622SJuan Castillo exit(1); 2146f971622SJuan Castillo } 215dfc90e26SJuan Castillo break; 216dfc90e26SJuan Castillo case EXT_TYPE_HASH: 217cebe1f23SYatharth Kochar /* 218cebe1f23SYatharth Kochar * Binary image must be specified 219cebe1f23SYatharth Kochar * unless it is explicitly made optional. 220cebe1f23SYatharth Kochar */ 22196103d5aSJuan Castillo if ((!ext->optional) && (ext->arg == NULL)) { 222dfc90e26SJuan Castillo ERROR("Image for '%s' not specified\n", 223dfc90e26SJuan Castillo ext->ln); 2246f971622SJuan Castillo exit(1); 2256f971622SJuan Castillo } 226dfc90e26SJuan Castillo break; 227dfc90e26SJuan Castillo default: 22896103d5aSJuan Castillo ERROR("Unknown extension type '%d' in '%s'\n", 22996103d5aSJuan Castillo ext->type, ext->ln); 2306f971622SJuan Castillo exit(1); 231dfc90e26SJuan Castillo break; 2326f971622SJuan Castillo } 2336f971622SJuan Castillo } 2346f971622SJuan Castillo } 2356f971622SJuan Castillo } 2366f971622SJuan Castillo 237159807e2SJuan Castillo /* Common command line options */ 238159807e2SJuan Castillo static const cmd_opt_t common_cmd_opt[] = { 239159807e2SJuan Castillo { 240159807e2SJuan Castillo { "help", no_argument, NULL, 'h' }, 241159807e2SJuan Castillo "Print this message and exit" 242159807e2SJuan Castillo }, 243159807e2SJuan Castillo { 244159807e2SJuan Castillo { "key-alg", required_argument, NULL, 'a' }, 245a8eb286aSSoby Mathew "Key algorithm: 'rsa' (default) - RSAPSS scheme as per \ 246a8eb286aSSoby Mathew PKCS#1 v2.1, 'rsa_1_5' - RSA PKCS#1 v1.5, 'ecdsa'" 247159807e2SJuan Castillo }, 248159807e2SJuan Castillo { 2492972247cSQixiang Xu { "hash-alg", required_argument, NULL, 's' }, 2502972247cSQixiang Xu "Hash algorithm : 'sha256' (default), 'sha384', 'sha512'" 2512972247cSQixiang Xu }, 2522972247cSQixiang Xu { 253159807e2SJuan Castillo { "save-keys", no_argument, NULL, 'k' }, 254159807e2SJuan Castillo "Save key pairs into files. Filenames must be provided" 255159807e2SJuan Castillo }, 256159807e2SJuan Castillo { 257159807e2SJuan Castillo { "new-keys", no_argument, NULL, 'n' }, 258159807e2SJuan Castillo "Generate new key pairs if no key files are provided" 259159807e2SJuan Castillo }, 260159807e2SJuan Castillo { 261159807e2SJuan Castillo { "print-cert", no_argument, NULL, 'p' }, 262159807e2SJuan Castillo "Print the certificates in the standard output" 263159807e2SJuan Castillo } 264159807e2SJuan Castillo }; 265159807e2SJuan Castillo 2666f971622SJuan Castillo int main(int argc, char *argv[]) 2676f971622SJuan Castillo { 268c893c733SMasahiro Yamada STACK_OF(X509_EXTENSION) * sk; 269742c4e14SMichalis Pappas X509_EXTENSION *cert_ext = NULL; 270c893c733SMasahiro Yamada ext_t *ext; 271c893c733SMasahiro Yamada key_t *key; 272c893c733SMasahiro Yamada cert_t *cert; 273c893c733SMasahiro Yamada FILE *file; 27496103d5aSJuan Castillo int i, j, ext_nid, nvctr; 2756f971622SJuan Castillo int c, opt_idx = 0; 276ad2c1a9aSJuan Castillo const struct option *cmd_opt; 277ad2c1a9aSJuan Castillo const char *cur_opt; 278ccbf890eSJuan Castillo unsigned int err_code; 2792972247cSQixiang Xu unsigned char md[SHA512_DIGEST_LENGTH]; 2802972247cSQixiang Xu unsigned int md_len; 281c3da66b1SJuan Castillo const EVP_MD *md_info; 2826f971622SJuan Castillo 2836f971622SJuan Castillo NOTICE("CoT Generation Tool: %s\n", build_msg); 2846f971622SJuan Castillo NOTICE("Target platform: %s\n", platform_msg); 2856f971622SJuan Castillo 286ccbf890eSJuan Castillo /* Set default options */ 287ccbf890eSJuan Castillo key_alg = KEY_ALG_RSA; 2882972247cSQixiang Xu hash_alg = HASH_ALG_SHA256; 289ccbf890eSJuan Castillo 290ad2c1a9aSJuan Castillo /* Add common command line options */ 291159807e2SJuan Castillo for (i = 0; i < NUM_ELEM(common_cmd_opt); i++) { 292159807e2SJuan Castillo cmd_opt_add(&common_cmd_opt[i]); 293159807e2SJuan Castillo } 294ad2c1a9aSJuan Castillo 295ad2c1a9aSJuan Castillo /* Initialize the certificates */ 296ad2c1a9aSJuan Castillo if (cert_init() != 0) { 297ad2c1a9aSJuan Castillo ERROR("Cannot initialize certificates\n"); 298ad2c1a9aSJuan Castillo exit(1); 299ad2c1a9aSJuan Castillo } 300ad2c1a9aSJuan Castillo 301ad2c1a9aSJuan Castillo /* Initialize the keys */ 302ad2c1a9aSJuan Castillo if (key_init() != 0) { 303ad2c1a9aSJuan Castillo ERROR("Cannot initialize keys\n"); 304ad2c1a9aSJuan Castillo exit(1); 305ad2c1a9aSJuan Castillo } 306ad2c1a9aSJuan Castillo 307ad2c1a9aSJuan Castillo /* Initialize the new types and register OIDs for the extensions */ 308ad2c1a9aSJuan Castillo if (ext_init() != 0) { 309ad2c1a9aSJuan Castillo ERROR("Cannot initialize TBB extensions\n"); 310ad2c1a9aSJuan Castillo exit(1); 311ad2c1a9aSJuan Castillo } 312ad2c1a9aSJuan Castillo 313ad2c1a9aSJuan Castillo /* Get the command line options populated during the initialization */ 314ad2c1a9aSJuan Castillo cmd_opt = cmd_opt_get_array(); 315ad2c1a9aSJuan Castillo 3166f971622SJuan Castillo while (1) { 3176f971622SJuan Castillo /* getopt_long stores the option index here. */ 3182972247cSQixiang Xu c = getopt_long(argc, argv, "a:hknps:", cmd_opt, &opt_idx); 3196f971622SJuan Castillo 3206f971622SJuan Castillo /* Detect the end of the options. */ 3216f971622SJuan Castillo if (c == -1) { 3226f971622SJuan Castillo break; 3236f971622SJuan Castillo } 3246f971622SJuan Castillo 3256f971622SJuan Castillo switch (c) { 326ccbf890eSJuan Castillo case 'a': 327ccbf890eSJuan Castillo key_alg = get_key_alg(optarg); 328ccbf890eSJuan Castillo if (key_alg < 0) { 329ccbf890eSJuan Castillo ERROR("Invalid key algorithm '%s'\n", optarg); 330ccbf890eSJuan Castillo exit(1); 331ccbf890eSJuan Castillo } 332ccbf890eSJuan Castillo break; 3336f971622SJuan Castillo case 'h': 334ad2c1a9aSJuan Castillo print_help(argv[0], cmd_opt); 335*600835d0SRoberto Vargas exit(0); 3366f971622SJuan Castillo case 'k': 3376f971622SJuan Castillo save_keys = 1; 3386f971622SJuan Castillo break; 3396f971622SJuan Castillo case 'n': 3406f971622SJuan Castillo new_keys = 1; 3416f971622SJuan Castillo break; 3426f971622SJuan Castillo case 'p': 3436f971622SJuan Castillo print_cert = 1; 3446f971622SJuan Castillo break; 3452972247cSQixiang Xu case 's': 3462972247cSQixiang Xu hash_alg = get_hash_alg(optarg); 3472972247cSQixiang Xu if (hash_alg < 0) { 3482972247cSQixiang Xu ERROR("Invalid hash algorithm '%s'\n", optarg); 3492972247cSQixiang Xu exit(1); 3502972247cSQixiang Xu } 3512972247cSQixiang Xu break; 352ad2c1a9aSJuan Castillo case CMD_OPT_EXT: 353ad2c1a9aSJuan Castillo cur_opt = cmd_opt_get_name(opt_idx); 354ad2c1a9aSJuan Castillo ext = ext_get_by_opt(cur_opt); 35596103d5aSJuan Castillo ext->arg = strdup(optarg); 3566f971622SJuan Castillo break; 357ad2c1a9aSJuan Castillo case CMD_OPT_KEY: 358ad2c1a9aSJuan Castillo cur_opt = cmd_opt_get_name(opt_idx); 359ad2c1a9aSJuan Castillo key = key_get_by_opt(cur_opt); 360ad2c1a9aSJuan Castillo key->fn = strdup(optarg); 3616f971622SJuan Castillo break; 362ad2c1a9aSJuan Castillo case CMD_OPT_CERT: 363ad2c1a9aSJuan Castillo cur_opt = cmd_opt_get_name(opt_idx); 364ad2c1a9aSJuan Castillo cert = cert_get_by_opt(cur_opt); 365ad2c1a9aSJuan Castillo cert->fn = strdup(optarg); 3666f971622SJuan Castillo break; 3676f971622SJuan Castillo case '?': 3686f971622SJuan Castillo default: 369159807e2SJuan Castillo print_help(argv[0], cmd_opt); 3706f971622SJuan Castillo exit(1); 3716f971622SJuan Castillo } 3726f971622SJuan Castillo } 3736f971622SJuan Castillo 3746f971622SJuan Castillo /* Check command line arguments */ 3756f971622SJuan Castillo check_cmd_params(); 3766f971622SJuan Castillo 3772972247cSQixiang Xu /* Indicate SHA as image hash algorithm in the certificate 378c3da66b1SJuan Castillo * extension */ 3792972247cSQixiang Xu if (hash_alg == HASH_ALG_SHA384) { 3802972247cSQixiang Xu md_info = EVP_sha384(); 3812972247cSQixiang Xu md_len = SHA384_DIGEST_LENGTH; 3822972247cSQixiang Xu } else if (hash_alg == HASH_ALG_SHA512) { 3832972247cSQixiang Xu md_info = EVP_sha512(); 3842972247cSQixiang Xu md_len = SHA512_DIGEST_LENGTH; 3852972247cSQixiang Xu } else { 386c3da66b1SJuan Castillo md_info = EVP_sha256(); 3872972247cSQixiang Xu md_len = SHA256_DIGEST_LENGTH; 3882972247cSQixiang Xu } 389c3da66b1SJuan Castillo 3906f971622SJuan Castillo /* Load private keys from files (or generate new ones) */ 39155e291a4SJuan Castillo for (i = 0 ; i < num_keys ; i++) { 392762f1ebeSMasahiro Yamada if (!key_new(&keys[i])) { 393762f1ebeSMasahiro Yamada ERROR("Failed to allocate key container\n"); 394762f1ebeSMasahiro Yamada exit(1); 395762f1ebeSMasahiro Yamada } 396762f1ebeSMasahiro Yamada 397ccbf890eSJuan Castillo /* First try to load the key from disk */ 398ccbf890eSJuan Castillo if (key_load(&keys[i], &err_code)) { 399ccbf890eSJuan Castillo /* Key loaded successfully */ 400ccbf890eSJuan Castillo continue; 401ccbf890eSJuan Castillo } 402ccbf890eSJuan Castillo 403ccbf890eSJuan Castillo /* Key not loaded. Check the error code */ 404762f1ebeSMasahiro Yamada if (err_code == KEY_ERR_LOAD) { 405ccbf890eSJuan Castillo /* File exists, but it does not contain a valid private 406ccbf890eSJuan Castillo * key. Abort. */ 407ccbf890eSJuan Castillo ERROR("Error loading '%s'\n", keys[i].fn); 4086f971622SJuan Castillo exit(1); 4096f971622SJuan Castillo } 410ccbf890eSJuan Castillo 411ccbf890eSJuan Castillo /* File does not exist, could not be opened or no filename was 412ccbf890eSJuan Castillo * given */ 413ccbf890eSJuan Castillo if (new_keys) { 414ccbf890eSJuan Castillo /* Try to create a new key */ 415ccbf890eSJuan Castillo NOTICE("Creating new key for '%s'\n", keys[i].desc); 416ccbf890eSJuan Castillo if (!key_create(&keys[i], key_alg)) { 417ccbf890eSJuan Castillo ERROR("Error creating key '%s'\n", keys[i].desc); 418ccbf890eSJuan Castillo exit(1); 4196f971622SJuan Castillo } 4206f971622SJuan Castillo } else { 421ccbf890eSJuan Castillo if (err_code == KEY_ERR_OPEN) { 422ccbf890eSJuan Castillo ERROR("Error opening '%s'\n", keys[i].fn); 423ccbf890eSJuan Castillo } else { 424ccbf890eSJuan Castillo ERROR("Key '%s' not specified\n", keys[i].desc); 4256f971622SJuan Castillo } 426ccbf890eSJuan Castillo exit(1); 4276f971622SJuan Castillo } 4286f971622SJuan Castillo } 4296f971622SJuan Castillo 43055e291a4SJuan Castillo /* Create the certificates */ 43155e291a4SJuan Castillo for (i = 0 ; i < num_certs ; i++) { 43255e291a4SJuan Castillo 43355e291a4SJuan Castillo cert = &certs[i]; 43455e291a4SJuan Castillo 43555e291a4SJuan Castillo /* Create a new stack of extensions. This stack will be used 43655e291a4SJuan Castillo * to create the certificate */ 4376f971622SJuan Castillo CHECK_NULL(sk, sk_X509_EXTENSION_new_null()); 4386f971622SJuan Castillo 43955e291a4SJuan Castillo for (j = 0 ; j < cert->num_ext ; j++) { 4406f971622SJuan Castillo 44155e291a4SJuan Castillo ext = &extensions[cert->ext[j]]; 44255e291a4SJuan Castillo 44355e291a4SJuan Castillo /* Get OpenSSL internal ID for this extension */ 44455e291a4SJuan Castillo CHECK_OID(ext_nid, ext->oid); 44555e291a4SJuan Castillo 44655e291a4SJuan Castillo /* 44755e291a4SJuan Castillo * Three types of extensions are currently supported: 44855e291a4SJuan Castillo * - EXT_TYPE_NVCOUNTER 44955e291a4SJuan Castillo * - EXT_TYPE_HASH 45055e291a4SJuan Castillo * - EXT_TYPE_PKEY 45155e291a4SJuan Castillo */ 45255e291a4SJuan Castillo switch (ext->type) { 45355e291a4SJuan Castillo case EXT_TYPE_NVCOUNTER: 454f16db56aSYatharth Kochar if (ext->arg) { 45596103d5aSJuan Castillo nvctr = atoi(ext->arg); 45655e291a4SJuan Castillo CHECK_NULL(cert_ext, ext_new_nvcounter(ext_nid, 45796103d5aSJuan Castillo EXT_CRIT, nvctr)); 458f16db56aSYatharth Kochar } 45955e291a4SJuan Castillo break; 46055e291a4SJuan Castillo case EXT_TYPE_HASH: 46196103d5aSJuan Castillo if (ext->arg == NULL) { 462cebe1f23SYatharth Kochar if (ext->optional) { 463cebe1f23SYatharth Kochar /* Include a hash filled with zeros */ 4642972247cSQixiang Xu memset(md, 0x0, SHA512_DIGEST_LENGTH); 465cebe1f23SYatharth Kochar } else { 466cebe1f23SYatharth Kochar /* Do not include this hash in the certificate */ 46755e291a4SJuan Castillo break; 46855e291a4SJuan Castillo } 469cebe1f23SYatharth Kochar } else { 470cebe1f23SYatharth Kochar /* Calculate the hash of the file */ 4712972247cSQixiang Xu if (!sha_file(hash_alg, ext->arg, md)) { 47255e291a4SJuan Castillo ERROR("Cannot calculate hash of %s\n", 47396103d5aSJuan Castillo ext->arg); 4746f971622SJuan Castillo exit(1); 4756f971622SJuan Castillo } 476cebe1f23SYatharth Kochar } 47755e291a4SJuan Castillo CHECK_NULL(cert_ext, ext_new_hash(ext_nid, 47855e291a4SJuan Castillo EXT_CRIT, md_info, md, 4792972247cSQixiang Xu md_len)); 48055e291a4SJuan Castillo break; 48155e291a4SJuan Castillo case EXT_TYPE_PKEY: 48255e291a4SJuan Castillo CHECK_NULL(cert_ext, ext_new_key(ext_nid, 48396103d5aSJuan Castillo EXT_CRIT, keys[ext->attr.key].key)); 48455e291a4SJuan Castillo break; 48555e291a4SJuan Castillo default: 48696103d5aSJuan Castillo ERROR("Unknown extension type '%d' in %s\n", 48796103d5aSJuan Castillo ext->type, cert->cn); 48855e291a4SJuan Castillo exit(1); 48955e291a4SJuan Castillo } 49055e291a4SJuan Castillo 49155e291a4SJuan Castillo /* Push the extension into the stack */ 49255e291a4SJuan Castillo sk_X509_EXTENSION_push(sk, cert_ext); 49355e291a4SJuan Castillo } 4946f971622SJuan Castillo 495a8eb286aSSoby Mathew /* Create certificate. Signed with corresponding key */ 4962972247cSQixiang Xu if (cert->fn && !cert_new(key_alg, hash_alg, cert, VAL_DAYS, 0, sk)) { 49755e291a4SJuan Castillo ERROR("Cannot create %s\n", cert->cn); 4986f971622SJuan Castillo exit(1); 4996f971622SJuan Castillo } 5006f971622SJuan Castillo 5016f971622SJuan Castillo sk_X509_EXTENSION_free(sk); 5026f971622SJuan Castillo } 5036f971622SJuan Castillo 5046f971622SJuan Castillo 5056f971622SJuan Castillo /* Print the certificates */ 5066f971622SJuan Castillo if (print_cert) { 50755e291a4SJuan Castillo for (i = 0 ; i < num_certs ; i++) { 5086f971622SJuan Castillo if (!certs[i].x) { 5096f971622SJuan Castillo continue; 5106f971622SJuan Castillo } 5116f971622SJuan Castillo printf("\n\n=====================================\n\n"); 5126f971622SJuan Castillo X509_print_fp(stdout, certs[i].x); 5136f971622SJuan Castillo } 5146f971622SJuan Castillo } 5156f971622SJuan Castillo 5166f971622SJuan Castillo /* Save created certificates to files */ 51755e291a4SJuan Castillo for (i = 0 ; i < num_certs ; i++) { 5186f971622SJuan Castillo if (certs[i].x && certs[i].fn) { 5196f971622SJuan Castillo file = fopen(certs[i].fn, "w"); 5206f971622SJuan Castillo if (file != NULL) { 5216f971622SJuan Castillo i2d_X509_fp(file, certs[i].x); 5226f971622SJuan Castillo fclose(file); 5236f971622SJuan Castillo } else { 5246f971622SJuan Castillo ERROR("Cannot create file %s\n", certs[i].fn); 5256f971622SJuan Castillo } 5266f971622SJuan Castillo } 5276f971622SJuan Castillo } 5286f971622SJuan Castillo 5296f971622SJuan Castillo /* Save keys */ 5306f971622SJuan Castillo if (save_keys) { 53155e291a4SJuan Castillo for (i = 0 ; i < num_keys ; i++) { 5326f971622SJuan Castillo if (!key_store(&keys[i])) { 5336f971622SJuan Castillo ERROR("Cannot save %s\n", keys[i].desc); 5346f971622SJuan Castillo } 5356f971622SJuan Castillo } 5366f971622SJuan Castillo } 5376f971622SJuan Castillo 5386f971622SJuan Castillo #ifndef OPENSSL_NO_ENGINE 5396f971622SJuan Castillo ENGINE_cleanup(); 5406f971622SJuan Castillo #endif 5416f971622SJuan Castillo CRYPTO_cleanup_all_ex_data(); 5426f971622SJuan Castillo 5436f971622SJuan Castillo return 0; 5446f971622SJuan Castillo } 545