16f971622SJuan Castillo /* 26f971622SJuan Castillo * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. 36f971622SJuan Castillo * 46f971622SJuan Castillo * Redistribution and use in source and binary forms, with or without 56f971622SJuan Castillo * modification, are permitted provided that the following conditions are met: 66f971622SJuan Castillo * 76f971622SJuan Castillo * Redistributions of source code must retain the above copyright notice, this 86f971622SJuan Castillo * list of conditions and the following disclaimer. 96f971622SJuan Castillo * 106f971622SJuan Castillo * Redistributions in binary form must reproduce the above copyright notice, 116f971622SJuan Castillo * this list of conditions and the following disclaimer in the documentation 126f971622SJuan Castillo * and/or other materials provided with the distribution. 136f971622SJuan Castillo * 146f971622SJuan Castillo * Neither the name of ARM nor the names of its contributors may be used 156f971622SJuan Castillo * to endorse or promote products derived from this software without specific 166f971622SJuan Castillo * prior written permission. 176f971622SJuan Castillo * 186f971622SJuan Castillo * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 196f971622SJuan Castillo * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 206f971622SJuan Castillo * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 216f971622SJuan Castillo * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 226f971622SJuan Castillo * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 236f971622SJuan Castillo * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 246f971622SJuan Castillo * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 256f971622SJuan Castillo * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 266f971622SJuan Castillo * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 276f971622SJuan Castillo * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 286f971622SJuan Castillo * POSSIBILITY OF SUCH DAMAGE. 296f971622SJuan Castillo */ 306f971622SJuan Castillo 31*159807e2SJuan Castillo #include <assert.h> 32*159807e2SJuan Castillo #include <ctype.h> 336f971622SJuan Castillo #include <getopt.h> 346f971622SJuan Castillo #include <stdio.h> 356f971622SJuan Castillo #include <stdlib.h> 366f971622SJuan Castillo #include <string.h> 376f971622SJuan Castillo 386f971622SJuan Castillo #include <openssl/conf.h> 396f971622SJuan Castillo #include <openssl/engine.h> 406f971622SJuan Castillo #include <openssl/err.h> 416f971622SJuan Castillo #include <openssl/pem.h> 426f971622SJuan Castillo #include <openssl/sha.h> 436f971622SJuan Castillo #include <openssl/x509v3.h> 446f971622SJuan Castillo 456f971622SJuan Castillo #include "cert.h" 46ad2c1a9aSJuan Castillo #include "cmd_opt.h" 476f971622SJuan Castillo #include "debug.h" 486f971622SJuan Castillo #include "ext.h" 496f971622SJuan Castillo #include "key.h" 506f971622SJuan Castillo #include "platform_oid.h" 516f971622SJuan Castillo #include "sha.h" 5255e291a4SJuan Castillo #include "tbbr/tbb_ext.h" 5355e291a4SJuan Castillo #include "tbbr/tbb_cert.h" 5455e291a4SJuan Castillo #include "tbbr/tbb_key.h" 556f971622SJuan Castillo 566f971622SJuan Castillo /* 576f971622SJuan Castillo * Helper macros to simplify the code. This macro assigns the return value of 586f971622SJuan Castillo * the 'fn' function to 'v' and exits if the value is NULL. 596f971622SJuan Castillo */ 606f971622SJuan Castillo #define CHECK_NULL(v, fn) \ 616f971622SJuan Castillo do { \ 626f971622SJuan Castillo v = fn; \ 636f971622SJuan Castillo if (v == NULL) { \ 646f971622SJuan Castillo ERROR("NULL object at %s:%d\n", __FILE__, __LINE__); \ 656f971622SJuan Castillo exit(1); \ 666f971622SJuan Castillo } \ 676f971622SJuan Castillo } while (0) 686f971622SJuan Castillo 696f971622SJuan Castillo /* 706f971622SJuan Castillo * This macro assigns the NID corresponding to 'oid' to 'v' and exits if the 716f971622SJuan Castillo * NID is undefined. 726f971622SJuan Castillo */ 736f971622SJuan Castillo #define CHECK_OID(v, oid) \ 746f971622SJuan Castillo do { \ 756f971622SJuan Castillo v = OBJ_txt2nid(oid); \ 766f971622SJuan Castillo if (v == NID_undef) { \ 776f971622SJuan Castillo ERROR("Cannot find TBB extension %s\n", oid); \ 786f971622SJuan Castillo exit(1); \ 796f971622SJuan Castillo } \ 806f971622SJuan Castillo } while (0) 816f971622SJuan Castillo 826f971622SJuan Castillo #define MAX_FILENAME_LEN 1024 836f971622SJuan Castillo #define VAL_DAYS 7300 846f971622SJuan Castillo #define ID_TO_BIT_MASK(id) (1 << id) 85ccbf890eSJuan Castillo #define NUM_ELEM(x) ((sizeof(x)) / (sizeof(x[0]))) 86*159807e2SJuan Castillo #define HELP_OPT_MAX_LEN 128 876f971622SJuan Castillo 886f971622SJuan Castillo /* Global options */ 89ccbf890eSJuan Castillo static int key_alg; 906f971622SJuan Castillo static int new_keys; 916f971622SJuan Castillo static int save_keys; 926f971622SJuan Castillo static int print_cert; 936f971622SJuan Castillo 946f971622SJuan Castillo /* Info messages created in the Makefile */ 956f971622SJuan Castillo extern const char build_msg[]; 966f971622SJuan Castillo extern const char platform_msg[]; 976f971622SJuan Castillo 986f971622SJuan Castillo 996f971622SJuan Castillo static char *strdup(const char *str) 1006f971622SJuan Castillo { 1016f971622SJuan Castillo int n = strlen(str) + 1; 1026f971622SJuan Castillo char *dup = malloc(n); 1036f971622SJuan Castillo if (dup) { 1046f971622SJuan Castillo strcpy(dup, str); 1056f971622SJuan Castillo } 1066f971622SJuan Castillo return dup; 1076f971622SJuan Castillo } 1086f971622SJuan Castillo 109ccbf890eSJuan Castillo static const char *key_algs_str[] = { 110ccbf890eSJuan Castillo [KEY_ALG_RSA] = "rsa", 111ed2a76eaSJuan Castillo #ifndef OPENSSL_NO_EC 112ccbf890eSJuan Castillo [KEY_ALG_ECDSA] = "ecdsa" 113ed2a76eaSJuan Castillo #endif /* OPENSSL_NO_EC */ 114ccbf890eSJuan Castillo }; 115ccbf890eSJuan Castillo 116ad2c1a9aSJuan Castillo static void print_help(const char *cmd, const struct option *long_opt) 1176f971622SJuan Castillo { 118*159807e2SJuan Castillo int rem, i = 0; 119*159807e2SJuan Castillo const struct option *opt; 120*159807e2SJuan Castillo char line[HELP_OPT_MAX_LEN]; 121*159807e2SJuan Castillo char *p; 122*159807e2SJuan Castillo 123*159807e2SJuan Castillo assert(cmd != NULL); 124*159807e2SJuan Castillo assert(long_opt != NULL); 125*159807e2SJuan Castillo 1266f971622SJuan Castillo printf("\n\n"); 1276f971622SJuan Castillo printf("The certificate generation tool loads the binary images and\n" 1286f971622SJuan Castillo "optionally the RSA keys, and outputs the key and content\n" 1296f971622SJuan Castillo "certificates properly signed to implement the chain of trust.\n" 1306f971622SJuan Castillo "If keys are provided, they must be in PEM format.\n" 1316f971622SJuan Castillo "Certificates are generated in DER format.\n"); 1326f971622SJuan Castillo printf("\n"); 133*159807e2SJuan Castillo printf("Usage:\n"); 134*159807e2SJuan Castillo printf("\t%s [OPTIONS]\n\n", cmd); 135*159807e2SJuan Castillo 136*159807e2SJuan Castillo printf("Available options:\n"); 137*159807e2SJuan Castillo i = 0; 138*159807e2SJuan Castillo opt = long_opt; 139*159807e2SJuan Castillo while (opt->name) { 140*159807e2SJuan Castillo p = line; 141*159807e2SJuan Castillo rem = HELP_OPT_MAX_LEN; 142*159807e2SJuan Castillo if (isalpha(opt->val)) { 143*159807e2SJuan Castillo /* Short format */ 144*159807e2SJuan Castillo sprintf(p, "-%c,", (char)opt->val); 145*159807e2SJuan Castillo p += 3; 146*159807e2SJuan Castillo rem -= 3; 1476f971622SJuan Castillo } 148*159807e2SJuan Castillo snprintf(p, rem, "--%s %s", opt->name, 149*159807e2SJuan Castillo (opt->has_arg == required_argument) ? "<arg>" : ""); 150*159807e2SJuan Castillo printf("\t%-32s %s\n", line, cmd_opt_get_help_msg(i)); 151*159807e2SJuan Castillo opt++; 152*159807e2SJuan Castillo i++; 153*159807e2SJuan Castillo } 1546f971622SJuan Castillo printf("\n"); 1556f971622SJuan Castillo 1566f971622SJuan Castillo exit(0); 1576f971622SJuan Castillo } 1586f971622SJuan Castillo 159ccbf890eSJuan Castillo static int get_key_alg(const char *key_alg_str) 160ccbf890eSJuan Castillo { 161ccbf890eSJuan Castillo int i; 162ccbf890eSJuan Castillo 163ccbf890eSJuan Castillo for (i = 0 ; i < NUM_ELEM(key_algs_str) ; i++) { 164ccbf890eSJuan Castillo if (0 == strcmp(key_alg_str, key_algs_str[i])) { 165ccbf890eSJuan Castillo return i; 166ccbf890eSJuan Castillo } 167ccbf890eSJuan Castillo } 168ccbf890eSJuan Castillo 169ccbf890eSJuan Castillo return -1; 170ccbf890eSJuan Castillo } 171ccbf890eSJuan Castillo 1726f971622SJuan Castillo static void check_cmd_params(void) 1736f971622SJuan Castillo { 174dfc90e26SJuan Castillo cert_t *cert; 175dfc90e26SJuan Castillo ext_t *ext; 176dfc90e26SJuan Castillo key_t *key; 177dfc90e26SJuan Castillo int i, j; 178dfc90e26SJuan Castillo 179ccbf890eSJuan Castillo /* Only save new keys */ 180ccbf890eSJuan Castillo if (save_keys && !new_keys) { 181ccbf890eSJuan Castillo ERROR("Only new keys can be saved to disk\n"); 182ccbf890eSJuan Castillo exit(1); 183ccbf890eSJuan Castillo } 184ccbf890eSJuan Castillo 185dfc90e26SJuan Castillo /* Check that all required options have been specified in the 186dfc90e26SJuan Castillo * command line */ 187dfc90e26SJuan Castillo for (i = 0; i < num_certs; i++) { 188dfc90e26SJuan Castillo cert = &certs[i]; 189dfc90e26SJuan Castillo if (cert->fn == NULL) { 190dfc90e26SJuan Castillo /* Certificate not requested. Skip to the next one */ 191dfc90e26SJuan Castillo continue; 192dfc90e26SJuan Castillo } 193dfc90e26SJuan Castillo 194dfc90e26SJuan Castillo /* Check that all parameters required to create this certificate 195dfc90e26SJuan Castillo * have been specified in the command line */ 196dfc90e26SJuan Castillo for (j = 0; j < cert->num_ext; j++) { 197dfc90e26SJuan Castillo ext = &extensions[cert->ext[j]]; 198dfc90e26SJuan Castillo switch (ext->type) { 199dfc90e26SJuan Castillo case EXT_TYPE_PKEY: 200dfc90e26SJuan Castillo /* Key filename must be specified */ 201dfc90e26SJuan Castillo key = &keys[ext->data.key]; 202dfc90e26SJuan Castillo if (!new_keys && key->fn == NULL) { 203dfc90e26SJuan Castillo ERROR("Key '%s' required by '%s' not " 204dfc90e26SJuan Castillo "specified\n", key->desc, 205dfc90e26SJuan Castillo cert->cn); 2066f971622SJuan Castillo exit(1); 2076f971622SJuan Castillo } 208dfc90e26SJuan Castillo break; 209dfc90e26SJuan Castillo case EXT_TYPE_HASH: 210cebe1f23SYatharth Kochar /* 211cebe1f23SYatharth Kochar * Binary image must be specified 212cebe1f23SYatharth Kochar * unless it is explicitly made optional. 213cebe1f23SYatharth Kochar */ 214cebe1f23SYatharth Kochar if ((!ext->optional) && (ext->data.fn == NULL)) { 215dfc90e26SJuan Castillo ERROR("Image for '%s' not specified\n", 216dfc90e26SJuan Castillo ext->ln); 2176f971622SJuan Castillo exit(1); 2186f971622SJuan Castillo } 219dfc90e26SJuan Castillo break; 220dfc90e26SJuan Castillo default: 221dfc90e26SJuan Castillo ERROR("Unknown extension type in '%s'\n", 222dfc90e26SJuan Castillo ext->ln); 2236f971622SJuan Castillo exit(1); 224dfc90e26SJuan Castillo break; 2256f971622SJuan Castillo } 2266f971622SJuan Castillo } 2276f971622SJuan Castillo } 2286f971622SJuan Castillo } 2296f971622SJuan Castillo 230*159807e2SJuan Castillo /* Common command line options */ 231*159807e2SJuan Castillo static const cmd_opt_t common_cmd_opt[] = { 232*159807e2SJuan Castillo { 233*159807e2SJuan Castillo { "help", no_argument, NULL, 'h' }, 234*159807e2SJuan Castillo "Print this message and exit" 235*159807e2SJuan Castillo }, 236*159807e2SJuan Castillo { 237*159807e2SJuan Castillo { "key-alg", required_argument, NULL, 'a' }, 238*159807e2SJuan Castillo "Key algorithm: 'rsa' (default), 'ecdsa'" 239*159807e2SJuan Castillo }, 240*159807e2SJuan Castillo { 241*159807e2SJuan Castillo { "save-keys", no_argument, NULL, 'k' }, 242*159807e2SJuan Castillo "Save key pairs into files. Filenames must be provided" 243*159807e2SJuan Castillo }, 244*159807e2SJuan Castillo { 245*159807e2SJuan Castillo { "new-keys", no_argument, NULL, 'n' }, 246*159807e2SJuan Castillo "Generate new key pairs if no key files are provided" 247*159807e2SJuan Castillo }, 248*159807e2SJuan Castillo { 249*159807e2SJuan Castillo { "print-cert", no_argument, NULL, 'p' }, 250*159807e2SJuan Castillo "Print the certificates in the standard output" 251*159807e2SJuan Castillo } 252*159807e2SJuan Castillo }; 253*159807e2SJuan Castillo 2546f971622SJuan Castillo int main(int argc, char *argv[]) 2556f971622SJuan Castillo { 2566f971622SJuan Castillo STACK_OF(X509_EXTENSION) * sk = NULL; 25755e291a4SJuan Castillo X509_EXTENSION *cert_ext = NULL; 25855e291a4SJuan Castillo ext_t *ext = NULL; 259ad2c1a9aSJuan Castillo key_t *key = NULL; 260ad2c1a9aSJuan Castillo cert_t *cert = NULL; 2616f971622SJuan Castillo FILE *file = NULL; 26255e291a4SJuan Castillo int i, j, ext_nid; 2636f971622SJuan Castillo int c, opt_idx = 0; 264ad2c1a9aSJuan Castillo const struct option *cmd_opt; 265ad2c1a9aSJuan Castillo const char *cur_opt; 266ccbf890eSJuan Castillo unsigned int err_code; 2676f971622SJuan Castillo unsigned char md[SHA256_DIGEST_LENGTH]; 268c3da66b1SJuan Castillo const EVP_MD *md_info; 2696f971622SJuan Castillo 2706f971622SJuan Castillo NOTICE("CoT Generation Tool: %s\n", build_msg); 2716f971622SJuan Castillo NOTICE("Target platform: %s\n", platform_msg); 2726f971622SJuan Castillo 273ccbf890eSJuan Castillo /* Set default options */ 274ccbf890eSJuan Castillo key_alg = KEY_ALG_RSA; 275ccbf890eSJuan Castillo 276ad2c1a9aSJuan Castillo /* Add common command line options */ 277*159807e2SJuan Castillo for (i = 0; i < NUM_ELEM(common_cmd_opt); i++) { 278*159807e2SJuan Castillo cmd_opt_add(&common_cmd_opt[i]); 279*159807e2SJuan Castillo } 280ad2c1a9aSJuan Castillo 281ad2c1a9aSJuan Castillo /* Initialize the certificates */ 282ad2c1a9aSJuan Castillo if (cert_init() != 0) { 283ad2c1a9aSJuan Castillo ERROR("Cannot initialize certificates\n"); 284ad2c1a9aSJuan Castillo exit(1); 285ad2c1a9aSJuan Castillo } 286ad2c1a9aSJuan Castillo 287ad2c1a9aSJuan Castillo /* Initialize the keys */ 288ad2c1a9aSJuan Castillo if (key_init() != 0) { 289ad2c1a9aSJuan Castillo ERROR("Cannot initialize keys\n"); 290ad2c1a9aSJuan Castillo exit(1); 291ad2c1a9aSJuan Castillo } 292ad2c1a9aSJuan Castillo 293ad2c1a9aSJuan Castillo /* Initialize the new types and register OIDs for the extensions */ 294ad2c1a9aSJuan Castillo if (ext_init() != 0) { 295ad2c1a9aSJuan Castillo ERROR("Cannot initialize TBB extensions\n"); 296ad2c1a9aSJuan Castillo exit(1); 297ad2c1a9aSJuan Castillo } 298ad2c1a9aSJuan Castillo 299ad2c1a9aSJuan Castillo /* Get the command line options populated during the initialization */ 300ad2c1a9aSJuan Castillo cmd_opt = cmd_opt_get_array(); 301ad2c1a9aSJuan Castillo 3026f971622SJuan Castillo while (1) { 3036f971622SJuan Castillo /* getopt_long stores the option index here. */ 304*159807e2SJuan Castillo c = getopt_long(argc, argv, "a:hknp", cmd_opt, &opt_idx); 3056f971622SJuan Castillo 3066f971622SJuan Castillo /* Detect the end of the options. */ 3076f971622SJuan Castillo if (c == -1) { 3086f971622SJuan Castillo break; 3096f971622SJuan Castillo } 3106f971622SJuan Castillo 3116f971622SJuan Castillo switch (c) { 312ccbf890eSJuan Castillo case 'a': 313ccbf890eSJuan Castillo key_alg = get_key_alg(optarg); 314ccbf890eSJuan Castillo if (key_alg < 0) { 315ccbf890eSJuan Castillo ERROR("Invalid key algorithm '%s'\n", optarg); 316ccbf890eSJuan Castillo exit(1); 317ccbf890eSJuan Castillo } 318ccbf890eSJuan Castillo break; 3196f971622SJuan Castillo case 'h': 320ad2c1a9aSJuan Castillo print_help(argv[0], cmd_opt); 3216f971622SJuan Castillo break; 3226f971622SJuan Castillo case 'k': 3236f971622SJuan Castillo save_keys = 1; 3246f971622SJuan Castillo break; 3256f971622SJuan Castillo case 'n': 3266f971622SJuan Castillo new_keys = 1; 3276f971622SJuan Castillo break; 3286f971622SJuan Castillo case 'p': 3296f971622SJuan Castillo print_cert = 1; 3306f971622SJuan Castillo break; 331ad2c1a9aSJuan Castillo case CMD_OPT_EXT: 332ad2c1a9aSJuan Castillo cur_opt = cmd_opt_get_name(opt_idx); 333ad2c1a9aSJuan Castillo ext = ext_get_by_opt(cur_opt); 334ad2c1a9aSJuan Castillo ext->data.fn = strdup(optarg); 3356f971622SJuan Castillo break; 336ad2c1a9aSJuan Castillo case CMD_OPT_KEY: 337ad2c1a9aSJuan Castillo cur_opt = cmd_opt_get_name(opt_idx); 338ad2c1a9aSJuan Castillo key = key_get_by_opt(cur_opt); 339ad2c1a9aSJuan Castillo key->fn = strdup(optarg); 3406f971622SJuan Castillo break; 341ad2c1a9aSJuan Castillo case CMD_OPT_CERT: 342ad2c1a9aSJuan Castillo cur_opt = cmd_opt_get_name(opt_idx); 343ad2c1a9aSJuan Castillo cert = cert_get_by_opt(cur_opt); 344ad2c1a9aSJuan Castillo cert->fn = strdup(optarg); 3456f971622SJuan Castillo break; 3466f971622SJuan Castillo case '?': 3476f971622SJuan Castillo default: 348*159807e2SJuan Castillo print_help(argv[0], cmd_opt); 3496f971622SJuan Castillo exit(1); 3506f971622SJuan Castillo } 3516f971622SJuan Castillo } 3526f971622SJuan Castillo 3536f971622SJuan Castillo /* Check command line arguments */ 3546f971622SJuan Castillo check_cmd_params(); 3556f971622SJuan Castillo 356c3da66b1SJuan Castillo /* Indicate SHA256 as image hash algorithm in the certificate 357c3da66b1SJuan Castillo * extension */ 358c3da66b1SJuan Castillo md_info = EVP_sha256(); 359c3da66b1SJuan Castillo 3606f971622SJuan Castillo /* Load private keys from files (or generate new ones) */ 36155e291a4SJuan Castillo for (i = 0 ; i < num_keys ; i++) { 362ccbf890eSJuan Castillo /* First try to load the key from disk */ 363ccbf890eSJuan Castillo if (key_load(&keys[i], &err_code)) { 364ccbf890eSJuan Castillo /* Key loaded successfully */ 365ccbf890eSJuan Castillo continue; 366ccbf890eSJuan Castillo } 367ccbf890eSJuan Castillo 368ccbf890eSJuan Castillo /* Key not loaded. Check the error code */ 369ccbf890eSJuan Castillo if (err_code == KEY_ERR_MALLOC) { 370ccbf890eSJuan Castillo /* Cannot allocate memory. Abort. */ 371ccbf890eSJuan Castillo ERROR("Malloc error while loading '%s'\n", keys[i].fn); 372ccbf890eSJuan Castillo exit(1); 373ccbf890eSJuan Castillo } else if (err_code == KEY_ERR_LOAD) { 374ccbf890eSJuan Castillo /* File exists, but it does not contain a valid private 375ccbf890eSJuan Castillo * key. Abort. */ 376ccbf890eSJuan Castillo ERROR("Error loading '%s'\n", keys[i].fn); 3776f971622SJuan Castillo exit(1); 3786f971622SJuan Castillo } 379ccbf890eSJuan Castillo 380ccbf890eSJuan Castillo /* File does not exist, could not be opened or no filename was 381ccbf890eSJuan Castillo * given */ 382ccbf890eSJuan Castillo if (new_keys) { 383ccbf890eSJuan Castillo /* Try to create a new key */ 384ccbf890eSJuan Castillo NOTICE("Creating new key for '%s'\n", keys[i].desc); 385ccbf890eSJuan Castillo if (!key_create(&keys[i], key_alg)) { 386ccbf890eSJuan Castillo ERROR("Error creating key '%s'\n", keys[i].desc); 387ccbf890eSJuan Castillo exit(1); 3886f971622SJuan Castillo } 3896f971622SJuan Castillo } else { 390ccbf890eSJuan Castillo if (err_code == KEY_ERR_OPEN) { 391ccbf890eSJuan Castillo ERROR("Error opening '%s'\n", keys[i].fn); 392ccbf890eSJuan Castillo } else { 393ccbf890eSJuan Castillo ERROR("Key '%s' not specified\n", keys[i].desc); 3946f971622SJuan Castillo } 395ccbf890eSJuan Castillo exit(1); 3966f971622SJuan Castillo } 3976f971622SJuan Castillo } 3986f971622SJuan Castillo 39955e291a4SJuan Castillo /* Create the certificates */ 40055e291a4SJuan Castillo for (i = 0 ; i < num_certs ; i++) { 40155e291a4SJuan Castillo 40255e291a4SJuan Castillo cert = &certs[i]; 40355e291a4SJuan Castillo 40455e291a4SJuan Castillo /* Create a new stack of extensions. This stack will be used 40555e291a4SJuan Castillo * to create the certificate */ 4066f971622SJuan Castillo CHECK_NULL(sk, sk_X509_EXTENSION_new_null()); 4076f971622SJuan Castillo 40855e291a4SJuan Castillo for (j = 0 ; j < cert->num_ext ; j++) { 4096f971622SJuan Castillo 41055e291a4SJuan Castillo ext = &extensions[cert->ext[j]]; 41155e291a4SJuan Castillo 41255e291a4SJuan Castillo /* Get OpenSSL internal ID for this extension */ 41355e291a4SJuan Castillo CHECK_OID(ext_nid, ext->oid); 41455e291a4SJuan Castillo 41555e291a4SJuan Castillo /* 41655e291a4SJuan Castillo * Three types of extensions are currently supported: 41755e291a4SJuan Castillo * - EXT_TYPE_NVCOUNTER 41855e291a4SJuan Castillo * - EXT_TYPE_HASH 41955e291a4SJuan Castillo * - EXT_TYPE_PKEY 42055e291a4SJuan Castillo */ 42155e291a4SJuan Castillo switch (ext->type) { 42255e291a4SJuan Castillo case EXT_TYPE_NVCOUNTER: 42355e291a4SJuan Castillo CHECK_NULL(cert_ext, ext_new_nvcounter(ext_nid, 42455e291a4SJuan Castillo EXT_CRIT, ext->data.nvcounter)); 42555e291a4SJuan Castillo break; 42655e291a4SJuan Castillo case EXT_TYPE_HASH: 42755e291a4SJuan Castillo if (ext->data.fn == NULL) { 428cebe1f23SYatharth Kochar if (ext->optional) { 429cebe1f23SYatharth Kochar /* Include a hash filled with zeros */ 430cebe1f23SYatharth Kochar memset(md, 0x0, SHA256_DIGEST_LENGTH); 431cebe1f23SYatharth Kochar } else { 432cebe1f23SYatharth Kochar /* Do not include this hash in the certificate */ 43355e291a4SJuan Castillo break; 43455e291a4SJuan Castillo } 435cebe1f23SYatharth Kochar } else { 436cebe1f23SYatharth Kochar /* Calculate the hash of the file */ 43755e291a4SJuan Castillo if (!sha_file(ext->data.fn, md)) { 43855e291a4SJuan Castillo ERROR("Cannot calculate hash of %s\n", 43955e291a4SJuan Castillo ext->data.fn); 4406f971622SJuan Castillo exit(1); 4416f971622SJuan Castillo } 442cebe1f23SYatharth Kochar } 44355e291a4SJuan Castillo CHECK_NULL(cert_ext, ext_new_hash(ext_nid, 44455e291a4SJuan Castillo EXT_CRIT, md_info, md, 4456f971622SJuan Castillo SHA256_DIGEST_LENGTH)); 44655e291a4SJuan Castillo break; 44755e291a4SJuan Castillo case EXT_TYPE_PKEY: 44855e291a4SJuan Castillo CHECK_NULL(cert_ext, ext_new_key(ext_nid, 44955e291a4SJuan Castillo EXT_CRIT, keys[ext->data.key].key)); 45055e291a4SJuan Castillo break; 45155e291a4SJuan Castillo default: 45255e291a4SJuan Castillo ERROR("Unknown extension type in %s\n", 45355e291a4SJuan Castillo cert->cn); 45455e291a4SJuan Castillo exit(1); 45555e291a4SJuan Castillo } 45655e291a4SJuan Castillo 45755e291a4SJuan Castillo /* Push the extension into the stack */ 45855e291a4SJuan Castillo sk_X509_EXTENSION_push(sk, cert_ext); 45955e291a4SJuan Castillo } 4606f971622SJuan Castillo 4616f971622SJuan Castillo /* Create certificate. Signed with ROT key */ 462dfc90e26SJuan Castillo if (cert->fn && !cert_new(cert, VAL_DAYS, 0, sk)) { 46355e291a4SJuan Castillo ERROR("Cannot create %s\n", cert->cn); 4646f971622SJuan Castillo exit(1); 4656f971622SJuan Castillo } 4666f971622SJuan Castillo 4676f971622SJuan Castillo sk_X509_EXTENSION_free(sk); 4686f971622SJuan Castillo } 4696f971622SJuan Castillo 4706f971622SJuan Castillo 4716f971622SJuan Castillo /* Print the certificates */ 4726f971622SJuan Castillo if (print_cert) { 47355e291a4SJuan Castillo for (i = 0 ; i < num_certs ; i++) { 4746f971622SJuan Castillo if (!certs[i].x) { 4756f971622SJuan Castillo continue; 4766f971622SJuan Castillo } 4776f971622SJuan Castillo printf("\n\n=====================================\n\n"); 4786f971622SJuan Castillo X509_print_fp(stdout, certs[i].x); 4796f971622SJuan Castillo } 4806f971622SJuan Castillo } 4816f971622SJuan Castillo 4826f971622SJuan Castillo /* Save created certificates to files */ 48355e291a4SJuan Castillo for (i = 0 ; i < num_certs ; i++) { 4846f971622SJuan Castillo if (certs[i].x && certs[i].fn) { 4856f971622SJuan Castillo file = fopen(certs[i].fn, "w"); 4866f971622SJuan Castillo if (file != NULL) { 4876f971622SJuan Castillo i2d_X509_fp(file, certs[i].x); 4886f971622SJuan Castillo fclose(file); 4896f971622SJuan Castillo } else { 4906f971622SJuan Castillo ERROR("Cannot create file %s\n", certs[i].fn); 4916f971622SJuan Castillo } 4926f971622SJuan Castillo } 4936f971622SJuan Castillo } 4946f971622SJuan Castillo 4956f971622SJuan Castillo /* Save keys */ 4966f971622SJuan Castillo if (save_keys) { 49755e291a4SJuan Castillo for (i = 0 ; i < num_keys ; i++) { 4986f971622SJuan Castillo if (!key_store(&keys[i])) { 4996f971622SJuan Castillo ERROR("Cannot save %s\n", keys[i].desc); 5006f971622SJuan Castillo } 5016f971622SJuan Castillo } 5026f971622SJuan Castillo } 5036f971622SJuan Castillo 5046f971622SJuan Castillo #ifndef OPENSSL_NO_ENGINE 5056f971622SJuan Castillo ENGINE_cleanup(); 5066f971622SJuan Castillo #endif 5076f971622SJuan Castillo CRYPTO_cleanup_all_ex_data(); 5086f971622SJuan Castillo 5096f971622SJuan Castillo return 0; 5106f971622SJuan Castillo } 511