xref: /rk3399_ARM-atf/tools/cert_create/src/main.c (revision 762f1ebe8d1b26e78cd4923f832a611c8a5f0a89)
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 
31159807e2SJuan Castillo #include <assert.h>
32159807e2SJuan Castillo #include <ctype.h>
336f971622SJuan Castillo #include <getopt.h>
346f971622SJuan Castillo #include <stdio.h>
356f971622SJuan Castillo #include <stdlib.h>
366f971622SJuan Castillo #include <string.h>
376f971622SJuan Castillo 
386f971622SJuan Castillo #include <openssl/conf.h>
396f971622SJuan Castillo #include <openssl/engine.h>
406f971622SJuan Castillo #include <openssl/err.h>
416f971622SJuan Castillo #include <openssl/pem.h>
426f971622SJuan Castillo #include <openssl/sha.h>
436f971622SJuan Castillo #include <openssl/x509v3.h>
446f971622SJuan Castillo 
456f971622SJuan Castillo #include "cert.h"
46ad2c1a9aSJuan Castillo #include "cmd_opt.h"
476f971622SJuan Castillo #include "debug.h"
486f971622SJuan Castillo #include "ext.h"
496f971622SJuan Castillo #include "key.h"
506f971622SJuan Castillo #include "platform_oid.h"
516f971622SJuan Castillo #include "sha.h"
5255e291a4SJuan Castillo #include "tbbr/tbb_ext.h"
5355e291a4SJuan Castillo #include "tbbr/tbb_cert.h"
5455e291a4SJuan Castillo #include "tbbr/tbb_key.h"
556f971622SJuan Castillo 
566f971622SJuan Castillo /*
576f971622SJuan Castillo  * Helper macros to simplify the code. This macro assigns the return value of
586f971622SJuan Castillo  * the 'fn' function to 'v' and exits if the value is NULL.
596f971622SJuan Castillo  */
606f971622SJuan Castillo #define CHECK_NULL(v, fn) \
616f971622SJuan Castillo 	do { \
626f971622SJuan Castillo 		v = fn; \
636f971622SJuan Castillo 		if (v == NULL) { \
646f971622SJuan Castillo 			ERROR("NULL object at %s:%d\n", __FILE__, __LINE__); \
656f971622SJuan Castillo 			exit(1); \
666f971622SJuan Castillo 		} \
676f971622SJuan Castillo 	} while (0)
686f971622SJuan Castillo 
696f971622SJuan Castillo /*
706f971622SJuan Castillo  * This macro assigns the NID corresponding to 'oid' to 'v' and exits if the
716f971622SJuan Castillo  * NID is undefined.
726f971622SJuan Castillo  */
736f971622SJuan Castillo #define CHECK_OID(v, oid) \
746f971622SJuan Castillo 	do { \
756f971622SJuan Castillo 		v = OBJ_txt2nid(oid); \
766f971622SJuan Castillo 		if (v == NID_undef) { \
776f971622SJuan Castillo 			ERROR("Cannot find TBB extension %s\n", oid); \
786f971622SJuan Castillo 			exit(1); \
796f971622SJuan Castillo 		} \
806f971622SJuan Castillo 	} while (0)
816f971622SJuan Castillo 
826f971622SJuan Castillo #define MAX_FILENAME_LEN		1024
836f971622SJuan Castillo #define VAL_DAYS			7300
846f971622SJuan Castillo #define ID_TO_BIT_MASK(id)		(1 << id)
85ccbf890eSJuan Castillo #define NUM_ELEM(x)			((sizeof(x)) / (sizeof(x[0])))
86159807e2SJuan Castillo #define HELP_OPT_MAX_LEN		128
876f971622SJuan Castillo 
886f971622SJuan Castillo /* Global options */
89ccbf890eSJuan Castillo static int key_alg;
906f971622SJuan Castillo static int new_keys;
916f971622SJuan Castillo static int save_keys;
926f971622SJuan Castillo static int print_cert;
936f971622SJuan Castillo 
946f971622SJuan Castillo /* Info messages created in the Makefile */
956f971622SJuan Castillo extern const char build_msg[];
966f971622SJuan Castillo extern const char platform_msg[];
976f971622SJuan Castillo 
986f971622SJuan Castillo 
996f971622SJuan Castillo static char *strdup(const char *str)
1006f971622SJuan Castillo {
1016f971622SJuan Castillo 	int n = strlen(str) + 1;
1026f971622SJuan Castillo 	char *dup = malloc(n);
1036f971622SJuan Castillo 	if (dup) {
1046f971622SJuan Castillo 		strcpy(dup, str);
1056f971622SJuan Castillo 	}
1066f971622SJuan Castillo 	return dup;
1076f971622SJuan Castillo }
1086f971622SJuan Castillo 
109ccbf890eSJuan Castillo static const char *key_algs_str[] = {
110ccbf890eSJuan Castillo 	[KEY_ALG_RSA] = "rsa",
111ed2a76eaSJuan Castillo #ifndef OPENSSL_NO_EC
112ccbf890eSJuan Castillo 	[KEY_ALG_ECDSA] = "ecdsa"
113ed2a76eaSJuan Castillo #endif /* OPENSSL_NO_EC */
114ccbf890eSJuan Castillo };
115ccbf890eSJuan Castillo 
116ad2c1a9aSJuan Castillo static void print_help(const char *cmd, const struct option *long_opt)
1176f971622SJuan Castillo {
118159807e2SJuan Castillo 	int rem, i = 0;
119159807e2SJuan Castillo 	const struct option *opt;
120159807e2SJuan Castillo 	char line[HELP_OPT_MAX_LEN];
121159807e2SJuan Castillo 	char *p;
122159807e2SJuan Castillo 
123159807e2SJuan Castillo 	assert(cmd != NULL);
124159807e2SJuan Castillo 	assert(long_opt != NULL);
125159807e2SJuan Castillo 
1266f971622SJuan Castillo 	printf("\n\n");
1276f971622SJuan Castillo 	printf("The certificate generation tool loads the binary images and\n"
1286f971622SJuan Castillo 	       "optionally the RSA keys, and outputs the key and content\n"
1296f971622SJuan Castillo 	       "certificates properly signed to implement the chain of trust.\n"
1306f971622SJuan Castillo 	       "If keys are provided, they must be in PEM format.\n"
1316f971622SJuan Castillo 	       "Certificates are generated in DER format.\n");
1326f971622SJuan Castillo 	printf("\n");
133159807e2SJuan Castillo 	printf("Usage:\n");
134159807e2SJuan Castillo 	printf("\t%s [OPTIONS]\n\n", cmd);
135159807e2SJuan Castillo 
136159807e2SJuan Castillo 	printf("Available options:\n");
137159807e2SJuan Castillo 	i = 0;
138159807e2SJuan Castillo 	opt = long_opt;
139159807e2SJuan Castillo 	while (opt->name) {
140159807e2SJuan Castillo 		p = line;
141159807e2SJuan Castillo 		rem = HELP_OPT_MAX_LEN;
142159807e2SJuan Castillo 		if (isalpha(opt->val)) {
143159807e2SJuan Castillo 			/* Short format */
144159807e2SJuan Castillo 			sprintf(p, "-%c,", (char)opt->val);
145159807e2SJuan Castillo 			p += 3;
146159807e2SJuan Castillo 			rem -= 3;
1476f971622SJuan Castillo 		}
148159807e2SJuan Castillo 		snprintf(p, rem, "--%s %s", opt->name,
149159807e2SJuan Castillo 			 (opt->has_arg == required_argument) ? "<arg>" : "");
150159807e2SJuan Castillo 		printf("\t%-32s %s\n", line, cmd_opt_get_help_msg(i));
151159807e2SJuan Castillo 		opt++;
152159807e2SJuan Castillo 		i++;
153159807e2SJuan Castillo 	}
1546f971622SJuan Castillo 	printf("\n");
1556f971622SJuan Castillo 
1566f971622SJuan Castillo 	exit(0);
1576f971622SJuan Castillo }
1586f971622SJuan Castillo 
159ccbf890eSJuan Castillo static int get_key_alg(const char *key_alg_str)
160ccbf890eSJuan Castillo {
161ccbf890eSJuan Castillo 	int i;
162ccbf890eSJuan Castillo 
163ccbf890eSJuan Castillo 	for (i = 0 ; i < NUM_ELEM(key_algs_str) ; i++) {
164ccbf890eSJuan Castillo 		if (0 == strcmp(key_alg_str, key_algs_str[i])) {
165ccbf890eSJuan Castillo 			return i;
166ccbf890eSJuan Castillo 		}
167ccbf890eSJuan Castillo 	}
168ccbf890eSJuan Castillo 
169ccbf890eSJuan Castillo 	return -1;
170ccbf890eSJuan Castillo }
171ccbf890eSJuan Castillo 
1726f971622SJuan Castillo static void check_cmd_params(void)
1736f971622SJuan Castillo {
174dfc90e26SJuan Castillo 	cert_t *cert;
175dfc90e26SJuan Castillo 	ext_t *ext;
176dfc90e26SJuan Castillo 	key_t *key;
177dfc90e26SJuan Castillo 	int i, j;
178dfc90e26SJuan Castillo 
179ccbf890eSJuan Castillo 	/* Only save new keys */
180ccbf890eSJuan Castillo 	if (save_keys && !new_keys) {
181ccbf890eSJuan Castillo 		ERROR("Only new keys can be saved to disk\n");
182ccbf890eSJuan Castillo 		exit(1);
183ccbf890eSJuan Castillo 	}
184ccbf890eSJuan Castillo 
185dfc90e26SJuan Castillo 	/* Check that all required options have been specified in the
186dfc90e26SJuan Castillo 	 * command line */
187dfc90e26SJuan Castillo 	for (i = 0; i < num_certs; i++) {
188dfc90e26SJuan Castillo 		cert = &certs[i];
189dfc90e26SJuan Castillo 		if (cert->fn == NULL) {
190dfc90e26SJuan Castillo 			/* Certificate not requested. Skip to the next one */
191dfc90e26SJuan Castillo 			continue;
192dfc90e26SJuan Castillo 		}
193dfc90e26SJuan Castillo 
194dfc90e26SJuan Castillo 		/* Check that all parameters required to create this certificate
195dfc90e26SJuan Castillo 		 * have been specified in the command line */
196dfc90e26SJuan Castillo 		for (j = 0; j < cert->num_ext; j++) {
197dfc90e26SJuan Castillo 			ext = &extensions[cert->ext[j]];
198dfc90e26SJuan Castillo 			switch (ext->type) {
19996103d5aSJuan Castillo 			case EXT_TYPE_NVCOUNTER:
20096103d5aSJuan Castillo 				/* Counter value must be specified */
20196103d5aSJuan Castillo 				if ((!ext->optional) && (ext->arg == NULL)) {
20296103d5aSJuan Castillo 					ERROR("Value for '%s' not specified\n",
20396103d5aSJuan Castillo 					      ext->ln);
20496103d5aSJuan Castillo 					exit(1);
20596103d5aSJuan Castillo 				}
20696103d5aSJuan Castillo 				break;
207dfc90e26SJuan Castillo 			case EXT_TYPE_PKEY:
208dfc90e26SJuan Castillo 				/* Key filename must be specified */
20996103d5aSJuan Castillo 				key = &keys[ext->attr.key];
210dfc90e26SJuan Castillo 				if (!new_keys && key->fn == NULL) {
211dfc90e26SJuan Castillo 					ERROR("Key '%s' required by '%s' not "
212dfc90e26SJuan Castillo 					      "specified\n", key->desc,
213dfc90e26SJuan Castillo 					      cert->cn);
2146f971622SJuan Castillo 					exit(1);
2156f971622SJuan Castillo 				}
216dfc90e26SJuan Castillo 				break;
217dfc90e26SJuan Castillo 			case EXT_TYPE_HASH:
218cebe1f23SYatharth Kochar 				/*
219cebe1f23SYatharth Kochar 				 * Binary image must be specified
220cebe1f23SYatharth Kochar 				 * unless it is explicitly made optional.
221cebe1f23SYatharth Kochar 				 */
22296103d5aSJuan Castillo 				if ((!ext->optional) && (ext->arg == NULL)) {
223dfc90e26SJuan Castillo 					ERROR("Image for '%s' not specified\n",
224dfc90e26SJuan Castillo 					      ext->ln);
2256f971622SJuan Castillo 					exit(1);
2266f971622SJuan Castillo 				}
227dfc90e26SJuan Castillo 				break;
228dfc90e26SJuan Castillo 			default:
22996103d5aSJuan Castillo 				ERROR("Unknown extension type '%d' in '%s'\n",
23096103d5aSJuan Castillo 				      ext->type, ext->ln);
2316f971622SJuan Castillo 				exit(1);
232dfc90e26SJuan Castillo 				break;
2336f971622SJuan Castillo 			}
2346f971622SJuan Castillo 		}
2356f971622SJuan Castillo 	}
2366f971622SJuan Castillo }
2376f971622SJuan Castillo 
238159807e2SJuan Castillo /* Common command line options */
239159807e2SJuan Castillo static const cmd_opt_t common_cmd_opt[] = {
240159807e2SJuan Castillo 	{
241159807e2SJuan Castillo 		{ "help", no_argument, NULL, 'h' },
242159807e2SJuan Castillo 		"Print this message and exit"
243159807e2SJuan Castillo 	},
244159807e2SJuan Castillo 	{
245159807e2SJuan Castillo 		{ "key-alg", required_argument, NULL, 'a' },
246159807e2SJuan Castillo 		"Key algorithm: 'rsa' (default), 'ecdsa'"
247159807e2SJuan Castillo 	},
248159807e2SJuan Castillo 	{
249159807e2SJuan Castillo 		{ "save-keys", no_argument, NULL, 'k' },
250159807e2SJuan Castillo 		"Save key pairs into files. Filenames must be provided"
251159807e2SJuan Castillo 	},
252159807e2SJuan Castillo 	{
253159807e2SJuan Castillo 		{ "new-keys", no_argument, NULL, 'n' },
254159807e2SJuan Castillo 		"Generate new key pairs if no key files are provided"
255159807e2SJuan Castillo 	},
256159807e2SJuan Castillo 	{
257159807e2SJuan Castillo 		{ "print-cert", no_argument, NULL, 'p' },
258159807e2SJuan Castillo 		"Print the certificates in the standard output"
259159807e2SJuan Castillo 	}
260159807e2SJuan Castillo };
261159807e2SJuan Castillo 
2626f971622SJuan Castillo int main(int argc, char *argv[])
2636f971622SJuan Castillo {
2646f971622SJuan Castillo 	STACK_OF(X509_EXTENSION) * sk = NULL;
26555e291a4SJuan Castillo 	X509_EXTENSION *cert_ext = NULL;
26655e291a4SJuan Castillo 	ext_t *ext = NULL;
267ad2c1a9aSJuan Castillo 	key_t *key = NULL;
268ad2c1a9aSJuan Castillo 	cert_t *cert = NULL;
2696f971622SJuan Castillo 	FILE *file = NULL;
27096103d5aSJuan Castillo 	int i, j, ext_nid, nvctr;
2716f971622SJuan Castillo 	int c, opt_idx = 0;
272ad2c1a9aSJuan Castillo 	const struct option *cmd_opt;
273ad2c1a9aSJuan Castillo 	const char *cur_opt;
274ccbf890eSJuan Castillo 	unsigned int err_code;
2756f971622SJuan Castillo 	unsigned char md[SHA256_DIGEST_LENGTH];
276c3da66b1SJuan Castillo 	const EVP_MD *md_info;
2776f971622SJuan Castillo 
2786f971622SJuan Castillo 	NOTICE("CoT Generation Tool: %s\n", build_msg);
2796f971622SJuan Castillo 	NOTICE("Target platform: %s\n", platform_msg);
2806f971622SJuan Castillo 
281ccbf890eSJuan Castillo 	/* Set default options */
282ccbf890eSJuan Castillo 	key_alg = KEY_ALG_RSA;
283ccbf890eSJuan Castillo 
284ad2c1a9aSJuan Castillo 	/* Add common command line options */
285159807e2SJuan Castillo 	for (i = 0; i < NUM_ELEM(common_cmd_opt); i++) {
286159807e2SJuan Castillo 		cmd_opt_add(&common_cmd_opt[i]);
287159807e2SJuan Castillo 	}
288ad2c1a9aSJuan Castillo 
289ad2c1a9aSJuan Castillo 	/* Initialize the certificates */
290ad2c1a9aSJuan Castillo 	if (cert_init() != 0) {
291ad2c1a9aSJuan Castillo 		ERROR("Cannot initialize certificates\n");
292ad2c1a9aSJuan Castillo 		exit(1);
293ad2c1a9aSJuan Castillo 	}
294ad2c1a9aSJuan Castillo 
295ad2c1a9aSJuan Castillo 	/* Initialize the keys */
296ad2c1a9aSJuan Castillo 	if (key_init() != 0) {
297ad2c1a9aSJuan Castillo 		ERROR("Cannot initialize keys\n");
298ad2c1a9aSJuan Castillo 		exit(1);
299ad2c1a9aSJuan Castillo 	}
300ad2c1a9aSJuan Castillo 
301ad2c1a9aSJuan Castillo 	/* Initialize the new types and register OIDs for the extensions */
302ad2c1a9aSJuan Castillo 	if (ext_init() != 0) {
303ad2c1a9aSJuan Castillo 		ERROR("Cannot initialize TBB extensions\n");
304ad2c1a9aSJuan Castillo 		exit(1);
305ad2c1a9aSJuan Castillo 	}
306ad2c1a9aSJuan Castillo 
307ad2c1a9aSJuan Castillo 	/* Get the command line options populated during the initialization */
308ad2c1a9aSJuan Castillo 	cmd_opt = cmd_opt_get_array();
309ad2c1a9aSJuan Castillo 
3106f971622SJuan Castillo 	while (1) {
3116f971622SJuan Castillo 		/* getopt_long stores the option index here. */
312159807e2SJuan Castillo 		c = getopt_long(argc, argv, "a:hknp", cmd_opt, &opt_idx);
3136f971622SJuan Castillo 
3146f971622SJuan Castillo 		/* Detect the end of the options. */
3156f971622SJuan Castillo 		if (c == -1) {
3166f971622SJuan Castillo 			break;
3176f971622SJuan Castillo 		}
3186f971622SJuan Castillo 
3196f971622SJuan Castillo 		switch (c) {
320ccbf890eSJuan Castillo 		case 'a':
321ccbf890eSJuan Castillo 			key_alg = get_key_alg(optarg);
322ccbf890eSJuan Castillo 			if (key_alg < 0) {
323ccbf890eSJuan Castillo 				ERROR("Invalid key algorithm '%s'\n", optarg);
324ccbf890eSJuan Castillo 				exit(1);
325ccbf890eSJuan Castillo 			}
326ccbf890eSJuan Castillo 			break;
3276f971622SJuan Castillo 		case 'h':
328ad2c1a9aSJuan Castillo 			print_help(argv[0], cmd_opt);
3296f971622SJuan Castillo 			break;
3306f971622SJuan Castillo 		case 'k':
3316f971622SJuan Castillo 			save_keys = 1;
3326f971622SJuan Castillo 			break;
3336f971622SJuan Castillo 		case 'n':
3346f971622SJuan Castillo 			new_keys = 1;
3356f971622SJuan Castillo 			break;
3366f971622SJuan Castillo 		case 'p':
3376f971622SJuan Castillo 			print_cert = 1;
3386f971622SJuan Castillo 			break;
339ad2c1a9aSJuan Castillo 		case CMD_OPT_EXT:
340ad2c1a9aSJuan Castillo 			cur_opt = cmd_opt_get_name(opt_idx);
341ad2c1a9aSJuan Castillo 			ext = ext_get_by_opt(cur_opt);
34296103d5aSJuan Castillo 			ext->arg = strdup(optarg);
3436f971622SJuan Castillo 			break;
344ad2c1a9aSJuan Castillo 		case CMD_OPT_KEY:
345ad2c1a9aSJuan Castillo 			cur_opt = cmd_opt_get_name(opt_idx);
346ad2c1a9aSJuan Castillo 			key = key_get_by_opt(cur_opt);
347ad2c1a9aSJuan Castillo 			key->fn = strdup(optarg);
3486f971622SJuan Castillo 			break;
349ad2c1a9aSJuan Castillo 		case CMD_OPT_CERT:
350ad2c1a9aSJuan Castillo 			cur_opt = cmd_opt_get_name(opt_idx);
351ad2c1a9aSJuan Castillo 			cert = cert_get_by_opt(cur_opt);
352ad2c1a9aSJuan Castillo 			cert->fn = strdup(optarg);
3536f971622SJuan Castillo 			break;
3546f971622SJuan Castillo 		case '?':
3556f971622SJuan Castillo 		default:
356159807e2SJuan Castillo 			print_help(argv[0], cmd_opt);
3576f971622SJuan Castillo 			exit(1);
3586f971622SJuan Castillo 		}
3596f971622SJuan Castillo 	}
3606f971622SJuan Castillo 
3616f971622SJuan Castillo 	/* Check command line arguments */
3626f971622SJuan Castillo 	check_cmd_params();
3636f971622SJuan Castillo 
364c3da66b1SJuan Castillo 	/* Indicate SHA256 as image hash algorithm in the certificate
365c3da66b1SJuan Castillo 	 * extension */
366c3da66b1SJuan Castillo 	md_info = EVP_sha256();
367c3da66b1SJuan Castillo 
3686f971622SJuan Castillo 	/* Load private keys from files (or generate new ones) */
36955e291a4SJuan Castillo 	for (i = 0 ; i < num_keys ; i++) {
370*762f1ebeSMasahiro Yamada 		if (!key_new(&keys[i])) {
371*762f1ebeSMasahiro Yamada 			ERROR("Failed to allocate key container\n");
372*762f1ebeSMasahiro Yamada 			exit(1);
373*762f1ebeSMasahiro Yamada 		}
374*762f1ebeSMasahiro Yamada 
375ccbf890eSJuan Castillo 		/* First try to load the key from disk */
376ccbf890eSJuan Castillo 		if (key_load(&keys[i], &err_code)) {
377ccbf890eSJuan Castillo 			/* Key loaded successfully */
378ccbf890eSJuan Castillo 			continue;
379ccbf890eSJuan Castillo 		}
380ccbf890eSJuan Castillo 
381ccbf890eSJuan Castillo 		/* Key not loaded. Check the error code */
382*762f1ebeSMasahiro Yamada 		if (err_code == KEY_ERR_LOAD) {
383ccbf890eSJuan Castillo 			/* File exists, but it does not contain a valid private
384ccbf890eSJuan Castillo 			 * key. Abort. */
385ccbf890eSJuan Castillo 			ERROR("Error loading '%s'\n", keys[i].fn);
3866f971622SJuan Castillo 			exit(1);
3876f971622SJuan Castillo 		}
388ccbf890eSJuan Castillo 
389ccbf890eSJuan Castillo 		/* File does not exist, could not be opened or no filename was
390ccbf890eSJuan Castillo 		 * given */
391ccbf890eSJuan Castillo 		if (new_keys) {
392ccbf890eSJuan Castillo 			/* Try to create a new key */
393ccbf890eSJuan Castillo 			NOTICE("Creating new key for '%s'\n", keys[i].desc);
394ccbf890eSJuan Castillo 			if (!key_create(&keys[i], key_alg)) {
395ccbf890eSJuan Castillo 				ERROR("Error creating key '%s'\n", keys[i].desc);
396ccbf890eSJuan Castillo 				exit(1);
3976f971622SJuan Castillo 			}
3986f971622SJuan Castillo 		} else {
399ccbf890eSJuan Castillo 			if (err_code == KEY_ERR_OPEN) {
400ccbf890eSJuan Castillo 				ERROR("Error opening '%s'\n", keys[i].fn);
401ccbf890eSJuan Castillo 			} else {
402ccbf890eSJuan Castillo 				ERROR("Key '%s' not specified\n", keys[i].desc);
4036f971622SJuan Castillo 			}
404ccbf890eSJuan Castillo 			exit(1);
4056f971622SJuan Castillo 		}
4066f971622SJuan Castillo 	}
4076f971622SJuan Castillo 
40855e291a4SJuan Castillo 	/* Create the certificates */
40955e291a4SJuan Castillo 	for (i = 0 ; i < num_certs ; i++) {
41055e291a4SJuan Castillo 
41155e291a4SJuan Castillo 		cert = &certs[i];
41255e291a4SJuan Castillo 
41355e291a4SJuan Castillo 		/* Create a new stack of extensions. This stack will be used
41455e291a4SJuan Castillo 		 * to create the certificate */
4156f971622SJuan Castillo 		CHECK_NULL(sk, sk_X509_EXTENSION_new_null());
4166f971622SJuan Castillo 
41755e291a4SJuan Castillo 		for (j = 0 ; j < cert->num_ext ; j++) {
4186f971622SJuan Castillo 
41955e291a4SJuan Castillo 			ext = &extensions[cert->ext[j]];
42055e291a4SJuan Castillo 
42155e291a4SJuan Castillo 			/* Get OpenSSL internal ID for this extension */
42255e291a4SJuan Castillo 			CHECK_OID(ext_nid, ext->oid);
42355e291a4SJuan Castillo 
42455e291a4SJuan Castillo 			/*
42555e291a4SJuan Castillo 			 * Three types of extensions are currently supported:
42655e291a4SJuan Castillo 			 *     - EXT_TYPE_NVCOUNTER
42755e291a4SJuan Castillo 			 *     - EXT_TYPE_HASH
42855e291a4SJuan Castillo 			 *     - EXT_TYPE_PKEY
42955e291a4SJuan Castillo 			 */
43055e291a4SJuan Castillo 			switch (ext->type) {
43155e291a4SJuan Castillo 			case EXT_TYPE_NVCOUNTER:
432f16db56aSYatharth Kochar 				if (ext->arg) {
43396103d5aSJuan Castillo 					nvctr = atoi(ext->arg);
43455e291a4SJuan Castillo 					CHECK_NULL(cert_ext, ext_new_nvcounter(ext_nid,
43596103d5aSJuan Castillo 						EXT_CRIT, nvctr));
436f16db56aSYatharth Kochar 				}
43755e291a4SJuan Castillo 				break;
43855e291a4SJuan Castillo 			case EXT_TYPE_HASH:
43996103d5aSJuan Castillo 				if (ext->arg == NULL) {
440cebe1f23SYatharth Kochar 					if (ext->optional) {
441cebe1f23SYatharth Kochar 						/* Include a hash filled with zeros */
442cebe1f23SYatharth Kochar 						memset(md, 0x0, SHA256_DIGEST_LENGTH);
443cebe1f23SYatharth Kochar 					} else {
444cebe1f23SYatharth Kochar 						/* Do not include this hash in the certificate */
44555e291a4SJuan Castillo 						break;
44655e291a4SJuan Castillo 					}
447cebe1f23SYatharth Kochar 				} else {
448cebe1f23SYatharth Kochar 					/* Calculate the hash of the file */
44996103d5aSJuan Castillo 					if (!sha_file(ext->arg, md)) {
45055e291a4SJuan Castillo 						ERROR("Cannot calculate hash of %s\n",
45196103d5aSJuan Castillo 							ext->arg);
4526f971622SJuan Castillo 						exit(1);
4536f971622SJuan Castillo 					}
454cebe1f23SYatharth Kochar 				}
45555e291a4SJuan Castillo 				CHECK_NULL(cert_ext, ext_new_hash(ext_nid,
45655e291a4SJuan Castillo 						EXT_CRIT, md_info, md,
4576f971622SJuan Castillo 						SHA256_DIGEST_LENGTH));
45855e291a4SJuan Castillo 				break;
45955e291a4SJuan Castillo 			case EXT_TYPE_PKEY:
46055e291a4SJuan Castillo 				CHECK_NULL(cert_ext, ext_new_key(ext_nid,
46196103d5aSJuan Castillo 					EXT_CRIT, keys[ext->attr.key].key));
46255e291a4SJuan Castillo 				break;
46355e291a4SJuan Castillo 			default:
46496103d5aSJuan Castillo 				ERROR("Unknown extension type '%d' in %s\n",
46596103d5aSJuan Castillo 						ext->type, cert->cn);
46655e291a4SJuan Castillo 				exit(1);
46755e291a4SJuan Castillo 			}
46855e291a4SJuan Castillo 
46955e291a4SJuan Castillo 			/* Push the extension into the stack */
47055e291a4SJuan Castillo 			sk_X509_EXTENSION_push(sk, cert_ext);
47155e291a4SJuan Castillo 		}
4726f971622SJuan Castillo 
4736f971622SJuan Castillo 		/* Create certificate. Signed with ROT key */
474dfc90e26SJuan Castillo 		if (cert->fn && !cert_new(cert, VAL_DAYS, 0, sk)) {
47555e291a4SJuan Castillo 			ERROR("Cannot create %s\n", cert->cn);
4766f971622SJuan Castillo 			exit(1);
4776f971622SJuan Castillo 		}
4786f971622SJuan Castillo 
4796f971622SJuan Castillo 		sk_X509_EXTENSION_free(sk);
4806f971622SJuan Castillo 	}
4816f971622SJuan Castillo 
4826f971622SJuan Castillo 
4836f971622SJuan Castillo 	/* Print the certificates */
4846f971622SJuan Castillo 	if (print_cert) {
48555e291a4SJuan Castillo 		for (i = 0 ; i < num_certs ; i++) {
4866f971622SJuan Castillo 			if (!certs[i].x) {
4876f971622SJuan Castillo 				continue;
4886f971622SJuan Castillo 			}
4896f971622SJuan Castillo 			printf("\n\n=====================================\n\n");
4906f971622SJuan Castillo 			X509_print_fp(stdout, certs[i].x);
4916f971622SJuan Castillo 		}
4926f971622SJuan Castillo 	}
4936f971622SJuan Castillo 
4946f971622SJuan Castillo 	/* Save created certificates to files */
49555e291a4SJuan Castillo 	for (i = 0 ; i < num_certs ; i++) {
4966f971622SJuan Castillo 		if (certs[i].x && certs[i].fn) {
4976f971622SJuan Castillo 			file = fopen(certs[i].fn, "w");
4986f971622SJuan Castillo 			if (file != NULL) {
4996f971622SJuan Castillo 				i2d_X509_fp(file, certs[i].x);
5006f971622SJuan Castillo 				fclose(file);
5016f971622SJuan Castillo 			} else {
5026f971622SJuan Castillo 				ERROR("Cannot create file %s\n", certs[i].fn);
5036f971622SJuan Castillo 			}
5046f971622SJuan Castillo 		}
5056f971622SJuan Castillo 	}
5066f971622SJuan Castillo 
5076f971622SJuan Castillo 	/* Save keys */
5086f971622SJuan Castillo 	if (save_keys) {
50955e291a4SJuan Castillo 		for (i = 0 ; i < num_keys ; i++) {
5106f971622SJuan Castillo 			if (!key_store(&keys[i])) {
5116f971622SJuan Castillo 				ERROR("Cannot save %s\n", keys[i].desc);
5126f971622SJuan Castillo 			}
5136f971622SJuan Castillo 		}
5146f971622SJuan Castillo 	}
5156f971622SJuan Castillo 
5166f971622SJuan Castillo #ifndef OPENSSL_NO_ENGINE
5176f971622SJuan Castillo 	ENGINE_cleanup();
5186f971622SJuan Castillo #endif
5196f971622SJuan Castillo 	CRYPTO_cleanup_all_ex_data();
5206f971622SJuan Castillo 
5216f971622SJuan Castillo 	return 0;
5226f971622SJuan Castillo }
523