xref: /rk3399_ARM-atf/tools/cert_create/src/main.c (revision 2972247cb4ae84ed660532cac426259a4f17c816)
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;
71*2972247cSQixiang 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 
99*2972247cSQixiang Xu static const char *hash_algs_str[] = {
100*2972247cSQixiang Xu 	[HASH_ALG_SHA256] = "sha256",
101*2972247cSQixiang Xu 	[HASH_ALG_SHA384] = "sha384",
102*2972247cSQixiang Xu 	[HASH_ALG_SHA512] = "sha512",
103*2972247cSQixiang Xu };
104*2972247cSQixiang 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 	exit(0);
1456f971622SJuan Castillo }
1466f971622SJuan Castillo 
147ccbf890eSJuan Castillo static int get_key_alg(const char *key_alg_str)
148ccbf890eSJuan Castillo {
149ccbf890eSJuan Castillo 	int i;
150ccbf890eSJuan Castillo 
151ccbf890eSJuan Castillo 	for (i = 0 ; i < NUM_ELEM(key_algs_str) ; i++) {
152ccbf890eSJuan Castillo 		if (0 == strcmp(key_alg_str, key_algs_str[i])) {
153ccbf890eSJuan Castillo 			return i;
154ccbf890eSJuan Castillo 		}
155ccbf890eSJuan Castillo 	}
156ccbf890eSJuan Castillo 
157ccbf890eSJuan Castillo 	return -1;
158ccbf890eSJuan Castillo }
159ccbf890eSJuan Castillo 
160*2972247cSQixiang Xu static int get_hash_alg(const char *hash_alg_str)
161*2972247cSQixiang Xu {
162*2972247cSQixiang Xu 	int i;
163*2972247cSQixiang Xu 
164*2972247cSQixiang Xu 	for (i = 0 ; i < NUM_ELEM(hash_algs_str) ; i++) {
165*2972247cSQixiang Xu 		if (0 == strcmp(hash_alg_str, hash_algs_str[i])) {
166*2972247cSQixiang Xu 			return i;
167*2972247cSQixiang Xu 		}
168*2972247cSQixiang Xu 	}
169*2972247cSQixiang Xu 
170*2972247cSQixiang Xu 	return -1;
171*2972247cSQixiang Xu }
172*2972247cSQixiang Xu 
1736f971622SJuan Castillo static void check_cmd_params(void)
1746f971622SJuan Castillo {
175dfc90e26SJuan Castillo 	cert_t *cert;
176dfc90e26SJuan Castillo 	ext_t *ext;
177dfc90e26SJuan Castillo 	key_t *key;
178dfc90e26SJuan Castillo 	int i, j;
179dfc90e26SJuan Castillo 
180ccbf890eSJuan Castillo 	/* Only save new keys */
181ccbf890eSJuan Castillo 	if (save_keys && !new_keys) {
182ccbf890eSJuan Castillo 		ERROR("Only new keys can be saved to disk\n");
183ccbf890eSJuan Castillo 		exit(1);
184ccbf890eSJuan Castillo 	}
185ccbf890eSJuan Castillo 
186dfc90e26SJuan Castillo 	/* Check that all required options have been specified in the
187dfc90e26SJuan Castillo 	 * command line */
188dfc90e26SJuan Castillo 	for (i = 0; i < num_certs; i++) {
189dfc90e26SJuan Castillo 		cert = &certs[i];
190dfc90e26SJuan Castillo 		if (cert->fn == NULL) {
191dfc90e26SJuan Castillo 			/* Certificate not requested. Skip to the next one */
192dfc90e26SJuan Castillo 			continue;
193dfc90e26SJuan Castillo 		}
194dfc90e26SJuan Castillo 
195dfc90e26SJuan Castillo 		/* Check that all parameters required to create this certificate
196dfc90e26SJuan Castillo 		 * have been specified in the command line */
197dfc90e26SJuan Castillo 		for (j = 0; j < cert->num_ext; j++) {
198dfc90e26SJuan Castillo 			ext = &extensions[cert->ext[j]];
199dfc90e26SJuan Castillo 			switch (ext->type) {
20096103d5aSJuan Castillo 			case EXT_TYPE_NVCOUNTER:
20196103d5aSJuan Castillo 				/* Counter value must be specified */
20296103d5aSJuan Castillo 				if ((!ext->optional) && (ext->arg == NULL)) {
20396103d5aSJuan Castillo 					ERROR("Value for '%s' not specified\n",
20496103d5aSJuan Castillo 					      ext->ln);
20596103d5aSJuan Castillo 					exit(1);
20696103d5aSJuan Castillo 				}
20796103d5aSJuan Castillo 				break;
208dfc90e26SJuan Castillo 			case EXT_TYPE_PKEY:
209dfc90e26SJuan Castillo 				/* Key filename must be specified */
21096103d5aSJuan Castillo 				key = &keys[ext->attr.key];
211dfc90e26SJuan Castillo 				if (!new_keys && key->fn == NULL) {
212dfc90e26SJuan Castillo 					ERROR("Key '%s' required by '%s' not "
213dfc90e26SJuan Castillo 					      "specified\n", key->desc,
214dfc90e26SJuan Castillo 					      cert->cn);
2156f971622SJuan Castillo 					exit(1);
2166f971622SJuan Castillo 				}
217dfc90e26SJuan Castillo 				break;
218dfc90e26SJuan Castillo 			case EXT_TYPE_HASH:
219cebe1f23SYatharth Kochar 				/*
220cebe1f23SYatharth Kochar 				 * Binary image must be specified
221cebe1f23SYatharth Kochar 				 * unless it is explicitly made optional.
222cebe1f23SYatharth Kochar 				 */
22396103d5aSJuan Castillo 				if ((!ext->optional) && (ext->arg == NULL)) {
224dfc90e26SJuan Castillo 					ERROR("Image for '%s' not specified\n",
225dfc90e26SJuan Castillo 					      ext->ln);
2266f971622SJuan Castillo 					exit(1);
2276f971622SJuan Castillo 				}
228dfc90e26SJuan Castillo 				break;
229dfc90e26SJuan Castillo 			default:
23096103d5aSJuan Castillo 				ERROR("Unknown extension type '%d' in '%s'\n",
23196103d5aSJuan Castillo 				      ext->type, ext->ln);
2326f971622SJuan Castillo 				exit(1);
233dfc90e26SJuan Castillo 				break;
2346f971622SJuan Castillo 			}
2356f971622SJuan Castillo 		}
2366f971622SJuan Castillo 	}
2376f971622SJuan Castillo }
2386f971622SJuan Castillo 
239159807e2SJuan Castillo /* Common command line options */
240159807e2SJuan Castillo static const cmd_opt_t common_cmd_opt[] = {
241159807e2SJuan Castillo 	{
242159807e2SJuan Castillo 		{ "help", no_argument, NULL, 'h' },
243159807e2SJuan Castillo 		"Print this message and exit"
244159807e2SJuan Castillo 	},
245159807e2SJuan Castillo 	{
246159807e2SJuan Castillo 		{ "key-alg", required_argument, NULL, 'a' },
247a8eb286aSSoby Mathew 		"Key algorithm: 'rsa' (default) - RSAPSS scheme as per \
248a8eb286aSSoby Mathew PKCS#1 v2.1, 'rsa_1_5' - RSA PKCS#1 v1.5, 'ecdsa'"
249159807e2SJuan Castillo 	},
250159807e2SJuan Castillo 	{
251*2972247cSQixiang Xu 		{ "hash-alg", required_argument, NULL, 's' },
252*2972247cSQixiang Xu 		"Hash algorithm : 'sha256' (default), 'sha384', 'sha512'"
253*2972247cSQixiang Xu 	},
254*2972247cSQixiang Xu 	{
255159807e2SJuan Castillo 		{ "save-keys", no_argument, NULL, 'k' },
256159807e2SJuan Castillo 		"Save key pairs into files. Filenames must be provided"
257159807e2SJuan Castillo 	},
258159807e2SJuan Castillo 	{
259159807e2SJuan Castillo 		{ "new-keys", no_argument, NULL, 'n' },
260159807e2SJuan Castillo 		"Generate new key pairs if no key files are provided"
261159807e2SJuan Castillo 	},
262159807e2SJuan Castillo 	{
263159807e2SJuan Castillo 		{ "print-cert", no_argument, NULL, 'p' },
264159807e2SJuan Castillo 		"Print the certificates in the standard output"
265159807e2SJuan Castillo 	}
266159807e2SJuan Castillo };
267159807e2SJuan Castillo 
2686f971622SJuan Castillo int main(int argc, char *argv[])
2696f971622SJuan Castillo {
270c893c733SMasahiro Yamada 	STACK_OF(X509_EXTENSION) * sk;
271742c4e14SMichalis Pappas 	X509_EXTENSION *cert_ext = NULL;
272c893c733SMasahiro Yamada 	ext_t *ext;
273c893c733SMasahiro Yamada 	key_t *key;
274c893c733SMasahiro Yamada 	cert_t *cert;
275c893c733SMasahiro Yamada 	FILE *file;
27696103d5aSJuan Castillo 	int i, j, ext_nid, nvctr;
2776f971622SJuan Castillo 	int c, opt_idx = 0;
278ad2c1a9aSJuan Castillo 	const struct option *cmd_opt;
279ad2c1a9aSJuan Castillo 	const char *cur_opt;
280ccbf890eSJuan Castillo 	unsigned int err_code;
281*2972247cSQixiang Xu 	unsigned char md[SHA512_DIGEST_LENGTH];
282*2972247cSQixiang Xu 	unsigned int  md_len;
283c3da66b1SJuan Castillo 	const EVP_MD *md_info;
2846f971622SJuan Castillo 
2856f971622SJuan Castillo 	NOTICE("CoT Generation Tool: %s\n", build_msg);
2866f971622SJuan Castillo 	NOTICE("Target platform: %s\n", platform_msg);
2876f971622SJuan Castillo 
288ccbf890eSJuan Castillo 	/* Set default options */
289ccbf890eSJuan Castillo 	key_alg = KEY_ALG_RSA;
290*2972247cSQixiang Xu 	hash_alg = HASH_ALG_SHA256;
291ccbf890eSJuan Castillo 
292ad2c1a9aSJuan Castillo 	/* Add common command line options */
293159807e2SJuan Castillo 	for (i = 0; i < NUM_ELEM(common_cmd_opt); i++) {
294159807e2SJuan Castillo 		cmd_opt_add(&common_cmd_opt[i]);
295159807e2SJuan Castillo 	}
296ad2c1a9aSJuan Castillo 
297ad2c1a9aSJuan Castillo 	/* Initialize the certificates */
298ad2c1a9aSJuan Castillo 	if (cert_init() != 0) {
299ad2c1a9aSJuan Castillo 		ERROR("Cannot initialize certificates\n");
300ad2c1a9aSJuan Castillo 		exit(1);
301ad2c1a9aSJuan Castillo 	}
302ad2c1a9aSJuan Castillo 
303ad2c1a9aSJuan Castillo 	/* Initialize the keys */
304ad2c1a9aSJuan Castillo 	if (key_init() != 0) {
305ad2c1a9aSJuan Castillo 		ERROR("Cannot initialize keys\n");
306ad2c1a9aSJuan Castillo 		exit(1);
307ad2c1a9aSJuan Castillo 	}
308ad2c1a9aSJuan Castillo 
309ad2c1a9aSJuan Castillo 	/* Initialize the new types and register OIDs for the extensions */
310ad2c1a9aSJuan Castillo 	if (ext_init() != 0) {
311ad2c1a9aSJuan Castillo 		ERROR("Cannot initialize TBB extensions\n");
312ad2c1a9aSJuan Castillo 		exit(1);
313ad2c1a9aSJuan Castillo 	}
314ad2c1a9aSJuan Castillo 
315ad2c1a9aSJuan Castillo 	/* Get the command line options populated during the initialization */
316ad2c1a9aSJuan Castillo 	cmd_opt = cmd_opt_get_array();
317ad2c1a9aSJuan Castillo 
3186f971622SJuan Castillo 	while (1) {
3196f971622SJuan Castillo 		/* getopt_long stores the option index here. */
320*2972247cSQixiang Xu 		c = getopt_long(argc, argv, "a:hknps:", cmd_opt, &opt_idx);
3216f971622SJuan Castillo 
3226f971622SJuan Castillo 		/* Detect the end of the options. */
3236f971622SJuan Castillo 		if (c == -1) {
3246f971622SJuan Castillo 			break;
3256f971622SJuan Castillo 		}
3266f971622SJuan Castillo 
3276f971622SJuan Castillo 		switch (c) {
328ccbf890eSJuan Castillo 		case 'a':
329ccbf890eSJuan Castillo 			key_alg = get_key_alg(optarg);
330ccbf890eSJuan Castillo 			if (key_alg < 0) {
331ccbf890eSJuan Castillo 				ERROR("Invalid key algorithm '%s'\n", optarg);
332ccbf890eSJuan Castillo 				exit(1);
333ccbf890eSJuan Castillo 			}
334ccbf890eSJuan Castillo 			break;
3356f971622SJuan Castillo 		case 'h':
336ad2c1a9aSJuan Castillo 			print_help(argv[0], cmd_opt);
3376f971622SJuan Castillo 			break;
3386f971622SJuan Castillo 		case 'k':
3396f971622SJuan Castillo 			save_keys = 1;
3406f971622SJuan Castillo 			break;
3416f971622SJuan Castillo 		case 'n':
3426f971622SJuan Castillo 			new_keys = 1;
3436f971622SJuan Castillo 			break;
3446f971622SJuan Castillo 		case 'p':
3456f971622SJuan Castillo 			print_cert = 1;
3466f971622SJuan Castillo 			break;
347*2972247cSQixiang Xu 		case 's':
348*2972247cSQixiang Xu 			hash_alg = get_hash_alg(optarg);
349*2972247cSQixiang Xu 			if (hash_alg < 0) {
350*2972247cSQixiang Xu 				ERROR("Invalid hash algorithm '%s'\n", optarg);
351*2972247cSQixiang Xu 				exit(1);
352*2972247cSQixiang Xu 			}
353*2972247cSQixiang Xu 			break;
354ad2c1a9aSJuan Castillo 		case CMD_OPT_EXT:
355ad2c1a9aSJuan Castillo 			cur_opt = cmd_opt_get_name(opt_idx);
356ad2c1a9aSJuan Castillo 			ext = ext_get_by_opt(cur_opt);
35796103d5aSJuan Castillo 			ext->arg = strdup(optarg);
3586f971622SJuan Castillo 			break;
359ad2c1a9aSJuan Castillo 		case CMD_OPT_KEY:
360ad2c1a9aSJuan Castillo 			cur_opt = cmd_opt_get_name(opt_idx);
361ad2c1a9aSJuan Castillo 			key = key_get_by_opt(cur_opt);
362ad2c1a9aSJuan Castillo 			key->fn = strdup(optarg);
3636f971622SJuan Castillo 			break;
364ad2c1a9aSJuan Castillo 		case CMD_OPT_CERT:
365ad2c1a9aSJuan Castillo 			cur_opt = cmd_opt_get_name(opt_idx);
366ad2c1a9aSJuan Castillo 			cert = cert_get_by_opt(cur_opt);
367ad2c1a9aSJuan Castillo 			cert->fn = strdup(optarg);
3686f971622SJuan Castillo 			break;
3696f971622SJuan Castillo 		case '?':
3706f971622SJuan Castillo 		default:
371159807e2SJuan Castillo 			print_help(argv[0], cmd_opt);
3726f971622SJuan Castillo 			exit(1);
3736f971622SJuan Castillo 		}
3746f971622SJuan Castillo 	}
3756f971622SJuan Castillo 
3766f971622SJuan Castillo 	/* Check command line arguments */
3776f971622SJuan Castillo 	check_cmd_params();
3786f971622SJuan Castillo 
379*2972247cSQixiang Xu 	/* Indicate SHA as image hash algorithm in the certificate
380c3da66b1SJuan Castillo 	 * extension */
381*2972247cSQixiang Xu 	if (hash_alg == HASH_ALG_SHA384) {
382*2972247cSQixiang Xu 		md_info = EVP_sha384();
383*2972247cSQixiang Xu 		md_len  = SHA384_DIGEST_LENGTH;
384*2972247cSQixiang Xu 	} else if (hash_alg == HASH_ALG_SHA512) {
385*2972247cSQixiang Xu 		md_info = EVP_sha512();
386*2972247cSQixiang Xu 		md_len  = SHA512_DIGEST_LENGTH;
387*2972247cSQixiang Xu 	} else {
388c3da66b1SJuan Castillo 		md_info = EVP_sha256();
389*2972247cSQixiang Xu 		md_len  = SHA256_DIGEST_LENGTH;
390*2972247cSQixiang Xu 	}
391c3da66b1SJuan Castillo 
3926f971622SJuan Castillo 	/* Load private keys from files (or generate new ones) */
39355e291a4SJuan Castillo 	for (i = 0 ; i < num_keys ; i++) {
394762f1ebeSMasahiro Yamada 		if (!key_new(&keys[i])) {
395762f1ebeSMasahiro Yamada 			ERROR("Failed to allocate key container\n");
396762f1ebeSMasahiro Yamada 			exit(1);
397762f1ebeSMasahiro Yamada 		}
398762f1ebeSMasahiro Yamada 
399ccbf890eSJuan Castillo 		/* First try to load the key from disk */
400ccbf890eSJuan Castillo 		if (key_load(&keys[i], &err_code)) {
401ccbf890eSJuan Castillo 			/* Key loaded successfully */
402ccbf890eSJuan Castillo 			continue;
403ccbf890eSJuan Castillo 		}
404ccbf890eSJuan Castillo 
405ccbf890eSJuan Castillo 		/* Key not loaded. Check the error code */
406762f1ebeSMasahiro Yamada 		if (err_code == KEY_ERR_LOAD) {
407ccbf890eSJuan Castillo 			/* File exists, but it does not contain a valid private
408ccbf890eSJuan Castillo 			 * key. Abort. */
409ccbf890eSJuan Castillo 			ERROR("Error loading '%s'\n", keys[i].fn);
4106f971622SJuan Castillo 			exit(1);
4116f971622SJuan Castillo 		}
412ccbf890eSJuan Castillo 
413ccbf890eSJuan Castillo 		/* File does not exist, could not be opened or no filename was
414ccbf890eSJuan Castillo 		 * given */
415ccbf890eSJuan Castillo 		if (new_keys) {
416ccbf890eSJuan Castillo 			/* Try to create a new key */
417ccbf890eSJuan Castillo 			NOTICE("Creating new key for '%s'\n", keys[i].desc);
418ccbf890eSJuan Castillo 			if (!key_create(&keys[i], key_alg)) {
419ccbf890eSJuan Castillo 				ERROR("Error creating key '%s'\n", keys[i].desc);
420ccbf890eSJuan Castillo 				exit(1);
4216f971622SJuan Castillo 			}
4226f971622SJuan Castillo 		} else {
423ccbf890eSJuan Castillo 			if (err_code == KEY_ERR_OPEN) {
424ccbf890eSJuan Castillo 				ERROR("Error opening '%s'\n", keys[i].fn);
425ccbf890eSJuan Castillo 			} else {
426ccbf890eSJuan Castillo 				ERROR("Key '%s' not specified\n", keys[i].desc);
4276f971622SJuan Castillo 			}
428ccbf890eSJuan Castillo 			exit(1);
4296f971622SJuan Castillo 		}
4306f971622SJuan Castillo 	}
4316f971622SJuan Castillo 
43255e291a4SJuan Castillo 	/* Create the certificates */
43355e291a4SJuan Castillo 	for (i = 0 ; i < num_certs ; i++) {
43455e291a4SJuan Castillo 
43555e291a4SJuan Castillo 		cert = &certs[i];
43655e291a4SJuan Castillo 
43755e291a4SJuan Castillo 		/* Create a new stack of extensions. This stack will be used
43855e291a4SJuan Castillo 		 * to create the certificate */
4396f971622SJuan Castillo 		CHECK_NULL(sk, sk_X509_EXTENSION_new_null());
4406f971622SJuan Castillo 
44155e291a4SJuan Castillo 		for (j = 0 ; j < cert->num_ext ; j++) {
4426f971622SJuan Castillo 
44355e291a4SJuan Castillo 			ext = &extensions[cert->ext[j]];
44455e291a4SJuan Castillo 
44555e291a4SJuan Castillo 			/* Get OpenSSL internal ID for this extension */
44655e291a4SJuan Castillo 			CHECK_OID(ext_nid, ext->oid);
44755e291a4SJuan Castillo 
44855e291a4SJuan Castillo 			/*
44955e291a4SJuan Castillo 			 * Three types of extensions are currently supported:
45055e291a4SJuan Castillo 			 *     - EXT_TYPE_NVCOUNTER
45155e291a4SJuan Castillo 			 *     - EXT_TYPE_HASH
45255e291a4SJuan Castillo 			 *     - EXT_TYPE_PKEY
45355e291a4SJuan Castillo 			 */
45455e291a4SJuan Castillo 			switch (ext->type) {
45555e291a4SJuan Castillo 			case EXT_TYPE_NVCOUNTER:
456f16db56aSYatharth Kochar 				if (ext->arg) {
45796103d5aSJuan Castillo 					nvctr = atoi(ext->arg);
45855e291a4SJuan Castillo 					CHECK_NULL(cert_ext, ext_new_nvcounter(ext_nid,
45996103d5aSJuan Castillo 						EXT_CRIT, nvctr));
460f16db56aSYatharth Kochar 				}
46155e291a4SJuan Castillo 				break;
46255e291a4SJuan Castillo 			case EXT_TYPE_HASH:
46396103d5aSJuan Castillo 				if (ext->arg == NULL) {
464cebe1f23SYatharth Kochar 					if (ext->optional) {
465cebe1f23SYatharth Kochar 						/* Include a hash filled with zeros */
466*2972247cSQixiang Xu 						memset(md, 0x0, SHA512_DIGEST_LENGTH);
467cebe1f23SYatharth Kochar 					} else {
468cebe1f23SYatharth Kochar 						/* Do not include this hash in the certificate */
46955e291a4SJuan Castillo 						break;
47055e291a4SJuan Castillo 					}
471cebe1f23SYatharth Kochar 				} else {
472cebe1f23SYatharth Kochar 					/* Calculate the hash of the file */
473*2972247cSQixiang Xu 					if (!sha_file(hash_alg, ext->arg, md)) {
47455e291a4SJuan Castillo 						ERROR("Cannot calculate hash of %s\n",
47596103d5aSJuan Castillo 							ext->arg);
4766f971622SJuan Castillo 						exit(1);
4776f971622SJuan Castillo 					}
478cebe1f23SYatharth Kochar 				}
47955e291a4SJuan Castillo 				CHECK_NULL(cert_ext, ext_new_hash(ext_nid,
48055e291a4SJuan Castillo 						EXT_CRIT, md_info, md,
481*2972247cSQixiang Xu 						md_len));
48255e291a4SJuan Castillo 				break;
48355e291a4SJuan Castillo 			case EXT_TYPE_PKEY:
48455e291a4SJuan Castillo 				CHECK_NULL(cert_ext, ext_new_key(ext_nid,
48596103d5aSJuan Castillo 					EXT_CRIT, keys[ext->attr.key].key));
48655e291a4SJuan Castillo 				break;
48755e291a4SJuan Castillo 			default:
48896103d5aSJuan Castillo 				ERROR("Unknown extension type '%d' in %s\n",
48996103d5aSJuan Castillo 						ext->type, cert->cn);
49055e291a4SJuan Castillo 				exit(1);
49155e291a4SJuan Castillo 			}
49255e291a4SJuan Castillo 
49355e291a4SJuan Castillo 			/* Push the extension into the stack */
49455e291a4SJuan Castillo 			sk_X509_EXTENSION_push(sk, cert_ext);
49555e291a4SJuan Castillo 		}
4966f971622SJuan Castillo 
497a8eb286aSSoby Mathew 		/* Create certificate. Signed with corresponding key */
498*2972247cSQixiang Xu 		if (cert->fn && !cert_new(key_alg, hash_alg, cert, VAL_DAYS, 0, sk)) {
49955e291a4SJuan Castillo 			ERROR("Cannot create %s\n", cert->cn);
5006f971622SJuan Castillo 			exit(1);
5016f971622SJuan Castillo 		}
5026f971622SJuan Castillo 
5036f971622SJuan Castillo 		sk_X509_EXTENSION_free(sk);
5046f971622SJuan Castillo 	}
5056f971622SJuan Castillo 
5066f971622SJuan Castillo 
5076f971622SJuan Castillo 	/* Print the certificates */
5086f971622SJuan Castillo 	if (print_cert) {
50955e291a4SJuan Castillo 		for (i = 0 ; i < num_certs ; i++) {
5106f971622SJuan Castillo 			if (!certs[i].x) {
5116f971622SJuan Castillo 				continue;
5126f971622SJuan Castillo 			}
5136f971622SJuan Castillo 			printf("\n\n=====================================\n\n");
5146f971622SJuan Castillo 			X509_print_fp(stdout, certs[i].x);
5156f971622SJuan Castillo 		}
5166f971622SJuan Castillo 	}
5176f971622SJuan Castillo 
5186f971622SJuan Castillo 	/* Save created certificates to files */
51955e291a4SJuan Castillo 	for (i = 0 ; i < num_certs ; i++) {
5206f971622SJuan Castillo 		if (certs[i].x && certs[i].fn) {
5216f971622SJuan Castillo 			file = fopen(certs[i].fn, "w");
5226f971622SJuan Castillo 			if (file != NULL) {
5236f971622SJuan Castillo 				i2d_X509_fp(file, certs[i].x);
5246f971622SJuan Castillo 				fclose(file);
5256f971622SJuan Castillo 			} else {
5266f971622SJuan Castillo 				ERROR("Cannot create file %s\n", certs[i].fn);
5276f971622SJuan Castillo 			}
5286f971622SJuan Castillo 		}
5296f971622SJuan Castillo 	}
5306f971622SJuan Castillo 
5316f971622SJuan Castillo 	/* Save keys */
5326f971622SJuan Castillo 	if (save_keys) {
53355e291a4SJuan Castillo 		for (i = 0 ; i < num_keys ; i++) {
5346f971622SJuan Castillo 			if (!key_store(&keys[i])) {
5356f971622SJuan Castillo 				ERROR("Cannot save %s\n", keys[i].desc);
5366f971622SJuan Castillo 			}
5376f971622SJuan Castillo 		}
5386f971622SJuan Castillo 	}
5396f971622SJuan Castillo 
5406f971622SJuan Castillo #ifndef OPENSSL_NO_ENGINE
5416f971622SJuan Castillo 	ENGINE_cleanup();
5426f971622SJuan Castillo #endif
5436f971622SJuan Castillo 	CRYPTO_cleanup_all_ex_data();
5446f971622SJuan Castillo 
5456f971622SJuan Castillo 	return 0;
5466f971622SJuan Castillo }
547