xref: /rk3399_ARM-atf/tools/cert_create/src/main.c (revision bb3b0c0b09ff1d969ddd49b99642740ce2a07064)
16f971622SJuan Castillo /*
2cf2dd17dSJuan Pablo Conde  * Copyright (c) 2015-2022, 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>
13dfe0f4c2SJustin Chadwell #include <stdbool.h>
146f971622SJuan Castillo 
156f971622SJuan Castillo #include <openssl/conf.h>
166f971622SJuan Castillo #include <openssl/engine.h>
176f971622SJuan Castillo #include <openssl/err.h>
186f971622SJuan Castillo #include <openssl/pem.h>
196f971622SJuan Castillo #include <openssl/sha.h>
206f971622SJuan Castillo #include <openssl/x509v3.h>
216f971622SJuan Castillo 
226f971622SJuan Castillo #include "cert.h"
23ad2c1a9aSJuan Castillo #include "cmd_opt.h"
246f971622SJuan Castillo #include "debug.h"
256f971622SJuan Castillo #include "ext.h"
266f971622SJuan Castillo #include "key.h"
276f971622SJuan Castillo #include "sha.h"
286f971622SJuan Castillo 
296f971622SJuan Castillo /*
306f971622SJuan Castillo  * Helper macros to simplify the code. This macro assigns the return value of
316f971622SJuan Castillo  * the 'fn' function to 'v' and exits if the value is NULL.
326f971622SJuan Castillo  */
336f971622SJuan Castillo #define CHECK_NULL(v, fn) \
346f971622SJuan Castillo 	do { \
356f971622SJuan Castillo 		v = fn; \
366f971622SJuan Castillo 		if (v == NULL) { \
376f971622SJuan Castillo 			ERROR("NULL object at %s:%d\n", __FILE__, __LINE__); \
386f971622SJuan Castillo 			exit(1); \
396f971622SJuan Castillo 		} \
406f971622SJuan Castillo 	} while (0)
416f971622SJuan Castillo 
426f971622SJuan Castillo /*
436f971622SJuan Castillo  * This macro assigns the NID corresponding to 'oid' to 'v' and exits if the
446f971622SJuan Castillo  * NID is undefined.
456f971622SJuan Castillo  */
466f971622SJuan Castillo #define CHECK_OID(v, oid) \
476f971622SJuan Castillo 	do { \
486f971622SJuan Castillo 		v = OBJ_txt2nid(oid); \
496f971622SJuan Castillo 		if (v == NID_undef) { \
50067f7e9cSSandrine Bailleux 			ERROR("Cannot find extension %s\n", oid); \
516f971622SJuan Castillo 			exit(1); \
526f971622SJuan Castillo 		} \
536f971622SJuan Castillo 	} while (0)
546f971622SJuan Castillo 
556f971622SJuan Castillo #define MAX_FILENAME_LEN		1024
566f971622SJuan Castillo #define VAL_DAYS			7300
576f971622SJuan Castillo #define ID_TO_BIT_MASK(id)		(1 << id)
58ccbf890eSJuan Castillo #define NUM_ELEM(x)			((sizeof(x)) / (sizeof(x[0])))
59159807e2SJuan Castillo #define HELP_OPT_MAX_LEN		128
606f971622SJuan Castillo 
616f971622SJuan Castillo /* Global options */
62ccbf890eSJuan Castillo static int key_alg;
632972247cSQixiang Xu static int hash_alg;
64dfe0f4c2SJustin Chadwell static int key_size;
656f971622SJuan Castillo static int new_keys;
666f971622SJuan Castillo static int save_keys;
676f971622SJuan Castillo static int print_cert;
686f971622SJuan Castillo 
696f971622SJuan Castillo /* Info messages created in the Makefile */
706f971622SJuan Castillo extern const char build_msg[];
716f971622SJuan Castillo extern const char platform_msg[];
726f971622SJuan Castillo 
736f971622SJuan Castillo 
746f971622SJuan Castillo static char *strdup(const char *str)
756f971622SJuan Castillo {
766f971622SJuan Castillo 	int n = strlen(str) + 1;
776f971622SJuan Castillo 	char *dup = malloc(n);
786f971622SJuan Castillo 	if (dup) {
796f971622SJuan Castillo 		strcpy(dup, str);
806f971622SJuan Castillo 	}
816f971622SJuan Castillo 	return dup;
826f971622SJuan Castillo }
836f971622SJuan Castillo 
84ccbf890eSJuan Castillo static const char *key_algs_str[] = {
85ccbf890eSJuan Castillo 	[KEY_ALG_RSA] = "rsa",
86ed2a76eaSJuan Castillo #ifndef OPENSSL_NO_EC
87e78ba69eSLionel Debieve 	[KEY_ALG_ECDSA_NIST] = "ecdsa",
88e78ba69eSLionel Debieve 	[KEY_ALG_ECDSA_BRAINPOOL_R] = "ecdsa-brainpool-regular",
89e78ba69eSLionel Debieve 	[KEY_ALG_ECDSA_BRAINPOOL_T] = "ecdsa-brainpool-twisted",
90ed2a76eaSJuan Castillo #endif /* OPENSSL_NO_EC */
91ccbf890eSJuan Castillo };
92ccbf890eSJuan Castillo 
932972247cSQixiang Xu static const char *hash_algs_str[] = {
942972247cSQixiang Xu 	[HASH_ALG_SHA256] = "sha256",
952972247cSQixiang Xu 	[HASH_ALG_SHA384] = "sha384",
962972247cSQixiang Xu 	[HASH_ALG_SHA512] = "sha512",
972972247cSQixiang Xu };
982972247cSQixiang Xu 
99ad2c1a9aSJuan Castillo static void print_help(const char *cmd, const struct option *long_opt)
1006f971622SJuan Castillo {
101159807e2SJuan Castillo 	int rem, i = 0;
102159807e2SJuan Castillo 	const struct option *opt;
103159807e2SJuan Castillo 	char line[HELP_OPT_MAX_LEN];
104159807e2SJuan Castillo 	char *p;
105159807e2SJuan Castillo 
106159807e2SJuan Castillo 	assert(cmd != NULL);
107159807e2SJuan Castillo 	assert(long_opt != NULL);
108159807e2SJuan Castillo 
1096f971622SJuan Castillo 	printf("\n\n");
1106f971622SJuan Castillo 	printf("The certificate generation tool loads the binary images and\n"
111e78ba69eSLionel Debieve 	       "optionally the RSA or ECC keys, and outputs the key and content\n"
1126f971622SJuan Castillo 	       "certificates properly signed to implement the chain of trust.\n"
1136f971622SJuan Castillo 	       "If keys are provided, they must be in PEM format.\n"
1146f971622SJuan Castillo 	       "Certificates are generated in DER format.\n");
1156f971622SJuan Castillo 	printf("\n");
116159807e2SJuan Castillo 	printf("Usage:\n");
117159807e2SJuan Castillo 	printf("\t%s [OPTIONS]\n\n", cmd);
118159807e2SJuan Castillo 
119159807e2SJuan Castillo 	printf("Available options:\n");
120159807e2SJuan Castillo 	opt = long_opt;
121159807e2SJuan Castillo 	while (opt->name) {
122159807e2SJuan Castillo 		p = line;
123159807e2SJuan Castillo 		rem = HELP_OPT_MAX_LEN;
124159807e2SJuan Castillo 		if (isalpha(opt->val)) {
125159807e2SJuan Castillo 			/* Short format */
126159807e2SJuan Castillo 			sprintf(p, "-%c,", (char)opt->val);
127159807e2SJuan Castillo 			p += 3;
128159807e2SJuan Castillo 			rem -= 3;
1296f971622SJuan Castillo 		}
130159807e2SJuan Castillo 		snprintf(p, rem, "--%s %s", opt->name,
131159807e2SJuan Castillo 			 (opt->has_arg == required_argument) ? "<arg>" : "");
132159807e2SJuan Castillo 		printf("\t%-32s %s\n", line, cmd_opt_get_help_msg(i));
133159807e2SJuan Castillo 		opt++;
134159807e2SJuan Castillo 		i++;
135159807e2SJuan Castillo 	}
1366f971622SJuan Castillo 	printf("\n");
1376f971622SJuan Castillo }
1386f971622SJuan Castillo 
139ccbf890eSJuan Castillo static int get_key_alg(const char *key_alg_str)
140ccbf890eSJuan Castillo {
141ccbf890eSJuan Castillo 	int i;
142ccbf890eSJuan Castillo 
143ccbf890eSJuan Castillo 	for (i = 0 ; i < NUM_ELEM(key_algs_str) ; i++) {
144ccbf890eSJuan Castillo 		if (0 == strcmp(key_alg_str, key_algs_str[i])) {
145ccbf890eSJuan Castillo 			return i;
146ccbf890eSJuan Castillo 		}
147ccbf890eSJuan Castillo 	}
148ccbf890eSJuan Castillo 
149ccbf890eSJuan Castillo 	return -1;
150ccbf890eSJuan Castillo }
151ccbf890eSJuan Castillo 
152dfe0f4c2SJustin Chadwell static int get_key_size(const char *key_size_str)
153dfe0f4c2SJustin Chadwell {
154dfe0f4c2SJustin Chadwell 	char *end;
155dfe0f4c2SJustin Chadwell 	long key_size;
156dfe0f4c2SJustin Chadwell 
157dfe0f4c2SJustin Chadwell 	key_size = strtol(key_size_str, &end, 10);
158dfe0f4c2SJustin Chadwell 	if (*end != '\0')
159dfe0f4c2SJustin Chadwell 		return -1;
160dfe0f4c2SJustin Chadwell 
161dfe0f4c2SJustin Chadwell 	return key_size;
162dfe0f4c2SJustin Chadwell }
163dfe0f4c2SJustin Chadwell 
1642972247cSQixiang Xu static int get_hash_alg(const char *hash_alg_str)
1652972247cSQixiang Xu {
1662972247cSQixiang Xu 	int i;
1672972247cSQixiang Xu 
1682972247cSQixiang Xu 	for (i = 0 ; i < NUM_ELEM(hash_algs_str) ; i++) {
1692972247cSQixiang Xu 		if (0 == strcmp(hash_alg_str, hash_algs_str[i])) {
1702972247cSQixiang Xu 			return i;
1712972247cSQixiang Xu 		}
1722972247cSQixiang Xu 	}
1732972247cSQixiang Xu 
1742972247cSQixiang Xu 	return -1;
1752972247cSQixiang Xu }
1762972247cSQixiang Xu 
1776f971622SJuan Castillo static void check_cmd_params(void)
1786f971622SJuan Castillo {
179dfc90e26SJuan Castillo 	cert_t *cert;
180dfc90e26SJuan Castillo 	ext_t *ext;
181dfc90e26SJuan Castillo 	key_t *key;
182dfc90e26SJuan Castillo 	int i, j;
183dfe0f4c2SJustin Chadwell 	bool valid_size;
184dfc90e26SJuan Castillo 
185ccbf890eSJuan Castillo 	/* Only save new keys */
186ccbf890eSJuan Castillo 	if (save_keys && !new_keys) {
187ccbf890eSJuan Castillo 		ERROR("Only new keys can be saved to disk\n");
188ccbf890eSJuan Castillo 		exit(1);
189ccbf890eSJuan Castillo 	}
190ccbf890eSJuan Castillo 
191dfe0f4c2SJustin Chadwell 	/* Validate key-size */
192dfe0f4c2SJustin Chadwell 	valid_size = false;
193dfe0f4c2SJustin Chadwell 	for (i = 0; i < KEY_SIZE_MAX_NUM; i++) {
194dfe0f4c2SJustin Chadwell 		if (key_size == KEY_SIZES[key_alg][i]) {
195dfe0f4c2SJustin Chadwell 			valid_size = true;
196dfe0f4c2SJustin Chadwell 			break;
197dfe0f4c2SJustin Chadwell 		}
198dfe0f4c2SJustin Chadwell 	}
199dfe0f4c2SJustin Chadwell 	if (!valid_size) {
200dfe0f4c2SJustin Chadwell 		ERROR("'%d' is not a valid key size for '%s'\n",
201dfe0f4c2SJustin Chadwell 				key_size, key_algs_str[key_alg]);
202dfe0f4c2SJustin Chadwell 		NOTICE("Valid sizes are: ");
203dfe0f4c2SJustin Chadwell 		for (i = 0; i < KEY_SIZE_MAX_NUM &&
204dfe0f4c2SJustin Chadwell 				KEY_SIZES[key_alg][i] != 0; i++) {
205dfe0f4c2SJustin Chadwell 			printf("%d ", KEY_SIZES[key_alg][i]);
206dfe0f4c2SJustin Chadwell 		}
207dfe0f4c2SJustin Chadwell 		printf("\n");
208dfe0f4c2SJustin Chadwell 		exit(1);
209dfe0f4c2SJustin Chadwell 	}
210dfe0f4c2SJustin Chadwell 
211dfc90e26SJuan Castillo 	/* Check that all required options have been specified in the
212dfc90e26SJuan Castillo 	 * command line */
213dfc90e26SJuan Castillo 	for (i = 0; i < num_certs; i++) {
214dfc90e26SJuan Castillo 		cert = &certs[i];
215dfc90e26SJuan Castillo 		if (cert->fn == NULL) {
216dfc90e26SJuan Castillo 			/* Certificate not requested. Skip to the next one */
217dfc90e26SJuan Castillo 			continue;
218dfc90e26SJuan Castillo 		}
219dfc90e26SJuan Castillo 
220dfc90e26SJuan Castillo 		/* Check that all parameters required to create this certificate
221dfc90e26SJuan Castillo 		 * have been specified in the command line */
222dfc90e26SJuan Castillo 		for (j = 0; j < cert->num_ext; j++) {
223dfc90e26SJuan Castillo 			ext = &extensions[cert->ext[j]];
224dfc90e26SJuan Castillo 			switch (ext->type) {
22596103d5aSJuan Castillo 			case EXT_TYPE_NVCOUNTER:
22696103d5aSJuan Castillo 				/* Counter value must be specified */
22796103d5aSJuan Castillo 				if ((!ext->optional) && (ext->arg == NULL)) {
22896103d5aSJuan Castillo 					ERROR("Value for '%s' not specified\n",
22996103d5aSJuan Castillo 					      ext->ln);
23096103d5aSJuan Castillo 					exit(1);
23196103d5aSJuan Castillo 				}
23296103d5aSJuan Castillo 				break;
233dfc90e26SJuan Castillo 			case EXT_TYPE_PKEY:
234dfc90e26SJuan Castillo 				/* Key filename must be specified */
23596103d5aSJuan Castillo 				key = &keys[ext->attr.key];
236dfc90e26SJuan Castillo 				if (!new_keys && key->fn == NULL) {
237dfc90e26SJuan Castillo 					ERROR("Key '%s' required by '%s' not "
238dfc90e26SJuan Castillo 					      "specified\n", key->desc,
239dfc90e26SJuan Castillo 					      cert->cn);
2406f971622SJuan Castillo 					exit(1);
2416f971622SJuan Castillo 				}
242dfc90e26SJuan Castillo 				break;
243dfc90e26SJuan Castillo 			case EXT_TYPE_HASH:
244cebe1f23SYatharth Kochar 				/*
245cebe1f23SYatharth Kochar 				 * Binary image must be specified
246cebe1f23SYatharth Kochar 				 * unless it is explicitly made optional.
247cebe1f23SYatharth Kochar 				 */
24896103d5aSJuan Castillo 				if ((!ext->optional) && (ext->arg == NULL)) {
249dfc90e26SJuan Castillo 					ERROR("Image for '%s' not specified\n",
250dfc90e26SJuan Castillo 					      ext->ln);
2516f971622SJuan Castillo 					exit(1);
2526f971622SJuan Castillo 				}
253dfc90e26SJuan Castillo 				break;
254dfc90e26SJuan Castillo 			default:
25596103d5aSJuan Castillo 				ERROR("Unknown extension type '%d' in '%s'\n",
25696103d5aSJuan Castillo 				      ext->type, ext->ln);
2576f971622SJuan Castillo 				exit(1);
258dfc90e26SJuan Castillo 				break;
2596f971622SJuan Castillo 			}
2606f971622SJuan Castillo 		}
2616f971622SJuan Castillo 	}
2626f971622SJuan Castillo }
2636f971622SJuan Castillo 
264159807e2SJuan Castillo /* Common command line options */
265159807e2SJuan Castillo static const cmd_opt_t common_cmd_opt[] = {
266159807e2SJuan Castillo 	{
267159807e2SJuan Castillo 		{ "help", no_argument, NULL, 'h' },
268159807e2SJuan Castillo 		"Print this message and exit"
269159807e2SJuan Castillo 	},
270159807e2SJuan Castillo 	{
271159807e2SJuan Castillo 		{ "key-alg", required_argument, NULL, 'a' },
272e78ba69eSLionel Debieve 		"Key algorithm: 'rsa' (default)- RSAPSS scheme as per PKCS#1 v2.1, " \
273e78ba69eSLionel Debieve 		"'ecdsa', 'ecdsa-brainpool-regular', 'ecdsa-brainpool-twisted'"
274159807e2SJuan Castillo 	},
275159807e2SJuan Castillo 	{
276dfe0f4c2SJustin Chadwell 		{ "key-size", required_argument, NULL, 'b' },
277dfe0f4c2SJustin Chadwell 		"Key size (for supported algorithms)."
278dfe0f4c2SJustin Chadwell 	},
279dfe0f4c2SJustin Chadwell 	{
2802972247cSQixiang Xu 		{ "hash-alg", required_argument, NULL, 's' },
2812972247cSQixiang Xu 		"Hash algorithm : 'sha256' (default), 'sha384', 'sha512'"
2822972247cSQixiang Xu 	},
2832972247cSQixiang Xu 	{
284159807e2SJuan Castillo 		{ "save-keys", no_argument, NULL, 'k' },
285159807e2SJuan Castillo 		"Save key pairs into files. Filenames must be provided"
286159807e2SJuan Castillo 	},
287159807e2SJuan Castillo 	{
288159807e2SJuan Castillo 		{ "new-keys", no_argument, NULL, 'n' },
289159807e2SJuan Castillo 		"Generate new key pairs if no key files are provided"
290159807e2SJuan Castillo 	},
291159807e2SJuan Castillo 	{
292159807e2SJuan Castillo 		{ "print-cert", no_argument, NULL, 'p' },
293159807e2SJuan Castillo 		"Print the certificates in the standard output"
294159807e2SJuan Castillo 	}
295159807e2SJuan Castillo };
296159807e2SJuan Castillo 
2976f971622SJuan Castillo int main(int argc, char *argv[])
2986f971622SJuan Castillo {
299c893c733SMasahiro Yamada 	STACK_OF(X509_EXTENSION) * sk;
300742c4e14SMichalis Pappas 	X509_EXTENSION *cert_ext = NULL;
301c893c733SMasahiro Yamada 	ext_t *ext;
302c893c733SMasahiro Yamada 	key_t *key;
303c893c733SMasahiro Yamada 	cert_t *cert;
304c893c733SMasahiro Yamada 	FILE *file;
30596103d5aSJuan Castillo 	int i, j, ext_nid, nvctr;
3066f971622SJuan Castillo 	int c, opt_idx = 0;
307ad2c1a9aSJuan Castillo 	const struct option *cmd_opt;
308ad2c1a9aSJuan Castillo 	const char *cur_opt;
309ccbf890eSJuan Castillo 	unsigned int err_code;
3102972247cSQixiang Xu 	unsigned char md[SHA512_DIGEST_LENGTH];
3112972247cSQixiang Xu 	unsigned int  md_len;
312c3da66b1SJuan Castillo 	const EVP_MD *md_info;
3136f971622SJuan Castillo 
3146f971622SJuan Castillo 	NOTICE("CoT Generation Tool: %s\n", build_msg);
3156f971622SJuan Castillo 	NOTICE("Target platform: %s\n", platform_msg);
3166f971622SJuan Castillo 
317ccbf890eSJuan Castillo 	/* Set default options */
318ccbf890eSJuan Castillo 	key_alg = KEY_ALG_RSA;
3192972247cSQixiang Xu 	hash_alg = HASH_ALG_SHA256;
320dfe0f4c2SJustin Chadwell 	key_size = -1;
321ccbf890eSJuan Castillo 
322ad2c1a9aSJuan Castillo 	/* Add common command line options */
323159807e2SJuan Castillo 	for (i = 0; i < NUM_ELEM(common_cmd_opt); i++) {
324159807e2SJuan Castillo 		cmd_opt_add(&common_cmd_opt[i]);
325159807e2SJuan Castillo 	}
326ad2c1a9aSJuan Castillo 
327ad2c1a9aSJuan Castillo 	/* Initialize the certificates */
328ad2c1a9aSJuan Castillo 	if (cert_init() != 0) {
329ad2c1a9aSJuan Castillo 		ERROR("Cannot initialize certificates\n");
330ad2c1a9aSJuan Castillo 		exit(1);
331ad2c1a9aSJuan Castillo 	}
332ad2c1a9aSJuan Castillo 
333ad2c1a9aSJuan Castillo 	/* Initialize the keys */
334ad2c1a9aSJuan Castillo 	if (key_init() != 0) {
335ad2c1a9aSJuan Castillo 		ERROR("Cannot initialize keys\n");
336ad2c1a9aSJuan Castillo 		exit(1);
337ad2c1a9aSJuan Castillo 	}
338ad2c1a9aSJuan Castillo 
339ad2c1a9aSJuan Castillo 	/* Initialize the new types and register OIDs for the extensions */
340ad2c1a9aSJuan Castillo 	if (ext_init() != 0) {
341067f7e9cSSandrine Bailleux 		ERROR("Cannot initialize extensions\n");
342ad2c1a9aSJuan Castillo 		exit(1);
343ad2c1a9aSJuan Castillo 	}
344ad2c1a9aSJuan Castillo 
345ad2c1a9aSJuan Castillo 	/* Get the command line options populated during the initialization */
346ad2c1a9aSJuan Castillo 	cmd_opt = cmd_opt_get_array();
347ad2c1a9aSJuan Castillo 
3486f971622SJuan Castillo 	while (1) {
3496f971622SJuan Castillo 		/* getopt_long stores the option index here. */
350dfe0f4c2SJustin Chadwell 		c = getopt_long(argc, argv, "a:b:hknps:", cmd_opt, &opt_idx);
3516f971622SJuan Castillo 
3526f971622SJuan Castillo 		/* Detect the end of the options. */
3536f971622SJuan Castillo 		if (c == -1) {
3546f971622SJuan Castillo 			break;
3556f971622SJuan Castillo 		}
3566f971622SJuan Castillo 
3576f971622SJuan Castillo 		switch (c) {
358ccbf890eSJuan Castillo 		case 'a':
359ccbf890eSJuan Castillo 			key_alg = get_key_alg(optarg);
360ccbf890eSJuan Castillo 			if (key_alg < 0) {
361ccbf890eSJuan Castillo 				ERROR("Invalid key algorithm '%s'\n", optarg);
362ccbf890eSJuan Castillo 				exit(1);
363ccbf890eSJuan Castillo 			}
364ccbf890eSJuan Castillo 			break;
365dfe0f4c2SJustin Chadwell 		case 'b':
366dfe0f4c2SJustin Chadwell 			key_size = get_key_size(optarg);
367dfe0f4c2SJustin Chadwell 			if (key_size <= 0) {
368dfe0f4c2SJustin Chadwell 				ERROR("Invalid key size '%s'\n", optarg);
369dfe0f4c2SJustin Chadwell 				exit(1);
370dfe0f4c2SJustin Chadwell 			}
371dfe0f4c2SJustin Chadwell 			break;
3726f971622SJuan Castillo 		case 'h':
373ad2c1a9aSJuan Castillo 			print_help(argv[0], cmd_opt);
374600835d0SRoberto Vargas 			exit(0);
3756f971622SJuan Castillo 		case 'k':
3766f971622SJuan Castillo 			save_keys = 1;
3776f971622SJuan Castillo 			break;
3786f971622SJuan Castillo 		case 'n':
3796f971622SJuan Castillo 			new_keys = 1;
3806f971622SJuan Castillo 			break;
3816f971622SJuan Castillo 		case 'p':
3826f971622SJuan Castillo 			print_cert = 1;
3836f971622SJuan Castillo 			break;
3842972247cSQixiang Xu 		case 's':
3852972247cSQixiang Xu 			hash_alg = get_hash_alg(optarg);
3862972247cSQixiang Xu 			if (hash_alg < 0) {
3872972247cSQixiang Xu 				ERROR("Invalid hash algorithm '%s'\n", optarg);
3882972247cSQixiang Xu 				exit(1);
3892972247cSQixiang Xu 			}
3902972247cSQixiang Xu 			break;
391ad2c1a9aSJuan Castillo 		case CMD_OPT_EXT:
392ad2c1a9aSJuan Castillo 			cur_opt = cmd_opt_get_name(opt_idx);
393ad2c1a9aSJuan Castillo 			ext = ext_get_by_opt(cur_opt);
39496103d5aSJuan Castillo 			ext->arg = strdup(optarg);
3956f971622SJuan Castillo 			break;
396ad2c1a9aSJuan Castillo 		case CMD_OPT_KEY:
397ad2c1a9aSJuan Castillo 			cur_opt = cmd_opt_get_name(opt_idx);
398ad2c1a9aSJuan Castillo 			key = key_get_by_opt(cur_opt);
399ad2c1a9aSJuan Castillo 			key->fn = strdup(optarg);
4006f971622SJuan Castillo 			break;
401ad2c1a9aSJuan Castillo 		case CMD_OPT_CERT:
402ad2c1a9aSJuan Castillo 			cur_opt = cmd_opt_get_name(opt_idx);
403ad2c1a9aSJuan Castillo 			cert = cert_get_by_opt(cur_opt);
404ad2c1a9aSJuan Castillo 			cert->fn = strdup(optarg);
4056f971622SJuan Castillo 			break;
4066f971622SJuan Castillo 		case '?':
4076f971622SJuan Castillo 		default:
408159807e2SJuan Castillo 			print_help(argv[0], cmd_opt);
4096f971622SJuan Castillo 			exit(1);
4106f971622SJuan Castillo 		}
4116f971622SJuan Castillo 	}
4126f971622SJuan Castillo 
413dfe0f4c2SJustin Chadwell 	/* Select a reasonable default key-size */
414dfe0f4c2SJustin Chadwell 	if (key_size == -1) {
415dfe0f4c2SJustin Chadwell 		key_size = KEY_SIZES[key_alg][0];
416dfe0f4c2SJustin Chadwell 	}
417dfe0f4c2SJustin Chadwell 
4186f971622SJuan Castillo 	/* Check command line arguments */
4196f971622SJuan Castillo 	check_cmd_params();
4206f971622SJuan Castillo 
4212972247cSQixiang Xu 	/* Indicate SHA as image hash algorithm in the certificate
422c3da66b1SJuan Castillo 	 * extension */
4232972247cSQixiang Xu 	if (hash_alg == HASH_ALG_SHA384) {
4242972247cSQixiang Xu 		md_info = EVP_sha384();
4252972247cSQixiang Xu 		md_len  = SHA384_DIGEST_LENGTH;
4262972247cSQixiang Xu 	} else if (hash_alg == HASH_ALG_SHA512) {
4272972247cSQixiang Xu 		md_info = EVP_sha512();
4282972247cSQixiang Xu 		md_len  = SHA512_DIGEST_LENGTH;
4292972247cSQixiang Xu 	} else {
430c3da66b1SJuan Castillo 		md_info = EVP_sha256();
4312972247cSQixiang Xu 		md_len  = SHA256_DIGEST_LENGTH;
4322972247cSQixiang Xu 	}
433c3da66b1SJuan Castillo 
4346f971622SJuan Castillo 	/* Load private keys from files (or generate new ones) */
43555e291a4SJuan Castillo 	for (i = 0 ; i < num_keys ; i++) {
436cf2dd17dSJuan Pablo Conde #if !USING_OPENSSL3
437762f1ebeSMasahiro Yamada 		if (!key_new(&keys[i])) {
438762f1ebeSMasahiro Yamada 			ERROR("Failed to allocate key container\n");
439762f1ebeSMasahiro Yamada 			exit(1);
440762f1ebeSMasahiro Yamada 		}
441cf2dd17dSJuan Pablo Conde #endif
442762f1ebeSMasahiro Yamada 
443ccbf890eSJuan Castillo 		/* First try to load the key from disk */
444*bb3b0c0bSSandrine Bailleux 		err_code = key_load(&keys[i]);
445*bb3b0c0bSSandrine Bailleux 		if (err_code == KEY_ERR_NONE) {
446ccbf890eSJuan Castillo 			/* Key loaded successfully */
447ccbf890eSJuan Castillo 			continue;
448ccbf890eSJuan Castillo 		}
449ccbf890eSJuan Castillo 
450ccbf890eSJuan Castillo 		/* Key not loaded. Check the error code */
451762f1ebeSMasahiro Yamada 		if (err_code == KEY_ERR_LOAD) {
452ccbf890eSJuan Castillo 			/* File exists, but it does not contain a valid private
453ccbf890eSJuan Castillo 			 * key. Abort. */
454ccbf890eSJuan Castillo 			ERROR("Error loading '%s'\n", keys[i].fn);
4556f971622SJuan Castillo 			exit(1);
4566f971622SJuan Castillo 		}
457ccbf890eSJuan Castillo 
458ccbf890eSJuan Castillo 		/* File does not exist, could not be opened or no filename was
459ccbf890eSJuan Castillo 		 * given */
460ccbf890eSJuan Castillo 		if (new_keys) {
461ccbf890eSJuan Castillo 			/* Try to create a new key */
462ccbf890eSJuan Castillo 			NOTICE("Creating new key for '%s'\n", keys[i].desc);
463dfe0f4c2SJustin Chadwell 			if (!key_create(&keys[i], key_alg, key_size)) {
464ccbf890eSJuan Castillo 				ERROR("Error creating key '%s'\n", keys[i].desc);
465ccbf890eSJuan Castillo 				exit(1);
4666f971622SJuan Castillo 			}
4676f971622SJuan Castillo 		} else {
468ccbf890eSJuan Castillo 			if (err_code == KEY_ERR_OPEN) {
469ccbf890eSJuan Castillo 				ERROR("Error opening '%s'\n", keys[i].fn);
470ccbf890eSJuan Castillo 			} else {
471ccbf890eSJuan Castillo 				ERROR("Key '%s' not specified\n", keys[i].desc);
4726f971622SJuan Castillo 			}
473ccbf890eSJuan Castillo 			exit(1);
4746f971622SJuan Castillo 		}
4756f971622SJuan Castillo 	}
4766f971622SJuan Castillo 
47755e291a4SJuan Castillo 	/* Create the certificates */
47855e291a4SJuan Castillo 	for (i = 0 ; i < num_certs ; i++) {
47955e291a4SJuan Castillo 
48055e291a4SJuan Castillo 		cert = &certs[i];
48155e291a4SJuan Castillo 
482294e2656SManish V Badarkhe 		if (cert->fn == NULL) {
483294e2656SManish V Badarkhe 			/* Certificate not requested. Skip to the next one */
484294e2656SManish V Badarkhe 			continue;
485294e2656SManish V Badarkhe 		}
486294e2656SManish V Badarkhe 
48755e291a4SJuan Castillo 		/* Create a new stack of extensions. This stack will be used
48855e291a4SJuan Castillo 		 * to create the certificate */
4896f971622SJuan Castillo 		CHECK_NULL(sk, sk_X509_EXTENSION_new_null());
4906f971622SJuan Castillo 
49155e291a4SJuan Castillo 		for (j = 0 ; j < cert->num_ext ; j++) {
4926f971622SJuan Castillo 
49355e291a4SJuan Castillo 			ext = &extensions[cert->ext[j]];
49455e291a4SJuan Castillo 
49555e291a4SJuan Castillo 			/* Get OpenSSL internal ID for this extension */
49655e291a4SJuan Castillo 			CHECK_OID(ext_nid, ext->oid);
49755e291a4SJuan Castillo 
49855e291a4SJuan Castillo 			/*
49955e291a4SJuan Castillo 			 * Three types of extensions are currently supported:
50055e291a4SJuan Castillo 			 *     - EXT_TYPE_NVCOUNTER
50155e291a4SJuan Castillo 			 *     - EXT_TYPE_HASH
50255e291a4SJuan Castillo 			 *     - EXT_TYPE_PKEY
50355e291a4SJuan Castillo 			 */
50455e291a4SJuan Castillo 			switch (ext->type) {
50555e291a4SJuan Castillo 			case EXT_TYPE_NVCOUNTER:
5061ed941c0SJimmy Brisson 				if (ext->optional && ext->arg == NULL) {
5071ed941c0SJimmy Brisson 					/* Skip this NVCounter */
5081ed941c0SJimmy Brisson 					continue;
5091ed941c0SJimmy Brisson 				} else {
5101ed941c0SJimmy Brisson 					/* Checked by `check_cmd_params` */
5111ed941c0SJimmy Brisson 					assert(ext->arg != NULL);
51296103d5aSJuan Castillo 					nvctr = atoi(ext->arg);
51355e291a4SJuan Castillo 					CHECK_NULL(cert_ext, ext_new_nvcounter(ext_nid,
51496103d5aSJuan Castillo 						EXT_CRIT, nvctr));
515f16db56aSYatharth Kochar 				}
51655e291a4SJuan Castillo 				break;
51755e291a4SJuan Castillo 			case EXT_TYPE_HASH:
51896103d5aSJuan Castillo 				if (ext->arg == NULL) {
519cebe1f23SYatharth Kochar 					if (ext->optional) {
520cebe1f23SYatharth Kochar 						/* Include a hash filled with zeros */
5212972247cSQixiang Xu 						memset(md, 0x0, SHA512_DIGEST_LENGTH);
522cebe1f23SYatharth Kochar 					} else {
523cebe1f23SYatharth Kochar 						/* Do not include this hash in the certificate */
5241ed941c0SJimmy Brisson 						continue;
52555e291a4SJuan Castillo 					}
526cebe1f23SYatharth Kochar 				} else {
527cebe1f23SYatharth Kochar 					/* Calculate the hash of the file */
5282972247cSQixiang Xu 					if (!sha_file(hash_alg, ext->arg, md)) {
52955e291a4SJuan Castillo 						ERROR("Cannot calculate hash of %s\n",
53096103d5aSJuan Castillo 							ext->arg);
5316f971622SJuan Castillo 						exit(1);
5326f971622SJuan Castillo 					}
533cebe1f23SYatharth Kochar 				}
53455e291a4SJuan Castillo 				CHECK_NULL(cert_ext, ext_new_hash(ext_nid,
53555e291a4SJuan Castillo 						EXT_CRIT, md_info, md,
5362972247cSQixiang Xu 						md_len));
53755e291a4SJuan Castillo 				break;
53855e291a4SJuan Castillo 			case EXT_TYPE_PKEY:
53955e291a4SJuan Castillo 				CHECK_NULL(cert_ext, ext_new_key(ext_nid,
54096103d5aSJuan Castillo 					EXT_CRIT, keys[ext->attr.key].key));
54155e291a4SJuan Castillo 				break;
54255e291a4SJuan Castillo 			default:
54396103d5aSJuan Castillo 				ERROR("Unknown extension type '%d' in %s\n",
54496103d5aSJuan Castillo 						ext->type, cert->cn);
54555e291a4SJuan Castillo 				exit(1);
54655e291a4SJuan Castillo 			}
54755e291a4SJuan Castillo 
54855e291a4SJuan Castillo 			/* Push the extension into the stack */
54955e291a4SJuan Castillo 			sk_X509_EXTENSION_push(sk, cert_ext);
55055e291a4SJuan Castillo 		}
5516f971622SJuan Castillo 
552a8eb286aSSoby Mathew 		/* Create certificate. Signed with corresponding key */
553294e2656SManish V Badarkhe 		if (!cert_new(hash_alg, cert, VAL_DAYS, 0, sk)) {
55455e291a4SJuan Castillo 			ERROR("Cannot create %s\n", cert->cn);
5556f971622SJuan Castillo 			exit(1);
5566f971622SJuan Castillo 		}
5576f971622SJuan Castillo 
558bea80198SJimmy Brisson 		for (cert_ext = sk_X509_EXTENSION_pop(sk); cert_ext != NULL;
559bea80198SJimmy Brisson 				cert_ext = sk_X509_EXTENSION_pop(sk)) {
560bea80198SJimmy Brisson 			X509_EXTENSION_free(cert_ext);
561bea80198SJimmy Brisson 		}
562bea80198SJimmy Brisson 
5636f971622SJuan Castillo 		sk_X509_EXTENSION_free(sk);
5646f971622SJuan Castillo 	}
5656f971622SJuan Castillo 
5666f971622SJuan Castillo 
5676f971622SJuan Castillo 	/* Print the certificates */
5686f971622SJuan Castillo 	if (print_cert) {
56955e291a4SJuan Castillo 		for (i = 0 ; i < num_certs ; i++) {
5706f971622SJuan Castillo 			if (!certs[i].x) {
5716f971622SJuan Castillo 				continue;
5726f971622SJuan Castillo 			}
5736f971622SJuan Castillo 			printf("\n\n=====================================\n\n");
5746f971622SJuan Castillo 			X509_print_fp(stdout, certs[i].x);
5756f971622SJuan Castillo 		}
5766f971622SJuan Castillo 	}
5776f971622SJuan Castillo 
5786f971622SJuan Castillo 	/* Save created certificates to files */
57955e291a4SJuan Castillo 	for (i = 0 ; i < num_certs ; i++) {
5806f971622SJuan Castillo 		if (certs[i].x && certs[i].fn) {
5816f971622SJuan Castillo 			file = fopen(certs[i].fn, "w");
5826f971622SJuan Castillo 			if (file != NULL) {
5836f971622SJuan Castillo 				i2d_X509_fp(file, certs[i].x);
5846f971622SJuan Castillo 				fclose(file);
5856f971622SJuan Castillo 			} else {
5866f971622SJuan Castillo 				ERROR("Cannot create file %s\n", certs[i].fn);
5876f971622SJuan Castillo 			}
5886f971622SJuan Castillo 		}
5896f971622SJuan Castillo 	}
5906f971622SJuan Castillo 
5916f971622SJuan Castillo 	/* Save keys */
5926f971622SJuan Castillo 	if (save_keys) {
59355e291a4SJuan Castillo 		for (i = 0 ; i < num_keys ; i++) {
5946f971622SJuan Castillo 			if (!key_store(&keys[i])) {
5956f971622SJuan Castillo 				ERROR("Cannot save %s\n", keys[i].desc);
5966f971622SJuan Castillo 			}
5976f971622SJuan Castillo 		}
5986f971622SJuan Castillo 	}
5996f971622SJuan Castillo 
6001f111f12SJimmy Brisson 	/* If we got here, then we must have filled the key array completely.
6011f111f12SJimmy Brisson 	 * We can then safely call free on all of the keys in the array
6021f111f12SJimmy Brisson 	 */
603cf2dd17dSJuan Pablo Conde 	key_cleanup();
6041f111f12SJimmy Brisson 
6056f971622SJuan Castillo #ifndef OPENSSL_NO_ENGINE
6066f971622SJuan Castillo 	ENGINE_cleanup();
6076f971622SJuan Castillo #endif
6086f971622SJuan Castillo 	CRYPTO_cleanup_all_ex_data();
6096f971622SJuan Castillo 
6104a34d18fSJimmy Brisson 
6114a34d18fSJimmy Brisson 	/* We allocated strings through strdup, so now we have to free them */
6124a34d18fSJimmy Brisson 
613cf2dd17dSJuan Pablo Conde 	ext_cleanup();
6144a34d18fSJimmy Brisson 
615cf2dd17dSJuan Pablo Conde 	cert_cleanup();
6164a34d18fSJimmy Brisson 
6176f971622SJuan Castillo 	return 0;
6186f971622SJuan Castillo }
619