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