blob: fe386b7c5b3e25600ed70b33decc26e4fba623df [file] [log] [blame]
Juan Castillo11abdcd2014-10-21 11:30:42 +01001/*
Juan Pablo Conde3539c742022-10-25 19:41:02 -04002 * Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved.
Juan Castillo11abdcd2014-10-21 11:30:42 +01003 *
dp-armfa3cf0b2017-05-03 09:38:09 +01004 * SPDX-License-Identifier: BSD-3-Clause
Juan Castillo11abdcd2014-10-21 11:30:42 +01005 */
6
Juan Castillo212f7382015-12-15 16:37:57 +00007#include <assert.h>
8#include <ctype.h>
Juan Castillo11abdcd2014-10-21 11:30:42 +01009#include <getopt.h>
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
Justin Chadwellfebe86c2019-07-29 17:13:45 +010013#include <stdbool.h>
Juan Castillo11abdcd2014-10-21 11:30:42 +010014
15#include <openssl/conf.h>
16#include <openssl/engine.h>
17#include <openssl/err.h>
18#include <openssl/pem.h>
19#include <openssl/sha.h>
20#include <openssl/x509v3.h>
21
22#include "cert.h"
Juan Castillo1218dd52015-07-03 16:23:16 +010023#include "cmd_opt.h"
Juan Castillo11abdcd2014-10-21 11:30:42 +010024#include "debug.h"
25#include "ext.h"
26#include "key.h"
Juan Castillo11abdcd2014-10-21 11:30:42 +010027#include "sha.h"
Juan Castillo11abdcd2014-10-21 11:30:42 +010028
29/*
30 * Helper macros to simplify the code. This macro assigns the return value of
31 * the 'fn' function to 'v' and exits if the value is NULL.
32 */
33#define CHECK_NULL(v, fn) \
34 do { \
35 v = fn; \
36 if (v == NULL) { \
37 ERROR("NULL object at %s:%d\n", __FILE__, __LINE__); \
38 exit(1); \
39 } \
40 } while (0)
41
42/*
43 * This macro assigns the NID corresponding to 'oid' to 'v' and exits if the
44 * NID is undefined.
45 */
46#define CHECK_OID(v, oid) \
47 do { \
48 v = OBJ_txt2nid(oid); \
49 if (v == NID_undef) { \
Sandrine Bailleux0d11b482020-01-15 11:01:25 +010050 ERROR("Cannot find extension %s\n", oid); \
Juan Castillo11abdcd2014-10-21 11:30:42 +010051 exit(1); \
52 } \
53 } while (0)
54
55#define MAX_FILENAME_LEN 1024
56#define VAL_DAYS 7300
57#define ID_TO_BIT_MASK(id) (1 << id)
Juan Castillof9f39c32015-06-01 16:34:23 +010058#define NUM_ELEM(x) ((sizeof(x)) / (sizeof(x[0])))
Juan Castillo212f7382015-12-15 16:37:57 +000059#define HELP_OPT_MAX_LEN 128
Juan Castillo11abdcd2014-10-21 11:30:42 +010060
61/* Global options */
Juan Castillof9f39c32015-06-01 16:34:23 +010062static int key_alg;
Qixiang Xu76a5a9b2017-11-09 13:51:58 +080063static int hash_alg;
Justin Chadwellfebe86c2019-07-29 17:13:45 +010064static int key_size;
Juan Castillo11abdcd2014-10-21 11:30:42 +010065static int new_keys;
66static int save_keys;
67static int print_cert;
Juan Castillo11abdcd2014-10-21 11:30:42 +010068
Juan Castillo11abdcd2014-10-21 11:30:42 +010069/* Info messages created in the Makefile */
70extern const char build_msg[];
71extern const char platform_msg[];
72
73
74static char *strdup(const char *str)
75{
76 int n = strlen(str) + 1;
77 char *dup = malloc(n);
78 if (dup) {
79 strcpy(dup, str);
80 }
81 return dup;
82}
83
Juan Castillof9f39c32015-06-01 16:34:23 +010084static const char *key_algs_str[] = {
85 [KEY_ALG_RSA] = "rsa",
Juan Castilloa2224ab2015-06-30 13:36:57 +010086#ifndef OPENSSL_NO_EC
Juan Castillof9f39c32015-06-01 16:34:23 +010087 [KEY_ALG_ECDSA] = "ecdsa"
Juan Castilloa2224ab2015-06-30 13:36:57 +010088#endif /* OPENSSL_NO_EC */
Juan Castillof9f39c32015-06-01 16:34:23 +010089};
90
Qixiang Xu76a5a9b2017-11-09 13:51:58 +080091static const char *hash_algs_str[] = {
92 [HASH_ALG_SHA256] = "sha256",
93 [HASH_ALG_SHA384] = "sha384",
94 [HASH_ALG_SHA512] = "sha512",
95};
96
Juan Castillo1218dd52015-07-03 16:23:16 +010097static void print_help(const char *cmd, const struct option *long_opt)
Juan Castillo11abdcd2014-10-21 11:30:42 +010098{
Juan Castillo212f7382015-12-15 16:37:57 +000099 int rem, i = 0;
100 const struct option *opt;
101 char line[HELP_OPT_MAX_LEN];
102 char *p;
103
104 assert(cmd != NULL);
105 assert(long_opt != NULL);
106
Juan Castillo11abdcd2014-10-21 11:30:42 +0100107 printf("\n\n");
108 printf("The certificate generation tool loads the binary images and\n"
109 "optionally the RSA keys, and outputs the key and content\n"
110 "certificates properly signed to implement the chain of trust.\n"
111 "If keys are provided, they must be in PEM format.\n"
112 "Certificates are generated in DER format.\n");
113 printf("\n");
Juan Castillo212f7382015-12-15 16:37:57 +0000114 printf("Usage:\n");
115 printf("\t%s [OPTIONS]\n\n", cmd);
116
117 printf("Available options:\n");
Juan Castillo212f7382015-12-15 16:37:57 +0000118 opt = long_opt;
119 while (opt->name) {
120 p = line;
121 rem = HELP_OPT_MAX_LEN;
122 if (isalpha(opt->val)) {
123 /* Short format */
124 sprintf(p, "-%c,", (char)opt->val);
125 p += 3;
126 rem -= 3;
127 }
128 snprintf(p, rem, "--%s %s", opt->name,
129 (opt->has_arg == required_argument) ? "<arg>" : "");
130 printf("\t%-32s %s\n", line, cmd_opt_get_help_msg(i));
131 opt++;
132 i++;
Juan Castillo11abdcd2014-10-21 11:30:42 +0100133 }
134 printf("\n");
Juan Castillo11abdcd2014-10-21 11:30:42 +0100135}
136
Juan Castillof9f39c32015-06-01 16:34:23 +0100137static int get_key_alg(const char *key_alg_str)
138{
139 int i;
140
141 for (i = 0 ; i < NUM_ELEM(key_algs_str) ; i++) {
142 if (0 == strcmp(key_alg_str, key_algs_str[i])) {
143 return i;
144 }
145 }
146
147 return -1;
148}
149
Justin Chadwellfebe86c2019-07-29 17:13:45 +0100150static int get_key_size(const char *key_size_str)
151{
152 char *end;
153 long key_size;
154
155 key_size = strtol(key_size_str, &end, 10);
156 if (*end != '\0')
157 return -1;
158
159 return key_size;
160}
161
Qixiang Xu76a5a9b2017-11-09 13:51:58 +0800162static int get_hash_alg(const char *hash_alg_str)
163{
164 int i;
165
166 for (i = 0 ; i < NUM_ELEM(hash_algs_str) ; i++) {
167 if (0 == strcmp(hash_alg_str, hash_algs_str[i])) {
168 return i;
169 }
170 }
171
172 return -1;
173}
174
Juan Castillo11abdcd2014-10-21 11:30:42 +0100175static void check_cmd_params(void)
176{
Juan Castillo86958fd2015-07-08 12:11:38 +0100177 cert_t *cert;
178 ext_t *ext;
179 key_t *key;
180 int i, j;
Justin Chadwellfebe86c2019-07-29 17:13:45 +0100181 bool valid_size;
Juan Castillo86958fd2015-07-08 12:11:38 +0100182
Juan Castillof9f39c32015-06-01 16:34:23 +0100183 /* Only save new keys */
184 if (save_keys && !new_keys) {
185 ERROR("Only new keys can be saved to disk\n");
186 exit(1);
187 }
188
Justin Chadwellfebe86c2019-07-29 17:13:45 +0100189 /* Validate key-size */
190 valid_size = false;
191 for (i = 0; i < KEY_SIZE_MAX_NUM; i++) {
192 if (key_size == KEY_SIZES[key_alg][i]) {
193 valid_size = true;
194 break;
195 }
196 }
197 if (!valid_size) {
198 ERROR("'%d' is not a valid key size for '%s'\n",
199 key_size, key_algs_str[key_alg]);
200 NOTICE("Valid sizes are: ");
201 for (i = 0; i < KEY_SIZE_MAX_NUM &&
202 KEY_SIZES[key_alg][i] != 0; i++) {
203 printf("%d ", KEY_SIZES[key_alg][i]);
204 }
205 printf("\n");
206 exit(1);
207 }
208
Juan Castillo86958fd2015-07-08 12:11:38 +0100209 /* Check that all required options have been specified in the
210 * command line */
211 for (i = 0; i < num_certs; i++) {
212 cert = &certs[i];
213 if (cert->fn == NULL) {
214 /* Certificate not requested. Skip to the next one */
215 continue;
Juan Castillo11abdcd2014-10-21 11:30:42 +0100216 }
217
Juan Castillo86958fd2015-07-08 12:11:38 +0100218 /* Check that all parameters required to create this certificate
219 * have been specified in the command line */
220 for (j = 0; j < cert->num_ext; j++) {
221 ext = &extensions[cert->ext[j]];
222 switch (ext->type) {
Juan Castillo43529982016-01-22 11:05:24 +0000223 case EXT_TYPE_NVCOUNTER:
224 /* Counter value must be specified */
225 if ((!ext->optional) && (ext->arg == NULL)) {
226 ERROR("Value for '%s' not specified\n",
227 ext->ln);
228 exit(1);
229 }
230 break;
Juan Castillo86958fd2015-07-08 12:11:38 +0100231 case EXT_TYPE_PKEY:
232 /* Key filename must be specified */
Juan Castillo43529982016-01-22 11:05:24 +0000233 key = &keys[ext->attr.key];
Juan Castillo86958fd2015-07-08 12:11:38 +0100234 if (!new_keys && key->fn == NULL) {
235 ERROR("Key '%s' required by '%s' not "
236 "specified\n", key->desc,
237 cert->cn);
238 exit(1);
239 }
240 break;
241 case EXT_TYPE_HASH:
Yatharth Kochar5752b592015-08-21 15:30:55 +0100242 /*
243 * Binary image must be specified
244 * unless it is explicitly made optional.
245 */
Juan Castillo43529982016-01-22 11:05:24 +0000246 if ((!ext->optional) && (ext->arg == NULL)) {
Juan Castillo86958fd2015-07-08 12:11:38 +0100247 ERROR("Image for '%s' not specified\n",
248 ext->ln);
249 exit(1);
250 }
251 break;
252 default:
Juan Castillo43529982016-01-22 11:05:24 +0000253 ERROR("Unknown extension type '%d' in '%s'\n",
254 ext->type, ext->ln);
Juan Castillo86958fd2015-07-08 12:11:38 +0100255 exit(1);
256 break;
257 }
Juan Castillo11abdcd2014-10-21 11:30:42 +0100258 }
259 }
260}
261
Juan Castillo212f7382015-12-15 16:37:57 +0000262/* Common command line options */
263static const cmd_opt_t common_cmd_opt[] = {
264 {
265 { "help", no_argument, NULL, 'h' },
266 "Print this message and exit"
267 },
268 {
269 { "key-alg", required_argument, NULL, 'a' },
Justin Chadwell3168a202019-09-09 15:24:31 +0100270 "Key algorithm: 'rsa' (default)- RSAPSS scheme as per PKCS#1 v2.1, 'ecdsa'"
Juan Castillo212f7382015-12-15 16:37:57 +0000271 },
272 {
Justin Chadwellfebe86c2019-07-29 17:13:45 +0100273 { "key-size", required_argument, NULL, 'b' },
274 "Key size (for supported algorithms)."
275 },
276 {
Qixiang Xu76a5a9b2017-11-09 13:51:58 +0800277 { "hash-alg", required_argument, NULL, 's' },
278 "Hash algorithm : 'sha256' (default), 'sha384', 'sha512'"
279 },
280 {
Juan Castillo212f7382015-12-15 16:37:57 +0000281 { "save-keys", no_argument, NULL, 'k' },
282 "Save key pairs into files. Filenames must be provided"
283 },
284 {
285 { "new-keys", no_argument, NULL, 'n' },
286 "Generate new key pairs if no key files are provided"
287 },
288 {
289 { "print-cert", no_argument, NULL, 'p' },
290 "Print the certificates in the standard output"
291 }
292};
293
Juan Castillo11abdcd2014-10-21 11:30:42 +0100294int main(int argc, char *argv[])
295{
Masahiro Yamada48cb5e52017-02-06 19:47:44 +0900296 STACK_OF(X509_EXTENSION) * sk;
Michalis Pappas38628942017-10-06 16:11:44 +0800297 X509_EXTENSION *cert_ext = NULL;
Masahiro Yamada48cb5e52017-02-06 19:47:44 +0900298 ext_t *ext;
299 key_t *key;
300 cert_t *cert;
301 FILE *file;
Juan Castillo43529982016-01-22 11:05:24 +0000302 int i, j, ext_nid, nvctr;
Juan Castillo11abdcd2014-10-21 11:30:42 +0100303 int c, opt_idx = 0;
Juan Castillo1218dd52015-07-03 16:23:16 +0100304 const struct option *cmd_opt;
305 const char *cur_opt;
Juan Castillof9f39c32015-06-01 16:34:23 +0100306 unsigned int err_code;
Qixiang Xu76a5a9b2017-11-09 13:51:58 +0800307 unsigned char md[SHA512_DIGEST_LENGTH];
308 unsigned int md_len;
Juan Castilloac402932015-03-05 14:30:00 +0000309 const EVP_MD *md_info;
Juan Castillo11abdcd2014-10-21 11:30:42 +0100310
311 NOTICE("CoT Generation Tool: %s\n", build_msg);
312 NOTICE("Target platform: %s\n", platform_msg);
313
Juan Castillof9f39c32015-06-01 16:34:23 +0100314 /* Set default options */
315 key_alg = KEY_ALG_RSA;
Qixiang Xu76a5a9b2017-11-09 13:51:58 +0800316 hash_alg = HASH_ALG_SHA256;
Justin Chadwellfebe86c2019-07-29 17:13:45 +0100317 key_size = -1;
Juan Castillof9f39c32015-06-01 16:34:23 +0100318
Juan Castillo1218dd52015-07-03 16:23:16 +0100319 /* Add common command line options */
Juan Castillo212f7382015-12-15 16:37:57 +0000320 for (i = 0; i < NUM_ELEM(common_cmd_opt); i++) {
321 cmd_opt_add(&common_cmd_opt[i]);
322 }
Juan Castillo1218dd52015-07-03 16:23:16 +0100323
324 /* Initialize the certificates */
325 if (cert_init() != 0) {
326 ERROR("Cannot initialize certificates\n");
327 exit(1);
328 }
329
330 /* Initialize the keys */
331 if (key_init() != 0) {
332 ERROR("Cannot initialize keys\n");
333 exit(1);
334 }
335
336 /* Initialize the new types and register OIDs for the extensions */
337 if (ext_init() != 0) {
Sandrine Bailleux0d11b482020-01-15 11:01:25 +0100338 ERROR("Cannot initialize extensions\n");
Juan Castillo1218dd52015-07-03 16:23:16 +0100339 exit(1);
340 }
341
342 /* Get the command line options populated during the initialization */
343 cmd_opt = cmd_opt_get_array();
344
Juan Castillo11abdcd2014-10-21 11:30:42 +0100345 while (1) {
346 /* getopt_long stores the option index here. */
Justin Chadwellfebe86c2019-07-29 17:13:45 +0100347 c = getopt_long(argc, argv, "a:b:hknps:", cmd_opt, &opt_idx);
Juan Castillo11abdcd2014-10-21 11:30:42 +0100348
349 /* Detect the end of the options. */
350 if (c == -1) {
351 break;
352 }
353
354 switch (c) {
Juan Castillof9f39c32015-06-01 16:34:23 +0100355 case 'a':
356 key_alg = get_key_alg(optarg);
357 if (key_alg < 0) {
358 ERROR("Invalid key algorithm '%s'\n", optarg);
359 exit(1);
360 }
361 break;
Justin Chadwellfebe86c2019-07-29 17:13:45 +0100362 case 'b':
363 key_size = get_key_size(optarg);
364 if (key_size <= 0) {
365 ERROR("Invalid key size '%s'\n", optarg);
366 exit(1);
367 }
368 break;
Juan Castillo11abdcd2014-10-21 11:30:42 +0100369 case 'h':
Juan Castillo1218dd52015-07-03 16:23:16 +0100370 print_help(argv[0], cmd_opt);
Roberto Vargas58a5b2b2018-06-27 08:23:22 +0100371 exit(0);
Juan Castillo11abdcd2014-10-21 11:30:42 +0100372 case 'k':
373 save_keys = 1;
374 break;
375 case 'n':
376 new_keys = 1;
377 break;
378 case 'p':
379 print_cert = 1;
380 break;
Qixiang Xu76a5a9b2017-11-09 13:51:58 +0800381 case 's':
382 hash_alg = get_hash_alg(optarg);
383 if (hash_alg < 0) {
384 ERROR("Invalid hash algorithm '%s'\n", optarg);
385 exit(1);
386 }
387 break;
Juan Castillo1218dd52015-07-03 16:23:16 +0100388 case CMD_OPT_EXT:
389 cur_opt = cmd_opt_get_name(opt_idx);
390 ext = ext_get_by_opt(cur_opt);
Juan Castillo43529982016-01-22 11:05:24 +0000391 ext->arg = strdup(optarg);
Juan Castillo11abdcd2014-10-21 11:30:42 +0100392 break;
Juan Castillo1218dd52015-07-03 16:23:16 +0100393 case CMD_OPT_KEY:
394 cur_opt = cmd_opt_get_name(opt_idx);
395 key = key_get_by_opt(cur_opt);
396 key->fn = strdup(optarg);
Juan Castillo11abdcd2014-10-21 11:30:42 +0100397 break;
Juan Castillo1218dd52015-07-03 16:23:16 +0100398 case CMD_OPT_CERT:
399 cur_opt = cmd_opt_get_name(opt_idx);
400 cert = cert_get_by_opt(cur_opt);
401 cert->fn = strdup(optarg);
Juan Castillo11abdcd2014-10-21 11:30:42 +0100402 break;
403 case '?':
404 default:
Juan Castillo212f7382015-12-15 16:37:57 +0000405 print_help(argv[0], cmd_opt);
Juan Castillo11abdcd2014-10-21 11:30:42 +0100406 exit(1);
407 }
408 }
409
Justin Chadwellfebe86c2019-07-29 17:13:45 +0100410 /* Select a reasonable default key-size */
411 if (key_size == -1) {
412 key_size = KEY_SIZES[key_alg][0];
413 }
414
Juan Castillo11abdcd2014-10-21 11:30:42 +0100415 /* Check command line arguments */
416 check_cmd_params();
417
Qixiang Xu76a5a9b2017-11-09 13:51:58 +0800418 /* Indicate SHA as image hash algorithm in the certificate
Juan Castilloac402932015-03-05 14:30:00 +0000419 * extension */
Qixiang Xu76a5a9b2017-11-09 13:51:58 +0800420 if (hash_alg == HASH_ALG_SHA384) {
421 md_info = EVP_sha384();
422 md_len = SHA384_DIGEST_LENGTH;
423 } else if (hash_alg == HASH_ALG_SHA512) {
424 md_info = EVP_sha512();
425 md_len = SHA512_DIGEST_LENGTH;
426 } else {
427 md_info = EVP_sha256();
428 md_len = SHA256_DIGEST_LENGTH;
429 }
Juan Castilloac402932015-03-05 14:30:00 +0000430
Juan Castillo11abdcd2014-10-21 11:30:42 +0100431 /* Load private keys from files (or generate new ones) */
Juan Castilloe6d30e92015-06-12 11:27:59 +0100432 for (i = 0 ; i < num_keys ; i++) {
Juan Pablo Conde3539c742022-10-25 19:41:02 -0400433#if !USING_OPENSSL3
Masahiro Yamadabccb1092017-02-06 21:15:01 +0900434 if (!key_new(&keys[i])) {
435 ERROR("Failed to allocate key container\n");
436 exit(1);
437 }
Juan Pablo Conde3539c742022-10-25 19:41:02 -0400438#endif
Masahiro Yamadabccb1092017-02-06 21:15:01 +0900439
Juan Castillof9f39c32015-06-01 16:34:23 +0100440 /* First try to load the key from disk */
441 if (key_load(&keys[i], &err_code)) {
442 /* Key loaded successfully */
443 continue;
444 }
445
446 /* Key not loaded. Check the error code */
Masahiro Yamadabccb1092017-02-06 21:15:01 +0900447 if (err_code == KEY_ERR_LOAD) {
Juan Castillof9f39c32015-06-01 16:34:23 +0100448 /* File exists, but it does not contain a valid private
449 * key. Abort. */
450 ERROR("Error loading '%s'\n", keys[i].fn);
451 exit(1);
Juan Castillo11abdcd2014-10-21 11:30:42 +0100452 }
Juan Castillof9f39c32015-06-01 16:34:23 +0100453
454 /* File does not exist, could not be opened or no filename was
455 * given */
456 if (new_keys) {
457 /* Try to create a new key */
458 NOTICE("Creating new key for '%s'\n", keys[i].desc);
Justin Chadwellfebe86c2019-07-29 17:13:45 +0100459 if (!key_create(&keys[i], key_alg, key_size)) {
Juan Castillof9f39c32015-06-01 16:34:23 +0100460 ERROR("Error creating key '%s'\n", keys[i].desc);
Juan Castillo11abdcd2014-10-21 11:30:42 +0100461 exit(1);
462 }
Juan Castillof9f39c32015-06-01 16:34:23 +0100463 } else {
464 if (err_code == KEY_ERR_OPEN) {
465 ERROR("Error opening '%s'\n", keys[i].fn);
466 } else {
467 ERROR("Key '%s' not specified\n", keys[i].desc);
468 }
469 exit(1);
Juan Castillo11abdcd2014-10-21 11:30:42 +0100470 }
471 }
Juan Castillo11abdcd2014-10-21 11:30:42 +0100472
Juan Castilloe6d30e92015-06-12 11:27:59 +0100473 /* Create the certificates */
474 for (i = 0 ; i < num_certs ; i++) {
Juan Castillo11abdcd2014-10-21 11:30:42 +0100475
Juan Castilloe6d30e92015-06-12 11:27:59 +0100476 cert = &certs[i];
Juan Castillo11abdcd2014-10-21 11:30:42 +0100477
Manish V Badarkhe2b7e70e2021-01-26 10:55:49 +0000478 if (cert->fn == NULL) {
479 /* Certificate not requested. Skip to the next one */
480 continue;
481 }
482
Juan Castilloe6d30e92015-06-12 11:27:59 +0100483 /* Create a new stack of extensions. This stack will be used
484 * to create the certificate */
Juan Castillo11abdcd2014-10-21 11:30:42 +0100485 CHECK_NULL(sk, sk_X509_EXTENSION_new_null());
Juan Castillo11abdcd2014-10-21 11:30:42 +0100486
Juan Castilloe6d30e92015-06-12 11:27:59 +0100487 for (j = 0 ; j < cert->num_ext ; j++) {
Juan Castillo11abdcd2014-10-21 11:30:42 +0100488
Juan Castilloe6d30e92015-06-12 11:27:59 +0100489 ext = &extensions[cert->ext[j]];
Juan Castillo11abdcd2014-10-21 11:30:42 +0100490
Juan Castilloe6d30e92015-06-12 11:27:59 +0100491 /* Get OpenSSL internal ID for this extension */
492 CHECK_OID(ext_nid, ext->oid);
Juan Castillo11abdcd2014-10-21 11:30:42 +0100493
Juan Castilloe6d30e92015-06-12 11:27:59 +0100494 /*
495 * Three types of extensions are currently supported:
496 * - EXT_TYPE_NVCOUNTER
497 * - EXT_TYPE_HASH
498 * - EXT_TYPE_PKEY
499 */
500 switch (ext->type) {
501 case EXT_TYPE_NVCOUNTER:
Jimmy Brissonc913fa62021-01-20 15:34:51 -0600502 if (ext->optional && ext->arg == NULL) {
503 /* Skip this NVCounter */
504 continue;
505 } else {
506 /* Checked by `check_cmd_params` */
507 assert(ext->arg != NULL);
Yatharth Kochar79f86402016-06-22 14:49:27 +0100508 nvctr = atoi(ext->arg);
509 CHECK_NULL(cert_ext, ext_new_nvcounter(ext_nid,
Juan Castillo43529982016-01-22 11:05:24 +0000510 EXT_CRIT, nvctr));
Yatharth Kochar79f86402016-06-22 14:49:27 +0100511 }
Juan Castilloe6d30e92015-06-12 11:27:59 +0100512 break;
513 case EXT_TYPE_HASH:
Juan Castillo43529982016-01-22 11:05:24 +0000514 if (ext->arg == NULL) {
Yatharth Kochar5752b592015-08-21 15:30:55 +0100515 if (ext->optional) {
516 /* Include a hash filled with zeros */
Qixiang Xu76a5a9b2017-11-09 13:51:58 +0800517 memset(md, 0x0, SHA512_DIGEST_LENGTH);
Yatharth Kochar5752b592015-08-21 15:30:55 +0100518 } else {
519 /* Do not include this hash in the certificate */
Jimmy Brissonc913fa62021-01-20 15:34:51 -0600520 continue;
Yatharth Kochar5752b592015-08-21 15:30:55 +0100521 }
522 } else {
523 /* Calculate the hash of the file */
Qixiang Xu76a5a9b2017-11-09 13:51:58 +0800524 if (!sha_file(hash_alg, ext->arg, md)) {
Yatharth Kochar5752b592015-08-21 15:30:55 +0100525 ERROR("Cannot calculate hash of %s\n",
Juan Castillo43529982016-01-22 11:05:24 +0000526 ext->arg);
Yatharth Kochar5752b592015-08-21 15:30:55 +0100527 exit(1);
528 }
Juan Castilloe6d30e92015-06-12 11:27:59 +0100529 }
530 CHECK_NULL(cert_ext, ext_new_hash(ext_nid,
531 EXT_CRIT, md_info, md,
Qixiang Xu76a5a9b2017-11-09 13:51:58 +0800532 md_len));
Juan Castilloe6d30e92015-06-12 11:27:59 +0100533 break;
534 case EXT_TYPE_PKEY:
535 CHECK_NULL(cert_ext, ext_new_key(ext_nid,
Juan Castillo43529982016-01-22 11:05:24 +0000536 EXT_CRIT, keys[ext->attr.key].key));
Juan Castilloe6d30e92015-06-12 11:27:59 +0100537 break;
538 default:
Juan Castillo43529982016-01-22 11:05:24 +0000539 ERROR("Unknown extension type '%d' in %s\n",
540 ext->type, cert->cn);
Juan Castilloe6d30e92015-06-12 11:27:59 +0100541 exit(1);
542 }
Juan Castillo11abdcd2014-10-21 11:30:42 +0100543
Juan Castilloe6d30e92015-06-12 11:27:59 +0100544 /* Push the extension into the stack */
545 sk_X509_EXTENSION_push(sk, cert_ext);
Juan Castillo11abdcd2014-10-21 11:30:42 +0100546 }
Juan Castillo11abdcd2014-10-21 11:30:42 +0100547
Soby Mathew2fd70f62017-08-31 11:50:29 +0100548 /* Create certificate. Signed with corresponding key */
Manish V Badarkhe2b7e70e2021-01-26 10:55:49 +0000549 if (!cert_new(hash_alg, cert, VAL_DAYS, 0, sk)) {
Juan Castilloe6d30e92015-06-12 11:27:59 +0100550 ERROR("Cannot create %s\n", cert->cn);
Juan Castillo11abdcd2014-10-21 11:30:42 +0100551 exit(1);
552 }
553
Jimmy Brisson63d06932020-07-24 14:31:48 -0500554 for (cert_ext = sk_X509_EXTENSION_pop(sk); cert_ext != NULL;
555 cert_ext = sk_X509_EXTENSION_pop(sk)) {
556 X509_EXTENSION_free(cert_ext);
557 }
558
Juan Castillo11abdcd2014-10-21 11:30:42 +0100559 sk_X509_EXTENSION_free(sk);
560 }
561
Juan Castillo11abdcd2014-10-21 11:30:42 +0100562
563 /* Print the certificates */
564 if (print_cert) {
Juan Castilloe6d30e92015-06-12 11:27:59 +0100565 for (i = 0 ; i < num_certs ; i++) {
Juan Castillo11abdcd2014-10-21 11:30:42 +0100566 if (!certs[i].x) {
567 continue;
568 }
569 printf("\n\n=====================================\n\n");
570 X509_print_fp(stdout, certs[i].x);
571 }
572 }
573
574 /* Save created certificates to files */
Juan Castilloe6d30e92015-06-12 11:27:59 +0100575 for (i = 0 ; i < num_certs ; i++) {
Juan Castillo11abdcd2014-10-21 11:30:42 +0100576 if (certs[i].x && certs[i].fn) {
577 file = fopen(certs[i].fn, "w");
578 if (file != NULL) {
579 i2d_X509_fp(file, certs[i].x);
580 fclose(file);
581 } else {
582 ERROR("Cannot create file %s\n", certs[i].fn);
583 }
584 }
585 }
586
587 /* Save keys */
588 if (save_keys) {
Juan Castilloe6d30e92015-06-12 11:27:59 +0100589 for (i = 0 ; i < num_keys ; i++) {
Juan Castillo11abdcd2014-10-21 11:30:42 +0100590 if (!key_store(&keys[i])) {
591 ERROR("Cannot save %s\n", keys[i].desc);
592 }
593 }
594 }
595
Jimmy Brisson53287962020-07-27 10:43:40 -0500596 /* If we got here, then we must have filled the key array completely.
597 * We can then safely call free on all of the keys in the array
598 */
Juan Pablo Conde3539c742022-10-25 19:41:02 -0400599 key_cleanup();
Jimmy Brisson53287962020-07-27 10:43:40 -0500600
Juan Castillo11abdcd2014-10-21 11:30:42 +0100601#ifndef OPENSSL_NO_ENGINE
602 ENGINE_cleanup();
603#endif
604 CRYPTO_cleanup_all_ex_data();
605
Jimmy Brisson54db69e2020-07-27 11:23:20 -0500606
607 /* We allocated strings through strdup, so now we have to free them */
Jimmy Brisson54db69e2020-07-27 11:23:20 -0500608
Juan Pablo Conde3539c742022-10-25 19:41:02 -0400609 ext_cleanup();
Jimmy Brisson54db69e2020-07-27 11:23:20 -0500610
Juan Pablo Conde3539c742022-10-25 19:41:02 -0400611 cert_cleanup();
Jimmy Brisson54db69e2020-07-27 11:23:20 -0500612
Juan Castillo11abdcd2014-10-21 11:30:42 +0100613 return 0;
614}