blob: 2ba110132a77087818039e3f71f4c2f3d9b97873 [file] [log] [blame]
Juan Castillo11abdcd2014-10-21 11:30:42 +01001/*
Sandrine Bailleux0b144832020-01-07 15:12:08 +01002 * Copyright (c) 2015-2020, 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
Juan Castilloe6d30e92015-06-12 11:27:59 +0100476 /* Create a new stack of extensions. This stack will be used
477 * to create the certificate */
Juan Castillo11abdcd2014-10-21 11:30:42 +0100478 CHECK_NULL(sk, sk_X509_EXTENSION_new_null());
Juan Castillo11abdcd2014-10-21 11:30:42 +0100479
Juan Castilloe6d30e92015-06-12 11:27:59 +0100480 for (j = 0 ; j < cert->num_ext ; j++) {
Juan Castillo11abdcd2014-10-21 11:30:42 +0100481
Juan Castilloe6d30e92015-06-12 11:27:59 +0100482 ext = &extensions[cert->ext[j]];
Juan Castillo11abdcd2014-10-21 11:30:42 +0100483
Juan Castilloe6d30e92015-06-12 11:27:59 +0100484 /* Get OpenSSL internal ID for this extension */
485 CHECK_OID(ext_nid, ext->oid);
Juan Castillo11abdcd2014-10-21 11:30:42 +0100486
Juan Castilloe6d30e92015-06-12 11:27:59 +0100487 /*
488 * Three types of extensions are currently supported:
489 * - EXT_TYPE_NVCOUNTER
490 * - EXT_TYPE_HASH
491 * - EXT_TYPE_PKEY
492 */
493 switch (ext->type) {
494 case EXT_TYPE_NVCOUNTER:
Yatharth Kochar79f86402016-06-22 14:49:27 +0100495 if (ext->arg) {
496 nvctr = atoi(ext->arg);
497 CHECK_NULL(cert_ext, ext_new_nvcounter(ext_nid,
Juan Castillo43529982016-01-22 11:05:24 +0000498 EXT_CRIT, nvctr));
Yatharth Kochar79f86402016-06-22 14:49:27 +0100499 }
Juan Castilloe6d30e92015-06-12 11:27:59 +0100500 break;
501 case EXT_TYPE_HASH:
Juan Castillo43529982016-01-22 11:05:24 +0000502 if (ext->arg == NULL) {
Yatharth Kochar5752b592015-08-21 15:30:55 +0100503 if (ext->optional) {
504 /* Include a hash filled with zeros */
Qixiang Xu76a5a9b2017-11-09 13:51:58 +0800505 memset(md, 0x0, SHA512_DIGEST_LENGTH);
Yatharth Kochar5752b592015-08-21 15:30:55 +0100506 } else {
507 /* Do not include this hash in the certificate */
508 break;
509 }
510 } else {
511 /* Calculate the hash of the file */
Qixiang Xu76a5a9b2017-11-09 13:51:58 +0800512 if (!sha_file(hash_alg, ext->arg, md)) {
Yatharth Kochar5752b592015-08-21 15:30:55 +0100513 ERROR("Cannot calculate hash of %s\n",
Juan Castillo43529982016-01-22 11:05:24 +0000514 ext->arg);
Yatharth Kochar5752b592015-08-21 15:30:55 +0100515 exit(1);
516 }
Juan Castilloe6d30e92015-06-12 11:27:59 +0100517 }
518 CHECK_NULL(cert_ext, ext_new_hash(ext_nid,
519 EXT_CRIT, md_info, md,
Qixiang Xu76a5a9b2017-11-09 13:51:58 +0800520 md_len));
Juan Castilloe6d30e92015-06-12 11:27:59 +0100521 break;
522 case EXT_TYPE_PKEY:
523 CHECK_NULL(cert_ext, ext_new_key(ext_nid,
Juan Castillo43529982016-01-22 11:05:24 +0000524 EXT_CRIT, keys[ext->attr.key].key));
Juan Castilloe6d30e92015-06-12 11:27:59 +0100525 break;
526 default:
Juan Castillo43529982016-01-22 11:05:24 +0000527 ERROR("Unknown extension type '%d' in %s\n",
528 ext->type, cert->cn);
Juan Castilloe6d30e92015-06-12 11:27:59 +0100529 exit(1);
530 }
Juan Castillo11abdcd2014-10-21 11:30:42 +0100531
Juan Castilloe6d30e92015-06-12 11:27:59 +0100532 /* Push the extension into the stack */
533 sk_X509_EXTENSION_push(sk, cert_ext);
Juan Castillo11abdcd2014-10-21 11:30:42 +0100534 }
Juan Castillo11abdcd2014-10-21 11:30:42 +0100535
Soby Mathew2fd70f62017-08-31 11:50:29 +0100536 /* Create certificate. Signed with corresponding key */
Justin Chadwell3168a202019-09-09 15:24:31 +0100537 if (cert->fn && !cert_new(hash_alg, cert, VAL_DAYS, 0, sk)) {
Juan Castilloe6d30e92015-06-12 11:27:59 +0100538 ERROR("Cannot create %s\n", cert->cn);
Juan Castillo11abdcd2014-10-21 11:30:42 +0100539 exit(1);
540 }
541
542 sk_X509_EXTENSION_free(sk);
543 }
544
Juan Castillo11abdcd2014-10-21 11:30:42 +0100545
546 /* Print the certificates */
547 if (print_cert) {
Juan Castilloe6d30e92015-06-12 11:27:59 +0100548 for (i = 0 ; i < num_certs ; i++) {
Juan Castillo11abdcd2014-10-21 11:30:42 +0100549 if (!certs[i].x) {
550 continue;
551 }
552 printf("\n\n=====================================\n\n");
553 X509_print_fp(stdout, certs[i].x);
554 }
555 }
556
557 /* Save created certificates to files */
Juan Castilloe6d30e92015-06-12 11:27:59 +0100558 for (i = 0 ; i < num_certs ; i++) {
Juan Castillo11abdcd2014-10-21 11:30:42 +0100559 if (certs[i].x && certs[i].fn) {
560 file = fopen(certs[i].fn, "w");
561 if (file != NULL) {
562 i2d_X509_fp(file, certs[i].x);
563 fclose(file);
564 } else {
565 ERROR("Cannot create file %s\n", certs[i].fn);
566 }
567 }
568 }
569
570 /* Save keys */
571 if (save_keys) {
Juan Castilloe6d30e92015-06-12 11:27:59 +0100572 for (i = 0 ; i < num_keys ; i++) {
Juan Castillo11abdcd2014-10-21 11:30:42 +0100573 if (!key_store(&keys[i])) {
574 ERROR("Cannot save %s\n", keys[i].desc);
575 }
576 }
577 }
578
Juan Castillo11abdcd2014-10-21 11:30:42 +0100579#ifndef OPENSSL_NO_ENGINE
580 ENGINE_cleanup();
581#endif
582 CRYPTO_cleanup_all_ex_data();
583
584 return 0;
585}