blob: b39378ca964c00e959ae3378e43a5c87965c88c9 [file] [log] [blame]
Juan Castillo11abdcd2014-10-21 11:30:42 +01001/*
Jimmy Brissonc913fa62021-01-20 15:34:51 -06002 * Copyright (c) 2015-2021, 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++) {
Masahiro Yamadabccb1092017-02-06 21:15:01 +0900433 if (!key_new(&keys[i])) {
434 ERROR("Failed to allocate key container\n");
435 exit(1);
436 }
437
Juan Castillof9f39c32015-06-01 16:34:23 +0100438 /* First try to load the key from disk */
439 if (key_load(&keys[i], &err_code)) {
440 /* Key loaded successfully */
441 continue;
442 }
443
444 /* Key not loaded. Check the error code */
Masahiro Yamadabccb1092017-02-06 21:15:01 +0900445 if (err_code == KEY_ERR_LOAD) {
Juan Castillof9f39c32015-06-01 16:34:23 +0100446 /* File exists, but it does not contain a valid private
447 * key. Abort. */
448 ERROR("Error loading '%s'\n", keys[i].fn);
449 exit(1);
Juan Castillo11abdcd2014-10-21 11:30:42 +0100450 }
Juan Castillof9f39c32015-06-01 16:34:23 +0100451
452 /* File does not exist, could not be opened or no filename was
453 * given */
454 if (new_keys) {
455 /* Try to create a new key */
456 NOTICE("Creating new key for '%s'\n", keys[i].desc);
Justin Chadwellfebe86c2019-07-29 17:13:45 +0100457 if (!key_create(&keys[i], key_alg, key_size)) {
Juan Castillof9f39c32015-06-01 16:34:23 +0100458 ERROR("Error creating key '%s'\n", keys[i].desc);
Juan Castillo11abdcd2014-10-21 11:30:42 +0100459 exit(1);
460 }
Juan Castillof9f39c32015-06-01 16:34:23 +0100461 } else {
462 if (err_code == KEY_ERR_OPEN) {
463 ERROR("Error opening '%s'\n", keys[i].fn);
464 } else {
465 ERROR("Key '%s' not specified\n", keys[i].desc);
466 }
467 exit(1);
Juan Castillo11abdcd2014-10-21 11:30:42 +0100468 }
469 }
Juan Castillo11abdcd2014-10-21 11:30:42 +0100470
Juan Castilloe6d30e92015-06-12 11:27:59 +0100471 /* Create the certificates */
472 for (i = 0 ; i < num_certs ; i++) {
Juan Castillo11abdcd2014-10-21 11:30:42 +0100473
Juan Castilloe6d30e92015-06-12 11:27:59 +0100474 cert = &certs[i];
Juan Castillo11abdcd2014-10-21 11:30:42 +0100475
Manish V Badarkhe2b7e70e2021-01-26 10:55:49 +0000476 if (cert->fn == NULL) {
477 /* Certificate not requested. Skip to the next one */
478 continue;
479 }
480
Juan Castilloe6d30e92015-06-12 11:27:59 +0100481 /* Create a new stack of extensions. This stack will be used
482 * to create the certificate */
Juan Castillo11abdcd2014-10-21 11:30:42 +0100483 CHECK_NULL(sk, sk_X509_EXTENSION_new_null());
Juan Castillo11abdcd2014-10-21 11:30:42 +0100484
Juan Castilloe6d30e92015-06-12 11:27:59 +0100485 for (j = 0 ; j < cert->num_ext ; j++) {
Juan Castillo11abdcd2014-10-21 11:30:42 +0100486
Juan Castilloe6d30e92015-06-12 11:27:59 +0100487 ext = &extensions[cert->ext[j]];
Juan Castillo11abdcd2014-10-21 11:30:42 +0100488
Juan Castilloe6d30e92015-06-12 11:27:59 +0100489 /* Get OpenSSL internal ID for this extension */
490 CHECK_OID(ext_nid, ext->oid);
Juan Castillo11abdcd2014-10-21 11:30:42 +0100491
Juan Castilloe6d30e92015-06-12 11:27:59 +0100492 /*
493 * Three types of extensions are currently supported:
494 * - EXT_TYPE_NVCOUNTER
495 * - EXT_TYPE_HASH
496 * - EXT_TYPE_PKEY
497 */
498 switch (ext->type) {
499 case EXT_TYPE_NVCOUNTER:
Jimmy Brissonc913fa62021-01-20 15:34:51 -0600500 if (ext->optional && ext->arg == NULL) {
501 /* Skip this NVCounter */
502 continue;
503 } else {
504 /* Checked by `check_cmd_params` */
505 assert(ext->arg != NULL);
Yatharth Kochar79f86402016-06-22 14:49:27 +0100506 nvctr = atoi(ext->arg);
507 CHECK_NULL(cert_ext, ext_new_nvcounter(ext_nid,
Juan Castillo43529982016-01-22 11:05:24 +0000508 EXT_CRIT, nvctr));
Yatharth Kochar79f86402016-06-22 14:49:27 +0100509 }
Juan Castilloe6d30e92015-06-12 11:27:59 +0100510 break;
511 case EXT_TYPE_HASH:
Juan Castillo43529982016-01-22 11:05:24 +0000512 if (ext->arg == NULL) {
Yatharth Kochar5752b592015-08-21 15:30:55 +0100513 if (ext->optional) {
514 /* Include a hash filled with zeros */
Qixiang Xu76a5a9b2017-11-09 13:51:58 +0800515 memset(md, 0x0, SHA512_DIGEST_LENGTH);
Yatharth Kochar5752b592015-08-21 15:30:55 +0100516 } else {
517 /* Do not include this hash in the certificate */
Jimmy Brissonc913fa62021-01-20 15:34:51 -0600518 continue;
Yatharth Kochar5752b592015-08-21 15:30:55 +0100519 }
520 } else {
521 /* Calculate the hash of the file */
Qixiang Xu76a5a9b2017-11-09 13:51:58 +0800522 if (!sha_file(hash_alg, ext->arg, md)) {
Yatharth Kochar5752b592015-08-21 15:30:55 +0100523 ERROR("Cannot calculate hash of %s\n",
Juan Castillo43529982016-01-22 11:05:24 +0000524 ext->arg);
Yatharth Kochar5752b592015-08-21 15:30:55 +0100525 exit(1);
526 }
Juan Castilloe6d30e92015-06-12 11:27:59 +0100527 }
528 CHECK_NULL(cert_ext, ext_new_hash(ext_nid,
529 EXT_CRIT, md_info, md,
Qixiang Xu76a5a9b2017-11-09 13:51:58 +0800530 md_len));
Juan Castilloe6d30e92015-06-12 11:27:59 +0100531 break;
532 case EXT_TYPE_PKEY:
533 CHECK_NULL(cert_ext, ext_new_key(ext_nid,
Juan Castillo43529982016-01-22 11:05:24 +0000534 EXT_CRIT, keys[ext->attr.key].key));
Juan Castilloe6d30e92015-06-12 11:27:59 +0100535 break;
536 default:
Juan Castillo43529982016-01-22 11:05:24 +0000537 ERROR("Unknown extension type '%d' in %s\n",
538 ext->type, cert->cn);
Juan Castilloe6d30e92015-06-12 11:27:59 +0100539 exit(1);
540 }
Juan Castillo11abdcd2014-10-21 11:30:42 +0100541
Juan Castilloe6d30e92015-06-12 11:27:59 +0100542 /* Push the extension into the stack */
543 sk_X509_EXTENSION_push(sk, cert_ext);
Juan Castillo11abdcd2014-10-21 11:30:42 +0100544 }
Juan Castillo11abdcd2014-10-21 11:30:42 +0100545
Soby Mathew2fd70f62017-08-31 11:50:29 +0100546 /* Create certificate. Signed with corresponding key */
Manish V Badarkhe2b7e70e2021-01-26 10:55:49 +0000547 if (!cert_new(hash_alg, cert, VAL_DAYS, 0, sk)) {
Juan Castilloe6d30e92015-06-12 11:27:59 +0100548 ERROR("Cannot create %s\n", cert->cn);
Juan Castillo11abdcd2014-10-21 11:30:42 +0100549 exit(1);
550 }
551
Jimmy Brisson63d06932020-07-24 14:31:48 -0500552 for (cert_ext = sk_X509_EXTENSION_pop(sk); cert_ext != NULL;
553 cert_ext = sk_X509_EXTENSION_pop(sk)) {
554 X509_EXTENSION_free(cert_ext);
555 }
556
Juan Castillo11abdcd2014-10-21 11:30:42 +0100557 sk_X509_EXTENSION_free(sk);
558 }
559
Juan Castillo11abdcd2014-10-21 11:30:42 +0100560
561 /* Print the certificates */
562 if (print_cert) {
Juan Castilloe6d30e92015-06-12 11:27:59 +0100563 for (i = 0 ; i < num_certs ; i++) {
Juan Castillo11abdcd2014-10-21 11:30:42 +0100564 if (!certs[i].x) {
565 continue;
566 }
567 printf("\n\n=====================================\n\n");
568 X509_print_fp(stdout, certs[i].x);
569 }
570 }
571
572 /* Save created certificates to files */
Juan Castilloe6d30e92015-06-12 11:27:59 +0100573 for (i = 0 ; i < num_certs ; i++) {
Juan Castillo11abdcd2014-10-21 11:30:42 +0100574 if (certs[i].x && certs[i].fn) {
575 file = fopen(certs[i].fn, "w");
576 if (file != NULL) {
577 i2d_X509_fp(file, certs[i].x);
578 fclose(file);
579 } else {
580 ERROR("Cannot create file %s\n", certs[i].fn);
581 }
582 }
583 }
584
585 /* Save keys */
586 if (save_keys) {
Juan Castilloe6d30e92015-06-12 11:27:59 +0100587 for (i = 0 ; i < num_keys ; i++) {
Juan Castillo11abdcd2014-10-21 11:30:42 +0100588 if (!key_store(&keys[i])) {
589 ERROR("Cannot save %s\n", keys[i].desc);
590 }
591 }
592 }
593
Jimmy Brisson53287962020-07-27 10:43:40 -0500594 /* If we got here, then we must have filled the key array completely.
595 * We can then safely call free on all of the keys in the array
596 */
597 for (i = 0; i < num_keys; i++) {
598 EVP_PKEY_free(keys[i].key);
599 }
600
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 */
608 for (i = 0; i < num_keys; i++) {
609 if (keys[i].fn != NULL) {
610 void *ptr = keys[i].fn;
611
612 keys[i].fn = NULL;
613 free(ptr);
614 }
615 }
616 for (i = 0; i < num_extensions; i++) {
617 if (extensions[i].arg != NULL) {
618 void *ptr = (void *)extensions[i].arg;
619
620 extensions[i].arg = NULL;
621 free(ptr);
622 }
623 }
624 for (i = 0; i < num_certs; i++) {
625 if (certs[i].fn != NULL) {
626 void *ptr = (void *)certs[i].fn;
627
628 certs[i].fn = NULL;
629 free(ptr);
630 }
631 }
632
Juan Castillo11abdcd2014-10-21 11:30:42 +0100633 return 0;
634}