1*6f971622SJuan Castillo /* 2*6f971622SJuan Castillo * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. 3*6f971622SJuan Castillo * 4*6f971622SJuan Castillo * Redistribution and use in source and binary forms, with or without 5*6f971622SJuan Castillo * modification, are permitted provided that the following conditions are met: 6*6f971622SJuan Castillo * 7*6f971622SJuan Castillo * Redistributions of source code must retain the above copyright notice, this 8*6f971622SJuan Castillo * list of conditions and the following disclaimer. 9*6f971622SJuan Castillo * 10*6f971622SJuan Castillo * Redistributions in binary form must reproduce the above copyright notice, 11*6f971622SJuan Castillo * this list of conditions and the following disclaimer in the documentation 12*6f971622SJuan Castillo * and/or other materials provided with the distribution. 13*6f971622SJuan Castillo * 14*6f971622SJuan Castillo * Neither the name of ARM nor the names of its contributors may be used 15*6f971622SJuan Castillo * to endorse or promote products derived from this software without specific 16*6f971622SJuan Castillo * prior written permission. 17*6f971622SJuan Castillo * 18*6f971622SJuan Castillo * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19*6f971622SJuan Castillo * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20*6f971622SJuan Castillo * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21*6f971622SJuan Castillo * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22*6f971622SJuan Castillo * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23*6f971622SJuan Castillo * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24*6f971622SJuan Castillo * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25*6f971622SJuan Castillo * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26*6f971622SJuan Castillo * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27*6f971622SJuan Castillo * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28*6f971622SJuan Castillo * POSSIBILITY OF SUCH DAMAGE. 29*6f971622SJuan Castillo */ 30*6f971622SJuan Castillo 31*6f971622SJuan Castillo #include <getopt.h> 32*6f971622SJuan Castillo #include <stdio.h> 33*6f971622SJuan Castillo #include <stdlib.h> 34*6f971622SJuan Castillo #include <string.h> 35*6f971622SJuan Castillo 36*6f971622SJuan Castillo #include <openssl/conf.h> 37*6f971622SJuan Castillo #include <openssl/engine.h> 38*6f971622SJuan Castillo #include <openssl/err.h> 39*6f971622SJuan Castillo #include <openssl/pem.h> 40*6f971622SJuan Castillo #include <openssl/sha.h> 41*6f971622SJuan Castillo #include <openssl/x509v3.h> 42*6f971622SJuan Castillo 43*6f971622SJuan Castillo #include "cert.h" 44*6f971622SJuan Castillo #include "debug.h" 45*6f971622SJuan Castillo #include "ext.h" 46*6f971622SJuan Castillo #include "key.h" 47*6f971622SJuan Castillo #include "platform_oid.h" 48*6f971622SJuan Castillo #include "sha.h" 49*6f971622SJuan Castillo #include "tbb_ext.h" 50*6f971622SJuan Castillo #include "tbb_cert.h" 51*6f971622SJuan Castillo #include "tbb_key.h" 52*6f971622SJuan Castillo 53*6f971622SJuan Castillo /* 54*6f971622SJuan Castillo * Helper macros to simplify the code. This macro assigns the return value of 55*6f971622SJuan Castillo * the 'fn' function to 'v' and exits if the value is NULL. 56*6f971622SJuan Castillo */ 57*6f971622SJuan Castillo #define CHECK_NULL(v, fn) \ 58*6f971622SJuan Castillo do { \ 59*6f971622SJuan Castillo v = fn; \ 60*6f971622SJuan Castillo if (v == NULL) { \ 61*6f971622SJuan Castillo ERROR("NULL object at %s:%d\n", __FILE__, __LINE__); \ 62*6f971622SJuan Castillo exit(1); \ 63*6f971622SJuan Castillo } \ 64*6f971622SJuan Castillo } while (0) 65*6f971622SJuan Castillo 66*6f971622SJuan Castillo /* 67*6f971622SJuan Castillo * This macro assigns the NID corresponding to 'oid' to 'v' and exits if the 68*6f971622SJuan Castillo * NID is undefined. 69*6f971622SJuan Castillo */ 70*6f971622SJuan Castillo #define CHECK_OID(v, oid) \ 71*6f971622SJuan Castillo do { \ 72*6f971622SJuan Castillo v = OBJ_txt2nid(oid); \ 73*6f971622SJuan Castillo if (v == NID_undef) { \ 74*6f971622SJuan Castillo ERROR("Cannot find TBB extension %s\n", oid); \ 75*6f971622SJuan Castillo exit(1); \ 76*6f971622SJuan Castillo } \ 77*6f971622SJuan Castillo } while (0) 78*6f971622SJuan Castillo 79*6f971622SJuan Castillo #define MAX_FILENAME_LEN 1024 80*6f971622SJuan Castillo #define VAL_DAYS 7300 81*6f971622SJuan Castillo #define ID_TO_BIT_MASK(id) (1 << id) 82*6f971622SJuan Castillo #define NVCOUNTER_VALUE 0 83*6f971622SJuan Castillo 84*6f971622SJuan Castillo /* Files */ 85*6f971622SJuan Castillo enum { 86*6f971622SJuan Castillo /* Image file names (inputs) */ 87*6f971622SJuan Castillo BL2_ID = 0, 88*6f971622SJuan Castillo BL30_ID, 89*6f971622SJuan Castillo BL31_ID, 90*6f971622SJuan Castillo BL32_ID, 91*6f971622SJuan Castillo BL33_ID, 92*6f971622SJuan Castillo /* Certificate file names (outputs) */ 93*6f971622SJuan Castillo BL2_CERT_ID, 94*6f971622SJuan Castillo TRUSTED_KEY_CERT_ID, 95*6f971622SJuan Castillo BL30_KEY_CERT_ID, 96*6f971622SJuan Castillo BL30_CERT_ID, 97*6f971622SJuan Castillo BL31_KEY_CERT_ID, 98*6f971622SJuan Castillo BL31_CERT_ID, 99*6f971622SJuan Castillo BL32_KEY_CERT_ID, 100*6f971622SJuan Castillo BL32_CERT_ID, 101*6f971622SJuan Castillo BL33_KEY_CERT_ID, 102*6f971622SJuan Castillo BL33_CERT_ID, 103*6f971622SJuan Castillo /* Key file names (input/output) */ 104*6f971622SJuan Castillo ROT_KEY_ID, 105*6f971622SJuan Castillo TRUSTED_WORLD_KEY_ID, 106*6f971622SJuan Castillo NON_TRUSTED_WORLD_KEY_ID, 107*6f971622SJuan Castillo BL30_KEY_ID, 108*6f971622SJuan Castillo BL31_KEY_ID, 109*6f971622SJuan Castillo BL32_KEY_ID, 110*6f971622SJuan Castillo BL33_KEY_ID, 111*6f971622SJuan Castillo NUM_OPTS 112*6f971622SJuan Castillo }; 113*6f971622SJuan Castillo 114*6f971622SJuan Castillo /* Global options */ 115*6f971622SJuan Castillo static int new_keys; 116*6f971622SJuan Castillo static int save_keys; 117*6f971622SJuan Castillo static int print_cert; 118*6f971622SJuan Castillo static int bl30_present; 119*6f971622SJuan Castillo static int bl32_present; 120*6f971622SJuan Castillo 121*6f971622SJuan Castillo /* We are not checking nvcounters in TF. Include them in the certificates but 122*6f971622SJuan Castillo * the value will be set to 0 */ 123*6f971622SJuan Castillo static int tf_nvcounter; 124*6f971622SJuan Castillo static int non_tf_nvcounter; 125*6f971622SJuan Castillo 126*6f971622SJuan Castillo /* Info messages created in the Makefile */ 127*6f971622SJuan Castillo extern const char build_msg[]; 128*6f971622SJuan Castillo extern const char platform_msg[]; 129*6f971622SJuan Castillo 130*6f971622SJuan Castillo 131*6f971622SJuan Castillo static char *strdup(const char *str) 132*6f971622SJuan Castillo { 133*6f971622SJuan Castillo int n = strlen(str) + 1; 134*6f971622SJuan Castillo char *dup = malloc(n); 135*6f971622SJuan Castillo if (dup) { 136*6f971622SJuan Castillo strcpy(dup, str); 137*6f971622SJuan Castillo } 138*6f971622SJuan Castillo return dup; 139*6f971622SJuan Castillo } 140*6f971622SJuan Castillo 141*6f971622SJuan Castillo /* Command line options */ 142*6f971622SJuan Castillo static const struct option long_opt[] = { 143*6f971622SJuan Castillo /* Binary images */ 144*6f971622SJuan Castillo {"bl2", required_argument, 0, BL2_ID}, 145*6f971622SJuan Castillo {"bl30", required_argument, 0, BL30_ID}, 146*6f971622SJuan Castillo {"bl31", required_argument, 0, BL31_ID}, 147*6f971622SJuan Castillo {"bl32", required_argument, 0, BL32_ID}, 148*6f971622SJuan Castillo {"bl33", required_argument, 0, BL33_ID}, 149*6f971622SJuan Castillo /* Certificate files */ 150*6f971622SJuan Castillo {"bl2-cert", required_argument, 0, BL2_CERT_ID}, 151*6f971622SJuan Castillo {"trusted-key-cert", required_argument, 0, TRUSTED_KEY_CERT_ID}, 152*6f971622SJuan Castillo {"bl30-key-cert", required_argument, 0, BL30_KEY_CERT_ID}, 153*6f971622SJuan Castillo {"bl30-cert", required_argument, 0, BL30_CERT_ID}, 154*6f971622SJuan Castillo {"bl31-key-cert", required_argument, 0, BL31_KEY_CERT_ID}, 155*6f971622SJuan Castillo {"bl31-cert", required_argument, 0, BL31_CERT_ID}, 156*6f971622SJuan Castillo {"bl32-key-cert", required_argument, 0, BL32_KEY_CERT_ID}, 157*6f971622SJuan Castillo {"bl32-cert", required_argument, 0, BL32_CERT_ID}, 158*6f971622SJuan Castillo {"bl33-key-cert", required_argument, 0, BL33_KEY_CERT_ID}, 159*6f971622SJuan Castillo {"bl33-cert", required_argument, 0, BL33_CERT_ID}, 160*6f971622SJuan Castillo /* Private key files */ 161*6f971622SJuan Castillo {"rot-key", required_argument, 0, ROT_KEY_ID}, 162*6f971622SJuan Castillo {"trusted-world-key", required_argument, 0, TRUSTED_WORLD_KEY_ID}, 163*6f971622SJuan Castillo {"non-trusted-world-key", required_argument, 0, NON_TRUSTED_WORLD_KEY_ID}, 164*6f971622SJuan Castillo {"bl30-key", required_argument, 0, BL30_KEY_ID}, 165*6f971622SJuan Castillo {"bl31-key", required_argument, 0, BL31_KEY_ID}, 166*6f971622SJuan Castillo {"bl32-key", required_argument, 0, BL32_KEY_ID}, 167*6f971622SJuan Castillo {"bl33-key", required_argument, 0, BL33_KEY_ID}, 168*6f971622SJuan Castillo /* Common options */ 169*6f971622SJuan Castillo {"help", no_argument, 0, 'h'}, 170*6f971622SJuan Castillo {"save-keys", no_argument, 0, 'k'}, 171*6f971622SJuan Castillo {"new-chain", no_argument, 0, 'n'}, 172*6f971622SJuan Castillo {"print-cert", no_argument, 0, 'p'}, 173*6f971622SJuan Castillo {0, 0, 0, 0} 174*6f971622SJuan Castillo }; 175*6f971622SJuan Castillo 176*6f971622SJuan Castillo static void print_help(const char *cmd) 177*6f971622SJuan Castillo { 178*6f971622SJuan Castillo int i = 0; 179*6f971622SJuan Castillo printf("\n\n"); 180*6f971622SJuan Castillo printf("The certificate generation tool loads the binary images and\n" 181*6f971622SJuan Castillo "optionally the RSA keys, and outputs the key and content\n" 182*6f971622SJuan Castillo "certificates properly signed to implement the chain of trust.\n" 183*6f971622SJuan Castillo "If keys are provided, they must be in PEM format.\n" 184*6f971622SJuan Castillo "Certificates are generated in DER format.\n"); 185*6f971622SJuan Castillo printf("\n"); 186*6f971622SJuan Castillo printf("Usage:\n\n"); 187*6f971622SJuan Castillo printf(" %s [-hknp] \\\n", cmd); 188*6f971622SJuan Castillo for (i = 0; i < NUM_OPTS; i++) { 189*6f971622SJuan Castillo printf(" --%s <file> \\\n", long_opt[i].name); 190*6f971622SJuan Castillo } 191*6f971622SJuan Castillo printf("\n"); 192*6f971622SJuan Castillo printf("-h Print help and exit\n"); 193*6f971622SJuan Castillo printf("-k Save key pairs into files. Filenames must be provided\n"); 194*6f971622SJuan Castillo printf("-n Generate new key pairs if no key files are provided\n"); 195*6f971622SJuan Castillo printf("-p Print the certificates in the standard output\n"); 196*6f971622SJuan Castillo printf("\n"); 197*6f971622SJuan Castillo 198*6f971622SJuan Castillo exit(0); 199*6f971622SJuan Castillo } 200*6f971622SJuan Castillo 201*6f971622SJuan Castillo static void check_cmd_params(void) 202*6f971622SJuan Castillo { 203*6f971622SJuan Castillo /* BL2, BL31 and BL33 are mandatory */ 204*6f971622SJuan Castillo if (certs[BL2_CERT].bin == NULL) { 205*6f971622SJuan Castillo ERROR("BL2 image not specified\n"); 206*6f971622SJuan Castillo exit(1); 207*6f971622SJuan Castillo } 208*6f971622SJuan Castillo 209*6f971622SJuan Castillo if (certs[BL31_CERT].bin == NULL) { 210*6f971622SJuan Castillo ERROR("BL31 image not specified\n"); 211*6f971622SJuan Castillo exit(1); 212*6f971622SJuan Castillo } 213*6f971622SJuan Castillo 214*6f971622SJuan Castillo if (certs[BL33_CERT].bin == NULL) { 215*6f971622SJuan Castillo ERROR("BL33 image not specified\n"); 216*6f971622SJuan Castillo exit(1); 217*6f971622SJuan Castillo } 218*6f971622SJuan Castillo 219*6f971622SJuan Castillo /* BL30 and BL32 are optional */ 220*6f971622SJuan Castillo if (certs[BL30_CERT].bin != NULL) { 221*6f971622SJuan Castillo bl30_present = 1; 222*6f971622SJuan Castillo } 223*6f971622SJuan Castillo 224*6f971622SJuan Castillo if (certs[BL32_CERT].bin != NULL) { 225*6f971622SJuan Castillo bl32_present = 1; 226*6f971622SJuan Castillo } 227*6f971622SJuan Castillo 228*6f971622SJuan Castillo /* TODO: Certificate filenames */ 229*6f971622SJuan Castillo 230*6f971622SJuan Castillo /* Filenames to store keys must be specified */ 231*6f971622SJuan Castillo if (save_keys || !new_keys) { 232*6f971622SJuan Castillo if (keys[ROT_KEY].fn == NULL) { 233*6f971622SJuan Castillo ERROR("ROT key not specified\n"); 234*6f971622SJuan Castillo exit(1); 235*6f971622SJuan Castillo } 236*6f971622SJuan Castillo 237*6f971622SJuan Castillo if (keys[TRUSTED_WORLD_KEY].fn == NULL) { 238*6f971622SJuan Castillo ERROR("Trusted World key not specified\n"); 239*6f971622SJuan Castillo exit(1); 240*6f971622SJuan Castillo } 241*6f971622SJuan Castillo 242*6f971622SJuan Castillo if (keys[NON_TRUSTED_WORLD_KEY].fn == NULL) { 243*6f971622SJuan Castillo ERROR("Non-trusted World key not specified\n"); 244*6f971622SJuan Castillo exit(1); 245*6f971622SJuan Castillo } 246*6f971622SJuan Castillo 247*6f971622SJuan Castillo if (keys[BL31_KEY].fn == NULL) { 248*6f971622SJuan Castillo ERROR("BL31 key not specified\n"); 249*6f971622SJuan Castillo exit(1); 250*6f971622SJuan Castillo } 251*6f971622SJuan Castillo 252*6f971622SJuan Castillo if (keys[BL33_KEY].fn == NULL) { 253*6f971622SJuan Castillo ERROR("BL33 key not specified\n"); 254*6f971622SJuan Castillo exit(1); 255*6f971622SJuan Castillo } 256*6f971622SJuan Castillo 257*6f971622SJuan Castillo if (bl30_present && (keys[BL30_KEY].fn == NULL)) { 258*6f971622SJuan Castillo ERROR("BL30 key not specified\n"); 259*6f971622SJuan Castillo exit(1); 260*6f971622SJuan Castillo } 261*6f971622SJuan Castillo 262*6f971622SJuan Castillo if (bl32_present && (keys[BL32_KEY].fn == NULL)) { 263*6f971622SJuan Castillo ERROR("BL32 key not specified\n"); 264*6f971622SJuan Castillo exit(1); 265*6f971622SJuan Castillo } 266*6f971622SJuan Castillo } 267*6f971622SJuan Castillo } 268*6f971622SJuan Castillo 269*6f971622SJuan Castillo int main(int argc, char *argv[]) 270*6f971622SJuan Castillo { 271*6f971622SJuan Castillo STACK_OF(X509_EXTENSION) * sk = NULL; 272*6f971622SJuan Castillo X509_EXTENSION *hash_ext = NULL; 273*6f971622SJuan Castillo X509_EXTENSION *nvctr_ext = NULL; 274*6f971622SJuan Castillo X509_EXTENSION *trusted_key_ext = NULL; 275*6f971622SJuan Castillo X509_EXTENSION *non_trusted_key_ext = NULL; 276*6f971622SJuan Castillo FILE *file = NULL; 277*6f971622SJuan Castillo int i, tz_nvctr_nid, ntz_nvctr_nid, hash_nid, pk_nid; 278*6f971622SJuan Castillo int c, opt_idx = 0; 279*6f971622SJuan Castillo unsigned char md[SHA256_DIGEST_LENGTH]; 280*6f971622SJuan Castillo 281*6f971622SJuan Castillo NOTICE("CoT Generation Tool: %s\n", build_msg); 282*6f971622SJuan Castillo NOTICE("Target platform: %s\n", platform_msg); 283*6f971622SJuan Castillo 284*6f971622SJuan Castillo while (1) { 285*6f971622SJuan Castillo /* getopt_long stores the option index here. */ 286*6f971622SJuan Castillo c = getopt_long(argc, argv, "hknp", long_opt, &opt_idx); 287*6f971622SJuan Castillo 288*6f971622SJuan Castillo /* Detect the end of the options. */ 289*6f971622SJuan Castillo if (c == -1) { 290*6f971622SJuan Castillo break; 291*6f971622SJuan Castillo } 292*6f971622SJuan Castillo 293*6f971622SJuan Castillo switch (c) { 294*6f971622SJuan Castillo case 'h': 295*6f971622SJuan Castillo print_help(argv[0]); 296*6f971622SJuan Castillo break; 297*6f971622SJuan Castillo case 'k': 298*6f971622SJuan Castillo save_keys = 1; 299*6f971622SJuan Castillo break; 300*6f971622SJuan Castillo case 'n': 301*6f971622SJuan Castillo new_keys = 1; 302*6f971622SJuan Castillo break; 303*6f971622SJuan Castillo case 'p': 304*6f971622SJuan Castillo print_cert = 1; 305*6f971622SJuan Castillo break; 306*6f971622SJuan Castillo case BL2_ID: 307*6f971622SJuan Castillo certs[BL2_CERT].bin = strdup(optarg); 308*6f971622SJuan Castillo break; 309*6f971622SJuan Castillo case BL30_ID: 310*6f971622SJuan Castillo certs[BL30_CERT].bin = strdup(optarg); 311*6f971622SJuan Castillo break; 312*6f971622SJuan Castillo case BL31_ID: 313*6f971622SJuan Castillo certs[BL31_CERT].bin = strdup(optarg); 314*6f971622SJuan Castillo break; 315*6f971622SJuan Castillo case BL32_ID: 316*6f971622SJuan Castillo certs[BL32_CERT].bin = strdup(optarg); 317*6f971622SJuan Castillo break; 318*6f971622SJuan Castillo case BL33_ID: 319*6f971622SJuan Castillo certs[BL33_CERT].bin = strdup(optarg); 320*6f971622SJuan Castillo break; 321*6f971622SJuan Castillo case BL2_CERT_ID: 322*6f971622SJuan Castillo certs[BL2_CERT].fn = strdup(optarg); 323*6f971622SJuan Castillo break; 324*6f971622SJuan Castillo case TRUSTED_KEY_CERT_ID: 325*6f971622SJuan Castillo certs[TRUSTED_KEY_CERT].fn = strdup(optarg); 326*6f971622SJuan Castillo break; 327*6f971622SJuan Castillo case BL30_KEY_CERT_ID: 328*6f971622SJuan Castillo certs[BL30_KEY_CERT].fn = strdup(optarg); 329*6f971622SJuan Castillo break; 330*6f971622SJuan Castillo case BL30_CERT_ID: 331*6f971622SJuan Castillo certs[BL30_CERT].fn = strdup(optarg); 332*6f971622SJuan Castillo break; 333*6f971622SJuan Castillo case BL31_KEY_CERT_ID: 334*6f971622SJuan Castillo certs[BL31_KEY_CERT].fn = strdup(optarg); 335*6f971622SJuan Castillo break; 336*6f971622SJuan Castillo case BL31_CERT_ID: 337*6f971622SJuan Castillo certs[BL31_CERT].fn = strdup(optarg); 338*6f971622SJuan Castillo break; 339*6f971622SJuan Castillo case BL32_KEY_CERT_ID: 340*6f971622SJuan Castillo certs[BL32_KEY_CERT].fn = strdup(optarg); 341*6f971622SJuan Castillo break; 342*6f971622SJuan Castillo case BL32_CERT_ID: 343*6f971622SJuan Castillo certs[BL32_CERT].fn = strdup(optarg); 344*6f971622SJuan Castillo break; 345*6f971622SJuan Castillo case BL33_KEY_CERT_ID: 346*6f971622SJuan Castillo certs[BL33_KEY_CERT].fn = strdup(optarg); 347*6f971622SJuan Castillo break; 348*6f971622SJuan Castillo case BL33_CERT_ID: 349*6f971622SJuan Castillo certs[BL33_CERT].fn = strdup(optarg); 350*6f971622SJuan Castillo break; 351*6f971622SJuan Castillo case ROT_KEY_ID: 352*6f971622SJuan Castillo keys[ROT_KEY].fn = strdup(optarg); 353*6f971622SJuan Castillo break; 354*6f971622SJuan Castillo case TRUSTED_WORLD_KEY_ID: 355*6f971622SJuan Castillo keys[TRUSTED_WORLD_KEY].fn = strdup(optarg); 356*6f971622SJuan Castillo break; 357*6f971622SJuan Castillo case NON_TRUSTED_WORLD_KEY_ID: 358*6f971622SJuan Castillo keys[NON_TRUSTED_WORLD_KEY].fn = strdup(optarg); 359*6f971622SJuan Castillo break; 360*6f971622SJuan Castillo case BL30_KEY_ID: 361*6f971622SJuan Castillo keys[BL30_KEY].fn = strdup(optarg); 362*6f971622SJuan Castillo break; 363*6f971622SJuan Castillo case BL31_KEY_ID: 364*6f971622SJuan Castillo keys[BL31_KEY].fn = strdup(optarg); 365*6f971622SJuan Castillo break; 366*6f971622SJuan Castillo case BL32_KEY_ID: 367*6f971622SJuan Castillo keys[BL32_KEY].fn = strdup(optarg); 368*6f971622SJuan Castillo break; 369*6f971622SJuan Castillo case BL33_KEY_ID: 370*6f971622SJuan Castillo keys[BL33_KEY].fn = strdup(optarg); 371*6f971622SJuan Castillo break; 372*6f971622SJuan Castillo case '?': 373*6f971622SJuan Castillo default: 374*6f971622SJuan Castillo printf("%s\n", optarg); 375*6f971622SJuan Castillo exit(1); 376*6f971622SJuan Castillo } 377*6f971622SJuan Castillo } 378*6f971622SJuan Castillo 379*6f971622SJuan Castillo /* Set the value of the NVCounters */ 380*6f971622SJuan Castillo tf_nvcounter = NVCOUNTER_VALUE; 381*6f971622SJuan Castillo non_tf_nvcounter = NVCOUNTER_VALUE; 382*6f971622SJuan Castillo 383*6f971622SJuan Castillo /* Check command line arguments */ 384*6f971622SJuan Castillo check_cmd_params(); 385*6f971622SJuan Castillo 386*6f971622SJuan Castillo /* Register the new types and OIDs for the extensions */ 387*6f971622SJuan Castillo if (ext_init(tbb_ext) != 0) { 388*6f971622SJuan Castillo ERROR("Cannot initialize TBB extensions\n"); 389*6f971622SJuan Castillo exit(1); 390*6f971622SJuan Castillo } 391*6f971622SJuan Castillo 392*6f971622SJuan Castillo /* Get non-volatile counters NIDs */ 393*6f971622SJuan Castillo CHECK_OID(tz_nvctr_nid, TZ_FW_NVCOUNTER_OID); 394*6f971622SJuan Castillo CHECK_OID(ntz_nvctr_nid, NTZ_FW_NVCOUNTER_OID); 395*6f971622SJuan Castillo 396*6f971622SJuan Castillo /* Load private keys from files (or generate new ones) */ 397*6f971622SJuan Castillo if (new_keys) { 398*6f971622SJuan Castillo for (i = 0 ; i < NUM_KEYS ; i++) { 399*6f971622SJuan Castillo if (!key_new(&keys[i])) { 400*6f971622SJuan Castillo ERROR("Error creating %s\n", keys[i].desc); 401*6f971622SJuan Castillo exit(1); 402*6f971622SJuan Castillo } 403*6f971622SJuan Castillo } 404*6f971622SJuan Castillo } else { 405*6f971622SJuan Castillo for (i = 0 ; i < NUM_KEYS ; i++) { 406*6f971622SJuan Castillo if (!key_load(&keys[i])) { 407*6f971622SJuan Castillo ERROR("Error loading %s\n", keys[i].desc); 408*6f971622SJuan Castillo exit(1); 409*6f971622SJuan Castillo } 410*6f971622SJuan Castillo } 411*6f971622SJuan Castillo } 412*6f971622SJuan Castillo 413*6f971622SJuan Castillo /* ********************************************************************* 414*6f971622SJuan Castillo * BL2 certificate (Trusted Boot Firmware certificate): 415*6f971622SJuan Castillo * - Self-signed with OEM ROT private key 416*6f971622SJuan Castillo * - Extensions: 417*6f971622SJuan Castillo * - TrustedFirmwareNVCounter (TODO) 418*6f971622SJuan Castillo * - BL2 hash 419*6f971622SJuan Castillo **********************************************************************/ 420*6f971622SJuan Castillo CHECK_NULL(sk, sk_X509_EXTENSION_new_null()); 421*6f971622SJuan Castillo 422*6f971622SJuan Castillo /* Add the NVCounter as a critical extension */ 423*6f971622SJuan Castillo CHECK_NULL(nvctr_ext, ext_new_nvcounter(tz_nvctr_nid, EXT_CRIT, 424*6f971622SJuan Castillo tf_nvcounter)); 425*6f971622SJuan Castillo sk_X509_EXTENSION_push(sk, nvctr_ext); 426*6f971622SJuan Castillo 427*6f971622SJuan Castillo /* Add hash of BL2 as an extension */ 428*6f971622SJuan Castillo if (!sha_file(certs[BL2_CERT].bin, md)) { 429*6f971622SJuan Castillo ERROR("Cannot calculate the hash of %s\n", certs[BL2_CERT].bin); 430*6f971622SJuan Castillo exit(1); 431*6f971622SJuan Castillo } 432*6f971622SJuan Castillo CHECK_OID(hash_nid, BL2_HASH_OID); 433*6f971622SJuan Castillo CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md, 434*6f971622SJuan Castillo SHA256_DIGEST_LENGTH)); 435*6f971622SJuan Castillo sk_X509_EXTENSION_push(sk, hash_ext); 436*6f971622SJuan Castillo 437*6f971622SJuan Castillo /* Create certificate. Signed with ROT key */ 438*6f971622SJuan Castillo if (!cert_new(&certs[BL2_CERT], VAL_DAYS, 0, sk)) { 439*6f971622SJuan Castillo ERROR("Cannot create %s\n", certs[BL2_CERT].cn); 440*6f971622SJuan Castillo exit(1); 441*6f971622SJuan Castillo } 442*6f971622SJuan Castillo sk_X509_EXTENSION_free(sk); 443*6f971622SJuan Castillo 444*6f971622SJuan Castillo /* ********************************************************************* 445*6f971622SJuan Castillo * Trusted Key certificate: 446*6f971622SJuan Castillo * - Self-signed with OEM ROT private key 447*6f971622SJuan Castillo * - Extensions: 448*6f971622SJuan Castillo * - TrustedFirmwareNVCounter (TODO) 449*6f971622SJuan Castillo * - TrustedWorldPK 450*6f971622SJuan Castillo * - NonTrustedWorldPK 451*6f971622SJuan Castillo **********************************************************************/ 452*6f971622SJuan Castillo CHECK_NULL(sk, sk_X509_EXTENSION_new_null()); 453*6f971622SJuan Castillo CHECK_NULL(nvctr_ext, ext_new_nvcounter(tz_nvctr_nid, EXT_CRIT, 454*6f971622SJuan Castillo tf_nvcounter)); 455*6f971622SJuan Castillo sk_X509_EXTENSION_push(sk, nvctr_ext); 456*6f971622SJuan Castillo CHECK_OID(pk_nid, TZ_WORLD_PK_OID); 457*6f971622SJuan Castillo CHECK_NULL(trusted_key_ext, ext_new_key(pk_nid, EXT_CRIT, 458*6f971622SJuan Castillo keys[TRUSTED_WORLD_KEY].key)); 459*6f971622SJuan Castillo sk_X509_EXTENSION_push(sk, trusted_key_ext); 460*6f971622SJuan Castillo CHECK_OID(pk_nid, NTZ_WORLD_PK_OID); 461*6f971622SJuan Castillo CHECK_NULL(non_trusted_key_ext, ext_new_key(pk_nid, EXT_CRIT, 462*6f971622SJuan Castillo keys[NON_TRUSTED_WORLD_KEY].key)); 463*6f971622SJuan Castillo sk_X509_EXTENSION_push(sk, non_trusted_key_ext); 464*6f971622SJuan Castillo if (!cert_new(&certs[TRUSTED_KEY_CERT], VAL_DAYS, 0, sk)) { 465*6f971622SJuan Castillo ERROR("Cannot create %s\n", certs[TRUSTED_KEY_CERT].cn); 466*6f971622SJuan Castillo exit(1); 467*6f971622SJuan Castillo } 468*6f971622SJuan Castillo sk_X509_EXTENSION_free(sk); 469*6f971622SJuan Castillo 470*6f971622SJuan Castillo /* ********************************************************************* 471*6f971622SJuan Castillo * BL30 Key certificate (Trusted SCP Firmware Key certificate): 472*6f971622SJuan Castillo * - Self-signed with Trusted World key 473*6f971622SJuan Castillo * - Extensions: 474*6f971622SJuan Castillo * - TrustedFirmwareNVCounter (TODO) 475*6f971622SJuan Castillo * - SCPFirmwareContentCertPK 476*6f971622SJuan Castillo **********************************************************************/ 477*6f971622SJuan Castillo if (bl30_present) { 478*6f971622SJuan Castillo CHECK_NULL(sk, sk_X509_EXTENSION_new_null()); 479*6f971622SJuan Castillo CHECK_NULL(nvctr_ext, ext_new_nvcounter(tz_nvctr_nid, EXT_CRIT, 480*6f971622SJuan Castillo tf_nvcounter)); 481*6f971622SJuan Castillo sk_X509_EXTENSION_push(sk, nvctr_ext); 482*6f971622SJuan Castillo CHECK_OID(pk_nid, BL30_CONTENT_CERT_PK_OID); 483*6f971622SJuan Castillo CHECK_NULL(trusted_key_ext, ext_new_key(pk_nid, EXT_CRIT, 484*6f971622SJuan Castillo keys[BL30_KEY].key)); 485*6f971622SJuan Castillo sk_X509_EXTENSION_push(sk, trusted_key_ext); 486*6f971622SJuan Castillo if (!cert_new(&certs[BL30_KEY_CERT], VAL_DAYS, 0, sk)) { 487*6f971622SJuan Castillo ERROR("Cannot create %s\n", certs[BL30_KEY_CERT].cn); 488*6f971622SJuan Castillo exit(1); 489*6f971622SJuan Castillo } 490*6f971622SJuan Castillo sk_X509_EXTENSION_free(sk); 491*6f971622SJuan Castillo } 492*6f971622SJuan Castillo 493*6f971622SJuan Castillo /* ********************************************************************* 494*6f971622SJuan Castillo * BL30 certificate (SCP Firmware Content certificate): 495*6f971622SJuan Castillo * - Signed with Trusted World Key 496*6f971622SJuan Castillo * - Extensions: 497*6f971622SJuan Castillo * - TrustedFirmwareNVCounter (TODO) 498*6f971622SJuan Castillo * - SCPFirmwareHash 499*6f971622SJuan Castillo **********************************************************************/ 500*6f971622SJuan Castillo if (bl30_present) { 501*6f971622SJuan Castillo CHECK_NULL(sk, sk_X509_EXTENSION_new_null()); 502*6f971622SJuan Castillo CHECK_NULL(nvctr_ext, ext_new_nvcounter(tz_nvctr_nid, EXT_CRIT, 503*6f971622SJuan Castillo tf_nvcounter)); 504*6f971622SJuan Castillo sk_X509_EXTENSION_push(sk, nvctr_ext); 505*6f971622SJuan Castillo 506*6f971622SJuan Castillo if (!sha_file(certs[BL30_CERT].bin, md)) { 507*6f971622SJuan Castillo ERROR("Cannot calculate the hash of %s\n", 508*6f971622SJuan Castillo certs[BL30_CERT].bin); 509*6f971622SJuan Castillo exit(1); 510*6f971622SJuan Castillo } 511*6f971622SJuan Castillo CHECK_OID(hash_nid, BL30_HASH_OID); 512*6f971622SJuan Castillo CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md, 513*6f971622SJuan Castillo SHA256_DIGEST_LENGTH)); 514*6f971622SJuan Castillo sk_X509_EXTENSION_push(sk, hash_ext); 515*6f971622SJuan Castillo 516*6f971622SJuan Castillo if (!cert_new(&certs[BL30_CERT], VAL_DAYS, 0, sk)) { 517*6f971622SJuan Castillo ERROR("Cannot create %s\n", certs[BL30_CERT].cn); 518*6f971622SJuan Castillo exit(1); 519*6f971622SJuan Castillo } 520*6f971622SJuan Castillo 521*6f971622SJuan Castillo sk_X509_EXTENSION_free(sk); 522*6f971622SJuan Castillo } 523*6f971622SJuan Castillo 524*6f971622SJuan Castillo /* ********************************************************************* 525*6f971622SJuan Castillo * BL31 Key certificate (Trusted SoC Firmware Key certificate): 526*6f971622SJuan Castillo * - Self-signed with Trusted World key 527*6f971622SJuan Castillo * - Extensions: 528*6f971622SJuan Castillo * - TrustedFirmwareNVCounter (TODO) 529*6f971622SJuan Castillo * - SoCFirmwareContentCertPK 530*6f971622SJuan Castillo **********************************************************************/ 531*6f971622SJuan Castillo CHECK_NULL(sk, sk_X509_EXTENSION_new_null()); 532*6f971622SJuan Castillo CHECK_NULL(nvctr_ext, ext_new_nvcounter(tz_nvctr_nid, EXT_CRIT, 533*6f971622SJuan Castillo tf_nvcounter)); 534*6f971622SJuan Castillo sk_X509_EXTENSION_push(sk, nvctr_ext); 535*6f971622SJuan Castillo CHECK_OID(pk_nid, BL31_CONTENT_CERT_PK_OID); 536*6f971622SJuan Castillo CHECK_NULL(trusted_key_ext, ext_new_key(pk_nid, EXT_CRIT, 537*6f971622SJuan Castillo keys[BL31_KEY].key)); 538*6f971622SJuan Castillo sk_X509_EXTENSION_push(sk, trusted_key_ext); 539*6f971622SJuan Castillo if (!cert_new(&certs[BL31_KEY_CERT], VAL_DAYS, 0, sk)) { 540*6f971622SJuan Castillo ERROR("Cannot create %s\n", certs[BL31_KEY_CERT].cn); 541*6f971622SJuan Castillo exit(1); 542*6f971622SJuan Castillo } 543*6f971622SJuan Castillo sk_X509_EXTENSION_free(sk); 544*6f971622SJuan Castillo 545*6f971622SJuan Castillo /* ********************************************************************* 546*6f971622SJuan Castillo * BL31 certificate (SOC Firmware Content certificate): 547*6f971622SJuan Castillo * - Signed with Trusted World Key 548*6f971622SJuan Castillo * - Extensions: 549*6f971622SJuan Castillo * - TrustedFirmwareNVCounter (TODO) 550*6f971622SJuan Castillo * - BL31 hash 551*6f971622SJuan Castillo **********************************************************************/ 552*6f971622SJuan Castillo CHECK_NULL(sk, sk_X509_EXTENSION_new_null()); 553*6f971622SJuan Castillo CHECK_NULL(nvctr_ext, ext_new_nvcounter(tz_nvctr_nid, EXT_CRIT, 554*6f971622SJuan Castillo tf_nvcounter)); 555*6f971622SJuan Castillo sk_X509_EXTENSION_push(sk, nvctr_ext); 556*6f971622SJuan Castillo 557*6f971622SJuan Castillo if (!sha_file(certs[BL31_CERT].bin, md)) { 558*6f971622SJuan Castillo ERROR("Cannot calculate the hash of %s\n", certs[BL31_CERT].bin); 559*6f971622SJuan Castillo exit(1); 560*6f971622SJuan Castillo } 561*6f971622SJuan Castillo CHECK_OID(hash_nid, BL31_HASH_OID); 562*6f971622SJuan Castillo CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md, 563*6f971622SJuan Castillo SHA256_DIGEST_LENGTH)); 564*6f971622SJuan Castillo sk_X509_EXTENSION_push(sk, hash_ext); 565*6f971622SJuan Castillo 566*6f971622SJuan Castillo if (!cert_new(&certs[BL31_CERT], VAL_DAYS, 0, sk)) { 567*6f971622SJuan Castillo ERROR("Cannot create %s\n", certs[BL31_CERT].cn); 568*6f971622SJuan Castillo exit(1); 569*6f971622SJuan Castillo } 570*6f971622SJuan Castillo 571*6f971622SJuan Castillo sk_X509_EXTENSION_free(sk); 572*6f971622SJuan Castillo 573*6f971622SJuan Castillo /* ********************************************************************* 574*6f971622SJuan Castillo * BL32 Key certificate (Trusted OS Firmware Key certificate): 575*6f971622SJuan Castillo * - Self-signed with Trusted World key 576*6f971622SJuan Castillo * - Extensions: 577*6f971622SJuan Castillo * - TrustedFirmwareNVCounter (TODO) 578*6f971622SJuan Castillo * - TrustedOSFirmwareContentCertPK 579*6f971622SJuan Castillo **********************************************************************/ 580*6f971622SJuan Castillo if (bl32_present) { 581*6f971622SJuan Castillo CHECK_NULL(sk, sk_X509_EXTENSION_new_null()); 582*6f971622SJuan Castillo CHECK_NULL(nvctr_ext, ext_new_nvcounter(tz_nvctr_nid, EXT_CRIT, 583*6f971622SJuan Castillo tf_nvcounter)); 584*6f971622SJuan Castillo sk_X509_EXTENSION_push(sk, nvctr_ext); 585*6f971622SJuan Castillo CHECK_OID(pk_nid, BL32_CONTENT_CERT_PK_OID); 586*6f971622SJuan Castillo CHECK_NULL(trusted_key_ext, ext_new_key(pk_nid, EXT_CRIT, 587*6f971622SJuan Castillo keys[BL32_KEY].key)); 588*6f971622SJuan Castillo sk_X509_EXTENSION_push(sk, trusted_key_ext); 589*6f971622SJuan Castillo if (!cert_new(&certs[BL32_KEY_CERT], VAL_DAYS, 0, sk)) { 590*6f971622SJuan Castillo ERROR("Cannot create %s\n", certs[BL32_KEY_CERT].cn); 591*6f971622SJuan Castillo exit(1); 592*6f971622SJuan Castillo } 593*6f971622SJuan Castillo sk_X509_EXTENSION_free(sk); 594*6f971622SJuan Castillo } 595*6f971622SJuan Castillo 596*6f971622SJuan Castillo /* ********************************************************************* 597*6f971622SJuan Castillo * BL32 certificate (TrustedOS Firmware Content certificate): 598*6f971622SJuan Castillo * - Signed with Trusted World Key 599*6f971622SJuan Castillo * - Extensions: 600*6f971622SJuan Castillo * - TrustedFirmwareNVCounter (TODO) 601*6f971622SJuan Castillo * - BL32 hash 602*6f971622SJuan Castillo **********************************************************************/ 603*6f971622SJuan Castillo if (bl32_present) { 604*6f971622SJuan Castillo CHECK_NULL(sk, sk_X509_EXTENSION_new_null()); 605*6f971622SJuan Castillo CHECK_NULL(nvctr_ext, ext_new_nvcounter(tz_nvctr_nid, EXT_CRIT, 606*6f971622SJuan Castillo tf_nvcounter)); 607*6f971622SJuan Castillo sk_X509_EXTENSION_push(sk, nvctr_ext); 608*6f971622SJuan Castillo 609*6f971622SJuan Castillo if (!sha_file(certs[BL32_CERT].bin, md)) { 610*6f971622SJuan Castillo ERROR("Cannot calculate the hash of %s\n", 611*6f971622SJuan Castillo certs[BL32_CERT].bin); 612*6f971622SJuan Castillo exit(1); 613*6f971622SJuan Castillo } 614*6f971622SJuan Castillo CHECK_OID(hash_nid, BL32_HASH_OID); 615*6f971622SJuan Castillo CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md, 616*6f971622SJuan Castillo SHA256_DIGEST_LENGTH)); 617*6f971622SJuan Castillo sk_X509_EXTENSION_push(sk, hash_ext); 618*6f971622SJuan Castillo 619*6f971622SJuan Castillo if (!cert_new(&certs[BL32_CERT], VAL_DAYS, 0, sk)) { 620*6f971622SJuan Castillo ERROR("Cannot create %s\n", certs[BL32_CERT].cn); 621*6f971622SJuan Castillo exit(1); 622*6f971622SJuan Castillo } 623*6f971622SJuan Castillo 624*6f971622SJuan Castillo sk_X509_EXTENSION_free(sk); 625*6f971622SJuan Castillo } 626*6f971622SJuan Castillo 627*6f971622SJuan Castillo /* ********************************************************************* 628*6f971622SJuan Castillo * BL33 Key certificate (Non Trusted Firmware Key certificate): 629*6f971622SJuan Castillo * - Self-signed with Non Trusted World key 630*6f971622SJuan Castillo * - Extensions: 631*6f971622SJuan Castillo * - NonTrustedFirmwareNVCounter (TODO) 632*6f971622SJuan Castillo * - NonTrustedFirmwareContentCertPK 633*6f971622SJuan Castillo **********************************************************************/ 634*6f971622SJuan Castillo CHECK_NULL(sk, sk_X509_EXTENSION_new_null()); 635*6f971622SJuan Castillo CHECK_NULL(nvctr_ext, ext_new_nvcounter(ntz_nvctr_nid, EXT_CRIT, 636*6f971622SJuan Castillo non_tf_nvcounter)); 637*6f971622SJuan Castillo sk_X509_EXTENSION_push(sk, nvctr_ext); 638*6f971622SJuan Castillo CHECK_OID(pk_nid, BL33_CONTENT_CERT_PK_OID); 639*6f971622SJuan Castillo CHECK_NULL(non_trusted_key_ext, ext_new_key(pk_nid, EXT_CRIT, 640*6f971622SJuan Castillo keys[BL33_KEY].key)); 641*6f971622SJuan Castillo sk_X509_EXTENSION_push(sk, non_trusted_key_ext); 642*6f971622SJuan Castillo if (!cert_new(&certs[BL33_KEY_CERT], VAL_DAYS, 0, sk)) { 643*6f971622SJuan Castillo ERROR("Cannot create %s\n", certs[BL33_KEY_CERT].cn); 644*6f971622SJuan Castillo exit(1); 645*6f971622SJuan Castillo } 646*6f971622SJuan Castillo sk_X509_EXTENSION_free(sk); 647*6f971622SJuan Castillo 648*6f971622SJuan Castillo /* ********************************************************************* 649*6f971622SJuan Castillo * BL33 certificate (Non-Trusted World Content certificate): 650*6f971622SJuan Castillo * - Signed with Non-Trusted World Key 651*6f971622SJuan Castillo * - Extensions: 652*6f971622SJuan Castillo * - NonTrustedFirmwareNVCounter (TODO) 653*6f971622SJuan Castillo * - BL33 hash 654*6f971622SJuan Castillo **********************************************************************/ 655*6f971622SJuan Castillo CHECK_NULL(sk, sk_X509_EXTENSION_new_null()); 656*6f971622SJuan Castillo CHECK_NULL(nvctr_ext, ext_new_nvcounter(ntz_nvctr_nid, EXT_CRIT, 657*6f971622SJuan Castillo non_tf_nvcounter)); 658*6f971622SJuan Castillo sk_X509_EXTENSION_push(sk, nvctr_ext); 659*6f971622SJuan Castillo 660*6f971622SJuan Castillo if (!sha_file(certs[BL33_CERT].bin, md)) { 661*6f971622SJuan Castillo ERROR("Cannot calculate the hash of %s\n", certs[BL33_CERT].bin); 662*6f971622SJuan Castillo exit(1); 663*6f971622SJuan Castillo } 664*6f971622SJuan Castillo CHECK_OID(hash_nid, BL33_HASH_OID); 665*6f971622SJuan Castillo CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md, 666*6f971622SJuan Castillo SHA256_DIGEST_LENGTH)); 667*6f971622SJuan Castillo sk_X509_EXTENSION_push(sk, hash_ext); 668*6f971622SJuan Castillo 669*6f971622SJuan Castillo if (!cert_new(&certs[BL33_CERT], VAL_DAYS, 0, sk)) { 670*6f971622SJuan Castillo ERROR("Cannot create %s\n", certs[BL33_CERT].cn); 671*6f971622SJuan Castillo exit(1); 672*6f971622SJuan Castillo } 673*6f971622SJuan Castillo sk_X509_EXTENSION_free(sk); 674*6f971622SJuan Castillo 675*6f971622SJuan Castillo /* Print the certificates */ 676*6f971622SJuan Castillo if (print_cert) { 677*6f971622SJuan Castillo for (i = 0 ; i < NUM_CERTIFICATES ; i++) { 678*6f971622SJuan Castillo if (!certs[i].x) { 679*6f971622SJuan Castillo continue; 680*6f971622SJuan Castillo } 681*6f971622SJuan Castillo printf("\n\n=====================================\n\n"); 682*6f971622SJuan Castillo X509_print_fp(stdout, certs[i].x); 683*6f971622SJuan Castillo } 684*6f971622SJuan Castillo } 685*6f971622SJuan Castillo 686*6f971622SJuan Castillo /* Save created certificates to files */ 687*6f971622SJuan Castillo for (i = 0 ; i < NUM_CERTIFICATES ; i++) { 688*6f971622SJuan Castillo if (certs[i].x && certs[i].fn) { 689*6f971622SJuan Castillo file = fopen(certs[i].fn, "w"); 690*6f971622SJuan Castillo if (file != NULL) { 691*6f971622SJuan Castillo i2d_X509_fp(file, certs[i].x); 692*6f971622SJuan Castillo fclose(file); 693*6f971622SJuan Castillo } else { 694*6f971622SJuan Castillo ERROR("Cannot create file %s\n", certs[i].fn); 695*6f971622SJuan Castillo } 696*6f971622SJuan Castillo } 697*6f971622SJuan Castillo } 698*6f971622SJuan Castillo 699*6f971622SJuan Castillo /* Save keys */ 700*6f971622SJuan Castillo if (save_keys) { 701*6f971622SJuan Castillo for (i = 0 ; i < NUM_KEYS ; i++) { 702*6f971622SJuan Castillo if (!key_store(&keys[i])) { 703*6f971622SJuan Castillo ERROR("Cannot save %s\n", keys[i].desc); 704*6f971622SJuan Castillo } 705*6f971622SJuan Castillo } 706*6f971622SJuan Castillo } 707*6f971622SJuan Castillo 708*6f971622SJuan Castillo X509_EXTENSION_free(hash_ext); 709*6f971622SJuan Castillo X509_EXTENSION_free(nvctr_ext); 710*6f971622SJuan Castillo X509_EXTENSION_free(trusted_key_ext); 711*6f971622SJuan Castillo X509_EXTENSION_free(non_trusted_key_ext); 712*6f971622SJuan Castillo 713*6f971622SJuan Castillo #ifndef OPENSSL_NO_ENGINE 714*6f971622SJuan Castillo ENGINE_cleanup(); 715*6f971622SJuan Castillo #endif 716*6f971622SJuan Castillo CRYPTO_cleanup_all_ex_data(); 717*6f971622SJuan Castillo 718*6f971622SJuan Castillo return 0; 719*6f971622SJuan Castillo } 720