xref: /rk3399_ARM-atf/tools/cert_create/src/main.c (revision e2c3611cf109b6d69cbf68de874e034b309ffd73)
16f971622SJuan Castillo /*
2a004ee8dSChris Kay  * Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved.
36f971622SJuan Castillo  *
482cb2c1aSdp-arm  * SPDX-License-Identifier: BSD-3-Clause
56f971622SJuan Castillo  */
66f971622SJuan Castillo 
7*ccbfd01dSManish V Badarkhe #define _POSIX_C_SOURCE 200809L
8*ccbfd01dSManish V Badarkhe 
9159807e2SJuan Castillo #include <assert.h>
10159807e2SJuan Castillo #include <ctype.h>
116f971622SJuan Castillo #include <getopt.h>
126f971622SJuan Castillo #include <stdio.h>
136f971622SJuan Castillo #include <stdlib.h>
146f971622SJuan Castillo #include <string.h>
15dfe0f4c2SJustin Chadwell #include <stdbool.h>
166f971622SJuan Castillo 
176f971622SJuan Castillo #include <openssl/conf.h>
186f971622SJuan Castillo #include <openssl/engine.h>
196f971622SJuan Castillo #include <openssl/err.h>
206f971622SJuan Castillo #include <openssl/pem.h>
216f971622SJuan Castillo #include <openssl/sha.h>
226f971622SJuan Castillo #include <openssl/x509v3.h>
236f971622SJuan Castillo 
246f971622SJuan Castillo #include "cert.h"
25ad2c1a9aSJuan Castillo #include "cmd_opt.h"
266f971622SJuan Castillo #include "debug.h"
276f971622SJuan Castillo #include "ext.h"
286f971622SJuan Castillo #include "key.h"
296f971622SJuan Castillo #include "sha.h"
306f971622SJuan Castillo 
316f971622SJuan Castillo /*
326f971622SJuan Castillo  * Helper macros to simplify the code. This macro assigns the return value of
336f971622SJuan Castillo  * the 'fn' function to 'v' and exits if the value is NULL.
346f971622SJuan Castillo  */
356f971622SJuan Castillo #define CHECK_NULL(v, fn) \
366f971622SJuan Castillo 	do { \
376f971622SJuan Castillo 		v = fn; \
386f971622SJuan Castillo 		if (v == NULL) { \
396f971622SJuan Castillo 			ERROR("NULL object at %s:%d\n", __FILE__, __LINE__); \
406f971622SJuan Castillo 			exit(1); \
416f971622SJuan Castillo 		} \
426f971622SJuan Castillo 	} while (0)
436f971622SJuan Castillo 
446f971622SJuan Castillo /*
456f971622SJuan Castillo  * This macro assigns the NID corresponding to 'oid' to 'v' and exits if the
466f971622SJuan Castillo  * NID is undefined.
476f971622SJuan Castillo  */
486f971622SJuan Castillo #define CHECK_OID(v, oid) \
496f971622SJuan Castillo 	do { \
506f971622SJuan Castillo 		v = OBJ_txt2nid(oid); \
516f971622SJuan Castillo 		if (v == NID_undef) { \
52067f7e9cSSandrine Bailleux 			ERROR("Cannot find extension %s\n", oid); \
536f971622SJuan Castillo 			exit(1); \
546f971622SJuan Castillo 		} \
556f971622SJuan Castillo 	} while (0)
566f971622SJuan Castillo 
576f971622SJuan Castillo #define MAX_FILENAME_LEN		1024
586f971622SJuan Castillo #define VAL_DAYS			7300
596f971622SJuan Castillo #define ID_TO_BIT_MASK(id)		(1 << id)
60ccbf890eSJuan Castillo #define NUM_ELEM(x)			((sizeof(x)) / (sizeof(x[0])))
61159807e2SJuan Castillo #define HELP_OPT_MAX_LEN		128
626f971622SJuan Castillo 
636f971622SJuan Castillo /* Global options */
64ccbf890eSJuan Castillo static int key_alg;
652972247cSQixiang Xu static int hash_alg;
66dfe0f4c2SJustin Chadwell static int key_size;
676f971622SJuan Castillo static int new_keys;
686f971622SJuan Castillo static int save_keys;
696f971622SJuan Castillo static int print_cert;
706f971622SJuan Castillo 
71a004ee8dSChris Kay static const char build_msg[] = "Built : " __TIME__ ", " __DATE__;
72a004ee8dSChris Kay static const char platform_msg[] = PLAT_MSG;
736f971622SJuan Castillo 
74ccbf890eSJuan Castillo static const char *key_algs_str[] = {
75ccbf890eSJuan Castillo 	[KEY_ALG_RSA] = "rsa",
76ed2a76eaSJuan Castillo #ifndef OPENSSL_NO_EC
77e78ba69eSLionel Debieve 	[KEY_ALG_ECDSA_NIST] = "ecdsa",
78c0c280dfSDonald Chan #if OPENSSL_VERSION_NUMBER >= 0x10100000L
79e78ba69eSLionel Debieve 	[KEY_ALG_ECDSA_BRAINPOOL_R] = "ecdsa-brainpool-regular",
80e78ba69eSLionel Debieve 	[KEY_ALG_ECDSA_BRAINPOOL_T] = "ecdsa-brainpool-twisted",
81c0c280dfSDonald Chan #endif
82ed2a76eaSJuan Castillo #endif /* OPENSSL_NO_EC */
83ccbf890eSJuan Castillo };
84ccbf890eSJuan Castillo 
852972247cSQixiang Xu static const char *hash_algs_str[] = {
862972247cSQixiang Xu 	[HASH_ALG_SHA256] = "sha256",
872972247cSQixiang Xu 	[HASH_ALG_SHA384] = "sha384",
882972247cSQixiang Xu 	[HASH_ALG_SHA512] = "sha512",
892972247cSQixiang Xu };
902972247cSQixiang Xu 
print_help(const char * cmd,const struct option * long_opt)91ad2c1a9aSJuan Castillo static void print_help(const char *cmd, const struct option *long_opt)
926f971622SJuan Castillo {
93159807e2SJuan Castillo 	int rem, i = 0;
94159807e2SJuan Castillo 	const struct option *opt;
95159807e2SJuan Castillo 	char line[HELP_OPT_MAX_LEN];
96159807e2SJuan Castillo 	char *p;
97159807e2SJuan Castillo 
98159807e2SJuan Castillo 	assert(cmd != NULL);
99159807e2SJuan Castillo 	assert(long_opt != NULL);
100159807e2SJuan Castillo 
1016f971622SJuan Castillo 	printf("\n\n");
1026f971622SJuan Castillo 	printf("The certificate generation tool loads the binary images and\n"
103e78ba69eSLionel Debieve 	       "optionally the RSA or ECC keys, and outputs the key and content\n"
1046f971622SJuan Castillo 	       "certificates properly signed to implement the chain of trust.\n"
1056f971622SJuan Castillo 	       "If keys are provided, they must be in PEM format.\n"
1066f971622SJuan Castillo 	       "Certificates are generated in DER format.\n");
1076f971622SJuan Castillo 	printf("\n");
108159807e2SJuan Castillo 	printf("Usage:\n");
109159807e2SJuan Castillo 	printf("\t%s [OPTIONS]\n\n", cmd);
110159807e2SJuan Castillo 
111159807e2SJuan Castillo 	printf("Available options:\n");
112159807e2SJuan Castillo 	opt = long_opt;
113159807e2SJuan Castillo 	while (opt->name) {
114159807e2SJuan Castillo 		p = line;
115159807e2SJuan Castillo 		rem = HELP_OPT_MAX_LEN;
116159807e2SJuan Castillo 		if (isalpha(opt->val)) {
117159807e2SJuan Castillo 			/* Short format */
118159807e2SJuan Castillo 			sprintf(p, "-%c,", (char)opt->val);
119159807e2SJuan Castillo 			p += 3;
120159807e2SJuan Castillo 			rem -= 3;
1216f971622SJuan Castillo 		}
122159807e2SJuan Castillo 		snprintf(p, rem, "--%s %s", opt->name,
123159807e2SJuan Castillo 			 (opt->has_arg == required_argument) ? "<arg>" : "");
124159807e2SJuan Castillo 		printf("\t%-32s %s\n", line, cmd_opt_get_help_msg(i));
125159807e2SJuan Castillo 		opt++;
126159807e2SJuan Castillo 		i++;
127159807e2SJuan Castillo 	}
1286f971622SJuan Castillo 	printf("\n");
1296f971622SJuan Castillo }
1306f971622SJuan Castillo 
get_key_alg(const char * key_alg_str)131ccbf890eSJuan Castillo static int get_key_alg(const char *key_alg_str)
132ccbf890eSJuan Castillo {
133ccbf890eSJuan Castillo 	int i;
134ccbf890eSJuan Castillo 
135ccbf890eSJuan Castillo 	for (i = 0 ; i < NUM_ELEM(key_algs_str) ; i++) {
136ccbf890eSJuan Castillo 		if (0 == strcmp(key_alg_str, key_algs_str[i])) {
137ccbf890eSJuan Castillo 			return i;
138ccbf890eSJuan Castillo 		}
139ccbf890eSJuan Castillo 	}
140ccbf890eSJuan Castillo 
141ccbf890eSJuan Castillo 	return -1;
142ccbf890eSJuan Castillo }
143ccbf890eSJuan Castillo 
get_key_size(const char * key_size_str)144dfe0f4c2SJustin Chadwell static int get_key_size(const char *key_size_str)
145dfe0f4c2SJustin Chadwell {
146dfe0f4c2SJustin Chadwell 	char *end;
147dfe0f4c2SJustin Chadwell 	long key_size;
148dfe0f4c2SJustin Chadwell 
149dfe0f4c2SJustin Chadwell 	key_size = strtol(key_size_str, &end, 10);
150dfe0f4c2SJustin Chadwell 	if (*end != '\0')
151dfe0f4c2SJustin Chadwell 		return -1;
152dfe0f4c2SJustin Chadwell 
153dfe0f4c2SJustin Chadwell 	return key_size;
154dfe0f4c2SJustin Chadwell }
155dfe0f4c2SJustin Chadwell 
get_hash_alg(const char * hash_alg_str)1562972247cSQixiang Xu static int get_hash_alg(const char *hash_alg_str)
1572972247cSQixiang Xu {
1582972247cSQixiang Xu 	int i;
1592972247cSQixiang Xu 
1602972247cSQixiang Xu 	for (i = 0 ; i < NUM_ELEM(hash_algs_str) ; i++) {
1612972247cSQixiang Xu 		if (0 == strcmp(hash_alg_str, hash_algs_str[i])) {
1622972247cSQixiang Xu 			return i;
1632972247cSQixiang Xu 		}
1642972247cSQixiang Xu 	}
1652972247cSQixiang Xu 
1662972247cSQixiang Xu 	return -1;
1672972247cSQixiang Xu }
1682972247cSQixiang Xu 
check_cmd_params(void)1696f971622SJuan Castillo static void check_cmd_params(void)
1706f971622SJuan Castillo {
171dfc90e26SJuan Castillo 	cert_t *cert;
172dfc90e26SJuan Castillo 	ext_t *ext;
173*ccbfd01dSManish V Badarkhe 	cert_key_t *key;
174dfc90e26SJuan Castillo 	int i, j;
175dfe0f4c2SJustin Chadwell 	bool valid_size;
176dfc90e26SJuan Castillo 
177ccbf890eSJuan Castillo 	/* Only save new keys */
178ccbf890eSJuan Castillo 	if (save_keys && !new_keys) {
179ccbf890eSJuan Castillo 		ERROR("Only new keys can be saved to disk\n");
180ccbf890eSJuan Castillo 		exit(1);
181ccbf890eSJuan Castillo 	}
182ccbf890eSJuan Castillo 
183dfe0f4c2SJustin Chadwell 	/* Validate key-size */
184dfe0f4c2SJustin Chadwell 	valid_size = false;
185dfe0f4c2SJustin Chadwell 	for (i = 0; i < KEY_SIZE_MAX_NUM; i++) {
186dfe0f4c2SJustin Chadwell 		if (key_size == KEY_SIZES[key_alg][i]) {
187dfe0f4c2SJustin Chadwell 			valid_size = true;
188dfe0f4c2SJustin Chadwell 			break;
189dfe0f4c2SJustin Chadwell 		}
190dfe0f4c2SJustin Chadwell 	}
191dfe0f4c2SJustin Chadwell 	if (!valid_size) {
192dfe0f4c2SJustin Chadwell 		ERROR("'%d' is not a valid key size for '%s'\n",
193dfe0f4c2SJustin Chadwell 				key_size, key_algs_str[key_alg]);
194dfe0f4c2SJustin Chadwell 		NOTICE("Valid sizes are: ");
195dfe0f4c2SJustin Chadwell 		for (i = 0; i < KEY_SIZE_MAX_NUM &&
196dfe0f4c2SJustin Chadwell 				KEY_SIZES[key_alg][i] != 0; i++) {
197dfe0f4c2SJustin Chadwell 			printf("%d ", KEY_SIZES[key_alg][i]);
198dfe0f4c2SJustin Chadwell 		}
199dfe0f4c2SJustin Chadwell 		printf("\n");
200dfe0f4c2SJustin Chadwell 		exit(1);
201dfe0f4c2SJustin Chadwell 	}
202dfe0f4c2SJustin Chadwell 
203dfc90e26SJuan Castillo 	/* Check that all required options have been specified in the
204dfc90e26SJuan Castillo 	 * command line */
205dfc90e26SJuan Castillo 	for (i = 0; i < num_certs; i++) {
206dfc90e26SJuan Castillo 		cert = &certs[i];
207dfc90e26SJuan Castillo 		if (cert->fn == NULL) {
208dfc90e26SJuan Castillo 			/* Certificate not requested. Skip to the next one */
209dfc90e26SJuan Castillo 			continue;
210dfc90e26SJuan Castillo 		}
211dfc90e26SJuan Castillo 
212dfc90e26SJuan Castillo 		/* Check that all parameters required to create this certificate
213dfc90e26SJuan Castillo 		 * have been specified in the command line */
214dfc90e26SJuan Castillo 		for (j = 0; j < cert->num_ext; j++) {
215dfc90e26SJuan Castillo 			ext = &extensions[cert->ext[j]];
216dfc90e26SJuan Castillo 			switch (ext->type) {
21796103d5aSJuan Castillo 			case EXT_TYPE_NVCOUNTER:
21896103d5aSJuan Castillo 				/* Counter value must be specified */
21996103d5aSJuan Castillo 				if ((!ext->optional) && (ext->arg == NULL)) {
22096103d5aSJuan Castillo 					ERROR("Value for '%s' not specified\n",
22196103d5aSJuan Castillo 					      ext->ln);
22296103d5aSJuan Castillo 					exit(1);
22396103d5aSJuan Castillo 				}
22496103d5aSJuan Castillo 				break;
225dfc90e26SJuan Castillo 			case EXT_TYPE_PKEY:
226dfc90e26SJuan Castillo 				/* Key filename must be specified */
22796103d5aSJuan Castillo 				key = &keys[ext->attr.key];
228dfc90e26SJuan Castillo 				if (!new_keys && key->fn == NULL) {
229dfc90e26SJuan Castillo 					ERROR("Key '%s' required by '%s' not "
230dfc90e26SJuan Castillo 					      "specified\n", key->desc,
231dfc90e26SJuan Castillo 					      cert->cn);
2326f971622SJuan Castillo 					exit(1);
2336f971622SJuan Castillo 				}
234dfc90e26SJuan Castillo 				break;
235dfc90e26SJuan Castillo 			case EXT_TYPE_HASH:
236cebe1f23SYatharth Kochar 				/*
237cebe1f23SYatharth Kochar 				 * Binary image must be specified
238cebe1f23SYatharth Kochar 				 * unless it is explicitly made optional.
239cebe1f23SYatharth Kochar 				 */
24096103d5aSJuan Castillo 				if ((!ext->optional) && (ext->arg == NULL)) {
241dfc90e26SJuan Castillo 					ERROR("Image for '%s' not specified\n",
242dfc90e26SJuan Castillo 					      ext->ln);
2436f971622SJuan Castillo 					exit(1);
2446f971622SJuan Castillo 				}
245dfc90e26SJuan Castillo 				break;
246dfc90e26SJuan Castillo 			default:
24796103d5aSJuan Castillo 				ERROR("Unknown extension type '%d' in '%s'\n",
24896103d5aSJuan Castillo 				      ext->type, ext->ln);
2496f971622SJuan Castillo 				exit(1);
250dfc90e26SJuan Castillo 				break;
2516f971622SJuan Castillo 			}
2526f971622SJuan Castillo 		}
2536f971622SJuan Castillo 	}
2546f971622SJuan Castillo }
2556f971622SJuan Castillo 
256159807e2SJuan Castillo /* Common command line options */
257159807e2SJuan Castillo static const cmd_opt_t common_cmd_opt[] = {
258159807e2SJuan Castillo 	{
259159807e2SJuan Castillo 		{ "help", no_argument, NULL, 'h' },
260159807e2SJuan Castillo 		"Print this message and exit"
261159807e2SJuan Castillo 	},
262159807e2SJuan Castillo 	{
263159807e2SJuan Castillo 		{ "key-alg", required_argument, NULL, 'a' },
264c0c280dfSDonald Chan 		"Key algorithm: 'rsa' (default)- RSAPSS scheme as per PKCS#1 v2.1, "
265c0c280dfSDonald Chan #if OPENSSL_VERSION_NUMBER >= 0x10100000L
266e78ba69eSLionel Debieve 		"'ecdsa', 'ecdsa-brainpool-regular', 'ecdsa-brainpool-twisted'"
267c0c280dfSDonald Chan #else
268c0c280dfSDonald Chan 		"'ecdsa'"
269c0c280dfSDonald Chan #endif
270159807e2SJuan Castillo 	},
271159807e2SJuan Castillo 	{
272dfe0f4c2SJustin Chadwell 		{ "key-size", required_argument, NULL, 'b' },
273dfe0f4c2SJustin Chadwell 		"Key size (for supported algorithms)."
274dfe0f4c2SJustin Chadwell 	},
275dfe0f4c2SJustin Chadwell 	{
2762972247cSQixiang Xu 		{ "hash-alg", required_argument, NULL, 's' },
2772972247cSQixiang Xu 		"Hash algorithm : 'sha256' (default), 'sha384', 'sha512'"
2782972247cSQixiang Xu 	},
2792972247cSQixiang Xu 	{
280159807e2SJuan Castillo 		{ "save-keys", no_argument, NULL, 'k' },
281159807e2SJuan Castillo 		"Save key pairs into files. Filenames must be provided"
282159807e2SJuan Castillo 	},
283159807e2SJuan Castillo 	{
284159807e2SJuan Castillo 		{ "new-keys", no_argument, NULL, 'n' },
285159807e2SJuan Castillo 		"Generate new key pairs if no key files are provided"
286159807e2SJuan Castillo 	},
287159807e2SJuan Castillo 	{
288159807e2SJuan Castillo 		{ "print-cert", no_argument, NULL, 'p' },
289159807e2SJuan Castillo 		"Print the certificates in the standard output"
290159807e2SJuan Castillo 	}
291159807e2SJuan Castillo };
292159807e2SJuan Castillo 
main(int argc,char * argv[])2936f971622SJuan Castillo int main(int argc, char *argv[])
2946f971622SJuan Castillo {
295c893c733SMasahiro Yamada 	STACK_OF(X509_EXTENSION) * sk;
296742c4e14SMichalis Pappas 	X509_EXTENSION *cert_ext = NULL;
297c893c733SMasahiro Yamada 	ext_t *ext;
298*ccbfd01dSManish V Badarkhe 	cert_key_t *key;
299c893c733SMasahiro Yamada 	cert_t *cert;
300c893c733SMasahiro Yamada 	FILE *file;
30196103d5aSJuan Castillo 	int i, j, ext_nid, nvctr;
3026f971622SJuan Castillo 	int c, opt_idx = 0;
303ad2c1a9aSJuan Castillo 	const struct option *cmd_opt;
304ad2c1a9aSJuan Castillo 	const char *cur_opt;
305ccbf890eSJuan Castillo 	unsigned int err_code;
3062972247cSQixiang Xu 	unsigned char md[SHA512_DIGEST_LENGTH];
3072972247cSQixiang Xu 	unsigned int  md_len;
308c3da66b1SJuan Castillo 	const EVP_MD *md_info;
3096f971622SJuan Castillo 
3106f971622SJuan Castillo 	NOTICE("CoT Generation Tool: %s\n", build_msg);
3116f971622SJuan Castillo 	NOTICE("Target platform: %s\n", platform_msg);
3126f971622SJuan Castillo 
313ccbf890eSJuan Castillo 	/* Set default options */
314ccbf890eSJuan Castillo 	key_alg = KEY_ALG_RSA;
3152972247cSQixiang Xu 	hash_alg = HASH_ALG_SHA256;
316dfe0f4c2SJustin Chadwell 	key_size = -1;
317ccbf890eSJuan Castillo 
318ad2c1a9aSJuan Castillo 	/* Add common command line options */
319159807e2SJuan Castillo 	for (i = 0; i < NUM_ELEM(common_cmd_opt); i++) {
320159807e2SJuan Castillo 		cmd_opt_add(&common_cmd_opt[i]);
321159807e2SJuan Castillo 	}
322ad2c1a9aSJuan Castillo 
323ad2c1a9aSJuan Castillo 	/* Initialize the certificates */
324ad2c1a9aSJuan Castillo 	if (cert_init() != 0) {
325ad2c1a9aSJuan Castillo 		ERROR("Cannot initialize certificates\n");
326ad2c1a9aSJuan Castillo 		exit(1);
327ad2c1a9aSJuan Castillo 	}
328ad2c1a9aSJuan Castillo 
329ad2c1a9aSJuan Castillo 	/* Initialize the keys */
330ad2c1a9aSJuan Castillo 	if (key_init() != 0) {
331ad2c1a9aSJuan Castillo 		ERROR("Cannot initialize keys\n");
332ad2c1a9aSJuan Castillo 		exit(1);
333ad2c1a9aSJuan Castillo 	}
334ad2c1a9aSJuan Castillo 
335ad2c1a9aSJuan Castillo 	/* Initialize the new types and register OIDs for the extensions */
336ad2c1a9aSJuan Castillo 	if (ext_init() != 0) {
337067f7e9cSSandrine Bailleux 		ERROR("Cannot initialize extensions\n");
338ad2c1a9aSJuan Castillo 		exit(1);
339ad2c1a9aSJuan Castillo 	}
340ad2c1a9aSJuan Castillo 
341ad2c1a9aSJuan Castillo 	/* Get the command line options populated during the initialization */
342ad2c1a9aSJuan Castillo 	cmd_opt = cmd_opt_get_array();
343ad2c1a9aSJuan Castillo 
3446f971622SJuan Castillo 	while (1) {
3456f971622SJuan Castillo 		/* getopt_long stores the option index here. */
346dfe0f4c2SJustin Chadwell 		c = getopt_long(argc, argv, "a:b:hknps:", cmd_opt, &opt_idx);
3476f971622SJuan Castillo 
3486f971622SJuan Castillo 		/* Detect the end of the options. */
3496f971622SJuan Castillo 		if (c == -1) {
3506f971622SJuan Castillo 			break;
3516f971622SJuan Castillo 		}
3526f971622SJuan Castillo 
3536f971622SJuan Castillo 		switch (c) {
354ccbf890eSJuan Castillo 		case 'a':
355ccbf890eSJuan Castillo 			key_alg = get_key_alg(optarg);
356ccbf890eSJuan Castillo 			if (key_alg < 0) {
357ccbf890eSJuan Castillo 				ERROR("Invalid key algorithm '%s'\n", optarg);
358ccbf890eSJuan Castillo 				exit(1);
359ccbf890eSJuan Castillo 			}
360ccbf890eSJuan Castillo 			break;
361dfe0f4c2SJustin Chadwell 		case 'b':
362dfe0f4c2SJustin Chadwell 			key_size = get_key_size(optarg);
363dfe0f4c2SJustin Chadwell 			if (key_size <= 0) {
364dfe0f4c2SJustin Chadwell 				ERROR("Invalid key size '%s'\n", optarg);
365dfe0f4c2SJustin Chadwell 				exit(1);
366dfe0f4c2SJustin Chadwell 			}
367dfe0f4c2SJustin Chadwell 			break;
3686f971622SJuan Castillo 		case 'h':
369ad2c1a9aSJuan Castillo 			print_help(argv[0], cmd_opt);
370600835d0SRoberto Vargas 			exit(0);
3716f971622SJuan Castillo 		case 'k':
3726f971622SJuan Castillo 			save_keys = 1;
3736f971622SJuan Castillo 			break;
3746f971622SJuan Castillo 		case 'n':
3756f971622SJuan Castillo 			new_keys = 1;
3766f971622SJuan Castillo 			break;
3776f971622SJuan Castillo 		case 'p':
3786f971622SJuan Castillo 			print_cert = 1;
3796f971622SJuan Castillo 			break;
3802972247cSQixiang Xu 		case 's':
3812972247cSQixiang Xu 			hash_alg = get_hash_alg(optarg);
3822972247cSQixiang Xu 			if (hash_alg < 0) {
3832972247cSQixiang Xu 				ERROR("Invalid hash algorithm '%s'\n", optarg);
3842972247cSQixiang Xu 				exit(1);
3852972247cSQixiang Xu 			}
3862972247cSQixiang Xu 			break;
387ad2c1a9aSJuan Castillo 		case CMD_OPT_EXT:
388ad2c1a9aSJuan Castillo 			cur_opt = cmd_opt_get_name(opt_idx);
389ad2c1a9aSJuan Castillo 			ext = ext_get_by_opt(cur_opt);
39096103d5aSJuan Castillo 			ext->arg = strdup(optarg);
3916f971622SJuan Castillo 			break;
392ad2c1a9aSJuan Castillo 		case CMD_OPT_KEY:
393ad2c1a9aSJuan Castillo 			cur_opt = cmd_opt_get_name(opt_idx);
394ad2c1a9aSJuan Castillo 			key = key_get_by_opt(cur_opt);
395ad2c1a9aSJuan Castillo 			key->fn = strdup(optarg);
3966f971622SJuan Castillo 			break;
397ad2c1a9aSJuan Castillo 		case CMD_OPT_CERT:
398ad2c1a9aSJuan Castillo 			cur_opt = cmd_opt_get_name(opt_idx);
399ad2c1a9aSJuan Castillo 			cert = cert_get_by_opt(cur_opt);
400ad2c1a9aSJuan Castillo 			cert->fn = strdup(optarg);
4016f971622SJuan Castillo 			break;
4026f971622SJuan Castillo 		case '?':
4036f971622SJuan Castillo 		default:
404159807e2SJuan Castillo 			print_help(argv[0], cmd_opt);
4056f971622SJuan Castillo 			exit(1);
4066f971622SJuan Castillo 		}
4076f971622SJuan Castillo 	}
4086f971622SJuan Castillo 
409dfe0f4c2SJustin Chadwell 	/* Select a reasonable default key-size */
410dfe0f4c2SJustin Chadwell 	if (key_size == -1) {
411dfe0f4c2SJustin Chadwell 		key_size = KEY_SIZES[key_alg][0];
412dfe0f4c2SJustin Chadwell 	}
413dfe0f4c2SJustin Chadwell 
4146f971622SJuan Castillo 	/* Check command line arguments */
4156f971622SJuan Castillo 	check_cmd_params();
4166f971622SJuan Castillo 
4172972247cSQixiang Xu 	/* Indicate SHA as image hash algorithm in the certificate
418c3da66b1SJuan Castillo 	 * extension */
4192972247cSQixiang Xu 	if (hash_alg == HASH_ALG_SHA384) {
4202972247cSQixiang Xu 		md_info = EVP_sha384();
4212972247cSQixiang Xu 		md_len  = SHA384_DIGEST_LENGTH;
4222972247cSQixiang Xu 	} else if (hash_alg == HASH_ALG_SHA512) {
4232972247cSQixiang Xu 		md_info = EVP_sha512();
4242972247cSQixiang Xu 		md_len  = SHA512_DIGEST_LENGTH;
4252972247cSQixiang Xu 	} else {
426c3da66b1SJuan Castillo 		md_info = EVP_sha256();
4272972247cSQixiang Xu 		md_len  = SHA256_DIGEST_LENGTH;
4282972247cSQixiang Xu 	}
429c3da66b1SJuan Castillo 
4306f971622SJuan Castillo 	/* Load private keys from files (or generate new ones) */
43155e291a4SJuan Castillo 	for (i = 0 ; i < num_keys ; i++) {
432cf2dd17dSJuan Pablo Conde #if !USING_OPENSSL3
433762f1ebeSMasahiro Yamada 		if (!key_new(&keys[i])) {
434762f1ebeSMasahiro Yamada 			ERROR("Failed to allocate key container\n");
435762f1ebeSMasahiro Yamada 			exit(1);
436762f1ebeSMasahiro Yamada 		}
437cf2dd17dSJuan Pablo Conde #endif
438762f1ebeSMasahiro Yamada 
439ccbf890eSJuan Castillo 		/* First try to load the key from disk */
440bb3b0c0bSSandrine Bailleux 		err_code = key_load(&keys[i]);
441bb3b0c0bSSandrine Bailleux 		if (err_code == KEY_ERR_NONE) {
442ccbf890eSJuan Castillo 			/* Key loaded successfully */
443ccbf890eSJuan Castillo 			continue;
444ccbf890eSJuan Castillo 		}
445ccbf890eSJuan Castillo 
446ccbf890eSJuan Castillo 		/* Key not loaded. Check the error code */
447762f1ebeSMasahiro Yamada 		if (err_code == KEY_ERR_LOAD) {
448ccbf890eSJuan Castillo 			/* File exists, but it does not contain a valid private
449ccbf890eSJuan Castillo 			 * key. Abort. */
450ccbf890eSJuan Castillo 			ERROR("Error loading '%s'\n", keys[i].fn);
4516f971622SJuan Castillo 			exit(1);
4526f971622SJuan Castillo 		}
453ccbf890eSJuan Castillo 
454ccbf890eSJuan Castillo 		/* File does not exist, could not be opened or no filename was
455ccbf890eSJuan Castillo 		 * given */
456ccbf890eSJuan Castillo 		if (new_keys) {
457ccbf890eSJuan Castillo 			/* Try to create a new key */
458ccbf890eSJuan Castillo 			NOTICE("Creating new key for '%s'\n", keys[i].desc);
459dfe0f4c2SJustin Chadwell 			if (!key_create(&keys[i], key_alg, key_size)) {
460ccbf890eSJuan Castillo 				ERROR("Error creating key '%s'\n", keys[i].desc);
461ccbf890eSJuan Castillo 				exit(1);
4626f971622SJuan Castillo 			}
4636f971622SJuan Castillo 		} else {
464ccbf890eSJuan Castillo 			if (err_code == KEY_ERR_OPEN) {
465ccbf890eSJuan Castillo 				ERROR("Error opening '%s'\n", keys[i].fn);
466ccbf890eSJuan Castillo 			} else {
467ccbf890eSJuan Castillo 				ERROR("Key '%s' not specified\n", keys[i].desc);
4686f971622SJuan Castillo 			}
469ccbf890eSJuan Castillo 			exit(1);
4706f971622SJuan Castillo 		}
4716f971622SJuan Castillo 	}
4726f971622SJuan Castillo 
47355e291a4SJuan Castillo 	/* Create the certificates */
47455e291a4SJuan Castillo 	for (i = 0 ; i < num_certs ; i++) {
47555e291a4SJuan Castillo 
47655e291a4SJuan Castillo 		cert = &certs[i];
47755e291a4SJuan Castillo 
478294e2656SManish V Badarkhe 		if (cert->fn == NULL) {
479294e2656SManish V Badarkhe 			/* Certificate not requested. Skip to the next one */
480294e2656SManish V Badarkhe 			continue;
481294e2656SManish V Badarkhe 		}
482294e2656SManish V Badarkhe 
48355e291a4SJuan Castillo 		/* Create a new stack of extensions. This stack will be used
48455e291a4SJuan Castillo 		 * to create the certificate */
4856f971622SJuan Castillo 		CHECK_NULL(sk, sk_X509_EXTENSION_new_null());
4866f971622SJuan Castillo 
48755e291a4SJuan Castillo 		for (j = 0 ; j < cert->num_ext ; j++) {
4886f971622SJuan Castillo 
48955e291a4SJuan Castillo 			ext = &extensions[cert->ext[j]];
49055e291a4SJuan Castillo 
49155e291a4SJuan Castillo 			/* Get OpenSSL internal ID for this extension */
49255e291a4SJuan Castillo 			CHECK_OID(ext_nid, ext->oid);
49355e291a4SJuan Castillo 
49455e291a4SJuan Castillo 			/*
49555e291a4SJuan Castillo 			 * Three types of extensions are currently supported:
49655e291a4SJuan Castillo 			 *     - EXT_TYPE_NVCOUNTER
49755e291a4SJuan Castillo 			 *     - EXT_TYPE_HASH
49855e291a4SJuan Castillo 			 *     - EXT_TYPE_PKEY
49955e291a4SJuan Castillo 			 */
50055e291a4SJuan Castillo 			switch (ext->type) {
50155e291a4SJuan Castillo 			case EXT_TYPE_NVCOUNTER:
5021ed941c0SJimmy Brisson 				if (ext->optional && ext->arg == NULL) {
5031ed941c0SJimmy Brisson 					/* Skip this NVCounter */
5041ed941c0SJimmy Brisson 					continue;
5051ed941c0SJimmy Brisson 				} else {
5061ed941c0SJimmy Brisson 					/* Checked by `check_cmd_params` */
5071ed941c0SJimmy Brisson 					assert(ext->arg != NULL);
50896103d5aSJuan Castillo 					nvctr = atoi(ext->arg);
50955e291a4SJuan Castillo 					CHECK_NULL(cert_ext, ext_new_nvcounter(ext_nid,
51096103d5aSJuan Castillo 						EXT_CRIT, nvctr));
511f16db56aSYatharth Kochar 				}
51255e291a4SJuan Castillo 				break;
51355e291a4SJuan Castillo 			case EXT_TYPE_HASH:
51496103d5aSJuan Castillo 				if (ext->arg == NULL) {
515cebe1f23SYatharth Kochar 					if (ext->optional) {
516cebe1f23SYatharth Kochar 						/* Include a hash filled with zeros */
5172972247cSQixiang Xu 						memset(md, 0x0, SHA512_DIGEST_LENGTH);
518cebe1f23SYatharth Kochar 					} else {
519cebe1f23SYatharth Kochar 						/* Do not include this hash in the certificate */
5201ed941c0SJimmy Brisson 						continue;
52155e291a4SJuan Castillo 					}
522cebe1f23SYatharth Kochar 				} else {
523cebe1f23SYatharth Kochar 					/* Calculate the hash of the file */
5242972247cSQixiang Xu 					if (!sha_file(hash_alg, ext->arg, md)) {
52555e291a4SJuan Castillo 						ERROR("Cannot calculate hash of %s\n",
52696103d5aSJuan Castillo 							ext->arg);
5276f971622SJuan Castillo 						exit(1);
5286f971622SJuan Castillo 					}
529cebe1f23SYatharth Kochar 				}
53055e291a4SJuan Castillo 				CHECK_NULL(cert_ext, ext_new_hash(ext_nid,
53155e291a4SJuan Castillo 						EXT_CRIT, md_info, md,
5322972247cSQixiang Xu 						md_len));
53355e291a4SJuan Castillo 				break;
53455e291a4SJuan Castillo 			case EXT_TYPE_PKEY:
53555e291a4SJuan Castillo 				CHECK_NULL(cert_ext, ext_new_key(ext_nid,
53696103d5aSJuan Castillo 					EXT_CRIT, keys[ext->attr.key].key));
53755e291a4SJuan Castillo 				break;
53855e291a4SJuan Castillo 			default:
53996103d5aSJuan Castillo 				ERROR("Unknown extension type '%d' in %s\n",
54096103d5aSJuan Castillo 						ext->type, cert->cn);
54155e291a4SJuan Castillo 				exit(1);
54255e291a4SJuan Castillo 			}
54355e291a4SJuan Castillo 
54455e291a4SJuan Castillo 			/* Push the extension into the stack */
54555e291a4SJuan Castillo 			sk_X509_EXTENSION_push(sk, cert_ext);
54655e291a4SJuan Castillo 		}
5476f971622SJuan Castillo 
548a8eb286aSSoby Mathew 		/* Create certificate. Signed with corresponding key */
549294e2656SManish V Badarkhe 		if (!cert_new(hash_alg, cert, VAL_DAYS, 0, sk)) {
55055e291a4SJuan Castillo 			ERROR("Cannot create %s\n", cert->cn);
5516f971622SJuan Castillo 			exit(1);
5526f971622SJuan Castillo 		}
5536f971622SJuan Castillo 
554bea80198SJimmy Brisson 		for (cert_ext = sk_X509_EXTENSION_pop(sk); cert_ext != NULL;
555bea80198SJimmy Brisson 				cert_ext = sk_X509_EXTENSION_pop(sk)) {
556bea80198SJimmy Brisson 			X509_EXTENSION_free(cert_ext);
557bea80198SJimmy Brisson 		}
558bea80198SJimmy Brisson 
5596f971622SJuan Castillo 		sk_X509_EXTENSION_free(sk);
5606f971622SJuan Castillo 	}
5616f971622SJuan Castillo 
5626f971622SJuan Castillo 
5636f971622SJuan Castillo 	/* Print the certificates */
5646f971622SJuan Castillo 	if (print_cert) {
56555e291a4SJuan Castillo 		for (i = 0 ; i < num_certs ; i++) {
5666f971622SJuan Castillo 			if (!certs[i].x) {
5676f971622SJuan Castillo 				continue;
5686f971622SJuan Castillo 			}
5696f971622SJuan Castillo 			printf("\n\n=====================================\n\n");
5706f971622SJuan Castillo 			X509_print_fp(stdout, certs[i].x);
5716f971622SJuan Castillo 		}
5726f971622SJuan Castillo 	}
5736f971622SJuan Castillo 
5746f971622SJuan Castillo 	/* Save created certificates to files */
57555e291a4SJuan Castillo 	for (i = 0 ; i < num_certs ; i++) {
5766f971622SJuan Castillo 		if (certs[i].x && certs[i].fn) {
5776f971622SJuan Castillo 			file = fopen(certs[i].fn, "w");
5786f971622SJuan Castillo 			if (file != NULL) {
5796f971622SJuan Castillo 				i2d_X509_fp(file, certs[i].x);
5806f971622SJuan Castillo 				fclose(file);
5816f971622SJuan Castillo 			} else {
5826f971622SJuan Castillo 				ERROR("Cannot create file %s\n", certs[i].fn);
5836f971622SJuan Castillo 			}
5846f971622SJuan Castillo 		}
5856f971622SJuan Castillo 	}
5866f971622SJuan Castillo 
5876f971622SJuan Castillo 	/* Save keys */
5886f971622SJuan Castillo 	if (save_keys) {
58955e291a4SJuan Castillo 		for (i = 0 ; i < num_keys ; i++) {
5906f971622SJuan Castillo 			if (!key_store(&keys[i])) {
5916f971622SJuan Castillo 				ERROR("Cannot save %s\n", keys[i].desc);
5926f971622SJuan Castillo 			}
5936f971622SJuan Castillo 		}
5946f971622SJuan Castillo 	}
5956f971622SJuan Castillo 
5961f111f12SJimmy Brisson 	/* If we got here, then we must have filled the key array completely.
5971f111f12SJimmy Brisson 	 * We can then safely call free on all of the keys in the array
5981f111f12SJimmy Brisson 	 */
599cf2dd17dSJuan Pablo Conde 	key_cleanup();
6001f111f12SJimmy Brisson 
6016f971622SJuan Castillo #ifndef OPENSSL_NO_ENGINE
6026f971622SJuan Castillo 	ENGINE_cleanup();
6036f971622SJuan Castillo #endif
6046f971622SJuan Castillo 	CRYPTO_cleanup_all_ex_data();
6056f971622SJuan Castillo 
6064a34d18fSJimmy Brisson 
6074a34d18fSJimmy Brisson 	/* We allocated strings through strdup, so now we have to free them */
6084a34d18fSJimmy Brisson 
609cf2dd17dSJuan Pablo Conde 	ext_cleanup();
6104a34d18fSJimmy Brisson 
611cf2dd17dSJuan Pablo Conde 	cert_cleanup();
6124a34d18fSJimmy Brisson 
6136f971622SJuan Castillo 	return 0;
6146f971622SJuan Castillo }
615