xref: /rk3399_ARM-atf/tools/cert_create/src/main.c (revision bb41eb7a9dc3e3b31df2e20237a2bcf1a3cae72a)
16f971622SJuan Castillo /*
2*bb41eb7aSMasahiro Yamada  * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
36f971622SJuan Castillo  *
482cb2c1aSdp-arm  * SPDX-License-Identifier: BSD-3-Clause
56f971622SJuan Castillo  */
66f971622SJuan Castillo 
7159807e2SJuan Castillo #include <assert.h>
8159807e2SJuan Castillo #include <ctype.h>
96f971622SJuan Castillo #include <getopt.h>
106f971622SJuan Castillo #include <stdio.h>
116f971622SJuan Castillo #include <stdlib.h>
126f971622SJuan Castillo #include <string.h>
136f971622SJuan Castillo 
146f971622SJuan Castillo #include <openssl/conf.h>
156f971622SJuan Castillo #include <openssl/engine.h>
166f971622SJuan Castillo #include <openssl/err.h>
176f971622SJuan Castillo #include <openssl/pem.h>
186f971622SJuan Castillo #include <openssl/sha.h>
196f971622SJuan Castillo #include <openssl/x509v3.h>
206f971622SJuan Castillo 
21*bb41eb7aSMasahiro Yamada #if USE_TBBR_DEFS
22*bb41eb7aSMasahiro Yamada #include <tbbr_oid.h>
23*bb41eb7aSMasahiro Yamada #else
24*bb41eb7aSMasahiro Yamada #include <platform_oid.h>
25*bb41eb7aSMasahiro Yamada #endif
26*bb41eb7aSMasahiro Yamada 
276f971622SJuan Castillo #include "cert.h"
28ad2c1a9aSJuan Castillo #include "cmd_opt.h"
296f971622SJuan Castillo #include "debug.h"
306f971622SJuan Castillo #include "ext.h"
316f971622SJuan Castillo #include "key.h"
326f971622SJuan Castillo #include "sha.h"
3355e291a4SJuan Castillo #include "tbbr/tbb_ext.h"
3455e291a4SJuan Castillo #include "tbbr/tbb_cert.h"
3555e291a4SJuan Castillo #include "tbbr/tbb_key.h"
366f971622SJuan Castillo 
376f971622SJuan Castillo /*
386f971622SJuan Castillo  * Helper macros to simplify the code. This macro assigns the return value of
396f971622SJuan Castillo  * the 'fn' function to 'v' and exits if the value is NULL.
406f971622SJuan Castillo  */
416f971622SJuan Castillo #define CHECK_NULL(v, fn) \
426f971622SJuan Castillo 	do { \
436f971622SJuan Castillo 		v = fn; \
446f971622SJuan Castillo 		if (v == NULL) { \
456f971622SJuan Castillo 			ERROR("NULL object at %s:%d\n", __FILE__, __LINE__); \
466f971622SJuan Castillo 			exit(1); \
476f971622SJuan Castillo 		} \
486f971622SJuan Castillo 	} while (0)
496f971622SJuan Castillo 
506f971622SJuan Castillo /*
516f971622SJuan Castillo  * This macro assigns the NID corresponding to 'oid' to 'v' and exits if the
526f971622SJuan Castillo  * NID is undefined.
536f971622SJuan Castillo  */
546f971622SJuan Castillo #define CHECK_OID(v, oid) \
556f971622SJuan Castillo 	do { \
566f971622SJuan Castillo 		v = OBJ_txt2nid(oid); \
576f971622SJuan Castillo 		if (v == NID_undef) { \
586f971622SJuan Castillo 			ERROR("Cannot find TBB extension %s\n", oid); \
596f971622SJuan Castillo 			exit(1); \
606f971622SJuan Castillo 		} \
616f971622SJuan Castillo 	} while (0)
626f971622SJuan Castillo 
636f971622SJuan Castillo #define MAX_FILENAME_LEN		1024
646f971622SJuan Castillo #define VAL_DAYS			7300
656f971622SJuan Castillo #define ID_TO_BIT_MASK(id)		(1 << id)
66ccbf890eSJuan Castillo #define NUM_ELEM(x)			((sizeof(x)) / (sizeof(x[0])))
67159807e2SJuan Castillo #define HELP_OPT_MAX_LEN		128
686f971622SJuan Castillo 
696f971622SJuan Castillo /* Global options */
70ccbf890eSJuan Castillo static int key_alg;
716f971622SJuan Castillo static int new_keys;
726f971622SJuan Castillo static int save_keys;
736f971622SJuan Castillo static int print_cert;
746f971622SJuan Castillo 
756f971622SJuan Castillo /* Info messages created in the Makefile */
766f971622SJuan Castillo extern const char build_msg[];
776f971622SJuan Castillo extern const char platform_msg[];
786f971622SJuan Castillo 
796f971622SJuan Castillo 
806f971622SJuan Castillo static char *strdup(const char *str)
816f971622SJuan Castillo {
826f971622SJuan Castillo 	int n = strlen(str) + 1;
836f971622SJuan Castillo 	char *dup = malloc(n);
846f971622SJuan Castillo 	if (dup) {
856f971622SJuan Castillo 		strcpy(dup, str);
866f971622SJuan Castillo 	}
876f971622SJuan Castillo 	return dup;
886f971622SJuan Castillo }
896f971622SJuan Castillo 
90ccbf890eSJuan Castillo static const char *key_algs_str[] = {
91ccbf890eSJuan Castillo 	[KEY_ALG_RSA] = "rsa",
92ed2a76eaSJuan Castillo #ifndef OPENSSL_NO_EC
93ccbf890eSJuan Castillo 	[KEY_ALG_ECDSA] = "ecdsa"
94ed2a76eaSJuan Castillo #endif /* OPENSSL_NO_EC */
95ccbf890eSJuan Castillo };
96ccbf890eSJuan Castillo 
97ad2c1a9aSJuan Castillo static void print_help(const char *cmd, const struct option *long_opt)
986f971622SJuan Castillo {
99159807e2SJuan Castillo 	int rem, i = 0;
100159807e2SJuan Castillo 	const struct option *opt;
101159807e2SJuan Castillo 	char line[HELP_OPT_MAX_LEN];
102159807e2SJuan Castillo 	char *p;
103159807e2SJuan Castillo 
104159807e2SJuan Castillo 	assert(cmd != NULL);
105159807e2SJuan Castillo 	assert(long_opt != NULL);
106159807e2SJuan Castillo 
1076f971622SJuan Castillo 	printf("\n\n");
1086f971622SJuan Castillo 	printf("The certificate generation tool loads the binary images and\n"
1096f971622SJuan Castillo 	       "optionally the RSA keys, and outputs the key and content\n"
1106f971622SJuan Castillo 	       "certificates properly signed to implement the chain of trust.\n"
1116f971622SJuan Castillo 	       "If keys are provided, they must be in PEM format.\n"
1126f971622SJuan Castillo 	       "Certificates are generated in DER format.\n");
1136f971622SJuan Castillo 	printf("\n");
114159807e2SJuan Castillo 	printf("Usage:\n");
115159807e2SJuan Castillo 	printf("\t%s [OPTIONS]\n\n", cmd);
116159807e2SJuan Castillo 
117159807e2SJuan Castillo 	printf("Available options:\n");
118159807e2SJuan Castillo 	opt = long_opt;
119159807e2SJuan Castillo 	while (opt->name) {
120159807e2SJuan Castillo 		p = line;
121159807e2SJuan Castillo 		rem = HELP_OPT_MAX_LEN;
122159807e2SJuan Castillo 		if (isalpha(opt->val)) {
123159807e2SJuan Castillo 			/* Short format */
124159807e2SJuan Castillo 			sprintf(p, "-%c,", (char)opt->val);
125159807e2SJuan Castillo 			p += 3;
126159807e2SJuan Castillo 			rem -= 3;
1276f971622SJuan Castillo 		}
128159807e2SJuan Castillo 		snprintf(p, rem, "--%s %s", opt->name,
129159807e2SJuan Castillo 			 (opt->has_arg == required_argument) ? "<arg>" : "");
130159807e2SJuan Castillo 		printf("\t%-32s %s\n", line, cmd_opt_get_help_msg(i));
131159807e2SJuan Castillo 		opt++;
132159807e2SJuan Castillo 		i++;
133159807e2SJuan Castillo 	}
1346f971622SJuan Castillo 	printf("\n");
1356f971622SJuan Castillo 
1366f971622SJuan Castillo 	exit(0);
1376f971622SJuan Castillo }
1386f971622SJuan Castillo 
139ccbf890eSJuan Castillo static int get_key_alg(const char *key_alg_str)
140ccbf890eSJuan Castillo {
141ccbf890eSJuan Castillo 	int i;
142ccbf890eSJuan Castillo 
143ccbf890eSJuan Castillo 	for (i = 0 ; i < NUM_ELEM(key_algs_str) ; i++) {
144ccbf890eSJuan Castillo 		if (0 == strcmp(key_alg_str, key_algs_str[i])) {
145ccbf890eSJuan Castillo 			return i;
146ccbf890eSJuan Castillo 		}
147ccbf890eSJuan Castillo 	}
148ccbf890eSJuan Castillo 
149ccbf890eSJuan Castillo 	return -1;
150ccbf890eSJuan Castillo }
151ccbf890eSJuan Castillo 
1526f971622SJuan Castillo static void check_cmd_params(void)
1536f971622SJuan Castillo {
154dfc90e26SJuan Castillo 	cert_t *cert;
155dfc90e26SJuan Castillo 	ext_t *ext;
156dfc90e26SJuan Castillo 	key_t *key;
157dfc90e26SJuan Castillo 	int i, j;
158dfc90e26SJuan Castillo 
159ccbf890eSJuan Castillo 	/* Only save new keys */
160ccbf890eSJuan Castillo 	if (save_keys && !new_keys) {
161ccbf890eSJuan Castillo 		ERROR("Only new keys can be saved to disk\n");
162ccbf890eSJuan Castillo 		exit(1);
163ccbf890eSJuan Castillo 	}
164ccbf890eSJuan Castillo 
165dfc90e26SJuan Castillo 	/* Check that all required options have been specified in the
166dfc90e26SJuan Castillo 	 * command line */
167dfc90e26SJuan Castillo 	for (i = 0; i < num_certs; i++) {
168dfc90e26SJuan Castillo 		cert = &certs[i];
169dfc90e26SJuan Castillo 		if (cert->fn == NULL) {
170dfc90e26SJuan Castillo 			/* Certificate not requested. Skip to the next one */
171dfc90e26SJuan Castillo 			continue;
172dfc90e26SJuan Castillo 		}
173dfc90e26SJuan Castillo 
174dfc90e26SJuan Castillo 		/* Check that all parameters required to create this certificate
175dfc90e26SJuan Castillo 		 * have been specified in the command line */
176dfc90e26SJuan Castillo 		for (j = 0; j < cert->num_ext; j++) {
177dfc90e26SJuan Castillo 			ext = &extensions[cert->ext[j]];
178dfc90e26SJuan Castillo 			switch (ext->type) {
17996103d5aSJuan Castillo 			case EXT_TYPE_NVCOUNTER:
18096103d5aSJuan Castillo 				/* Counter value must be specified */
18196103d5aSJuan Castillo 				if ((!ext->optional) && (ext->arg == NULL)) {
18296103d5aSJuan Castillo 					ERROR("Value for '%s' not specified\n",
18396103d5aSJuan Castillo 					      ext->ln);
18496103d5aSJuan Castillo 					exit(1);
18596103d5aSJuan Castillo 				}
18696103d5aSJuan Castillo 				break;
187dfc90e26SJuan Castillo 			case EXT_TYPE_PKEY:
188dfc90e26SJuan Castillo 				/* Key filename must be specified */
18996103d5aSJuan Castillo 				key = &keys[ext->attr.key];
190dfc90e26SJuan Castillo 				if (!new_keys && key->fn == NULL) {
191dfc90e26SJuan Castillo 					ERROR("Key '%s' required by '%s' not "
192dfc90e26SJuan Castillo 					      "specified\n", key->desc,
193dfc90e26SJuan Castillo 					      cert->cn);
1946f971622SJuan Castillo 					exit(1);
1956f971622SJuan Castillo 				}
196dfc90e26SJuan Castillo 				break;
197dfc90e26SJuan Castillo 			case EXT_TYPE_HASH:
198cebe1f23SYatharth Kochar 				/*
199cebe1f23SYatharth Kochar 				 * Binary image must be specified
200cebe1f23SYatharth Kochar 				 * unless it is explicitly made optional.
201cebe1f23SYatharth Kochar 				 */
20296103d5aSJuan Castillo 				if ((!ext->optional) && (ext->arg == NULL)) {
203dfc90e26SJuan Castillo 					ERROR("Image for '%s' not specified\n",
204dfc90e26SJuan Castillo 					      ext->ln);
2056f971622SJuan Castillo 					exit(1);
2066f971622SJuan Castillo 				}
207dfc90e26SJuan Castillo 				break;
208dfc90e26SJuan Castillo 			default:
20996103d5aSJuan Castillo 				ERROR("Unknown extension type '%d' in '%s'\n",
21096103d5aSJuan Castillo 				      ext->type, ext->ln);
2116f971622SJuan Castillo 				exit(1);
212dfc90e26SJuan Castillo 				break;
2136f971622SJuan Castillo 			}
2146f971622SJuan Castillo 		}
2156f971622SJuan Castillo 	}
2166f971622SJuan Castillo }
2176f971622SJuan Castillo 
218159807e2SJuan Castillo /* Common command line options */
219159807e2SJuan Castillo static const cmd_opt_t common_cmd_opt[] = {
220159807e2SJuan Castillo 	{
221159807e2SJuan Castillo 		{ "help", no_argument, NULL, 'h' },
222159807e2SJuan Castillo 		"Print this message and exit"
223159807e2SJuan Castillo 	},
224159807e2SJuan Castillo 	{
225159807e2SJuan Castillo 		{ "key-alg", required_argument, NULL, 'a' },
226159807e2SJuan Castillo 		"Key algorithm: 'rsa' (default), 'ecdsa'"
227159807e2SJuan Castillo 	},
228159807e2SJuan Castillo 	{
229159807e2SJuan Castillo 		{ "save-keys", no_argument, NULL, 'k' },
230159807e2SJuan Castillo 		"Save key pairs into files. Filenames must be provided"
231159807e2SJuan Castillo 	},
232159807e2SJuan Castillo 	{
233159807e2SJuan Castillo 		{ "new-keys", no_argument, NULL, 'n' },
234159807e2SJuan Castillo 		"Generate new key pairs if no key files are provided"
235159807e2SJuan Castillo 	},
236159807e2SJuan Castillo 	{
237159807e2SJuan Castillo 		{ "print-cert", no_argument, NULL, 'p' },
238159807e2SJuan Castillo 		"Print the certificates in the standard output"
239159807e2SJuan Castillo 	}
240159807e2SJuan Castillo };
241159807e2SJuan Castillo 
2426f971622SJuan Castillo int main(int argc, char *argv[])
2436f971622SJuan Castillo {
244c893c733SMasahiro Yamada 	STACK_OF(X509_EXTENSION) * sk;
245c893c733SMasahiro Yamada 	X509_EXTENSION *cert_ext;
246c893c733SMasahiro Yamada 	ext_t *ext;
247c893c733SMasahiro Yamada 	key_t *key;
248c893c733SMasahiro Yamada 	cert_t *cert;
249c893c733SMasahiro Yamada 	FILE *file;
25096103d5aSJuan Castillo 	int i, j, ext_nid, nvctr;
2516f971622SJuan Castillo 	int c, opt_idx = 0;
252ad2c1a9aSJuan Castillo 	const struct option *cmd_opt;
253ad2c1a9aSJuan Castillo 	const char *cur_opt;
254ccbf890eSJuan Castillo 	unsigned int err_code;
2556f971622SJuan Castillo 	unsigned char md[SHA256_DIGEST_LENGTH];
256c3da66b1SJuan Castillo 	const EVP_MD *md_info;
2576f971622SJuan Castillo 
2586f971622SJuan Castillo 	NOTICE("CoT Generation Tool: %s\n", build_msg);
2596f971622SJuan Castillo 	NOTICE("Target platform: %s\n", platform_msg);
2606f971622SJuan Castillo 
261ccbf890eSJuan Castillo 	/* Set default options */
262ccbf890eSJuan Castillo 	key_alg = KEY_ALG_RSA;
263ccbf890eSJuan Castillo 
264ad2c1a9aSJuan Castillo 	/* Add common command line options */
265159807e2SJuan Castillo 	for (i = 0; i < NUM_ELEM(common_cmd_opt); i++) {
266159807e2SJuan Castillo 		cmd_opt_add(&common_cmd_opt[i]);
267159807e2SJuan Castillo 	}
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. */
292159807e2SJuan Castillo 		c = getopt_long(argc, argv, "a:hknp", 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);
32296103d5aSJuan Castillo 			ext->arg = 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:
336159807e2SJuan Castillo 			print_help(argv[0], cmd_opt);
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++) {
350762f1ebeSMasahiro Yamada 		if (!key_new(&keys[i])) {
351762f1ebeSMasahiro Yamada 			ERROR("Failed to allocate key container\n");
352762f1ebeSMasahiro Yamada 			exit(1);
353762f1ebeSMasahiro Yamada 		}
354762f1ebeSMasahiro Yamada 
355ccbf890eSJuan Castillo 		/* First try to load the key from disk */
356ccbf890eSJuan Castillo 		if (key_load(&keys[i], &err_code)) {
357ccbf890eSJuan Castillo 			/* Key loaded successfully */
358ccbf890eSJuan Castillo 			continue;
359ccbf890eSJuan Castillo 		}
360ccbf890eSJuan Castillo 
361ccbf890eSJuan Castillo 		/* Key not loaded. Check the error code */
362762f1ebeSMasahiro Yamada 		if (err_code == KEY_ERR_LOAD) {
363ccbf890eSJuan Castillo 			/* File exists, but it does not contain a valid private
364ccbf890eSJuan Castillo 			 * key. Abort. */
365ccbf890eSJuan Castillo 			ERROR("Error loading '%s'\n", keys[i].fn);
3666f971622SJuan Castillo 			exit(1);
3676f971622SJuan Castillo 		}
368ccbf890eSJuan Castillo 
369ccbf890eSJuan Castillo 		/* File does not exist, could not be opened or no filename was
370ccbf890eSJuan Castillo 		 * given */
371ccbf890eSJuan Castillo 		if (new_keys) {
372ccbf890eSJuan Castillo 			/* Try to create a new key */
373ccbf890eSJuan Castillo 			NOTICE("Creating new key for '%s'\n", keys[i].desc);
374ccbf890eSJuan Castillo 			if (!key_create(&keys[i], key_alg)) {
375ccbf890eSJuan Castillo 				ERROR("Error creating key '%s'\n", keys[i].desc);
376ccbf890eSJuan Castillo 				exit(1);
3776f971622SJuan Castillo 			}
3786f971622SJuan Castillo 		} else {
379ccbf890eSJuan Castillo 			if (err_code == KEY_ERR_OPEN) {
380ccbf890eSJuan Castillo 				ERROR("Error opening '%s'\n", keys[i].fn);
381ccbf890eSJuan Castillo 			} else {
382ccbf890eSJuan Castillo 				ERROR("Key '%s' not specified\n", keys[i].desc);
3836f971622SJuan Castillo 			}
384ccbf890eSJuan Castillo 			exit(1);
3856f971622SJuan Castillo 		}
3866f971622SJuan Castillo 	}
3876f971622SJuan Castillo 
38855e291a4SJuan Castillo 	/* Create the certificates */
38955e291a4SJuan Castillo 	for (i = 0 ; i < num_certs ; i++) {
39055e291a4SJuan Castillo 
39155e291a4SJuan Castillo 		cert = &certs[i];
39255e291a4SJuan Castillo 
39355e291a4SJuan Castillo 		/* Create a new stack of extensions. This stack will be used
39455e291a4SJuan Castillo 		 * to create the certificate */
3956f971622SJuan Castillo 		CHECK_NULL(sk, sk_X509_EXTENSION_new_null());
3966f971622SJuan Castillo 
39755e291a4SJuan Castillo 		for (j = 0 ; j < cert->num_ext ; j++) {
3986f971622SJuan Castillo 
39955e291a4SJuan Castillo 			ext = &extensions[cert->ext[j]];
40055e291a4SJuan Castillo 
40155e291a4SJuan Castillo 			/* Get OpenSSL internal ID for this extension */
40255e291a4SJuan Castillo 			CHECK_OID(ext_nid, ext->oid);
40355e291a4SJuan Castillo 
40455e291a4SJuan Castillo 			/*
40555e291a4SJuan Castillo 			 * Three types of extensions are currently supported:
40655e291a4SJuan Castillo 			 *     - EXT_TYPE_NVCOUNTER
40755e291a4SJuan Castillo 			 *     - EXT_TYPE_HASH
40855e291a4SJuan Castillo 			 *     - EXT_TYPE_PKEY
40955e291a4SJuan Castillo 			 */
41055e291a4SJuan Castillo 			switch (ext->type) {
41155e291a4SJuan Castillo 			case EXT_TYPE_NVCOUNTER:
412f16db56aSYatharth Kochar 				if (ext->arg) {
41396103d5aSJuan Castillo 					nvctr = atoi(ext->arg);
41455e291a4SJuan Castillo 					CHECK_NULL(cert_ext, ext_new_nvcounter(ext_nid,
41596103d5aSJuan Castillo 						EXT_CRIT, nvctr));
416f16db56aSYatharth Kochar 				}
41755e291a4SJuan Castillo 				break;
41855e291a4SJuan Castillo 			case EXT_TYPE_HASH:
41996103d5aSJuan Castillo 				if (ext->arg == NULL) {
420cebe1f23SYatharth Kochar 					if (ext->optional) {
421cebe1f23SYatharth Kochar 						/* Include a hash filled with zeros */
422cebe1f23SYatharth Kochar 						memset(md, 0x0, SHA256_DIGEST_LENGTH);
423cebe1f23SYatharth Kochar 					} else {
424cebe1f23SYatharth Kochar 						/* Do not include this hash in the certificate */
42555e291a4SJuan Castillo 						break;
42655e291a4SJuan Castillo 					}
427cebe1f23SYatharth Kochar 				} else {
428cebe1f23SYatharth Kochar 					/* Calculate the hash of the file */
42996103d5aSJuan Castillo 					if (!sha_file(ext->arg, md)) {
43055e291a4SJuan Castillo 						ERROR("Cannot calculate hash of %s\n",
43196103d5aSJuan Castillo 							ext->arg);
4326f971622SJuan Castillo 						exit(1);
4336f971622SJuan Castillo 					}
434cebe1f23SYatharth Kochar 				}
43555e291a4SJuan Castillo 				CHECK_NULL(cert_ext, ext_new_hash(ext_nid,
43655e291a4SJuan Castillo 						EXT_CRIT, md_info, md,
4376f971622SJuan Castillo 						SHA256_DIGEST_LENGTH));
43855e291a4SJuan Castillo 				break;
43955e291a4SJuan Castillo 			case EXT_TYPE_PKEY:
44055e291a4SJuan Castillo 				CHECK_NULL(cert_ext, ext_new_key(ext_nid,
44196103d5aSJuan Castillo 					EXT_CRIT, keys[ext->attr.key].key));
44255e291a4SJuan Castillo 				break;
44355e291a4SJuan Castillo 			default:
44496103d5aSJuan Castillo 				ERROR("Unknown extension type '%d' in %s\n",
44596103d5aSJuan Castillo 						ext->type, cert->cn);
44655e291a4SJuan Castillo 				exit(1);
44755e291a4SJuan Castillo 			}
44855e291a4SJuan Castillo 
44955e291a4SJuan Castillo 			/* Push the extension into the stack */
45055e291a4SJuan Castillo 			sk_X509_EXTENSION_push(sk, cert_ext);
45155e291a4SJuan Castillo 		}
4526f971622SJuan Castillo 
4536f971622SJuan Castillo 		/* Create certificate. Signed with ROT key */
454dfc90e26SJuan Castillo 		if (cert->fn && !cert_new(cert, VAL_DAYS, 0, sk)) {
45555e291a4SJuan Castillo 			ERROR("Cannot create %s\n", cert->cn);
4566f971622SJuan Castillo 			exit(1);
4576f971622SJuan Castillo 		}
4586f971622SJuan Castillo 
4596f971622SJuan Castillo 		sk_X509_EXTENSION_free(sk);
4606f971622SJuan Castillo 	}
4616f971622SJuan Castillo 
4626f971622SJuan Castillo 
4636f971622SJuan Castillo 	/* Print the certificates */
4646f971622SJuan Castillo 	if (print_cert) {
46555e291a4SJuan Castillo 		for (i = 0 ; i < num_certs ; i++) {
4666f971622SJuan Castillo 			if (!certs[i].x) {
4676f971622SJuan Castillo 				continue;
4686f971622SJuan Castillo 			}
4696f971622SJuan Castillo 			printf("\n\n=====================================\n\n");
4706f971622SJuan Castillo 			X509_print_fp(stdout, certs[i].x);
4716f971622SJuan Castillo 		}
4726f971622SJuan Castillo 	}
4736f971622SJuan Castillo 
4746f971622SJuan Castillo 	/* Save created certificates to files */
47555e291a4SJuan Castillo 	for (i = 0 ; i < num_certs ; i++) {
4766f971622SJuan Castillo 		if (certs[i].x && certs[i].fn) {
4776f971622SJuan Castillo 			file = fopen(certs[i].fn, "w");
4786f971622SJuan Castillo 			if (file != NULL) {
4796f971622SJuan Castillo 				i2d_X509_fp(file, certs[i].x);
4806f971622SJuan Castillo 				fclose(file);
4816f971622SJuan Castillo 			} else {
4826f971622SJuan Castillo 				ERROR("Cannot create file %s\n", certs[i].fn);
4836f971622SJuan Castillo 			}
4846f971622SJuan Castillo 		}
4856f971622SJuan Castillo 	}
4866f971622SJuan Castillo 
4876f971622SJuan Castillo 	/* Save keys */
4886f971622SJuan Castillo 	if (save_keys) {
48955e291a4SJuan Castillo 		for (i = 0 ; i < num_keys ; i++) {
4906f971622SJuan Castillo 			if (!key_store(&keys[i])) {
4916f971622SJuan Castillo 				ERROR("Cannot save %s\n", keys[i].desc);
4926f971622SJuan Castillo 			}
4936f971622SJuan Castillo 		}
4946f971622SJuan Castillo 	}
4956f971622SJuan Castillo 
4966f971622SJuan Castillo #ifndef OPENSSL_NO_ENGINE
4976f971622SJuan Castillo 	ENGINE_cleanup();
4986f971622SJuan Castillo #endif
4996f971622SJuan Castillo 	CRYPTO_cleanup_all_ex_data();
5006f971622SJuan Castillo 
5016f971622SJuan Castillo 	return 0;
5026f971622SJuan Castillo }
503