xref: /rk3399_ARM-atf/tools/cert_create/src/main.c (revision cebe1f238fff5ad7eadb42dd1abd3ec897c27e64)
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 
316f971622SJuan Castillo #include <getopt.h>
326f971622SJuan Castillo #include <stdio.h>
336f971622SJuan Castillo #include <stdlib.h>
346f971622SJuan Castillo #include <string.h>
356f971622SJuan Castillo 
366f971622SJuan Castillo #include <openssl/conf.h>
376f971622SJuan Castillo #include <openssl/engine.h>
386f971622SJuan Castillo #include <openssl/err.h>
396f971622SJuan Castillo #include <openssl/pem.h>
406f971622SJuan Castillo #include <openssl/sha.h>
416f971622SJuan Castillo #include <openssl/x509v3.h>
426f971622SJuan Castillo 
436f971622SJuan Castillo #include "cert.h"
44ad2c1a9aSJuan Castillo #include "cmd_opt.h"
456f971622SJuan Castillo #include "debug.h"
466f971622SJuan Castillo #include "ext.h"
476f971622SJuan Castillo #include "key.h"
486f971622SJuan Castillo #include "platform_oid.h"
496f971622SJuan Castillo #include "sha.h"
5055e291a4SJuan Castillo #include "tbbr/tbb_ext.h"
5155e291a4SJuan Castillo #include "tbbr/tbb_cert.h"
5255e291a4SJuan Castillo #include "tbbr/tbb_key.h"
536f971622SJuan Castillo 
546f971622SJuan Castillo /*
556f971622SJuan Castillo  * Helper macros to simplify the code. This macro assigns the return value of
566f971622SJuan Castillo  * the 'fn' function to 'v' and exits if the value is NULL.
576f971622SJuan Castillo  */
586f971622SJuan Castillo #define CHECK_NULL(v, fn) \
596f971622SJuan Castillo 	do { \
606f971622SJuan Castillo 		v = fn; \
616f971622SJuan Castillo 		if (v == NULL) { \
626f971622SJuan Castillo 			ERROR("NULL object at %s:%d\n", __FILE__, __LINE__); \
636f971622SJuan Castillo 			exit(1); \
646f971622SJuan Castillo 		} \
656f971622SJuan Castillo 	} while (0)
666f971622SJuan Castillo 
676f971622SJuan Castillo /*
686f971622SJuan Castillo  * This macro assigns the NID corresponding to 'oid' to 'v' and exits if the
696f971622SJuan Castillo  * NID is undefined.
706f971622SJuan Castillo  */
716f971622SJuan Castillo #define CHECK_OID(v, oid) \
726f971622SJuan Castillo 	do { \
736f971622SJuan Castillo 		v = OBJ_txt2nid(oid); \
746f971622SJuan Castillo 		if (v == NID_undef) { \
756f971622SJuan Castillo 			ERROR("Cannot find TBB extension %s\n", oid); \
766f971622SJuan Castillo 			exit(1); \
776f971622SJuan Castillo 		} \
786f971622SJuan Castillo 	} while (0)
796f971622SJuan Castillo 
806f971622SJuan Castillo #define MAX_FILENAME_LEN		1024
816f971622SJuan Castillo #define VAL_DAYS			7300
826f971622SJuan Castillo #define ID_TO_BIT_MASK(id)		(1 << id)
83ccbf890eSJuan Castillo #define NUM_ELEM(x)			((sizeof(x)) / (sizeof(x[0])))
846f971622SJuan Castillo 
856f971622SJuan Castillo /* Files */
866f971622SJuan Castillo enum {
876f971622SJuan Castillo 	/* Image file names (inputs) */
886f971622SJuan Castillo 	BL2_ID = 0,
896f971622SJuan Castillo 	BL30_ID,
906f971622SJuan Castillo 	BL31_ID,
916f971622SJuan Castillo 	BL32_ID,
926f971622SJuan Castillo 	BL33_ID,
936f971622SJuan Castillo 	/* Certificate file names (outputs) */
946f971622SJuan Castillo 	BL2_CERT_ID,
956f971622SJuan Castillo 	TRUSTED_KEY_CERT_ID,
966f971622SJuan Castillo 	BL30_KEY_CERT_ID,
976f971622SJuan Castillo 	BL30_CERT_ID,
986f971622SJuan Castillo 	BL31_KEY_CERT_ID,
996f971622SJuan Castillo 	BL31_CERT_ID,
1006f971622SJuan Castillo 	BL32_KEY_CERT_ID,
1016f971622SJuan Castillo 	BL32_CERT_ID,
1026f971622SJuan Castillo 	BL33_KEY_CERT_ID,
1036f971622SJuan Castillo 	BL33_CERT_ID,
1046f971622SJuan Castillo 	/* Key file names (input/output) */
1056f971622SJuan Castillo 	ROT_KEY_ID,
1066f971622SJuan Castillo 	TRUSTED_WORLD_KEY_ID,
1076f971622SJuan Castillo 	NON_TRUSTED_WORLD_KEY_ID,
1086f971622SJuan Castillo 	BL30_KEY_ID,
1096f971622SJuan Castillo 	BL31_KEY_ID,
1106f971622SJuan Castillo 	BL32_KEY_ID,
1116f971622SJuan Castillo 	BL33_KEY_ID,
1126f971622SJuan Castillo 	NUM_OPTS
1136f971622SJuan Castillo };
1146f971622SJuan Castillo 
1156f971622SJuan Castillo /* Global options */
116ccbf890eSJuan Castillo static int key_alg;
1176f971622SJuan Castillo static int new_keys;
1186f971622SJuan Castillo static int save_keys;
1196f971622SJuan Castillo static int print_cert;
1206f971622SJuan Castillo 
1216f971622SJuan Castillo /* Info messages created in the Makefile */
1226f971622SJuan Castillo extern const char build_msg[];
1236f971622SJuan Castillo extern const char platform_msg[];
1246f971622SJuan Castillo 
1256f971622SJuan Castillo 
1266f971622SJuan Castillo static char *strdup(const char *str)
1276f971622SJuan Castillo {
1286f971622SJuan Castillo 	int n = strlen(str) + 1;
1296f971622SJuan Castillo 	char *dup = malloc(n);
1306f971622SJuan Castillo 	if (dup) {
1316f971622SJuan Castillo 		strcpy(dup, str);
1326f971622SJuan Castillo 	}
1336f971622SJuan Castillo 	return dup;
1346f971622SJuan Castillo }
1356f971622SJuan Castillo 
136ccbf890eSJuan Castillo static const char *key_algs_str[] = {
137ccbf890eSJuan Castillo 	[KEY_ALG_RSA] = "rsa",
138ed2a76eaSJuan Castillo #ifndef OPENSSL_NO_EC
139ccbf890eSJuan Castillo 	[KEY_ALG_ECDSA] = "ecdsa"
140ed2a76eaSJuan Castillo #endif /* OPENSSL_NO_EC */
141ccbf890eSJuan Castillo };
142ccbf890eSJuan Castillo 
143ad2c1a9aSJuan Castillo static void print_help(const char *cmd, const struct option *long_opt)
1446f971622SJuan Castillo {
1456f971622SJuan Castillo 	int i = 0;
1466f971622SJuan Castillo 	printf("\n\n");
1476f971622SJuan Castillo 	printf("The certificate generation tool loads the binary images and\n"
1486f971622SJuan Castillo 	       "optionally the RSA keys, and outputs the key and content\n"
1496f971622SJuan Castillo 	       "certificates properly signed to implement the chain of trust.\n"
1506f971622SJuan Castillo 	       "If keys are provided, they must be in PEM format.\n"
1516f971622SJuan Castillo 	       "Certificates are generated in DER format.\n");
1526f971622SJuan Castillo 	printf("\n");
1536f971622SJuan Castillo 	printf("Usage:\n\n");
1546f971622SJuan Castillo 	printf("    %s [-hknp] \\\n", cmd);
1556f971622SJuan Castillo 	for (i = 0; i < NUM_OPTS; i++) {
1566f971622SJuan Castillo 		printf("        --%s <file>  \\\n", long_opt[i].name);
1576f971622SJuan Castillo 	}
1586f971622SJuan Castillo 	printf("\n");
159ccbf890eSJuan Castillo 	printf("-a    Key algorithm: rsa (default), ecdsa\n");
1606f971622SJuan Castillo 	printf("-h    Print help and exit\n");
1616f971622SJuan Castillo 	printf("-k    Save key pairs into files. Filenames must be provided\n");
1626f971622SJuan Castillo 	printf("-n    Generate new key pairs if no key files are provided\n");
1636f971622SJuan Castillo 	printf("-p    Print the certificates in the standard output\n");
1646f971622SJuan Castillo 	printf("\n");
1656f971622SJuan Castillo 
1666f971622SJuan Castillo 	exit(0);
1676f971622SJuan Castillo }
1686f971622SJuan Castillo 
169ccbf890eSJuan Castillo static int get_key_alg(const char *key_alg_str)
170ccbf890eSJuan Castillo {
171ccbf890eSJuan Castillo 	int i;
172ccbf890eSJuan Castillo 
173ccbf890eSJuan Castillo 	for (i = 0 ; i < NUM_ELEM(key_algs_str) ; i++) {
174ccbf890eSJuan Castillo 		if (0 == strcmp(key_alg_str, key_algs_str[i])) {
175ccbf890eSJuan Castillo 			return i;
176ccbf890eSJuan Castillo 		}
177ccbf890eSJuan Castillo 	}
178ccbf890eSJuan Castillo 
179ccbf890eSJuan Castillo 	return -1;
180ccbf890eSJuan Castillo }
181ccbf890eSJuan Castillo 
1826f971622SJuan Castillo static void check_cmd_params(void)
1836f971622SJuan Castillo {
184dfc90e26SJuan Castillo 	cert_t *cert;
185dfc90e26SJuan Castillo 	ext_t *ext;
186dfc90e26SJuan Castillo 	key_t *key;
187dfc90e26SJuan Castillo 	int i, j;
188dfc90e26SJuan Castillo 
189ccbf890eSJuan Castillo 	/* Only save new keys */
190ccbf890eSJuan Castillo 	if (save_keys && !new_keys) {
191ccbf890eSJuan Castillo 		ERROR("Only new keys can be saved to disk\n");
192ccbf890eSJuan Castillo 		exit(1);
193ccbf890eSJuan Castillo 	}
194ccbf890eSJuan Castillo 
195dfc90e26SJuan Castillo 	/* Check that all required options have been specified in the
196dfc90e26SJuan Castillo 	 * command line */
197dfc90e26SJuan Castillo 	for (i = 0; i < num_certs; i++) {
198dfc90e26SJuan Castillo 		cert = &certs[i];
199dfc90e26SJuan Castillo 		if (cert->fn == NULL) {
200dfc90e26SJuan Castillo 			/* Certificate not requested. Skip to the next one */
201dfc90e26SJuan Castillo 			continue;
202dfc90e26SJuan Castillo 		}
203dfc90e26SJuan Castillo 
204dfc90e26SJuan Castillo 		/* Check that all parameters required to create this certificate
205dfc90e26SJuan Castillo 		 * have been specified in the command line */
206dfc90e26SJuan Castillo 		for (j = 0; j < cert->num_ext; j++) {
207dfc90e26SJuan Castillo 			ext = &extensions[cert->ext[j]];
208dfc90e26SJuan Castillo 			switch (ext->type) {
209dfc90e26SJuan Castillo 			case EXT_TYPE_PKEY:
210dfc90e26SJuan Castillo 				/* Key filename must be specified */
211dfc90e26SJuan Castillo 				key = &keys[ext->data.key];
212dfc90e26SJuan Castillo 				if (!new_keys && key->fn == NULL) {
213dfc90e26SJuan Castillo 					ERROR("Key '%s' required by '%s' not "
214dfc90e26SJuan Castillo 					      "specified\n", key->desc,
215dfc90e26SJuan Castillo 					      cert->cn);
2166f971622SJuan Castillo 					exit(1);
2176f971622SJuan Castillo 				}
218dfc90e26SJuan Castillo 				break;
219dfc90e26SJuan Castillo 			case EXT_TYPE_HASH:
220*cebe1f23SYatharth Kochar 				/*
221*cebe1f23SYatharth Kochar 				 * Binary image must be specified
222*cebe1f23SYatharth Kochar 				 * unless it is explicitly made optional.
223*cebe1f23SYatharth Kochar 				 */
224*cebe1f23SYatharth Kochar 				if ((!ext->optional) && (ext->data.fn == NULL)) {
225dfc90e26SJuan Castillo 					ERROR("Image for '%s' not specified\n",
226dfc90e26SJuan Castillo 					      ext->ln);
2276f971622SJuan Castillo 					exit(1);
2286f971622SJuan Castillo 				}
229dfc90e26SJuan Castillo 				break;
230dfc90e26SJuan Castillo 			default:
231dfc90e26SJuan Castillo 				ERROR("Unknown extension type in '%s'\n",
232dfc90e26SJuan Castillo 				      ext->ln);
2336f971622SJuan Castillo 				exit(1);
234dfc90e26SJuan Castillo 				break;
2356f971622SJuan Castillo 			}
2366f971622SJuan Castillo 		}
2376f971622SJuan Castillo 	}
2386f971622SJuan Castillo }
2396f971622SJuan Castillo 
2406f971622SJuan Castillo int main(int argc, char *argv[])
2416f971622SJuan Castillo {
2426f971622SJuan Castillo 	STACK_OF(X509_EXTENSION) * sk = NULL;
24355e291a4SJuan Castillo 	X509_EXTENSION *cert_ext = NULL;
24455e291a4SJuan Castillo 	ext_t *ext = NULL;
245ad2c1a9aSJuan Castillo 	key_t *key = NULL;
246ad2c1a9aSJuan Castillo 	cert_t *cert = NULL;
2476f971622SJuan Castillo 	FILE *file = NULL;
24855e291a4SJuan Castillo 	int i, j, ext_nid;
2496f971622SJuan Castillo 	int c, opt_idx = 0;
250ad2c1a9aSJuan Castillo 	const struct option *cmd_opt;
251ad2c1a9aSJuan Castillo 	const char *cur_opt;
252ccbf890eSJuan Castillo 	unsigned int err_code;
2536f971622SJuan Castillo 	unsigned char md[SHA256_DIGEST_LENGTH];
254c3da66b1SJuan Castillo 	const EVP_MD *md_info;
2556f971622SJuan Castillo 
2566f971622SJuan Castillo 	NOTICE("CoT Generation Tool: %s\n", build_msg);
2576f971622SJuan Castillo 	NOTICE("Target platform: %s\n", platform_msg);
2586f971622SJuan Castillo 
259ccbf890eSJuan Castillo 	/* Set default options */
260ccbf890eSJuan Castillo 	key_alg = KEY_ALG_RSA;
261ccbf890eSJuan Castillo 
262ad2c1a9aSJuan Castillo 	/* Add common command line options */
263ad2c1a9aSJuan Castillo 	cmd_opt_add("key-alg", required_argument, 'a');
264ad2c1a9aSJuan Castillo 	cmd_opt_add("help", no_argument, 'h');
265ad2c1a9aSJuan Castillo 	cmd_opt_add("save-keys", no_argument, 'k');
266ad2c1a9aSJuan Castillo 	cmd_opt_add("new-chain", no_argument, 'n');
267ad2c1a9aSJuan Castillo 	cmd_opt_add("print-cert", no_argument, 'p');
268ad2c1a9aSJuan Castillo 
269ad2c1a9aSJuan Castillo 	/* Initialize the certificates */
270ad2c1a9aSJuan Castillo 	if (cert_init() != 0) {
271ad2c1a9aSJuan Castillo 		ERROR("Cannot initialize certificates\n");
272ad2c1a9aSJuan Castillo 		exit(1);
273ad2c1a9aSJuan Castillo 	}
274ad2c1a9aSJuan Castillo 
275ad2c1a9aSJuan Castillo 	/* Initialize the keys */
276ad2c1a9aSJuan Castillo 	if (key_init() != 0) {
277ad2c1a9aSJuan Castillo 		ERROR("Cannot initialize keys\n");
278ad2c1a9aSJuan Castillo 		exit(1);
279ad2c1a9aSJuan Castillo 	}
280ad2c1a9aSJuan Castillo 
281ad2c1a9aSJuan Castillo 	/* Initialize the new types and register OIDs for the extensions */
282ad2c1a9aSJuan Castillo 	if (ext_init() != 0) {
283ad2c1a9aSJuan Castillo 		ERROR("Cannot initialize TBB extensions\n");
284ad2c1a9aSJuan Castillo 		exit(1);
285ad2c1a9aSJuan Castillo 	}
286ad2c1a9aSJuan Castillo 
287ad2c1a9aSJuan Castillo 	/* Get the command line options populated during the initialization */
288ad2c1a9aSJuan Castillo 	cmd_opt = cmd_opt_get_array();
289ad2c1a9aSJuan Castillo 
2906f971622SJuan Castillo 	while (1) {
2916f971622SJuan Castillo 		/* getopt_long stores the option index here. */
292ad2c1a9aSJuan Castillo 		c = getopt_long(argc, argv, "ahknp", cmd_opt, &opt_idx);
2936f971622SJuan Castillo 
2946f971622SJuan Castillo 		/* Detect the end of the options. */
2956f971622SJuan Castillo 		if (c == -1) {
2966f971622SJuan Castillo 			break;
2976f971622SJuan Castillo 		}
2986f971622SJuan Castillo 
2996f971622SJuan Castillo 		switch (c) {
300ccbf890eSJuan Castillo 		case 'a':
301ccbf890eSJuan Castillo 			key_alg = get_key_alg(optarg);
302ccbf890eSJuan Castillo 			if (key_alg < 0) {
303ccbf890eSJuan Castillo 				ERROR("Invalid key algorithm '%s'\n", optarg);
304ccbf890eSJuan Castillo 				exit(1);
305ccbf890eSJuan Castillo 			}
306ccbf890eSJuan Castillo 			break;
3076f971622SJuan Castillo 		case 'h':
308ad2c1a9aSJuan Castillo 			print_help(argv[0], cmd_opt);
3096f971622SJuan Castillo 			break;
3106f971622SJuan Castillo 		case 'k':
3116f971622SJuan Castillo 			save_keys = 1;
3126f971622SJuan Castillo 			break;
3136f971622SJuan Castillo 		case 'n':
3146f971622SJuan Castillo 			new_keys = 1;
3156f971622SJuan Castillo 			break;
3166f971622SJuan Castillo 		case 'p':
3176f971622SJuan Castillo 			print_cert = 1;
3186f971622SJuan Castillo 			break;
319ad2c1a9aSJuan Castillo 		case CMD_OPT_EXT:
320ad2c1a9aSJuan Castillo 			cur_opt = cmd_opt_get_name(opt_idx);
321ad2c1a9aSJuan Castillo 			ext = ext_get_by_opt(cur_opt);
322ad2c1a9aSJuan Castillo 			ext->data.fn = strdup(optarg);
3236f971622SJuan Castillo 			break;
324ad2c1a9aSJuan Castillo 		case CMD_OPT_KEY:
325ad2c1a9aSJuan Castillo 			cur_opt = cmd_opt_get_name(opt_idx);
326ad2c1a9aSJuan Castillo 			key = key_get_by_opt(cur_opt);
327ad2c1a9aSJuan Castillo 			key->fn = strdup(optarg);
3286f971622SJuan Castillo 			break;
329ad2c1a9aSJuan Castillo 		case CMD_OPT_CERT:
330ad2c1a9aSJuan Castillo 			cur_opt = cmd_opt_get_name(opt_idx);
331ad2c1a9aSJuan Castillo 			cert = cert_get_by_opt(cur_opt);
332ad2c1a9aSJuan Castillo 			cert->fn = strdup(optarg);
3336f971622SJuan Castillo 			break;
3346f971622SJuan Castillo 		case '?':
3356f971622SJuan Castillo 		default:
3366f971622SJuan Castillo 			printf("%s\n", optarg);
3376f971622SJuan Castillo 			exit(1);
3386f971622SJuan Castillo 		}
3396f971622SJuan Castillo 	}
3406f971622SJuan Castillo 
3416f971622SJuan Castillo 	/* Check command line arguments */
3426f971622SJuan Castillo 	check_cmd_params();
3436f971622SJuan Castillo 
344c3da66b1SJuan Castillo 	/* Indicate SHA256 as image hash algorithm in the certificate
345c3da66b1SJuan Castillo 	 * extension */
346c3da66b1SJuan Castillo 	md_info = EVP_sha256();
347c3da66b1SJuan Castillo 
3486f971622SJuan Castillo 	/* Load private keys from files (or generate new ones) */
34955e291a4SJuan Castillo 	for (i = 0 ; i < num_keys ; i++) {
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 */
357ccbf890eSJuan Castillo 		if (err_code == KEY_ERR_MALLOC) {
358ccbf890eSJuan Castillo 			/* Cannot allocate memory. Abort. */
359ccbf890eSJuan Castillo 			ERROR("Malloc error while loading '%s'\n", keys[i].fn);
360ccbf890eSJuan Castillo 			exit(1);
361ccbf890eSJuan Castillo 		} else if (err_code == KEY_ERR_LOAD) {
362ccbf890eSJuan Castillo 			/* File exists, but it does not contain a valid private
363ccbf890eSJuan Castillo 			 * key. Abort. */
364ccbf890eSJuan Castillo 			ERROR("Error loading '%s'\n", keys[i].fn);
3656f971622SJuan Castillo 			exit(1);
3666f971622SJuan Castillo 		}
367ccbf890eSJuan Castillo 
368ccbf890eSJuan Castillo 		/* File does not exist, could not be opened or no filename was
369ccbf890eSJuan Castillo 		 * given */
370ccbf890eSJuan Castillo 		if (new_keys) {
371ccbf890eSJuan Castillo 			/* Try to create a new key */
372ccbf890eSJuan Castillo 			NOTICE("Creating new key for '%s'\n", keys[i].desc);
373ccbf890eSJuan Castillo 			if (!key_create(&keys[i], key_alg)) {
374ccbf890eSJuan Castillo 				ERROR("Error creating key '%s'\n", keys[i].desc);
375ccbf890eSJuan Castillo 				exit(1);
3766f971622SJuan Castillo 			}
3776f971622SJuan Castillo 		} else {
378ccbf890eSJuan Castillo 			if (err_code == KEY_ERR_OPEN) {
379ccbf890eSJuan Castillo 				ERROR("Error opening '%s'\n", keys[i].fn);
380ccbf890eSJuan Castillo 			} else {
381ccbf890eSJuan Castillo 				ERROR("Key '%s' not specified\n", keys[i].desc);
3826f971622SJuan Castillo 			}
383ccbf890eSJuan Castillo 			exit(1);
3846f971622SJuan Castillo 		}
3856f971622SJuan Castillo 	}
3866f971622SJuan Castillo 
38755e291a4SJuan Castillo 	/* Create the certificates */
38855e291a4SJuan Castillo 	for (i = 0 ; i < num_certs ; i++) {
38955e291a4SJuan Castillo 
39055e291a4SJuan Castillo 		cert = &certs[i];
39155e291a4SJuan Castillo 
39255e291a4SJuan Castillo 		/* Create a new stack of extensions. This stack will be used
39355e291a4SJuan Castillo 		 * to create the certificate */
3946f971622SJuan Castillo 		CHECK_NULL(sk, sk_X509_EXTENSION_new_null());
3956f971622SJuan Castillo 
39655e291a4SJuan Castillo 		for (j = 0 ; j < cert->num_ext ; j++) {
3976f971622SJuan Castillo 
39855e291a4SJuan Castillo 			ext = &extensions[cert->ext[j]];
39955e291a4SJuan Castillo 
40055e291a4SJuan Castillo 			/* Get OpenSSL internal ID for this extension */
40155e291a4SJuan Castillo 			CHECK_OID(ext_nid, ext->oid);
40255e291a4SJuan Castillo 
40355e291a4SJuan Castillo 			/*
40455e291a4SJuan Castillo 			 * Three types of extensions are currently supported:
40555e291a4SJuan Castillo 			 *     - EXT_TYPE_NVCOUNTER
40655e291a4SJuan Castillo 			 *     - EXT_TYPE_HASH
40755e291a4SJuan Castillo 			 *     - EXT_TYPE_PKEY
40855e291a4SJuan Castillo 			 */
40955e291a4SJuan Castillo 			switch (ext->type) {
41055e291a4SJuan Castillo 			case EXT_TYPE_NVCOUNTER:
41155e291a4SJuan Castillo 				CHECK_NULL(cert_ext, ext_new_nvcounter(ext_nid,
41255e291a4SJuan Castillo 						EXT_CRIT, ext->data.nvcounter));
41355e291a4SJuan Castillo 				break;
41455e291a4SJuan Castillo 			case EXT_TYPE_HASH:
41555e291a4SJuan Castillo 				if (ext->data.fn == NULL) {
416*cebe1f23SYatharth Kochar 					if (ext->optional) {
417*cebe1f23SYatharth Kochar 						/* Include a hash filled with zeros */
418*cebe1f23SYatharth Kochar 						memset(md, 0x0, SHA256_DIGEST_LENGTH);
419*cebe1f23SYatharth Kochar 					} else {
420*cebe1f23SYatharth Kochar 						/* Do not include this hash in the certificate */
42155e291a4SJuan Castillo 						break;
42255e291a4SJuan Castillo 					}
423*cebe1f23SYatharth Kochar 				} else {
424*cebe1f23SYatharth Kochar 					/* Calculate the hash of the file */
42555e291a4SJuan Castillo 					if (!sha_file(ext->data.fn, md)) {
42655e291a4SJuan Castillo 						ERROR("Cannot calculate hash of %s\n",
42755e291a4SJuan Castillo 							ext->data.fn);
4286f971622SJuan Castillo 						exit(1);
4296f971622SJuan Castillo 					}
430*cebe1f23SYatharth Kochar 				}
43155e291a4SJuan Castillo 				CHECK_NULL(cert_ext, ext_new_hash(ext_nid,
43255e291a4SJuan Castillo 						EXT_CRIT, md_info, md,
4336f971622SJuan Castillo 						SHA256_DIGEST_LENGTH));
43455e291a4SJuan Castillo 				break;
43555e291a4SJuan Castillo 			case EXT_TYPE_PKEY:
43655e291a4SJuan Castillo 				CHECK_NULL(cert_ext, ext_new_key(ext_nid,
43755e291a4SJuan Castillo 					EXT_CRIT, keys[ext->data.key].key));
43855e291a4SJuan Castillo 				break;
43955e291a4SJuan Castillo 			default:
44055e291a4SJuan Castillo 				ERROR("Unknown extension type in %s\n",
44155e291a4SJuan Castillo 						cert->cn);
44255e291a4SJuan Castillo 				exit(1);
44355e291a4SJuan Castillo 			}
44455e291a4SJuan Castillo 
44555e291a4SJuan Castillo 			/* Push the extension into the stack */
44655e291a4SJuan Castillo 			sk_X509_EXTENSION_push(sk, cert_ext);
44755e291a4SJuan Castillo 		}
4486f971622SJuan Castillo 
4496f971622SJuan Castillo 		/* Create certificate. Signed with ROT key */
450dfc90e26SJuan Castillo 		if (cert->fn && !cert_new(cert, VAL_DAYS, 0, sk)) {
45155e291a4SJuan Castillo 			ERROR("Cannot create %s\n", cert->cn);
4526f971622SJuan Castillo 			exit(1);
4536f971622SJuan Castillo 		}
4546f971622SJuan Castillo 
4556f971622SJuan Castillo 		sk_X509_EXTENSION_free(sk);
4566f971622SJuan Castillo 	}
4576f971622SJuan Castillo 
4586f971622SJuan Castillo 
4596f971622SJuan Castillo 	/* Print the certificates */
4606f971622SJuan Castillo 	if (print_cert) {
46155e291a4SJuan Castillo 		for (i = 0 ; i < num_certs ; i++) {
4626f971622SJuan Castillo 			if (!certs[i].x) {
4636f971622SJuan Castillo 				continue;
4646f971622SJuan Castillo 			}
4656f971622SJuan Castillo 			printf("\n\n=====================================\n\n");
4666f971622SJuan Castillo 			X509_print_fp(stdout, certs[i].x);
4676f971622SJuan Castillo 		}
4686f971622SJuan Castillo 	}
4696f971622SJuan Castillo 
4706f971622SJuan Castillo 	/* Save created certificates to files */
47155e291a4SJuan Castillo 	for (i = 0 ; i < num_certs ; i++) {
4726f971622SJuan Castillo 		if (certs[i].x && certs[i].fn) {
4736f971622SJuan Castillo 			file = fopen(certs[i].fn, "w");
4746f971622SJuan Castillo 			if (file != NULL) {
4756f971622SJuan Castillo 				i2d_X509_fp(file, certs[i].x);
4766f971622SJuan Castillo 				fclose(file);
4776f971622SJuan Castillo 			} else {
4786f971622SJuan Castillo 				ERROR("Cannot create file %s\n", certs[i].fn);
4796f971622SJuan Castillo 			}
4806f971622SJuan Castillo 		}
4816f971622SJuan Castillo 	}
4826f971622SJuan Castillo 
4836f971622SJuan Castillo 	/* Save keys */
4846f971622SJuan Castillo 	if (save_keys) {
48555e291a4SJuan Castillo 		for (i = 0 ; i < num_keys ; i++) {
4866f971622SJuan Castillo 			if (!key_store(&keys[i])) {
4876f971622SJuan Castillo 				ERROR("Cannot save %s\n", keys[i].desc);
4886f971622SJuan Castillo 			}
4896f971622SJuan Castillo 		}
4906f971622SJuan Castillo 	}
4916f971622SJuan Castillo 
4926f971622SJuan Castillo #ifndef OPENSSL_NO_ENGINE
4936f971622SJuan Castillo 	ENGINE_cleanup();
4946f971622SJuan Castillo #endif
4956f971622SJuan Castillo 	CRYPTO_cleanup_all_ex_data();
4966f971622SJuan Castillo 
4976f971622SJuan Castillo 	return 0;
4986f971622SJuan Castillo }
499