16f971622SJuan Castillo /* 26f971622SJuan Castillo * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. 36f971622SJuan Castillo * 4*82cb2c1aSdp-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 216f971622SJuan Castillo #include "cert.h" 22ad2c1a9aSJuan Castillo #include "cmd_opt.h" 236f971622SJuan Castillo #include "debug.h" 246f971622SJuan Castillo #include "ext.h" 256f971622SJuan Castillo #include "key.h" 266f971622SJuan Castillo #include "platform_oid.h" 276f971622SJuan Castillo #include "sha.h" 2855e291a4SJuan Castillo #include "tbbr/tbb_ext.h" 2955e291a4SJuan Castillo #include "tbbr/tbb_cert.h" 3055e291a4SJuan Castillo #include "tbbr/tbb_key.h" 316f971622SJuan Castillo 326f971622SJuan Castillo /* 336f971622SJuan Castillo * Helper macros to simplify the code. This macro assigns the return value of 346f971622SJuan Castillo * the 'fn' function to 'v' and exits if the value is NULL. 356f971622SJuan Castillo */ 366f971622SJuan Castillo #define CHECK_NULL(v, fn) \ 376f971622SJuan Castillo do { \ 386f971622SJuan Castillo v = fn; \ 396f971622SJuan Castillo if (v == NULL) { \ 406f971622SJuan Castillo ERROR("NULL object at %s:%d\n", __FILE__, __LINE__); \ 416f971622SJuan Castillo exit(1); \ 426f971622SJuan Castillo } \ 436f971622SJuan Castillo } while (0) 446f971622SJuan Castillo 456f971622SJuan Castillo /* 466f971622SJuan Castillo * This macro assigns the NID corresponding to 'oid' to 'v' and exits if the 476f971622SJuan Castillo * NID is undefined. 486f971622SJuan Castillo */ 496f971622SJuan Castillo #define CHECK_OID(v, oid) \ 506f971622SJuan Castillo do { \ 516f971622SJuan Castillo v = OBJ_txt2nid(oid); \ 526f971622SJuan Castillo if (v == NID_undef) { \ 536f971622SJuan Castillo ERROR("Cannot find TBB extension %s\n", oid); \ 546f971622SJuan Castillo exit(1); \ 556f971622SJuan Castillo } \ 566f971622SJuan Castillo } while (0) 576f971622SJuan Castillo 586f971622SJuan Castillo #define MAX_FILENAME_LEN 1024 596f971622SJuan Castillo #define VAL_DAYS 7300 606f971622SJuan Castillo #define ID_TO_BIT_MASK(id) (1 << id) 61ccbf890eSJuan Castillo #define NUM_ELEM(x) ((sizeof(x)) / (sizeof(x[0]))) 62159807e2SJuan Castillo #define HELP_OPT_MAX_LEN 128 636f971622SJuan Castillo 646f971622SJuan Castillo /* Global options */ 65ccbf890eSJuan Castillo static int key_alg; 666f971622SJuan Castillo static int new_keys; 676f971622SJuan Castillo static int save_keys; 686f971622SJuan Castillo static int print_cert; 696f971622SJuan Castillo 706f971622SJuan Castillo /* Info messages created in the Makefile */ 716f971622SJuan Castillo extern const char build_msg[]; 726f971622SJuan Castillo extern const char platform_msg[]; 736f971622SJuan Castillo 746f971622SJuan Castillo 756f971622SJuan Castillo static char *strdup(const char *str) 766f971622SJuan Castillo { 776f971622SJuan Castillo int n = strlen(str) + 1; 786f971622SJuan Castillo char *dup = malloc(n); 796f971622SJuan Castillo if (dup) { 806f971622SJuan Castillo strcpy(dup, str); 816f971622SJuan Castillo } 826f971622SJuan Castillo return dup; 836f971622SJuan Castillo } 846f971622SJuan Castillo 85ccbf890eSJuan Castillo static const char *key_algs_str[] = { 86ccbf890eSJuan Castillo [KEY_ALG_RSA] = "rsa", 87ed2a76eaSJuan Castillo #ifndef OPENSSL_NO_EC 88ccbf890eSJuan Castillo [KEY_ALG_ECDSA] = "ecdsa" 89ed2a76eaSJuan Castillo #endif /* OPENSSL_NO_EC */ 90ccbf890eSJuan Castillo }; 91ccbf890eSJuan Castillo 92ad2c1a9aSJuan Castillo static void print_help(const char *cmd, const struct option *long_opt) 936f971622SJuan Castillo { 94159807e2SJuan Castillo int rem, i = 0; 95159807e2SJuan Castillo const struct option *opt; 96159807e2SJuan Castillo char line[HELP_OPT_MAX_LEN]; 97159807e2SJuan Castillo char *p; 98159807e2SJuan Castillo 99159807e2SJuan Castillo assert(cmd != NULL); 100159807e2SJuan Castillo assert(long_opt != NULL); 101159807e2SJuan Castillo 1026f971622SJuan Castillo printf("\n\n"); 1036f971622SJuan Castillo printf("The certificate generation tool loads the binary images and\n" 1046f971622SJuan Castillo "optionally the RSA keys, and outputs the key and content\n" 1056f971622SJuan Castillo "certificates properly signed to implement the chain of trust.\n" 1066f971622SJuan Castillo "If keys are provided, they must be in PEM format.\n" 1076f971622SJuan Castillo "Certificates are generated in DER format.\n"); 1086f971622SJuan Castillo printf("\n"); 109159807e2SJuan Castillo printf("Usage:\n"); 110159807e2SJuan Castillo printf("\t%s [OPTIONS]\n\n", cmd); 111159807e2SJuan Castillo 112159807e2SJuan Castillo printf("Available options:\n"); 113159807e2SJuan Castillo opt = long_opt; 114159807e2SJuan Castillo while (opt->name) { 115159807e2SJuan Castillo p = line; 116159807e2SJuan Castillo rem = HELP_OPT_MAX_LEN; 117159807e2SJuan Castillo if (isalpha(opt->val)) { 118159807e2SJuan Castillo /* Short format */ 119159807e2SJuan Castillo sprintf(p, "-%c,", (char)opt->val); 120159807e2SJuan Castillo p += 3; 121159807e2SJuan Castillo rem -= 3; 1226f971622SJuan Castillo } 123159807e2SJuan Castillo snprintf(p, rem, "--%s %s", opt->name, 124159807e2SJuan Castillo (opt->has_arg == required_argument) ? "<arg>" : ""); 125159807e2SJuan Castillo printf("\t%-32s %s\n", line, cmd_opt_get_help_msg(i)); 126159807e2SJuan Castillo opt++; 127159807e2SJuan Castillo i++; 128159807e2SJuan Castillo } 1296f971622SJuan Castillo printf("\n"); 1306f971622SJuan Castillo 1316f971622SJuan Castillo exit(0); 1326f971622SJuan Castillo } 1336f971622SJuan Castillo 134ccbf890eSJuan Castillo static int get_key_alg(const char *key_alg_str) 135ccbf890eSJuan Castillo { 136ccbf890eSJuan Castillo int i; 137ccbf890eSJuan Castillo 138ccbf890eSJuan Castillo for (i = 0 ; i < NUM_ELEM(key_algs_str) ; i++) { 139ccbf890eSJuan Castillo if (0 == strcmp(key_alg_str, key_algs_str[i])) { 140ccbf890eSJuan Castillo return i; 141ccbf890eSJuan Castillo } 142ccbf890eSJuan Castillo } 143ccbf890eSJuan Castillo 144ccbf890eSJuan Castillo return -1; 145ccbf890eSJuan Castillo } 146ccbf890eSJuan Castillo 1476f971622SJuan Castillo static void check_cmd_params(void) 1486f971622SJuan Castillo { 149dfc90e26SJuan Castillo cert_t *cert; 150dfc90e26SJuan Castillo ext_t *ext; 151dfc90e26SJuan Castillo key_t *key; 152dfc90e26SJuan Castillo int i, j; 153dfc90e26SJuan Castillo 154ccbf890eSJuan Castillo /* Only save new keys */ 155ccbf890eSJuan Castillo if (save_keys && !new_keys) { 156ccbf890eSJuan Castillo ERROR("Only new keys can be saved to disk\n"); 157ccbf890eSJuan Castillo exit(1); 158ccbf890eSJuan Castillo } 159ccbf890eSJuan Castillo 160dfc90e26SJuan Castillo /* Check that all required options have been specified in the 161dfc90e26SJuan Castillo * command line */ 162dfc90e26SJuan Castillo for (i = 0; i < num_certs; i++) { 163dfc90e26SJuan Castillo cert = &certs[i]; 164dfc90e26SJuan Castillo if (cert->fn == NULL) { 165dfc90e26SJuan Castillo /* Certificate not requested. Skip to the next one */ 166dfc90e26SJuan Castillo continue; 167dfc90e26SJuan Castillo } 168dfc90e26SJuan Castillo 169dfc90e26SJuan Castillo /* Check that all parameters required to create this certificate 170dfc90e26SJuan Castillo * have been specified in the command line */ 171dfc90e26SJuan Castillo for (j = 0; j < cert->num_ext; j++) { 172dfc90e26SJuan Castillo ext = &extensions[cert->ext[j]]; 173dfc90e26SJuan Castillo switch (ext->type) { 17496103d5aSJuan Castillo case EXT_TYPE_NVCOUNTER: 17596103d5aSJuan Castillo /* Counter value must be specified */ 17696103d5aSJuan Castillo if ((!ext->optional) && (ext->arg == NULL)) { 17796103d5aSJuan Castillo ERROR("Value for '%s' not specified\n", 17896103d5aSJuan Castillo ext->ln); 17996103d5aSJuan Castillo exit(1); 18096103d5aSJuan Castillo } 18196103d5aSJuan Castillo break; 182dfc90e26SJuan Castillo case EXT_TYPE_PKEY: 183dfc90e26SJuan Castillo /* Key filename must be specified */ 18496103d5aSJuan Castillo key = &keys[ext->attr.key]; 185dfc90e26SJuan Castillo if (!new_keys && key->fn == NULL) { 186dfc90e26SJuan Castillo ERROR("Key '%s' required by '%s' not " 187dfc90e26SJuan Castillo "specified\n", key->desc, 188dfc90e26SJuan Castillo cert->cn); 1896f971622SJuan Castillo exit(1); 1906f971622SJuan Castillo } 191dfc90e26SJuan Castillo break; 192dfc90e26SJuan Castillo case EXT_TYPE_HASH: 193cebe1f23SYatharth Kochar /* 194cebe1f23SYatharth Kochar * Binary image must be specified 195cebe1f23SYatharth Kochar * unless it is explicitly made optional. 196cebe1f23SYatharth Kochar */ 19796103d5aSJuan Castillo if ((!ext->optional) && (ext->arg == NULL)) { 198dfc90e26SJuan Castillo ERROR("Image for '%s' not specified\n", 199dfc90e26SJuan Castillo ext->ln); 2006f971622SJuan Castillo exit(1); 2016f971622SJuan Castillo } 202dfc90e26SJuan Castillo break; 203dfc90e26SJuan Castillo default: 20496103d5aSJuan Castillo ERROR("Unknown extension type '%d' in '%s'\n", 20596103d5aSJuan Castillo ext->type, ext->ln); 2066f971622SJuan Castillo exit(1); 207dfc90e26SJuan Castillo break; 2086f971622SJuan Castillo } 2096f971622SJuan Castillo } 2106f971622SJuan Castillo } 2116f971622SJuan Castillo } 2126f971622SJuan Castillo 213159807e2SJuan Castillo /* Common command line options */ 214159807e2SJuan Castillo static const cmd_opt_t common_cmd_opt[] = { 215159807e2SJuan Castillo { 216159807e2SJuan Castillo { "help", no_argument, NULL, 'h' }, 217159807e2SJuan Castillo "Print this message and exit" 218159807e2SJuan Castillo }, 219159807e2SJuan Castillo { 220159807e2SJuan Castillo { "key-alg", required_argument, NULL, 'a' }, 221159807e2SJuan Castillo "Key algorithm: 'rsa' (default), 'ecdsa'" 222159807e2SJuan Castillo }, 223159807e2SJuan Castillo { 224159807e2SJuan Castillo { "save-keys", no_argument, NULL, 'k' }, 225159807e2SJuan Castillo "Save key pairs into files. Filenames must be provided" 226159807e2SJuan Castillo }, 227159807e2SJuan Castillo { 228159807e2SJuan Castillo { "new-keys", no_argument, NULL, 'n' }, 229159807e2SJuan Castillo "Generate new key pairs if no key files are provided" 230159807e2SJuan Castillo }, 231159807e2SJuan Castillo { 232159807e2SJuan Castillo { "print-cert", no_argument, NULL, 'p' }, 233159807e2SJuan Castillo "Print the certificates in the standard output" 234159807e2SJuan Castillo } 235159807e2SJuan Castillo }; 236159807e2SJuan Castillo 2376f971622SJuan Castillo int main(int argc, char *argv[]) 2386f971622SJuan Castillo { 239c893c733SMasahiro Yamada STACK_OF(X509_EXTENSION) * sk; 240c893c733SMasahiro Yamada X509_EXTENSION *cert_ext; 241c893c733SMasahiro Yamada ext_t *ext; 242c893c733SMasahiro Yamada key_t *key; 243c893c733SMasahiro Yamada cert_t *cert; 244c893c733SMasahiro Yamada FILE *file; 24596103d5aSJuan Castillo int i, j, ext_nid, nvctr; 2466f971622SJuan Castillo int c, opt_idx = 0; 247ad2c1a9aSJuan Castillo const struct option *cmd_opt; 248ad2c1a9aSJuan Castillo const char *cur_opt; 249ccbf890eSJuan Castillo unsigned int err_code; 2506f971622SJuan Castillo unsigned char md[SHA256_DIGEST_LENGTH]; 251c3da66b1SJuan Castillo const EVP_MD *md_info; 2526f971622SJuan Castillo 2536f971622SJuan Castillo NOTICE("CoT Generation Tool: %s\n", build_msg); 2546f971622SJuan Castillo NOTICE("Target platform: %s\n", platform_msg); 2556f971622SJuan Castillo 256ccbf890eSJuan Castillo /* Set default options */ 257ccbf890eSJuan Castillo key_alg = KEY_ALG_RSA; 258ccbf890eSJuan Castillo 259ad2c1a9aSJuan Castillo /* Add common command line options */ 260159807e2SJuan Castillo for (i = 0; i < NUM_ELEM(common_cmd_opt); i++) { 261159807e2SJuan Castillo cmd_opt_add(&common_cmd_opt[i]); 262159807e2SJuan Castillo } 263ad2c1a9aSJuan Castillo 264ad2c1a9aSJuan Castillo /* Initialize the certificates */ 265ad2c1a9aSJuan Castillo if (cert_init() != 0) { 266ad2c1a9aSJuan Castillo ERROR("Cannot initialize certificates\n"); 267ad2c1a9aSJuan Castillo exit(1); 268ad2c1a9aSJuan Castillo } 269ad2c1a9aSJuan Castillo 270ad2c1a9aSJuan Castillo /* Initialize the keys */ 271ad2c1a9aSJuan Castillo if (key_init() != 0) { 272ad2c1a9aSJuan Castillo ERROR("Cannot initialize keys\n"); 273ad2c1a9aSJuan Castillo exit(1); 274ad2c1a9aSJuan Castillo } 275ad2c1a9aSJuan Castillo 276ad2c1a9aSJuan Castillo /* Initialize the new types and register OIDs for the extensions */ 277ad2c1a9aSJuan Castillo if (ext_init() != 0) { 278ad2c1a9aSJuan Castillo ERROR("Cannot initialize TBB extensions\n"); 279ad2c1a9aSJuan Castillo exit(1); 280ad2c1a9aSJuan Castillo } 281ad2c1a9aSJuan Castillo 282ad2c1a9aSJuan Castillo /* Get the command line options populated during the initialization */ 283ad2c1a9aSJuan Castillo cmd_opt = cmd_opt_get_array(); 284ad2c1a9aSJuan Castillo 2856f971622SJuan Castillo while (1) { 2866f971622SJuan Castillo /* getopt_long stores the option index here. */ 287159807e2SJuan Castillo c = getopt_long(argc, argv, "a:hknp", cmd_opt, &opt_idx); 2886f971622SJuan Castillo 2896f971622SJuan Castillo /* Detect the end of the options. */ 2906f971622SJuan Castillo if (c == -1) { 2916f971622SJuan Castillo break; 2926f971622SJuan Castillo } 2936f971622SJuan Castillo 2946f971622SJuan Castillo switch (c) { 295ccbf890eSJuan Castillo case 'a': 296ccbf890eSJuan Castillo key_alg = get_key_alg(optarg); 297ccbf890eSJuan Castillo if (key_alg < 0) { 298ccbf890eSJuan Castillo ERROR("Invalid key algorithm '%s'\n", optarg); 299ccbf890eSJuan Castillo exit(1); 300ccbf890eSJuan Castillo } 301ccbf890eSJuan Castillo break; 3026f971622SJuan Castillo case 'h': 303ad2c1a9aSJuan Castillo print_help(argv[0], cmd_opt); 3046f971622SJuan Castillo break; 3056f971622SJuan Castillo case 'k': 3066f971622SJuan Castillo save_keys = 1; 3076f971622SJuan Castillo break; 3086f971622SJuan Castillo case 'n': 3096f971622SJuan Castillo new_keys = 1; 3106f971622SJuan Castillo break; 3116f971622SJuan Castillo case 'p': 3126f971622SJuan Castillo print_cert = 1; 3136f971622SJuan Castillo break; 314ad2c1a9aSJuan Castillo case CMD_OPT_EXT: 315ad2c1a9aSJuan Castillo cur_opt = cmd_opt_get_name(opt_idx); 316ad2c1a9aSJuan Castillo ext = ext_get_by_opt(cur_opt); 31796103d5aSJuan Castillo ext->arg = strdup(optarg); 3186f971622SJuan Castillo break; 319ad2c1a9aSJuan Castillo case CMD_OPT_KEY: 320ad2c1a9aSJuan Castillo cur_opt = cmd_opt_get_name(opt_idx); 321ad2c1a9aSJuan Castillo key = key_get_by_opt(cur_opt); 322ad2c1a9aSJuan Castillo key->fn = strdup(optarg); 3236f971622SJuan Castillo break; 324ad2c1a9aSJuan Castillo case CMD_OPT_CERT: 325ad2c1a9aSJuan Castillo cur_opt = cmd_opt_get_name(opt_idx); 326ad2c1a9aSJuan Castillo cert = cert_get_by_opt(cur_opt); 327ad2c1a9aSJuan Castillo cert->fn = strdup(optarg); 3286f971622SJuan Castillo break; 3296f971622SJuan Castillo case '?': 3306f971622SJuan Castillo default: 331159807e2SJuan Castillo print_help(argv[0], cmd_opt); 3326f971622SJuan Castillo exit(1); 3336f971622SJuan Castillo } 3346f971622SJuan Castillo } 3356f971622SJuan Castillo 3366f971622SJuan Castillo /* Check command line arguments */ 3376f971622SJuan Castillo check_cmd_params(); 3386f971622SJuan Castillo 339c3da66b1SJuan Castillo /* Indicate SHA256 as image hash algorithm in the certificate 340c3da66b1SJuan Castillo * extension */ 341c3da66b1SJuan Castillo md_info = EVP_sha256(); 342c3da66b1SJuan Castillo 3436f971622SJuan Castillo /* Load private keys from files (or generate new ones) */ 34455e291a4SJuan Castillo for (i = 0 ; i < num_keys ; i++) { 345762f1ebeSMasahiro Yamada if (!key_new(&keys[i])) { 346762f1ebeSMasahiro Yamada ERROR("Failed to allocate key container\n"); 347762f1ebeSMasahiro Yamada exit(1); 348762f1ebeSMasahiro Yamada } 349762f1ebeSMasahiro Yamada 350ccbf890eSJuan Castillo /* First try to load the key from disk */ 351ccbf890eSJuan Castillo if (key_load(&keys[i], &err_code)) { 352ccbf890eSJuan Castillo /* Key loaded successfully */ 353ccbf890eSJuan Castillo continue; 354ccbf890eSJuan Castillo } 355ccbf890eSJuan Castillo 356ccbf890eSJuan Castillo /* Key not loaded. Check the error code */ 357762f1ebeSMasahiro Yamada if (err_code == KEY_ERR_LOAD) { 358ccbf890eSJuan Castillo /* File exists, but it does not contain a valid private 359ccbf890eSJuan Castillo * key. Abort. */ 360ccbf890eSJuan Castillo ERROR("Error loading '%s'\n", keys[i].fn); 3616f971622SJuan Castillo exit(1); 3626f971622SJuan Castillo } 363ccbf890eSJuan Castillo 364ccbf890eSJuan Castillo /* File does not exist, could not be opened or no filename was 365ccbf890eSJuan Castillo * given */ 366ccbf890eSJuan Castillo if (new_keys) { 367ccbf890eSJuan Castillo /* Try to create a new key */ 368ccbf890eSJuan Castillo NOTICE("Creating new key for '%s'\n", keys[i].desc); 369ccbf890eSJuan Castillo if (!key_create(&keys[i], key_alg)) { 370ccbf890eSJuan Castillo ERROR("Error creating key '%s'\n", keys[i].desc); 371ccbf890eSJuan Castillo exit(1); 3726f971622SJuan Castillo } 3736f971622SJuan Castillo } else { 374ccbf890eSJuan Castillo if (err_code == KEY_ERR_OPEN) { 375ccbf890eSJuan Castillo ERROR("Error opening '%s'\n", keys[i].fn); 376ccbf890eSJuan Castillo } else { 377ccbf890eSJuan Castillo ERROR("Key '%s' not specified\n", keys[i].desc); 3786f971622SJuan Castillo } 379ccbf890eSJuan Castillo exit(1); 3806f971622SJuan Castillo } 3816f971622SJuan Castillo } 3826f971622SJuan Castillo 38355e291a4SJuan Castillo /* Create the certificates */ 38455e291a4SJuan Castillo for (i = 0 ; i < num_certs ; i++) { 38555e291a4SJuan Castillo 38655e291a4SJuan Castillo cert = &certs[i]; 38755e291a4SJuan Castillo 38855e291a4SJuan Castillo /* Create a new stack of extensions. This stack will be used 38955e291a4SJuan Castillo * to create the certificate */ 3906f971622SJuan Castillo CHECK_NULL(sk, sk_X509_EXTENSION_new_null()); 3916f971622SJuan Castillo 39255e291a4SJuan Castillo for (j = 0 ; j < cert->num_ext ; j++) { 3936f971622SJuan Castillo 39455e291a4SJuan Castillo ext = &extensions[cert->ext[j]]; 39555e291a4SJuan Castillo 39655e291a4SJuan Castillo /* Get OpenSSL internal ID for this extension */ 39755e291a4SJuan Castillo CHECK_OID(ext_nid, ext->oid); 39855e291a4SJuan Castillo 39955e291a4SJuan Castillo /* 40055e291a4SJuan Castillo * Three types of extensions are currently supported: 40155e291a4SJuan Castillo * - EXT_TYPE_NVCOUNTER 40255e291a4SJuan Castillo * - EXT_TYPE_HASH 40355e291a4SJuan Castillo * - EXT_TYPE_PKEY 40455e291a4SJuan Castillo */ 40555e291a4SJuan Castillo switch (ext->type) { 40655e291a4SJuan Castillo case EXT_TYPE_NVCOUNTER: 407f16db56aSYatharth Kochar if (ext->arg) { 40896103d5aSJuan Castillo nvctr = atoi(ext->arg); 40955e291a4SJuan Castillo CHECK_NULL(cert_ext, ext_new_nvcounter(ext_nid, 41096103d5aSJuan Castillo EXT_CRIT, nvctr)); 411f16db56aSYatharth Kochar } 41255e291a4SJuan Castillo break; 41355e291a4SJuan Castillo case EXT_TYPE_HASH: 41496103d5aSJuan Castillo if (ext->arg == NULL) { 415cebe1f23SYatharth Kochar if (ext->optional) { 416cebe1f23SYatharth Kochar /* Include a hash filled with zeros */ 417cebe1f23SYatharth Kochar memset(md, 0x0, SHA256_DIGEST_LENGTH); 418cebe1f23SYatharth Kochar } else { 419cebe1f23SYatharth Kochar /* Do not include this hash in the certificate */ 42055e291a4SJuan Castillo break; 42155e291a4SJuan Castillo } 422cebe1f23SYatharth Kochar } else { 423cebe1f23SYatharth Kochar /* Calculate the hash of the file */ 42496103d5aSJuan Castillo if (!sha_file(ext->arg, md)) { 42555e291a4SJuan Castillo ERROR("Cannot calculate hash of %s\n", 42696103d5aSJuan Castillo ext->arg); 4276f971622SJuan Castillo exit(1); 4286f971622SJuan Castillo } 429cebe1f23SYatharth Kochar } 43055e291a4SJuan Castillo CHECK_NULL(cert_ext, ext_new_hash(ext_nid, 43155e291a4SJuan Castillo EXT_CRIT, md_info, md, 4326f971622SJuan Castillo SHA256_DIGEST_LENGTH)); 43355e291a4SJuan Castillo break; 43455e291a4SJuan Castillo case EXT_TYPE_PKEY: 43555e291a4SJuan Castillo CHECK_NULL(cert_ext, ext_new_key(ext_nid, 43696103d5aSJuan Castillo EXT_CRIT, keys[ext->attr.key].key)); 43755e291a4SJuan Castillo break; 43855e291a4SJuan Castillo default: 43996103d5aSJuan Castillo ERROR("Unknown extension type '%d' in %s\n", 44096103d5aSJuan Castillo ext->type, cert->cn); 44155e291a4SJuan Castillo exit(1); 44255e291a4SJuan Castillo } 44355e291a4SJuan Castillo 44455e291a4SJuan Castillo /* Push the extension into the stack */ 44555e291a4SJuan Castillo sk_X509_EXTENSION_push(sk, cert_ext); 44655e291a4SJuan Castillo } 4476f971622SJuan Castillo 4486f971622SJuan Castillo /* Create certificate. Signed with ROT key */ 449dfc90e26SJuan Castillo if (cert->fn && !cert_new(cert, VAL_DAYS, 0, sk)) { 45055e291a4SJuan Castillo ERROR("Cannot create %s\n", cert->cn); 4516f971622SJuan Castillo exit(1); 4526f971622SJuan Castillo } 4536f971622SJuan Castillo 4546f971622SJuan Castillo sk_X509_EXTENSION_free(sk); 4556f971622SJuan Castillo } 4566f971622SJuan Castillo 4576f971622SJuan Castillo 4586f971622SJuan Castillo /* Print the certificates */ 4596f971622SJuan Castillo if (print_cert) { 46055e291a4SJuan Castillo for (i = 0 ; i < num_certs ; i++) { 4616f971622SJuan Castillo if (!certs[i].x) { 4626f971622SJuan Castillo continue; 4636f971622SJuan Castillo } 4646f971622SJuan Castillo printf("\n\n=====================================\n\n"); 4656f971622SJuan Castillo X509_print_fp(stdout, certs[i].x); 4666f971622SJuan Castillo } 4676f971622SJuan Castillo } 4686f971622SJuan Castillo 4696f971622SJuan Castillo /* Save created certificates to files */ 47055e291a4SJuan Castillo for (i = 0 ; i < num_certs ; i++) { 4716f971622SJuan Castillo if (certs[i].x && certs[i].fn) { 4726f971622SJuan Castillo file = fopen(certs[i].fn, "w"); 4736f971622SJuan Castillo if (file != NULL) { 4746f971622SJuan Castillo i2d_X509_fp(file, certs[i].x); 4756f971622SJuan Castillo fclose(file); 4766f971622SJuan Castillo } else { 4776f971622SJuan Castillo ERROR("Cannot create file %s\n", certs[i].fn); 4786f971622SJuan Castillo } 4796f971622SJuan Castillo } 4806f971622SJuan Castillo } 4816f971622SJuan Castillo 4826f971622SJuan Castillo /* Save keys */ 4836f971622SJuan Castillo if (save_keys) { 48455e291a4SJuan Castillo for (i = 0 ; i < num_keys ; i++) { 4856f971622SJuan Castillo if (!key_store(&keys[i])) { 4866f971622SJuan Castillo ERROR("Cannot save %s\n", keys[i].desc); 4876f971622SJuan Castillo } 4886f971622SJuan Castillo } 4896f971622SJuan Castillo } 4906f971622SJuan Castillo 4916f971622SJuan Castillo #ifndef OPENSSL_NO_ENGINE 4926f971622SJuan Castillo ENGINE_cleanup(); 4936f971622SJuan Castillo #endif 4946f971622SJuan Castillo CRYPTO_cleanup_all_ex_data(); 4956f971622SJuan Castillo 4966f971622SJuan Castillo return 0; 4976f971622SJuan Castillo } 498