xref: /rk3399_ARM-atf/tools/cert_create/src/main.c (revision 600835d028a1303346a981eb6080a766806a6ae5)
16f971622SJuan Castillo /*
2bb41eb7aSMasahiro 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 
21bb41eb7aSMasahiro Yamada #if USE_TBBR_DEFS
22bb41eb7aSMasahiro Yamada #include <tbbr_oid.h>
23bb41eb7aSMasahiro Yamada #else
24bb41eb7aSMasahiro Yamada #include <platform_oid.h>
25bb41eb7aSMasahiro Yamada #endif
26bb41eb7aSMasahiro 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_cert.h"
342a4b4b71SIsla Mitchell #include "tbbr/tbb_ext.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;
712972247cSQixiang Xu static int hash_alg;
726f971622SJuan Castillo static int new_keys;
736f971622SJuan Castillo static int save_keys;
746f971622SJuan Castillo static int print_cert;
756f971622SJuan Castillo 
766f971622SJuan Castillo /* Info messages created in the Makefile */
776f971622SJuan Castillo extern const char build_msg[];
786f971622SJuan Castillo extern const char platform_msg[];
796f971622SJuan Castillo 
806f971622SJuan Castillo 
816f971622SJuan Castillo static char *strdup(const char *str)
826f971622SJuan Castillo {
836f971622SJuan Castillo 	int n = strlen(str) + 1;
846f971622SJuan Castillo 	char *dup = malloc(n);
856f971622SJuan Castillo 	if (dup) {
866f971622SJuan Castillo 		strcpy(dup, str);
876f971622SJuan Castillo 	}
886f971622SJuan Castillo 	return dup;
896f971622SJuan Castillo }
906f971622SJuan Castillo 
91ccbf890eSJuan Castillo static const char *key_algs_str[] = {
92ccbf890eSJuan Castillo 	[KEY_ALG_RSA] = "rsa",
93a8eb286aSSoby Mathew 	[KEY_ALG_RSA_1_5] = "rsa_1_5",
94ed2a76eaSJuan Castillo #ifndef OPENSSL_NO_EC
95ccbf890eSJuan Castillo 	[KEY_ALG_ECDSA] = "ecdsa"
96ed2a76eaSJuan Castillo #endif /* OPENSSL_NO_EC */
97ccbf890eSJuan Castillo };
98ccbf890eSJuan Castillo 
992972247cSQixiang Xu static const char *hash_algs_str[] = {
1002972247cSQixiang Xu 	[HASH_ALG_SHA256] = "sha256",
1012972247cSQixiang Xu 	[HASH_ALG_SHA384] = "sha384",
1022972247cSQixiang Xu 	[HASH_ALG_SHA512] = "sha512",
1032972247cSQixiang Xu };
1042972247cSQixiang Xu 
105ad2c1a9aSJuan Castillo static void print_help(const char *cmd, const struct option *long_opt)
1066f971622SJuan Castillo {
107159807e2SJuan Castillo 	int rem, i = 0;
108159807e2SJuan Castillo 	const struct option *opt;
109159807e2SJuan Castillo 	char line[HELP_OPT_MAX_LEN];
110159807e2SJuan Castillo 	char *p;
111159807e2SJuan Castillo 
112159807e2SJuan Castillo 	assert(cmd != NULL);
113159807e2SJuan Castillo 	assert(long_opt != NULL);
114159807e2SJuan Castillo 
1156f971622SJuan Castillo 	printf("\n\n");
1166f971622SJuan Castillo 	printf("The certificate generation tool loads the binary images and\n"
1176f971622SJuan Castillo 	       "optionally the RSA keys, and outputs the key and content\n"
1186f971622SJuan Castillo 	       "certificates properly signed to implement the chain of trust.\n"
1196f971622SJuan Castillo 	       "If keys are provided, they must be in PEM format.\n"
1206f971622SJuan Castillo 	       "Certificates are generated in DER format.\n");
1216f971622SJuan Castillo 	printf("\n");
122159807e2SJuan Castillo 	printf("Usage:\n");
123159807e2SJuan Castillo 	printf("\t%s [OPTIONS]\n\n", cmd);
124159807e2SJuan Castillo 
125159807e2SJuan Castillo 	printf("Available options:\n");
126159807e2SJuan Castillo 	opt = long_opt;
127159807e2SJuan Castillo 	while (opt->name) {
128159807e2SJuan Castillo 		p = line;
129159807e2SJuan Castillo 		rem = HELP_OPT_MAX_LEN;
130159807e2SJuan Castillo 		if (isalpha(opt->val)) {
131159807e2SJuan Castillo 			/* Short format */
132159807e2SJuan Castillo 			sprintf(p, "-%c,", (char)opt->val);
133159807e2SJuan Castillo 			p += 3;
134159807e2SJuan Castillo 			rem -= 3;
1356f971622SJuan Castillo 		}
136159807e2SJuan Castillo 		snprintf(p, rem, "--%s %s", opt->name,
137159807e2SJuan Castillo 			 (opt->has_arg == required_argument) ? "<arg>" : "");
138159807e2SJuan Castillo 		printf("\t%-32s %s\n", line, cmd_opt_get_help_msg(i));
139159807e2SJuan Castillo 		opt++;
140159807e2SJuan Castillo 		i++;
141159807e2SJuan Castillo 	}
1426f971622SJuan Castillo 	printf("\n");
1436f971622SJuan Castillo }
1446f971622SJuan Castillo 
145ccbf890eSJuan Castillo static int get_key_alg(const char *key_alg_str)
146ccbf890eSJuan Castillo {
147ccbf890eSJuan Castillo 	int i;
148ccbf890eSJuan Castillo 
149ccbf890eSJuan Castillo 	for (i = 0 ; i < NUM_ELEM(key_algs_str) ; i++) {
150ccbf890eSJuan Castillo 		if (0 == strcmp(key_alg_str, key_algs_str[i])) {
151ccbf890eSJuan Castillo 			return i;
152ccbf890eSJuan Castillo 		}
153ccbf890eSJuan Castillo 	}
154ccbf890eSJuan Castillo 
155ccbf890eSJuan Castillo 	return -1;
156ccbf890eSJuan Castillo }
157ccbf890eSJuan Castillo 
1582972247cSQixiang Xu static int get_hash_alg(const char *hash_alg_str)
1592972247cSQixiang Xu {
1602972247cSQixiang Xu 	int i;
1612972247cSQixiang Xu 
1622972247cSQixiang Xu 	for (i = 0 ; i < NUM_ELEM(hash_algs_str) ; i++) {
1632972247cSQixiang Xu 		if (0 == strcmp(hash_alg_str, hash_algs_str[i])) {
1642972247cSQixiang Xu 			return i;
1652972247cSQixiang Xu 		}
1662972247cSQixiang Xu 	}
1672972247cSQixiang Xu 
1682972247cSQixiang Xu 	return -1;
1692972247cSQixiang Xu }
1702972247cSQixiang Xu 
1716f971622SJuan Castillo static void check_cmd_params(void)
1726f971622SJuan Castillo {
173dfc90e26SJuan Castillo 	cert_t *cert;
174dfc90e26SJuan Castillo 	ext_t *ext;
175dfc90e26SJuan Castillo 	key_t *key;
176dfc90e26SJuan Castillo 	int i, j;
177dfc90e26SJuan Castillo 
178ccbf890eSJuan Castillo 	/* Only save new keys */
179ccbf890eSJuan Castillo 	if (save_keys && !new_keys) {
180ccbf890eSJuan Castillo 		ERROR("Only new keys can be saved to disk\n");
181ccbf890eSJuan Castillo 		exit(1);
182ccbf890eSJuan Castillo 	}
183ccbf890eSJuan Castillo 
184dfc90e26SJuan Castillo 	/* Check that all required options have been specified in the
185dfc90e26SJuan Castillo 	 * command line */
186dfc90e26SJuan Castillo 	for (i = 0; i < num_certs; i++) {
187dfc90e26SJuan Castillo 		cert = &certs[i];
188dfc90e26SJuan Castillo 		if (cert->fn == NULL) {
189dfc90e26SJuan Castillo 			/* Certificate not requested. Skip to the next one */
190dfc90e26SJuan Castillo 			continue;
191dfc90e26SJuan Castillo 		}
192dfc90e26SJuan Castillo 
193dfc90e26SJuan Castillo 		/* Check that all parameters required to create this certificate
194dfc90e26SJuan Castillo 		 * have been specified in the command line */
195dfc90e26SJuan Castillo 		for (j = 0; j < cert->num_ext; j++) {
196dfc90e26SJuan Castillo 			ext = &extensions[cert->ext[j]];
197dfc90e26SJuan Castillo 			switch (ext->type) {
19896103d5aSJuan Castillo 			case EXT_TYPE_NVCOUNTER:
19996103d5aSJuan Castillo 				/* Counter value must be specified */
20096103d5aSJuan Castillo 				if ((!ext->optional) && (ext->arg == NULL)) {
20196103d5aSJuan Castillo 					ERROR("Value for '%s' not specified\n",
20296103d5aSJuan Castillo 					      ext->ln);
20396103d5aSJuan Castillo 					exit(1);
20496103d5aSJuan Castillo 				}
20596103d5aSJuan Castillo 				break;
206dfc90e26SJuan Castillo 			case EXT_TYPE_PKEY:
207dfc90e26SJuan Castillo 				/* Key filename must be specified */
20896103d5aSJuan Castillo 				key = &keys[ext->attr.key];
209dfc90e26SJuan Castillo 				if (!new_keys && key->fn == NULL) {
210dfc90e26SJuan Castillo 					ERROR("Key '%s' required by '%s' not "
211dfc90e26SJuan Castillo 					      "specified\n", key->desc,
212dfc90e26SJuan Castillo 					      cert->cn);
2136f971622SJuan Castillo 					exit(1);
2146f971622SJuan Castillo 				}
215dfc90e26SJuan Castillo 				break;
216dfc90e26SJuan Castillo 			case EXT_TYPE_HASH:
217cebe1f23SYatharth Kochar 				/*
218cebe1f23SYatharth Kochar 				 * Binary image must be specified
219cebe1f23SYatharth Kochar 				 * unless it is explicitly made optional.
220cebe1f23SYatharth Kochar 				 */
22196103d5aSJuan Castillo 				if ((!ext->optional) && (ext->arg == NULL)) {
222dfc90e26SJuan Castillo 					ERROR("Image for '%s' not specified\n",
223dfc90e26SJuan Castillo 					      ext->ln);
2246f971622SJuan Castillo 					exit(1);
2256f971622SJuan Castillo 				}
226dfc90e26SJuan Castillo 				break;
227dfc90e26SJuan Castillo 			default:
22896103d5aSJuan Castillo 				ERROR("Unknown extension type '%d' in '%s'\n",
22996103d5aSJuan Castillo 				      ext->type, ext->ln);
2306f971622SJuan Castillo 				exit(1);
231dfc90e26SJuan Castillo 				break;
2326f971622SJuan Castillo 			}
2336f971622SJuan Castillo 		}
2346f971622SJuan Castillo 	}
2356f971622SJuan Castillo }
2366f971622SJuan Castillo 
237159807e2SJuan Castillo /* Common command line options */
238159807e2SJuan Castillo static const cmd_opt_t common_cmd_opt[] = {
239159807e2SJuan Castillo 	{
240159807e2SJuan Castillo 		{ "help", no_argument, NULL, 'h' },
241159807e2SJuan Castillo 		"Print this message and exit"
242159807e2SJuan Castillo 	},
243159807e2SJuan Castillo 	{
244159807e2SJuan Castillo 		{ "key-alg", required_argument, NULL, 'a' },
245a8eb286aSSoby Mathew 		"Key algorithm: 'rsa' (default) - RSAPSS scheme as per \
246a8eb286aSSoby Mathew PKCS#1 v2.1, 'rsa_1_5' - RSA PKCS#1 v1.5, 'ecdsa'"
247159807e2SJuan Castillo 	},
248159807e2SJuan Castillo 	{
2492972247cSQixiang Xu 		{ "hash-alg", required_argument, NULL, 's' },
2502972247cSQixiang Xu 		"Hash algorithm : 'sha256' (default), 'sha384', 'sha512'"
2512972247cSQixiang Xu 	},
2522972247cSQixiang Xu 	{
253159807e2SJuan Castillo 		{ "save-keys", no_argument, NULL, 'k' },
254159807e2SJuan Castillo 		"Save key pairs into files. Filenames must be provided"
255159807e2SJuan Castillo 	},
256159807e2SJuan Castillo 	{
257159807e2SJuan Castillo 		{ "new-keys", no_argument, NULL, 'n' },
258159807e2SJuan Castillo 		"Generate new key pairs if no key files are provided"
259159807e2SJuan Castillo 	},
260159807e2SJuan Castillo 	{
261159807e2SJuan Castillo 		{ "print-cert", no_argument, NULL, 'p' },
262159807e2SJuan Castillo 		"Print the certificates in the standard output"
263159807e2SJuan Castillo 	}
264159807e2SJuan Castillo };
265159807e2SJuan Castillo 
2666f971622SJuan Castillo int main(int argc, char *argv[])
2676f971622SJuan Castillo {
268c893c733SMasahiro Yamada 	STACK_OF(X509_EXTENSION) * sk;
269742c4e14SMichalis Pappas 	X509_EXTENSION *cert_ext = NULL;
270c893c733SMasahiro Yamada 	ext_t *ext;
271c893c733SMasahiro Yamada 	key_t *key;
272c893c733SMasahiro Yamada 	cert_t *cert;
273c893c733SMasahiro Yamada 	FILE *file;
27496103d5aSJuan Castillo 	int i, j, ext_nid, nvctr;
2756f971622SJuan Castillo 	int c, opt_idx = 0;
276ad2c1a9aSJuan Castillo 	const struct option *cmd_opt;
277ad2c1a9aSJuan Castillo 	const char *cur_opt;
278ccbf890eSJuan Castillo 	unsigned int err_code;
2792972247cSQixiang Xu 	unsigned char md[SHA512_DIGEST_LENGTH];
2802972247cSQixiang Xu 	unsigned int  md_len;
281c3da66b1SJuan Castillo 	const EVP_MD *md_info;
2826f971622SJuan Castillo 
2836f971622SJuan Castillo 	NOTICE("CoT Generation Tool: %s\n", build_msg);
2846f971622SJuan Castillo 	NOTICE("Target platform: %s\n", platform_msg);
2856f971622SJuan Castillo 
286ccbf890eSJuan Castillo 	/* Set default options */
287ccbf890eSJuan Castillo 	key_alg = KEY_ALG_RSA;
2882972247cSQixiang Xu 	hash_alg = HASH_ALG_SHA256;
289ccbf890eSJuan Castillo 
290ad2c1a9aSJuan Castillo 	/* Add common command line options */
291159807e2SJuan Castillo 	for (i = 0; i < NUM_ELEM(common_cmd_opt); i++) {
292159807e2SJuan Castillo 		cmd_opt_add(&common_cmd_opt[i]);
293159807e2SJuan Castillo 	}
294ad2c1a9aSJuan Castillo 
295ad2c1a9aSJuan Castillo 	/* Initialize the certificates */
296ad2c1a9aSJuan Castillo 	if (cert_init() != 0) {
297ad2c1a9aSJuan Castillo 		ERROR("Cannot initialize certificates\n");
298ad2c1a9aSJuan Castillo 		exit(1);
299ad2c1a9aSJuan Castillo 	}
300ad2c1a9aSJuan Castillo 
301ad2c1a9aSJuan Castillo 	/* Initialize the keys */
302ad2c1a9aSJuan Castillo 	if (key_init() != 0) {
303ad2c1a9aSJuan Castillo 		ERROR("Cannot initialize keys\n");
304ad2c1a9aSJuan Castillo 		exit(1);
305ad2c1a9aSJuan Castillo 	}
306ad2c1a9aSJuan Castillo 
307ad2c1a9aSJuan Castillo 	/* Initialize the new types and register OIDs for the extensions */
308ad2c1a9aSJuan Castillo 	if (ext_init() != 0) {
309ad2c1a9aSJuan Castillo 		ERROR("Cannot initialize TBB extensions\n");
310ad2c1a9aSJuan Castillo 		exit(1);
311ad2c1a9aSJuan Castillo 	}
312ad2c1a9aSJuan Castillo 
313ad2c1a9aSJuan Castillo 	/* Get the command line options populated during the initialization */
314ad2c1a9aSJuan Castillo 	cmd_opt = cmd_opt_get_array();
315ad2c1a9aSJuan Castillo 
3166f971622SJuan Castillo 	while (1) {
3176f971622SJuan Castillo 		/* getopt_long stores the option index here. */
3182972247cSQixiang Xu 		c = getopt_long(argc, argv, "a:hknps:", cmd_opt, &opt_idx);
3196f971622SJuan Castillo 
3206f971622SJuan Castillo 		/* Detect the end of the options. */
3216f971622SJuan Castillo 		if (c == -1) {
3226f971622SJuan Castillo 			break;
3236f971622SJuan Castillo 		}
3246f971622SJuan Castillo 
3256f971622SJuan Castillo 		switch (c) {
326ccbf890eSJuan Castillo 		case 'a':
327ccbf890eSJuan Castillo 			key_alg = get_key_alg(optarg);
328ccbf890eSJuan Castillo 			if (key_alg < 0) {
329ccbf890eSJuan Castillo 				ERROR("Invalid key algorithm '%s'\n", optarg);
330ccbf890eSJuan Castillo 				exit(1);
331ccbf890eSJuan Castillo 			}
332ccbf890eSJuan Castillo 			break;
3336f971622SJuan Castillo 		case 'h':
334ad2c1a9aSJuan Castillo 			print_help(argv[0], cmd_opt);
335*600835d0SRoberto Vargas 			exit(0);
3366f971622SJuan Castillo 		case 'k':
3376f971622SJuan Castillo 			save_keys = 1;
3386f971622SJuan Castillo 			break;
3396f971622SJuan Castillo 		case 'n':
3406f971622SJuan Castillo 			new_keys = 1;
3416f971622SJuan Castillo 			break;
3426f971622SJuan Castillo 		case 'p':
3436f971622SJuan Castillo 			print_cert = 1;
3446f971622SJuan Castillo 			break;
3452972247cSQixiang Xu 		case 's':
3462972247cSQixiang Xu 			hash_alg = get_hash_alg(optarg);
3472972247cSQixiang Xu 			if (hash_alg < 0) {
3482972247cSQixiang Xu 				ERROR("Invalid hash algorithm '%s'\n", optarg);
3492972247cSQixiang Xu 				exit(1);
3502972247cSQixiang Xu 			}
3512972247cSQixiang Xu 			break;
352ad2c1a9aSJuan Castillo 		case CMD_OPT_EXT:
353ad2c1a9aSJuan Castillo 			cur_opt = cmd_opt_get_name(opt_idx);
354ad2c1a9aSJuan Castillo 			ext = ext_get_by_opt(cur_opt);
35596103d5aSJuan Castillo 			ext->arg = strdup(optarg);
3566f971622SJuan Castillo 			break;
357ad2c1a9aSJuan Castillo 		case CMD_OPT_KEY:
358ad2c1a9aSJuan Castillo 			cur_opt = cmd_opt_get_name(opt_idx);
359ad2c1a9aSJuan Castillo 			key = key_get_by_opt(cur_opt);
360ad2c1a9aSJuan Castillo 			key->fn = strdup(optarg);
3616f971622SJuan Castillo 			break;
362ad2c1a9aSJuan Castillo 		case CMD_OPT_CERT:
363ad2c1a9aSJuan Castillo 			cur_opt = cmd_opt_get_name(opt_idx);
364ad2c1a9aSJuan Castillo 			cert = cert_get_by_opt(cur_opt);
365ad2c1a9aSJuan Castillo 			cert->fn = strdup(optarg);
3666f971622SJuan Castillo 			break;
3676f971622SJuan Castillo 		case '?':
3686f971622SJuan Castillo 		default:
369159807e2SJuan Castillo 			print_help(argv[0], cmd_opt);
3706f971622SJuan Castillo 			exit(1);
3716f971622SJuan Castillo 		}
3726f971622SJuan Castillo 	}
3736f971622SJuan Castillo 
3746f971622SJuan Castillo 	/* Check command line arguments */
3756f971622SJuan Castillo 	check_cmd_params();
3766f971622SJuan Castillo 
3772972247cSQixiang Xu 	/* Indicate SHA as image hash algorithm in the certificate
378c3da66b1SJuan Castillo 	 * extension */
3792972247cSQixiang Xu 	if (hash_alg == HASH_ALG_SHA384) {
3802972247cSQixiang Xu 		md_info = EVP_sha384();
3812972247cSQixiang Xu 		md_len  = SHA384_DIGEST_LENGTH;
3822972247cSQixiang Xu 	} else if (hash_alg == HASH_ALG_SHA512) {
3832972247cSQixiang Xu 		md_info = EVP_sha512();
3842972247cSQixiang Xu 		md_len  = SHA512_DIGEST_LENGTH;
3852972247cSQixiang Xu 	} else {
386c3da66b1SJuan Castillo 		md_info = EVP_sha256();
3872972247cSQixiang Xu 		md_len  = SHA256_DIGEST_LENGTH;
3882972247cSQixiang Xu 	}
389c3da66b1SJuan Castillo 
3906f971622SJuan Castillo 	/* Load private keys from files (or generate new ones) */
39155e291a4SJuan Castillo 	for (i = 0 ; i < num_keys ; i++) {
392762f1ebeSMasahiro Yamada 		if (!key_new(&keys[i])) {
393762f1ebeSMasahiro Yamada 			ERROR("Failed to allocate key container\n");
394762f1ebeSMasahiro Yamada 			exit(1);
395762f1ebeSMasahiro Yamada 		}
396762f1ebeSMasahiro Yamada 
397ccbf890eSJuan Castillo 		/* First try to load the key from disk */
398ccbf890eSJuan Castillo 		if (key_load(&keys[i], &err_code)) {
399ccbf890eSJuan Castillo 			/* Key loaded successfully */
400ccbf890eSJuan Castillo 			continue;
401ccbf890eSJuan Castillo 		}
402ccbf890eSJuan Castillo 
403ccbf890eSJuan Castillo 		/* Key not loaded. Check the error code */
404762f1ebeSMasahiro Yamada 		if (err_code == KEY_ERR_LOAD) {
405ccbf890eSJuan Castillo 			/* File exists, but it does not contain a valid private
406ccbf890eSJuan Castillo 			 * key. Abort. */
407ccbf890eSJuan Castillo 			ERROR("Error loading '%s'\n", keys[i].fn);
4086f971622SJuan Castillo 			exit(1);
4096f971622SJuan Castillo 		}
410ccbf890eSJuan Castillo 
411ccbf890eSJuan Castillo 		/* File does not exist, could not be opened or no filename was
412ccbf890eSJuan Castillo 		 * given */
413ccbf890eSJuan Castillo 		if (new_keys) {
414ccbf890eSJuan Castillo 			/* Try to create a new key */
415ccbf890eSJuan Castillo 			NOTICE("Creating new key for '%s'\n", keys[i].desc);
416ccbf890eSJuan Castillo 			if (!key_create(&keys[i], key_alg)) {
417ccbf890eSJuan Castillo 				ERROR("Error creating key '%s'\n", keys[i].desc);
418ccbf890eSJuan Castillo 				exit(1);
4196f971622SJuan Castillo 			}
4206f971622SJuan Castillo 		} else {
421ccbf890eSJuan Castillo 			if (err_code == KEY_ERR_OPEN) {
422ccbf890eSJuan Castillo 				ERROR("Error opening '%s'\n", keys[i].fn);
423ccbf890eSJuan Castillo 			} else {
424ccbf890eSJuan Castillo 				ERROR("Key '%s' not specified\n", keys[i].desc);
4256f971622SJuan Castillo 			}
426ccbf890eSJuan Castillo 			exit(1);
4276f971622SJuan Castillo 		}
4286f971622SJuan Castillo 	}
4296f971622SJuan Castillo 
43055e291a4SJuan Castillo 	/* Create the certificates */
43155e291a4SJuan Castillo 	for (i = 0 ; i < num_certs ; i++) {
43255e291a4SJuan Castillo 
43355e291a4SJuan Castillo 		cert = &certs[i];
43455e291a4SJuan Castillo 
43555e291a4SJuan Castillo 		/* Create a new stack of extensions. This stack will be used
43655e291a4SJuan Castillo 		 * to create the certificate */
4376f971622SJuan Castillo 		CHECK_NULL(sk, sk_X509_EXTENSION_new_null());
4386f971622SJuan Castillo 
43955e291a4SJuan Castillo 		for (j = 0 ; j < cert->num_ext ; j++) {
4406f971622SJuan Castillo 
44155e291a4SJuan Castillo 			ext = &extensions[cert->ext[j]];
44255e291a4SJuan Castillo 
44355e291a4SJuan Castillo 			/* Get OpenSSL internal ID for this extension */
44455e291a4SJuan Castillo 			CHECK_OID(ext_nid, ext->oid);
44555e291a4SJuan Castillo 
44655e291a4SJuan Castillo 			/*
44755e291a4SJuan Castillo 			 * Three types of extensions are currently supported:
44855e291a4SJuan Castillo 			 *     - EXT_TYPE_NVCOUNTER
44955e291a4SJuan Castillo 			 *     - EXT_TYPE_HASH
45055e291a4SJuan Castillo 			 *     - EXT_TYPE_PKEY
45155e291a4SJuan Castillo 			 */
45255e291a4SJuan Castillo 			switch (ext->type) {
45355e291a4SJuan Castillo 			case EXT_TYPE_NVCOUNTER:
454f16db56aSYatharth Kochar 				if (ext->arg) {
45596103d5aSJuan Castillo 					nvctr = atoi(ext->arg);
45655e291a4SJuan Castillo 					CHECK_NULL(cert_ext, ext_new_nvcounter(ext_nid,
45796103d5aSJuan Castillo 						EXT_CRIT, nvctr));
458f16db56aSYatharth Kochar 				}
45955e291a4SJuan Castillo 				break;
46055e291a4SJuan Castillo 			case EXT_TYPE_HASH:
46196103d5aSJuan Castillo 				if (ext->arg == NULL) {
462cebe1f23SYatharth Kochar 					if (ext->optional) {
463cebe1f23SYatharth Kochar 						/* Include a hash filled with zeros */
4642972247cSQixiang Xu 						memset(md, 0x0, SHA512_DIGEST_LENGTH);
465cebe1f23SYatharth Kochar 					} else {
466cebe1f23SYatharth Kochar 						/* Do not include this hash in the certificate */
46755e291a4SJuan Castillo 						break;
46855e291a4SJuan Castillo 					}
469cebe1f23SYatharth Kochar 				} else {
470cebe1f23SYatharth Kochar 					/* Calculate the hash of the file */
4712972247cSQixiang Xu 					if (!sha_file(hash_alg, ext->arg, md)) {
47255e291a4SJuan Castillo 						ERROR("Cannot calculate hash of %s\n",
47396103d5aSJuan Castillo 							ext->arg);
4746f971622SJuan Castillo 						exit(1);
4756f971622SJuan Castillo 					}
476cebe1f23SYatharth Kochar 				}
47755e291a4SJuan Castillo 				CHECK_NULL(cert_ext, ext_new_hash(ext_nid,
47855e291a4SJuan Castillo 						EXT_CRIT, md_info, md,
4792972247cSQixiang Xu 						md_len));
48055e291a4SJuan Castillo 				break;
48155e291a4SJuan Castillo 			case EXT_TYPE_PKEY:
48255e291a4SJuan Castillo 				CHECK_NULL(cert_ext, ext_new_key(ext_nid,
48396103d5aSJuan Castillo 					EXT_CRIT, keys[ext->attr.key].key));
48455e291a4SJuan Castillo 				break;
48555e291a4SJuan Castillo 			default:
48696103d5aSJuan Castillo 				ERROR("Unknown extension type '%d' in %s\n",
48796103d5aSJuan Castillo 						ext->type, cert->cn);
48855e291a4SJuan Castillo 				exit(1);
48955e291a4SJuan Castillo 			}
49055e291a4SJuan Castillo 
49155e291a4SJuan Castillo 			/* Push the extension into the stack */
49255e291a4SJuan Castillo 			sk_X509_EXTENSION_push(sk, cert_ext);
49355e291a4SJuan Castillo 		}
4946f971622SJuan Castillo 
495a8eb286aSSoby Mathew 		/* Create certificate. Signed with corresponding key */
4962972247cSQixiang Xu 		if (cert->fn && !cert_new(key_alg, hash_alg, cert, VAL_DAYS, 0, sk)) {
49755e291a4SJuan Castillo 			ERROR("Cannot create %s\n", cert->cn);
4986f971622SJuan Castillo 			exit(1);
4996f971622SJuan Castillo 		}
5006f971622SJuan Castillo 
5016f971622SJuan Castillo 		sk_X509_EXTENSION_free(sk);
5026f971622SJuan Castillo 	}
5036f971622SJuan Castillo 
5046f971622SJuan Castillo 
5056f971622SJuan Castillo 	/* Print the certificates */
5066f971622SJuan Castillo 	if (print_cert) {
50755e291a4SJuan Castillo 		for (i = 0 ; i < num_certs ; i++) {
5086f971622SJuan Castillo 			if (!certs[i].x) {
5096f971622SJuan Castillo 				continue;
5106f971622SJuan Castillo 			}
5116f971622SJuan Castillo 			printf("\n\n=====================================\n\n");
5126f971622SJuan Castillo 			X509_print_fp(stdout, certs[i].x);
5136f971622SJuan Castillo 		}
5146f971622SJuan Castillo 	}
5156f971622SJuan Castillo 
5166f971622SJuan Castillo 	/* Save created certificates to files */
51755e291a4SJuan Castillo 	for (i = 0 ; i < num_certs ; i++) {
5186f971622SJuan Castillo 		if (certs[i].x && certs[i].fn) {
5196f971622SJuan Castillo 			file = fopen(certs[i].fn, "w");
5206f971622SJuan Castillo 			if (file != NULL) {
5216f971622SJuan Castillo 				i2d_X509_fp(file, certs[i].x);
5226f971622SJuan Castillo 				fclose(file);
5236f971622SJuan Castillo 			} else {
5246f971622SJuan Castillo 				ERROR("Cannot create file %s\n", certs[i].fn);
5256f971622SJuan Castillo 			}
5266f971622SJuan Castillo 		}
5276f971622SJuan Castillo 	}
5286f971622SJuan Castillo 
5296f971622SJuan Castillo 	/* Save keys */
5306f971622SJuan Castillo 	if (save_keys) {
53155e291a4SJuan Castillo 		for (i = 0 ; i < num_keys ; i++) {
5326f971622SJuan Castillo 			if (!key_store(&keys[i])) {
5336f971622SJuan Castillo 				ERROR("Cannot save %s\n", keys[i].desc);
5346f971622SJuan Castillo 			}
5356f971622SJuan Castillo 		}
5366f971622SJuan Castillo 	}
5376f971622SJuan Castillo 
5386f971622SJuan Castillo #ifndef OPENSSL_NO_ENGINE
5396f971622SJuan Castillo 	ENGINE_cleanup();
5406f971622SJuan Castillo #endif
5416f971622SJuan Castillo 	CRYPTO_cleanup_all_ex_data();
5426f971622SJuan Castillo 
5436f971622SJuan Castillo 	return 0;
5446f971622SJuan Castillo }
545