1*54fd6939SJiyong Park /*
2*54fd6939SJiyong Park * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
3*54fd6939SJiyong Park *
4*54fd6939SJiyong Park * SPDX-License-Identifier: BSD-3-Clause
5*54fd6939SJiyong Park */
6*54fd6939SJiyong Park
7*54fd6939SJiyong Park #include <assert.h>
8*54fd6939SJiyong Park #include <ctype.h>
9*54fd6939SJiyong Park #include <getopt.h>
10*54fd6939SJiyong Park #include <stdio.h>
11*54fd6939SJiyong Park #include <stdlib.h>
12*54fd6939SJiyong Park #include <string.h>
13*54fd6939SJiyong Park #include <stdbool.h>
14*54fd6939SJiyong Park
15*54fd6939SJiyong Park #include <openssl/conf.h>
16*54fd6939SJiyong Park #include <openssl/engine.h>
17*54fd6939SJiyong Park #include <openssl/err.h>
18*54fd6939SJiyong Park #include <openssl/pem.h>
19*54fd6939SJiyong Park #include <openssl/sha.h>
20*54fd6939SJiyong Park #include <openssl/x509v3.h>
21*54fd6939SJiyong Park
22*54fd6939SJiyong Park #include "cert.h"
23*54fd6939SJiyong Park #include "cmd_opt.h"
24*54fd6939SJiyong Park #include "debug.h"
25*54fd6939SJiyong Park #include "ext.h"
26*54fd6939SJiyong Park #include "key.h"
27*54fd6939SJiyong Park #include "sha.h"
28*54fd6939SJiyong Park
29*54fd6939SJiyong Park /*
30*54fd6939SJiyong Park * Helper macros to simplify the code. This macro assigns the return value of
31*54fd6939SJiyong Park * the 'fn' function to 'v' and exits if the value is NULL.
32*54fd6939SJiyong Park */
33*54fd6939SJiyong Park #define CHECK_NULL(v, fn) \
34*54fd6939SJiyong Park do { \
35*54fd6939SJiyong Park v = fn; \
36*54fd6939SJiyong Park if (v == NULL) { \
37*54fd6939SJiyong Park ERROR("NULL object at %s:%d\n", __FILE__, __LINE__); \
38*54fd6939SJiyong Park exit(1); \
39*54fd6939SJiyong Park } \
40*54fd6939SJiyong Park } while (0)
41*54fd6939SJiyong Park
42*54fd6939SJiyong Park /*
43*54fd6939SJiyong Park * This macro assigns the NID corresponding to 'oid' to 'v' and exits if the
44*54fd6939SJiyong Park * NID is undefined.
45*54fd6939SJiyong Park */
46*54fd6939SJiyong Park #define CHECK_OID(v, oid) \
47*54fd6939SJiyong Park do { \
48*54fd6939SJiyong Park v = OBJ_txt2nid(oid); \
49*54fd6939SJiyong Park if (v == NID_undef) { \
50*54fd6939SJiyong Park ERROR("Cannot find extension %s\n", oid); \
51*54fd6939SJiyong Park exit(1); \
52*54fd6939SJiyong Park } \
53*54fd6939SJiyong Park } while (0)
54*54fd6939SJiyong Park
55*54fd6939SJiyong Park #define MAX_FILENAME_LEN 1024
56*54fd6939SJiyong Park #define VAL_DAYS 7300
57*54fd6939SJiyong Park #define ID_TO_BIT_MASK(id) (1 << id)
58*54fd6939SJiyong Park #define NUM_ELEM(x) ((sizeof(x)) / (sizeof(x[0])))
59*54fd6939SJiyong Park #define HELP_OPT_MAX_LEN 128
60*54fd6939SJiyong Park
61*54fd6939SJiyong Park /* Global options */
62*54fd6939SJiyong Park static int key_alg;
63*54fd6939SJiyong Park static int hash_alg;
64*54fd6939SJiyong Park static int key_size;
65*54fd6939SJiyong Park static int new_keys;
66*54fd6939SJiyong Park static int save_keys;
67*54fd6939SJiyong Park static int print_cert;
68*54fd6939SJiyong Park
69*54fd6939SJiyong Park /* Info messages created in the Makefile */
70*54fd6939SJiyong Park extern const char build_msg[];
71*54fd6939SJiyong Park extern const char platform_msg[];
72*54fd6939SJiyong Park
73*54fd6939SJiyong Park
strdup(const char * str)74*54fd6939SJiyong Park static char *strdup(const char *str)
75*54fd6939SJiyong Park {
76*54fd6939SJiyong Park int n = strlen(str) + 1;
77*54fd6939SJiyong Park char *dup = malloc(n);
78*54fd6939SJiyong Park if (dup) {
79*54fd6939SJiyong Park strcpy(dup, str);
80*54fd6939SJiyong Park }
81*54fd6939SJiyong Park return dup;
82*54fd6939SJiyong Park }
83*54fd6939SJiyong Park
84*54fd6939SJiyong Park static const char *key_algs_str[] = {
85*54fd6939SJiyong Park [KEY_ALG_RSA] = "rsa",
86*54fd6939SJiyong Park #ifndef OPENSSL_NO_EC
87*54fd6939SJiyong Park [KEY_ALG_ECDSA] = "ecdsa"
88*54fd6939SJiyong Park #endif /* OPENSSL_NO_EC */
89*54fd6939SJiyong Park };
90*54fd6939SJiyong Park
91*54fd6939SJiyong Park static const char *hash_algs_str[] = {
92*54fd6939SJiyong Park [HASH_ALG_SHA256] = "sha256",
93*54fd6939SJiyong Park [HASH_ALG_SHA384] = "sha384",
94*54fd6939SJiyong Park [HASH_ALG_SHA512] = "sha512",
95*54fd6939SJiyong Park };
96*54fd6939SJiyong Park
print_help(const char * cmd,const struct option * long_opt)97*54fd6939SJiyong Park static void print_help(const char *cmd, const struct option *long_opt)
98*54fd6939SJiyong Park {
99*54fd6939SJiyong Park int rem, i = 0;
100*54fd6939SJiyong Park const struct option *opt;
101*54fd6939SJiyong Park char line[HELP_OPT_MAX_LEN];
102*54fd6939SJiyong Park char *p;
103*54fd6939SJiyong Park
104*54fd6939SJiyong Park assert(cmd != NULL);
105*54fd6939SJiyong Park assert(long_opt != NULL);
106*54fd6939SJiyong Park
107*54fd6939SJiyong Park printf("\n\n");
108*54fd6939SJiyong Park printf("The certificate generation tool loads the binary images and\n"
109*54fd6939SJiyong Park "optionally the RSA keys, and outputs the key and content\n"
110*54fd6939SJiyong Park "certificates properly signed to implement the chain of trust.\n"
111*54fd6939SJiyong Park "If keys are provided, they must be in PEM format.\n"
112*54fd6939SJiyong Park "Certificates are generated in DER format.\n");
113*54fd6939SJiyong Park printf("\n");
114*54fd6939SJiyong Park printf("Usage:\n");
115*54fd6939SJiyong Park printf("\t%s [OPTIONS]\n\n", cmd);
116*54fd6939SJiyong Park
117*54fd6939SJiyong Park printf("Available options:\n");
118*54fd6939SJiyong Park opt = long_opt;
119*54fd6939SJiyong Park while (opt->name) {
120*54fd6939SJiyong Park p = line;
121*54fd6939SJiyong Park rem = HELP_OPT_MAX_LEN;
122*54fd6939SJiyong Park if (isalpha(opt->val)) {
123*54fd6939SJiyong Park /* Short format */
124*54fd6939SJiyong Park sprintf(p, "-%c,", (char)opt->val);
125*54fd6939SJiyong Park p += 3;
126*54fd6939SJiyong Park rem -= 3;
127*54fd6939SJiyong Park }
128*54fd6939SJiyong Park snprintf(p, rem, "--%s %s", opt->name,
129*54fd6939SJiyong Park (opt->has_arg == required_argument) ? "<arg>" : "");
130*54fd6939SJiyong Park printf("\t%-32s %s\n", line, cmd_opt_get_help_msg(i));
131*54fd6939SJiyong Park opt++;
132*54fd6939SJiyong Park i++;
133*54fd6939SJiyong Park }
134*54fd6939SJiyong Park printf("\n");
135*54fd6939SJiyong Park }
136*54fd6939SJiyong Park
get_key_alg(const char * key_alg_str)137*54fd6939SJiyong Park static int get_key_alg(const char *key_alg_str)
138*54fd6939SJiyong Park {
139*54fd6939SJiyong Park int i;
140*54fd6939SJiyong Park
141*54fd6939SJiyong Park for (i = 0 ; i < NUM_ELEM(key_algs_str) ; i++) {
142*54fd6939SJiyong Park if (0 == strcmp(key_alg_str, key_algs_str[i])) {
143*54fd6939SJiyong Park return i;
144*54fd6939SJiyong Park }
145*54fd6939SJiyong Park }
146*54fd6939SJiyong Park
147*54fd6939SJiyong Park return -1;
148*54fd6939SJiyong Park }
149*54fd6939SJiyong Park
get_key_size(const char * key_size_str)150*54fd6939SJiyong Park static int get_key_size(const char *key_size_str)
151*54fd6939SJiyong Park {
152*54fd6939SJiyong Park char *end;
153*54fd6939SJiyong Park long key_size;
154*54fd6939SJiyong Park
155*54fd6939SJiyong Park key_size = strtol(key_size_str, &end, 10);
156*54fd6939SJiyong Park if (*end != '\0')
157*54fd6939SJiyong Park return -1;
158*54fd6939SJiyong Park
159*54fd6939SJiyong Park return key_size;
160*54fd6939SJiyong Park }
161*54fd6939SJiyong Park
get_hash_alg(const char * hash_alg_str)162*54fd6939SJiyong Park static int get_hash_alg(const char *hash_alg_str)
163*54fd6939SJiyong Park {
164*54fd6939SJiyong Park int i;
165*54fd6939SJiyong Park
166*54fd6939SJiyong Park for (i = 0 ; i < NUM_ELEM(hash_algs_str) ; i++) {
167*54fd6939SJiyong Park if (0 == strcmp(hash_alg_str, hash_algs_str[i])) {
168*54fd6939SJiyong Park return i;
169*54fd6939SJiyong Park }
170*54fd6939SJiyong Park }
171*54fd6939SJiyong Park
172*54fd6939SJiyong Park return -1;
173*54fd6939SJiyong Park }
174*54fd6939SJiyong Park
check_cmd_params(void)175*54fd6939SJiyong Park static void check_cmd_params(void)
176*54fd6939SJiyong Park {
177*54fd6939SJiyong Park cert_t *cert;
178*54fd6939SJiyong Park ext_t *ext;
179*54fd6939SJiyong Park key_t *key;
180*54fd6939SJiyong Park int i, j;
181*54fd6939SJiyong Park bool valid_size;
182*54fd6939SJiyong Park
183*54fd6939SJiyong Park /* Only save new keys */
184*54fd6939SJiyong Park if (save_keys && !new_keys) {
185*54fd6939SJiyong Park ERROR("Only new keys can be saved to disk\n");
186*54fd6939SJiyong Park exit(1);
187*54fd6939SJiyong Park }
188*54fd6939SJiyong Park
189*54fd6939SJiyong Park /* Validate key-size */
190*54fd6939SJiyong Park valid_size = false;
191*54fd6939SJiyong Park for (i = 0; i < KEY_SIZE_MAX_NUM; i++) {
192*54fd6939SJiyong Park if (key_size == KEY_SIZES[key_alg][i]) {
193*54fd6939SJiyong Park valid_size = true;
194*54fd6939SJiyong Park break;
195*54fd6939SJiyong Park }
196*54fd6939SJiyong Park }
197*54fd6939SJiyong Park if (!valid_size) {
198*54fd6939SJiyong Park ERROR("'%d' is not a valid key size for '%s'\n",
199*54fd6939SJiyong Park key_size, key_algs_str[key_alg]);
200*54fd6939SJiyong Park NOTICE("Valid sizes are: ");
201*54fd6939SJiyong Park for (i = 0; i < KEY_SIZE_MAX_NUM &&
202*54fd6939SJiyong Park KEY_SIZES[key_alg][i] != 0; i++) {
203*54fd6939SJiyong Park printf("%d ", KEY_SIZES[key_alg][i]);
204*54fd6939SJiyong Park }
205*54fd6939SJiyong Park printf("\n");
206*54fd6939SJiyong Park exit(1);
207*54fd6939SJiyong Park }
208*54fd6939SJiyong Park
209*54fd6939SJiyong Park /* Check that all required options have been specified in the
210*54fd6939SJiyong Park * command line */
211*54fd6939SJiyong Park for (i = 0; i < num_certs; i++) {
212*54fd6939SJiyong Park cert = &certs[i];
213*54fd6939SJiyong Park if (cert->fn == NULL) {
214*54fd6939SJiyong Park /* Certificate not requested. Skip to the next one */
215*54fd6939SJiyong Park continue;
216*54fd6939SJiyong Park }
217*54fd6939SJiyong Park
218*54fd6939SJiyong Park /* Check that all parameters required to create this certificate
219*54fd6939SJiyong Park * have been specified in the command line */
220*54fd6939SJiyong Park for (j = 0; j < cert->num_ext; j++) {
221*54fd6939SJiyong Park ext = &extensions[cert->ext[j]];
222*54fd6939SJiyong Park switch (ext->type) {
223*54fd6939SJiyong Park case EXT_TYPE_NVCOUNTER:
224*54fd6939SJiyong Park /* Counter value must be specified */
225*54fd6939SJiyong Park if ((!ext->optional) && (ext->arg == NULL)) {
226*54fd6939SJiyong Park ERROR("Value for '%s' not specified\n",
227*54fd6939SJiyong Park ext->ln);
228*54fd6939SJiyong Park exit(1);
229*54fd6939SJiyong Park }
230*54fd6939SJiyong Park break;
231*54fd6939SJiyong Park case EXT_TYPE_PKEY:
232*54fd6939SJiyong Park /* Key filename must be specified */
233*54fd6939SJiyong Park key = &keys[ext->attr.key];
234*54fd6939SJiyong Park if (!new_keys && key->fn == NULL) {
235*54fd6939SJiyong Park ERROR("Key '%s' required by '%s' not "
236*54fd6939SJiyong Park "specified\n", key->desc,
237*54fd6939SJiyong Park cert->cn);
238*54fd6939SJiyong Park exit(1);
239*54fd6939SJiyong Park }
240*54fd6939SJiyong Park break;
241*54fd6939SJiyong Park case EXT_TYPE_HASH:
242*54fd6939SJiyong Park /*
243*54fd6939SJiyong Park * Binary image must be specified
244*54fd6939SJiyong Park * unless it is explicitly made optional.
245*54fd6939SJiyong Park */
246*54fd6939SJiyong Park if ((!ext->optional) && (ext->arg == NULL)) {
247*54fd6939SJiyong Park ERROR("Image for '%s' not specified\n",
248*54fd6939SJiyong Park ext->ln);
249*54fd6939SJiyong Park exit(1);
250*54fd6939SJiyong Park }
251*54fd6939SJiyong Park break;
252*54fd6939SJiyong Park default:
253*54fd6939SJiyong Park ERROR("Unknown extension type '%d' in '%s'\n",
254*54fd6939SJiyong Park ext->type, ext->ln);
255*54fd6939SJiyong Park exit(1);
256*54fd6939SJiyong Park break;
257*54fd6939SJiyong Park }
258*54fd6939SJiyong Park }
259*54fd6939SJiyong Park }
260*54fd6939SJiyong Park }
261*54fd6939SJiyong Park
262*54fd6939SJiyong Park /* Common command line options */
263*54fd6939SJiyong Park static const cmd_opt_t common_cmd_opt[] = {
264*54fd6939SJiyong Park {
265*54fd6939SJiyong Park { "help", no_argument, NULL, 'h' },
266*54fd6939SJiyong Park "Print this message and exit"
267*54fd6939SJiyong Park },
268*54fd6939SJiyong Park {
269*54fd6939SJiyong Park { "key-alg", required_argument, NULL, 'a' },
270*54fd6939SJiyong Park "Key algorithm: 'rsa' (default)- RSAPSS scheme as per PKCS#1 v2.1, 'ecdsa'"
271*54fd6939SJiyong Park },
272*54fd6939SJiyong Park {
273*54fd6939SJiyong Park { "key-size", required_argument, NULL, 'b' },
274*54fd6939SJiyong Park "Key size (for supported algorithms)."
275*54fd6939SJiyong Park },
276*54fd6939SJiyong Park {
277*54fd6939SJiyong Park { "hash-alg", required_argument, NULL, 's' },
278*54fd6939SJiyong Park "Hash algorithm : 'sha256' (default), 'sha384', 'sha512'"
279*54fd6939SJiyong Park },
280*54fd6939SJiyong Park {
281*54fd6939SJiyong Park { "save-keys", no_argument, NULL, 'k' },
282*54fd6939SJiyong Park "Save key pairs into files. Filenames must be provided"
283*54fd6939SJiyong Park },
284*54fd6939SJiyong Park {
285*54fd6939SJiyong Park { "new-keys", no_argument, NULL, 'n' },
286*54fd6939SJiyong Park "Generate new key pairs if no key files are provided"
287*54fd6939SJiyong Park },
288*54fd6939SJiyong Park {
289*54fd6939SJiyong Park { "print-cert", no_argument, NULL, 'p' },
290*54fd6939SJiyong Park "Print the certificates in the standard output"
291*54fd6939SJiyong Park }
292*54fd6939SJiyong Park };
293*54fd6939SJiyong Park
main(int argc,char * argv[])294*54fd6939SJiyong Park int main(int argc, char *argv[])
295*54fd6939SJiyong Park {
296*54fd6939SJiyong Park STACK_OF(X509_EXTENSION) * sk;
297*54fd6939SJiyong Park X509_EXTENSION *cert_ext = NULL;
298*54fd6939SJiyong Park ext_t *ext;
299*54fd6939SJiyong Park key_t *key;
300*54fd6939SJiyong Park cert_t *cert;
301*54fd6939SJiyong Park FILE *file;
302*54fd6939SJiyong Park int i, j, ext_nid, nvctr;
303*54fd6939SJiyong Park int c, opt_idx = 0;
304*54fd6939SJiyong Park const struct option *cmd_opt;
305*54fd6939SJiyong Park const char *cur_opt;
306*54fd6939SJiyong Park unsigned int err_code;
307*54fd6939SJiyong Park unsigned char md[SHA512_DIGEST_LENGTH];
308*54fd6939SJiyong Park unsigned int md_len;
309*54fd6939SJiyong Park const EVP_MD *md_info;
310*54fd6939SJiyong Park
311*54fd6939SJiyong Park NOTICE("CoT Generation Tool: %s\n", build_msg);
312*54fd6939SJiyong Park NOTICE("Target platform: %s\n", platform_msg);
313*54fd6939SJiyong Park
314*54fd6939SJiyong Park /* Set default options */
315*54fd6939SJiyong Park key_alg = KEY_ALG_RSA;
316*54fd6939SJiyong Park hash_alg = HASH_ALG_SHA256;
317*54fd6939SJiyong Park key_size = -1;
318*54fd6939SJiyong Park
319*54fd6939SJiyong Park /* Add common command line options */
320*54fd6939SJiyong Park for (i = 0; i < NUM_ELEM(common_cmd_opt); i++) {
321*54fd6939SJiyong Park cmd_opt_add(&common_cmd_opt[i]);
322*54fd6939SJiyong Park }
323*54fd6939SJiyong Park
324*54fd6939SJiyong Park /* Initialize the certificates */
325*54fd6939SJiyong Park if (cert_init() != 0) {
326*54fd6939SJiyong Park ERROR("Cannot initialize certificates\n");
327*54fd6939SJiyong Park exit(1);
328*54fd6939SJiyong Park }
329*54fd6939SJiyong Park
330*54fd6939SJiyong Park /* Initialize the keys */
331*54fd6939SJiyong Park if (key_init() != 0) {
332*54fd6939SJiyong Park ERROR("Cannot initialize keys\n");
333*54fd6939SJiyong Park exit(1);
334*54fd6939SJiyong Park }
335*54fd6939SJiyong Park
336*54fd6939SJiyong Park /* Initialize the new types and register OIDs for the extensions */
337*54fd6939SJiyong Park if (ext_init() != 0) {
338*54fd6939SJiyong Park ERROR("Cannot initialize extensions\n");
339*54fd6939SJiyong Park exit(1);
340*54fd6939SJiyong Park }
341*54fd6939SJiyong Park
342*54fd6939SJiyong Park /* Get the command line options populated during the initialization */
343*54fd6939SJiyong Park cmd_opt = cmd_opt_get_array();
344*54fd6939SJiyong Park
345*54fd6939SJiyong Park while (1) {
346*54fd6939SJiyong Park /* getopt_long stores the option index here. */
347*54fd6939SJiyong Park c = getopt_long(argc, argv, "a:b:hknps:", cmd_opt, &opt_idx);
348*54fd6939SJiyong Park
349*54fd6939SJiyong Park /* Detect the end of the options. */
350*54fd6939SJiyong Park if (c == -1) {
351*54fd6939SJiyong Park break;
352*54fd6939SJiyong Park }
353*54fd6939SJiyong Park
354*54fd6939SJiyong Park switch (c) {
355*54fd6939SJiyong Park case 'a':
356*54fd6939SJiyong Park key_alg = get_key_alg(optarg);
357*54fd6939SJiyong Park if (key_alg < 0) {
358*54fd6939SJiyong Park ERROR("Invalid key algorithm '%s'\n", optarg);
359*54fd6939SJiyong Park exit(1);
360*54fd6939SJiyong Park }
361*54fd6939SJiyong Park break;
362*54fd6939SJiyong Park case 'b':
363*54fd6939SJiyong Park key_size = get_key_size(optarg);
364*54fd6939SJiyong Park if (key_size <= 0) {
365*54fd6939SJiyong Park ERROR("Invalid key size '%s'\n", optarg);
366*54fd6939SJiyong Park exit(1);
367*54fd6939SJiyong Park }
368*54fd6939SJiyong Park break;
369*54fd6939SJiyong Park case 'h':
370*54fd6939SJiyong Park print_help(argv[0], cmd_opt);
371*54fd6939SJiyong Park exit(0);
372*54fd6939SJiyong Park case 'k':
373*54fd6939SJiyong Park save_keys = 1;
374*54fd6939SJiyong Park break;
375*54fd6939SJiyong Park case 'n':
376*54fd6939SJiyong Park new_keys = 1;
377*54fd6939SJiyong Park break;
378*54fd6939SJiyong Park case 'p':
379*54fd6939SJiyong Park print_cert = 1;
380*54fd6939SJiyong Park break;
381*54fd6939SJiyong Park case 's':
382*54fd6939SJiyong Park hash_alg = get_hash_alg(optarg);
383*54fd6939SJiyong Park if (hash_alg < 0) {
384*54fd6939SJiyong Park ERROR("Invalid hash algorithm '%s'\n", optarg);
385*54fd6939SJiyong Park exit(1);
386*54fd6939SJiyong Park }
387*54fd6939SJiyong Park break;
388*54fd6939SJiyong Park case CMD_OPT_EXT:
389*54fd6939SJiyong Park cur_opt = cmd_opt_get_name(opt_idx);
390*54fd6939SJiyong Park ext = ext_get_by_opt(cur_opt);
391*54fd6939SJiyong Park ext->arg = strdup(optarg);
392*54fd6939SJiyong Park break;
393*54fd6939SJiyong Park case CMD_OPT_KEY:
394*54fd6939SJiyong Park cur_opt = cmd_opt_get_name(opt_idx);
395*54fd6939SJiyong Park key = key_get_by_opt(cur_opt);
396*54fd6939SJiyong Park key->fn = strdup(optarg);
397*54fd6939SJiyong Park break;
398*54fd6939SJiyong Park case CMD_OPT_CERT:
399*54fd6939SJiyong Park cur_opt = cmd_opt_get_name(opt_idx);
400*54fd6939SJiyong Park cert = cert_get_by_opt(cur_opt);
401*54fd6939SJiyong Park cert->fn = strdup(optarg);
402*54fd6939SJiyong Park break;
403*54fd6939SJiyong Park case '?':
404*54fd6939SJiyong Park default:
405*54fd6939SJiyong Park print_help(argv[0], cmd_opt);
406*54fd6939SJiyong Park exit(1);
407*54fd6939SJiyong Park }
408*54fd6939SJiyong Park }
409*54fd6939SJiyong Park
410*54fd6939SJiyong Park /* Select a reasonable default key-size */
411*54fd6939SJiyong Park if (key_size == -1) {
412*54fd6939SJiyong Park key_size = KEY_SIZES[key_alg][0];
413*54fd6939SJiyong Park }
414*54fd6939SJiyong Park
415*54fd6939SJiyong Park /* Check command line arguments */
416*54fd6939SJiyong Park check_cmd_params();
417*54fd6939SJiyong Park
418*54fd6939SJiyong Park /* Indicate SHA as image hash algorithm in the certificate
419*54fd6939SJiyong Park * extension */
420*54fd6939SJiyong Park if (hash_alg == HASH_ALG_SHA384) {
421*54fd6939SJiyong Park md_info = EVP_sha384();
422*54fd6939SJiyong Park md_len = SHA384_DIGEST_LENGTH;
423*54fd6939SJiyong Park } else if (hash_alg == HASH_ALG_SHA512) {
424*54fd6939SJiyong Park md_info = EVP_sha512();
425*54fd6939SJiyong Park md_len = SHA512_DIGEST_LENGTH;
426*54fd6939SJiyong Park } else {
427*54fd6939SJiyong Park md_info = EVP_sha256();
428*54fd6939SJiyong Park md_len = SHA256_DIGEST_LENGTH;
429*54fd6939SJiyong Park }
430*54fd6939SJiyong Park
431*54fd6939SJiyong Park /* Load private keys from files (or generate new ones) */
432*54fd6939SJiyong Park for (i = 0 ; i < num_keys ; i++) {
433*54fd6939SJiyong Park if (!key_new(&keys[i])) {
434*54fd6939SJiyong Park ERROR("Failed to allocate key container\n");
435*54fd6939SJiyong Park exit(1);
436*54fd6939SJiyong Park }
437*54fd6939SJiyong Park
438*54fd6939SJiyong Park /* First try to load the key from disk */
439*54fd6939SJiyong Park if (key_load(&keys[i], &err_code)) {
440*54fd6939SJiyong Park /* Key loaded successfully */
441*54fd6939SJiyong Park continue;
442*54fd6939SJiyong Park }
443*54fd6939SJiyong Park
444*54fd6939SJiyong Park /* Key not loaded. Check the error code */
445*54fd6939SJiyong Park if (err_code == KEY_ERR_LOAD) {
446*54fd6939SJiyong Park /* File exists, but it does not contain a valid private
447*54fd6939SJiyong Park * key. Abort. */
448*54fd6939SJiyong Park ERROR("Error loading '%s'\n", keys[i].fn);
449*54fd6939SJiyong Park exit(1);
450*54fd6939SJiyong Park }
451*54fd6939SJiyong Park
452*54fd6939SJiyong Park /* File does not exist, could not be opened or no filename was
453*54fd6939SJiyong Park * given */
454*54fd6939SJiyong Park if (new_keys) {
455*54fd6939SJiyong Park /* Try to create a new key */
456*54fd6939SJiyong Park NOTICE("Creating new key for '%s'\n", keys[i].desc);
457*54fd6939SJiyong Park if (!key_create(&keys[i], key_alg, key_size)) {
458*54fd6939SJiyong Park ERROR("Error creating key '%s'\n", keys[i].desc);
459*54fd6939SJiyong Park exit(1);
460*54fd6939SJiyong Park }
461*54fd6939SJiyong Park } else {
462*54fd6939SJiyong Park if (err_code == KEY_ERR_OPEN) {
463*54fd6939SJiyong Park ERROR("Error opening '%s'\n", keys[i].fn);
464*54fd6939SJiyong Park } else {
465*54fd6939SJiyong Park ERROR("Key '%s' not specified\n", keys[i].desc);
466*54fd6939SJiyong Park }
467*54fd6939SJiyong Park exit(1);
468*54fd6939SJiyong Park }
469*54fd6939SJiyong Park }
470*54fd6939SJiyong Park
471*54fd6939SJiyong Park /* Create the certificates */
472*54fd6939SJiyong Park for (i = 0 ; i < num_certs ; i++) {
473*54fd6939SJiyong Park
474*54fd6939SJiyong Park cert = &certs[i];
475*54fd6939SJiyong Park
476*54fd6939SJiyong Park if (cert->fn == NULL) {
477*54fd6939SJiyong Park /* Certificate not requested. Skip to the next one */
478*54fd6939SJiyong Park continue;
479*54fd6939SJiyong Park }
480*54fd6939SJiyong Park
481*54fd6939SJiyong Park /* Create a new stack of extensions. This stack will be used
482*54fd6939SJiyong Park * to create the certificate */
483*54fd6939SJiyong Park CHECK_NULL(sk, sk_X509_EXTENSION_new_null());
484*54fd6939SJiyong Park
485*54fd6939SJiyong Park for (j = 0 ; j < cert->num_ext ; j++) {
486*54fd6939SJiyong Park
487*54fd6939SJiyong Park ext = &extensions[cert->ext[j]];
488*54fd6939SJiyong Park
489*54fd6939SJiyong Park /* Get OpenSSL internal ID for this extension */
490*54fd6939SJiyong Park CHECK_OID(ext_nid, ext->oid);
491*54fd6939SJiyong Park
492*54fd6939SJiyong Park /*
493*54fd6939SJiyong Park * Three types of extensions are currently supported:
494*54fd6939SJiyong Park * - EXT_TYPE_NVCOUNTER
495*54fd6939SJiyong Park * - EXT_TYPE_HASH
496*54fd6939SJiyong Park * - EXT_TYPE_PKEY
497*54fd6939SJiyong Park */
498*54fd6939SJiyong Park switch (ext->type) {
499*54fd6939SJiyong Park case EXT_TYPE_NVCOUNTER:
500*54fd6939SJiyong Park if (ext->optional && ext->arg == NULL) {
501*54fd6939SJiyong Park /* Skip this NVCounter */
502*54fd6939SJiyong Park continue;
503*54fd6939SJiyong Park } else {
504*54fd6939SJiyong Park /* Checked by `check_cmd_params` */
505*54fd6939SJiyong Park assert(ext->arg != NULL);
506*54fd6939SJiyong Park nvctr = atoi(ext->arg);
507*54fd6939SJiyong Park CHECK_NULL(cert_ext, ext_new_nvcounter(ext_nid,
508*54fd6939SJiyong Park EXT_CRIT, nvctr));
509*54fd6939SJiyong Park }
510*54fd6939SJiyong Park break;
511*54fd6939SJiyong Park case EXT_TYPE_HASH:
512*54fd6939SJiyong Park if (ext->arg == NULL) {
513*54fd6939SJiyong Park if (ext->optional) {
514*54fd6939SJiyong Park /* Include a hash filled with zeros */
515*54fd6939SJiyong Park memset(md, 0x0, SHA512_DIGEST_LENGTH);
516*54fd6939SJiyong Park } else {
517*54fd6939SJiyong Park /* Do not include this hash in the certificate */
518*54fd6939SJiyong Park continue;
519*54fd6939SJiyong Park }
520*54fd6939SJiyong Park } else {
521*54fd6939SJiyong Park /* Calculate the hash of the file */
522*54fd6939SJiyong Park if (!sha_file(hash_alg, ext->arg, md)) {
523*54fd6939SJiyong Park ERROR("Cannot calculate hash of %s\n",
524*54fd6939SJiyong Park ext->arg);
525*54fd6939SJiyong Park exit(1);
526*54fd6939SJiyong Park }
527*54fd6939SJiyong Park }
528*54fd6939SJiyong Park CHECK_NULL(cert_ext, ext_new_hash(ext_nid,
529*54fd6939SJiyong Park EXT_CRIT, md_info, md,
530*54fd6939SJiyong Park md_len));
531*54fd6939SJiyong Park break;
532*54fd6939SJiyong Park case EXT_TYPE_PKEY:
533*54fd6939SJiyong Park CHECK_NULL(cert_ext, ext_new_key(ext_nid,
534*54fd6939SJiyong Park EXT_CRIT, keys[ext->attr.key].key));
535*54fd6939SJiyong Park break;
536*54fd6939SJiyong Park default:
537*54fd6939SJiyong Park ERROR("Unknown extension type '%d' in %s\n",
538*54fd6939SJiyong Park ext->type, cert->cn);
539*54fd6939SJiyong Park exit(1);
540*54fd6939SJiyong Park }
541*54fd6939SJiyong Park
542*54fd6939SJiyong Park /* Push the extension into the stack */
543*54fd6939SJiyong Park sk_X509_EXTENSION_push(sk, cert_ext);
544*54fd6939SJiyong Park }
545*54fd6939SJiyong Park
546*54fd6939SJiyong Park /* Create certificate. Signed with corresponding key */
547*54fd6939SJiyong Park if (!cert_new(hash_alg, cert, VAL_DAYS, 0, sk)) {
548*54fd6939SJiyong Park ERROR("Cannot create %s\n", cert->cn);
549*54fd6939SJiyong Park exit(1);
550*54fd6939SJiyong Park }
551*54fd6939SJiyong Park
552*54fd6939SJiyong Park for (cert_ext = sk_X509_EXTENSION_pop(sk); cert_ext != NULL;
553*54fd6939SJiyong Park cert_ext = sk_X509_EXTENSION_pop(sk)) {
554*54fd6939SJiyong Park X509_EXTENSION_free(cert_ext);
555*54fd6939SJiyong Park }
556*54fd6939SJiyong Park
557*54fd6939SJiyong Park sk_X509_EXTENSION_free(sk);
558*54fd6939SJiyong Park }
559*54fd6939SJiyong Park
560*54fd6939SJiyong Park
561*54fd6939SJiyong Park /* Print the certificates */
562*54fd6939SJiyong Park if (print_cert) {
563*54fd6939SJiyong Park for (i = 0 ; i < num_certs ; i++) {
564*54fd6939SJiyong Park if (!certs[i].x) {
565*54fd6939SJiyong Park continue;
566*54fd6939SJiyong Park }
567*54fd6939SJiyong Park printf("\n\n=====================================\n\n");
568*54fd6939SJiyong Park X509_print_fp(stdout, certs[i].x);
569*54fd6939SJiyong Park }
570*54fd6939SJiyong Park }
571*54fd6939SJiyong Park
572*54fd6939SJiyong Park /* Save created certificates to files */
573*54fd6939SJiyong Park for (i = 0 ; i < num_certs ; i++) {
574*54fd6939SJiyong Park if (certs[i].x && certs[i].fn) {
575*54fd6939SJiyong Park file = fopen(certs[i].fn, "w");
576*54fd6939SJiyong Park if (file != NULL) {
577*54fd6939SJiyong Park i2d_X509_fp(file, certs[i].x);
578*54fd6939SJiyong Park fclose(file);
579*54fd6939SJiyong Park } else {
580*54fd6939SJiyong Park ERROR("Cannot create file %s\n", certs[i].fn);
581*54fd6939SJiyong Park }
582*54fd6939SJiyong Park }
583*54fd6939SJiyong Park }
584*54fd6939SJiyong Park
585*54fd6939SJiyong Park /* Save keys */
586*54fd6939SJiyong Park if (save_keys) {
587*54fd6939SJiyong Park for (i = 0 ; i < num_keys ; i++) {
588*54fd6939SJiyong Park if (!key_store(&keys[i])) {
589*54fd6939SJiyong Park ERROR("Cannot save %s\n", keys[i].desc);
590*54fd6939SJiyong Park }
591*54fd6939SJiyong Park }
592*54fd6939SJiyong Park }
593*54fd6939SJiyong Park
594*54fd6939SJiyong Park /* If we got here, then we must have filled the key array completely.
595*54fd6939SJiyong Park * We can then safely call free on all of the keys in the array
596*54fd6939SJiyong Park */
597*54fd6939SJiyong Park for (i = 0; i < num_keys; i++) {
598*54fd6939SJiyong Park EVP_PKEY_free(keys[i].key);
599*54fd6939SJiyong Park }
600*54fd6939SJiyong Park
601*54fd6939SJiyong Park #ifndef OPENSSL_NO_ENGINE
602*54fd6939SJiyong Park ENGINE_cleanup();
603*54fd6939SJiyong Park #endif
604*54fd6939SJiyong Park CRYPTO_cleanup_all_ex_data();
605*54fd6939SJiyong Park
606*54fd6939SJiyong Park
607*54fd6939SJiyong Park /* We allocated strings through strdup, so now we have to free them */
608*54fd6939SJiyong Park for (i = 0; i < num_keys; i++) {
609*54fd6939SJiyong Park if (keys[i].fn != NULL) {
610*54fd6939SJiyong Park void *ptr = keys[i].fn;
611*54fd6939SJiyong Park
612*54fd6939SJiyong Park keys[i].fn = NULL;
613*54fd6939SJiyong Park free(ptr);
614*54fd6939SJiyong Park }
615*54fd6939SJiyong Park }
616*54fd6939SJiyong Park for (i = 0; i < num_extensions; i++) {
617*54fd6939SJiyong Park if (extensions[i].arg != NULL) {
618*54fd6939SJiyong Park void *ptr = (void *)extensions[i].arg;
619*54fd6939SJiyong Park
620*54fd6939SJiyong Park extensions[i].arg = NULL;
621*54fd6939SJiyong Park free(ptr);
622*54fd6939SJiyong Park }
623*54fd6939SJiyong Park }
624*54fd6939SJiyong Park for (i = 0; i < num_certs; i++) {
625*54fd6939SJiyong Park if (certs[i].fn != NULL) {
626*54fd6939SJiyong Park void *ptr = (void *)certs[i].fn;
627*54fd6939SJiyong Park
628*54fd6939SJiyong Park certs[i].fn = NULL;
629*54fd6939SJiyong Park free(ptr);
630*54fd6939SJiyong Park }
631*54fd6939SJiyong Park }
632*54fd6939SJiyong Park
633*54fd6939SJiyong Park return 0;
634*54fd6939SJiyong Park }
635