blob: 0b2575e84a9d6ebc9da35b3405f3a5bcd38c79f3 [file] [log] [blame]
Tom Rini0344c602024-10-08 13:56:50 -06001/*
2 * Certificate generation and signing
3 *
4 * Copyright The Mbed TLS Contributors
5 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6 */
7
8#include "mbedtls/build_info.h"
9
10#include "mbedtls/platform.h"
11/* md.h is included this early since MD_CAN_XXX macros are defined there. */
12#include "mbedtls/md.h"
13
14#if !defined(MBEDTLS_X509_CRT_WRITE_C) || \
15 !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_FS_IO) || \
16 !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_CTR_DRBG_C) || \
17 !defined(MBEDTLS_ERROR_C) || !defined(MBEDTLS_MD_CAN_SHA256) || \
18 !defined(MBEDTLS_PEM_WRITE_C) || !defined(MBEDTLS_MD_C)
19int main(void)
20{
21 mbedtls_printf("MBEDTLS_X509_CRT_WRITE_C and/or MBEDTLS_X509_CRT_PARSE_C and/or "
22 "MBEDTLS_FS_IO and/or MBEDTLS_MD_CAN_SHA256 and/or "
23 "MBEDTLS_ENTROPY_C and/or MBEDTLS_CTR_DRBG_C and/or "
24 "MBEDTLS_ERROR_C not defined.\n");
25 mbedtls_exit(0);
26}
27#else
28
29#include "mbedtls/x509_crt.h"
30#include "mbedtls/x509_csr.h"
31#include "mbedtls/oid.h"
32#include "mbedtls/entropy.h"
33#include "mbedtls/ctr_drbg.h"
34#include "mbedtls/error.h"
35#include "test/helpers.h"
36
37#include <stdio.h>
38#include <stdlib.h>
39#include <string.h>
40#include <errno.h>
41
42#define SET_OID(x, oid) \
43 do { x.len = MBEDTLS_OID_SIZE(oid); x.p = (unsigned char *) oid; } while (0)
44
45#if defined(MBEDTLS_X509_CSR_PARSE_C)
46#define USAGE_CSR \
47 " request_file=%%s default: (empty)\n" \
48 " If request_file is specified, subject_key,\n" \
49 " subject_pwd and subject_name are ignored!\n"
50#else
51#define USAGE_CSR ""
52#endif /* MBEDTLS_X509_CSR_PARSE_C */
53
54#define FORMAT_PEM 0
55#define FORMAT_DER 1
56
57#define DFL_ISSUER_CRT ""
58#define DFL_REQUEST_FILE ""
59#define DFL_SUBJECT_KEY "subject.key"
60#define DFL_ISSUER_KEY "ca.key"
61#define DFL_SUBJECT_PWD ""
62#define DFL_ISSUER_PWD ""
63#define DFL_OUTPUT_FILENAME "cert.crt"
64#define DFL_SUBJECT_NAME "CN=Cert,O=mbed TLS,C=UK"
65#define DFL_ISSUER_NAME "CN=CA,O=mbed TLS,C=UK"
66#define DFL_NOT_BEFORE "20010101000000"
67#define DFL_NOT_AFTER "20301231235959"
68#define DFL_SERIAL "1"
69#define DFL_SERIAL_HEX "1"
70#define DFL_EXT_SUBJECTALTNAME ""
71#define DFL_SELFSIGN 0
72#define DFL_IS_CA 0
73#define DFL_MAX_PATHLEN -1
74#define DFL_SIG_ALG MBEDTLS_MD_SHA256
75#define DFL_KEY_USAGE 0
76#define DFL_EXT_KEY_USAGE NULL
77#define DFL_NS_CERT_TYPE 0
78#define DFL_VERSION 3
79#define DFL_AUTH_IDENT 1
80#define DFL_SUBJ_IDENT 1
81#define DFL_CONSTRAINTS 1
82#define DFL_DIGEST MBEDTLS_MD_SHA256
83#define DFL_FORMAT FORMAT_PEM
84
85#define USAGE \
86 "\n usage: cert_write param=<>...\n" \
87 "\n acceptable parameters:\n" \
88 USAGE_CSR \
89 " subject_key=%%s default: subject.key\n" \
90 " subject_pwd=%%s default: (empty)\n" \
91 " subject_name=%%s default: CN=Cert,O=mbed TLS,C=UK\n" \
92 "\n" \
93 " issuer_crt=%%s default: (empty)\n" \
94 " If issuer_crt is specified, issuer_name is\n" \
95 " ignored!\n" \
96 " issuer_name=%%s default: CN=CA,O=mbed TLS,C=UK\n" \
97 "\n" \
98 " selfsign=%%d default: 0 (false)\n" \
99 " If selfsign is enabled, issuer_name and\n" \
100 " issuer_key are required (issuer_crt and\n" \
101 " subject_* are ignored\n" \
102 " issuer_key=%%s default: ca.key\n" \
103 " issuer_pwd=%%s default: (empty)\n" \
104 " output_file=%%s default: cert.crt\n" \
105 " serial=%%s default: 1\n" \
106 " In decimal format; it can be used as\n" \
107 " alternative to serial_hex, but it's\n" \
108 " limited in max length to\n" \
109 " unsigned long long int\n" \
110 " serial_hex=%%s default: 1\n" \
111 " In hex format; it can be used as\n" \
112 " alternative to serial\n" \
113 " not_before=%%s default: 20010101000000\n" \
114 " not_after=%%s default: 20301231235959\n" \
115 " is_ca=%%d default: 0 (disabled)\n" \
116 " max_pathlen=%%d default: -1 (none)\n" \
117 " md=%%s default: SHA256\n" \
118 " Supported values (if enabled):\n" \
119 " MD5, RIPEMD160, SHA1,\n" \
120 " SHA224, SHA256, SHA384, SHA512\n" \
121 " version=%%d default: 3\n" \
122 " Possible values: 1, 2, 3\n" \
123 " subject_identifier=%%s default: 1\n" \
124 " Possible values: 0, 1\n" \
125 " (Considered for v3 only)\n" \
126 " san=%%s default: (none)\n" \
127 " Semicolon-separated-list of values:\n" \
128 " DNS:value\n" \
129 " URI:value\n" \
130 " RFC822:value\n" \
131 " IP:value (Only IPv4 is supported)\n" \
132 " DN:list of comma separated key=value pairs\n" \
133 " authority_identifier=%%s default: 1\n" \
134 " Possible values: 0, 1\n" \
135 " (Considered for v3 only)\n" \
136 " basic_constraints=%%d default: 1\n" \
137 " Possible values: 0, 1\n" \
138 " (Considered for v3 only)\n" \
139 " key_usage=%%s default: (empty)\n" \
140 " Comma-separated-list of values:\n" \
141 " digital_signature\n" \
142 " non_repudiation\n" \
143 " key_encipherment\n" \
144 " data_encipherment\n" \
145 " key_agreement\n" \
146 " key_cert_sign\n" \
147 " crl_sign\n" \
148 " (Considered for v3 only)\n" \
149 " ext_key_usage=%%s default: (empty)\n" \
150 " Comma-separated-list of values:\n" \
151 " serverAuth\n" \
152 " clientAuth\n" \
153 " codeSigning\n" \
154 " emailProtection\n" \
155 " timeStamping\n" \
156 " OCSPSigning\n" \
157 " ns_cert_type=%%s default: (empty)\n" \
158 " Comma-separated-list of values:\n" \
159 " ssl_client\n" \
160 " ssl_server\n" \
161 " email\n" \
162 " object_signing\n" \
163 " ssl_ca\n" \
164 " email_ca\n" \
165 " object_signing_ca\n" \
166 " format=pem|der default: pem\n" \
167 "\n"
168
169typedef enum {
170 SERIAL_FRMT_UNSPEC,
171 SERIAL_FRMT_DEC,
172 SERIAL_FRMT_HEX
173} serial_format_t;
174
175/*
176 * global options
177 */
178struct options {
179 const char *issuer_crt; /* filename of the issuer certificate */
180 const char *request_file; /* filename of the certificate request */
181 const char *subject_key; /* filename of the subject key file */
182 const char *issuer_key; /* filename of the issuer key file */
183 const char *subject_pwd; /* password for the subject key file */
184 const char *issuer_pwd; /* password for the issuer key file */
185 const char *output_file; /* where to store the constructed CRT */
186 const char *subject_name; /* subject name for certificate */
187 mbedtls_x509_san_list *san_list; /* subjectAltName for certificate */
188 const char *issuer_name; /* issuer name for certificate */
189 const char *not_before; /* validity period not before */
190 const char *not_after; /* validity period not after */
191 const char *serial; /* serial number string (decimal) */
192 const char *serial_hex; /* serial number string (hex) */
193 int selfsign; /* selfsign the certificate */
194 int is_ca; /* is a CA certificate */
195 int max_pathlen; /* maximum CA path length */
196 int authority_identifier; /* add authority identifier to CRT */
197 int subject_identifier; /* add subject identifier to CRT */
198 int basic_constraints; /* add basic constraints ext to CRT */
199 int version; /* CRT version */
200 mbedtls_md_type_t md; /* Hash used for signing */
201 unsigned char key_usage; /* key usage flags */
202 mbedtls_asn1_sequence *ext_key_usage; /* extended key usages */
203 unsigned char ns_cert_type; /* NS cert type */
204 int format; /* format */
205} opt;
206
207int write_certificate(mbedtls_x509write_cert *crt, const char *output_file,
208 int (*f_rng)(void *, unsigned char *, size_t),
209 void *p_rng)
210{
211 int ret;
212 FILE *f;
213 unsigned char output_buf[4096];
214 unsigned char *output_start;
215 size_t len = 0;
216
217 memset(output_buf, 0, 4096);
218 if (opt.format == FORMAT_DER) {
219 ret = mbedtls_x509write_crt_der(crt, output_buf, 4096,
220 f_rng, p_rng);
221 if (ret < 0) {
222 return ret;
223 }
224
225 len = ret;
226 output_start = output_buf + 4096 - len;
227 } else {
228 ret = mbedtls_x509write_crt_pem(crt, output_buf, 4096,
229 f_rng, p_rng);
230 if (ret < 0) {
231 return ret;
232 }
233
234 len = strlen((char *) output_buf);
235 output_start = output_buf;
236 }
237
238 if ((f = fopen(output_file, "w")) == NULL) {
239 return -1;
240 }
241
242 if (fwrite(output_start, 1, len, f) != len) {
243 fclose(f);
244 return -1;
245 }
246
247 fclose(f);
248
249 return 0;
250}
251
252int parse_serial_decimal_format(unsigned char *obuf, size_t obufmax,
253 const char *ibuf, size_t *len)
254{
255 unsigned long long int dec;
256 unsigned int remaining_bytes = sizeof(dec);
257 unsigned char *p = obuf;
258 unsigned char val;
259 char *end_ptr = NULL;
260
261 errno = 0;
262 dec = strtoull(ibuf, &end_ptr, 10);
263
264 if ((errno != 0) || (end_ptr == ibuf)) {
265 return -1;
266 }
267
268 *len = 0;
269
270 while (remaining_bytes > 0) {
271 if (obufmax < (*len + 1)) {
272 return -1;
273 }
274
275 val = (dec >> ((remaining_bytes - 1) * 8)) & 0xFF;
276
277 /* Skip leading zeros */
278 if ((val != 0) || (*len != 0)) {
279 *p = val;
280 (*len)++;
281 p++;
282 }
283
284 remaining_bytes--;
285 }
286
287 return 0;
288}
289
290int main(int argc, char *argv[])
291{
292 int ret = 1;
293 int exit_code = MBEDTLS_EXIT_FAILURE;
294 mbedtls_x509_crt issuer_crt;
295 mbedtls_pk_context loaded_issuer_key, loaded_subject_key;
296 mbedtls_pk_context *issuer_key = &loaded_issuer_key,
297 *subject_key = &loaded_subject_key;
298 char buf[1024];
299 char issuer_name[256];
300 int i;
301 char *p, *q, *r;
302#if defined(MBEDTLS_X509_CSR_PARSE_C)
303 char subject_name[256];
304 mbedtls_x509_csr csr;
305#endif
306 mbedtls_x509write_cert crt;
307 serial_format_t serial_frmt = SERIAL_FRMT_UNSPEC;
308 unsigned char serial[MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN];
309 size_t serial_len;
310 mbedtls_asn1_sequence *ext_key_usage;
311 mbedtls_entropy_context entropy;
312 mbedtls_ctr_drbg_context ctr_drbg;
313 const char *pers = "crt example app";
314 mbedtls_x509_san_list *cur, *prev;
315 mbedtls_asn1_named_data *ext_san_dirname = NULL;
316 uint8_t ip[4] = { 0 };
317 /*
318 * Set to sane values
319 */
320 mbedtls_x509write_crt_init(&crt);
321 mbedtls_pk_init(&loaded_issuer_key);
322 mbedtls_pk_init(&loaded_subject_key);
323 mbedtls_ctr_drbg_init(&ctr_drbg);
324 mbedtls_entropy_init(&entropy);
325#if defined(MBEDTLS_X509_CSR_PARSE_C)
326 mbedtls_x509_csr_init(&csr);
327#endif
328 mbedtls_x509_crt_init(&issuer_crt);
329 memset(buf, 0, sizeof(buf));
330 memset(serial, 0, sizeof(serial));
331
332#if defined(MBEDTLS_USE_PSA_CRYPTO)
333 psa_status_t status = psa_crypto_init();
334 if (status != PSA_SUCCESS) {
335 mbedtls_fprintf(stderr, "Failed to initialize PSA Crypto implementation: %d\n",
336 (int) status);
337 goto exit;
338 }
339#endif /* MBEDTLS_USE_PSA_CRYPTO */
340
341 if (argc < 2) {
342usage:
343 mbedtls_printf(USAGE);
344 goto exit;
345 }
346
347 opt.issuer_crt = DFL_ISSUER_CRT;
348 opt.request_file = DFL_REQUEST_FILE;
349 opt.subject_key = DFL_SUBJECT_KEY;
350 opt.issuer_key = DFL_ISSUER_KEY;
351 opt.subject_pwd = DFL_SUBJECT_PWD;
352 opt.issuer_pwd = DFL_ISSUER_PWD;
353 opt.output_file = DFL_OUTPUT_FILENAME;
354 opt.subject_name = DFL_SUBJECT_NAME;
355 opt.issuer_name = DFL_ISSUER_NAME;
356 opt.not_before = DFL_NOT_BEFORE;
357 opt.not_after = DFL_NOT_AFTER;
358 opt.serial = DFL_SERIAL;
359 opt.serial_hex = DFL_SERIAL_HEX;
360 opt.selfsign = DFL_SELFSIGN;
361 opt.is_ca = DFL_IS_CA;
362 opt.max_pathlen = DFL_MAX_PATHLEN;
363 opt.key_usage = DFL_KEY_USAGE;
364 opt.ext_key_usage = DFL_EXT_KEY_USAGE;
365 opt.ns_cert_type = DFL_NS_CERT_TYPE;
366 opt.version = DFL_VERSION - 1;
367 opt.md = DFL_DIGEST;
368 opt.subject_identifier = DFL_SUBJ_IDENT;
369 opt.authority_identifier = DFL_AUTH_IDENT;
370 opt.basic_constraints = DFL_CONSTRAINTS;
371 opt.format = DFL_FORMAT;
372 opt.san_list = NULL;
373
374 for (i = 1; i < argc; i++) {
375
376 p = argv[i];
377 if ((q = strchr(p, '=')) == NULL) {
378 goto usage;
379 }
380 *q++ = '\0';
381
382 if (strcmp(p, "request_file") == 0) {
383 opt.request_file = q;
384 } else if (strcmp(p, "subject_key") == 0) {
385 opt.subject_key = q;
386 } else if (strcmp(p, "issuer_key") == 0) {
387 opt.issuer_key = q;
388 } else if (strcmp(p, "subject_pwd") == 0) {
389 opt.subject_pwd = q;
390 } else if (strcmp(p, "issuer_pwd") == 0) {
391 opt.issuer_pwd = q;
392 } else if (strcmp(p, "issuer_crt") == 0) {
393 opt.issuer_crt = q;
394 } else if (strcmp(p, "output_file") == 0) {
395 opt.output_file = q;
396 } else if (strcmp(p, "subject_name") == 0) {
397 opt.subject_name = q;
398 } else if (strcmp(p, "issuer_name") == 0) {
399 opt.issuer_name = q;
400 } else if (strcmp(p, "not_before") == 0) {
401 opt.not_before = q;
402 } else if (strcmp(p, "not_after") == 0) {
403 opt.not_after = q;
404 } else if (strcmp(p, "serial") == 0) {
405 if (serial_frmt != SERIAL_FRMT_UNSPEC) {
406 mbedtls_printf("Invalid attempt to set the serial more than once\n");
407 goto usage;
408 }
409 serial_frmt = SERIAL_FRMT_DEC;
410 opt.serial = q;
411 } else if (strcmp(p, "serial_hex") == 0) {
412 if (serial_frmt != SERIAL_FRMT_UNSPEC) {
413 mbedtls_printf("Invalid attempt to set the serial more than once\n");
414 goto usage;
415 }
416 serial_frmt = SERIAL_FRMT_HEX;
417 opt.serial_hex = q;
418 } else if (strcmp(p, "authority_identifier") == 0) {
419 opt.authority_identifier = atoi(q);
420 if (opt.authority_identifier != 0 &&
421 opt.authority_identifier != 1) {
422 mbedtls_printf("Invalid argument for option %s\n", p);
423 goto usage;
424 }
425 } else if (strcmp(p, "subject_identifier") == 0) {
426 opt.subject_identifier = atoi(q);
427 if (opt.subject_identifier != 0 &&
428 opt.subject_identifier != 1) {
429 mbedtls_printf("Invalid argument for option %s\n", p);
430 goto usage;
431 }
432 } else if (strcmp(p, "basic_constraints") == 0) {
433 opt.basic_constraints = atoi(q);
434 if (opt.basic_constraints != 0 &&
435 opt.basic_constraints != 1) {
436 mbedtls_printf("Invalid argument for option %s\n", p);
437 goto usage;
438 }
439 } else if (strcmp(p, "md") == 0) {
440 const mbedtls_md_info_t *md_info =
441 mbedtls_md_info_from_string(q);
442 if (md_info == NULL) {
443 mbedtls_printf("Invalid argument for option %s\n", p);
444 goto usage;
445 }
446 opt.md = mbedtls_md_get_type(md_info);
447 } else if (strcmp(p, "version") == 0) {
448 opt.version = atoi(q);
449 if (opt.version < 1 || opt.version > 3) {
450 mbedtls_printf("Invalid argument for option %s\n", p);
451 goto usage;
452 }
453 opt.version--;
454 } else if (strcmp(p, "selfsign") == 0) {
455 opt.selfsign = atoi(q);
456 if (opt.selfsign < 0 || opt.selfsign > 1) {
457 mbedtls_printf("Invalid argument for option %s\n", p);
458 goto usage;
459 }
460 } else if (strcmp(p, "is_ca") == 0) {
461 opt.is_ca = atoi(q);
462 if (opt.is_ca < 0 || opt.is_ca > 1) {
463 mbedtls_printf("Invalid argument for option %s\n", p);
464 goto usage;
465 }
466 } else if (strcmp(p, "max_pathlen") == 0) {
467 opt.max_pathlen = atoi(q);
468 if (opt.max_pathlen < -1 || opt.max_pathlen > 127) {
469 mbedtls_printf("Invalid argument for option %s\n", p);
470 goto usage;
471 }
472 } else if (strcmp(p, "key_usage") == 0) {
473 while (q != NULL) {
474 if ((r = strchr(q, ',')) != NULL) {
475 *r++ = '\0';
476 }
477
478 if (strcmp(q, "digital_signature") == 0) {
479 opt.key_usage |= MBEDTLS_X509_KU_DIGITAL_SIGNATURE;
480 } else if (strcmp(q, "non_repudiation") == 0) {
481 opt.key_usage |= MBEDTLS_X509_KU_NON_REPUDIATION;
482 } else if (strcmp(q, "key_encipherment") == 0) {
483 opt.key_usage |= MBEDTLS_X509_KU_KEY_ENCIPHERMENT;
484 } else if (strcmp(q, "data_encipherment") == 0) {
485 opt.key_usage |= MBEDTLS_X509_KU_DATA_ENCIPHERMENT;
486 } else if (strcmp(q, "key_agreement") == 0) {
487 opt.key_usage |= MBEDTLS_X509_KU_KEY_AGREEMENT;
488 } else if (strcmp(q, "key_cert_sign") == 0) {
489 opt.key_usage |= MBEDTLS_X509_KU_KEY_CERT_SIGN;
490 } else if (strcmp(q, "crl_sign") == 0) {
491 opt.key_usage |= MBEDTLS_X509_KU_CRL_SIGN;
492 } else {
493 mbedtls_printf("Invalid argument for option %s\n", p);
494 goto usage;
495 }
496
497 q = r;
498 }
499 } else if (strcmp(p, "ext_key_usage") == 0) {
500 mbedtls_asn1_sequence **tail = &opt.ext_key_usage;
501
502 while (q != NULL) {
503 if ((r = strchr(q, ',')) != NULL) {
504 *r++ = '\0';
505 }
506
507 ext_key_usage = mbedtls_calloc(1, sizeof(mbedtls_asn1_sequence));
508 ext_key_usage->buf.tag = MBEDTLS_ASN1_OID;
509 if (strcmp(q, "serverAuth") == 0) {
510 SET_OID(ext_key_usage->buf, MBEDTLS_OID_SERVER_AUTH);
511 } else if (strcmp(q, "clientAuth") == 0) {
512 SET_OID(ext_key_usage->buf, MBEDTLS_OID_CLIENT_AUTH);
513 } else if (strcmp(q, "codeSigning") == 0) {
514 SET_OID(ext_key_usage->buf, MBEDTLS_OID_CODE_SIGNING);
515 } else if (strcmp(q, "emailProtection") == 0) {
516 SET_OID(ext_key_usage->buf, MBEDTLS_OID_EMAIL_PROTECTION);
517 } else if (strcmp(q, "timeStamping") == 0) {
518 SET_OID(ext_key_usage->buf, MBEDTLS_OID_TIME_STAMPING);
519 } else if (strcmp(q, "OCSPSigning") == 0) {
520 SET_OID(ext_key_usage->buf, MBEDTLS_OID_OCSP_SIGNING);
521 } else if (strcmp(q, "any") == 0) {
522 SET_OID(ext_key_usage->buf, MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE);
523 } else {
524 mbedtls_printf("Invalid argument for option %s\n", p);
525 goto usage;
526 }
527
528 *tail = ext_key_usage;
529 tail = &ext_key_usage->next;
530
531 q = r;
532 }
533 } else if (strcmp(p, "san") == 0) {
534 char *subtype_value;
535 prev = NULL;
536
537 while (q != NULL) {
538 char *semicolon;
539 r = q;
540
541 /* Find the first non-escaped ; occurrence and remove escaped ones */
542 do {
543 if ((semicolon = strchr(r, ';')) != NULL) {
544 if (*(semicolon-1) != '\\') {
545 r = semicolon;
546 break;
547 }
548 /* Remove the escape character */
549 size_t size_left = strlen(semicolon);
550 memmove(semicolon-1, semicolon, size_left);
551 *(semicolon + size_left - 1) = '\0';
552 /* r will now point at the character after the semicolon */
553 r = semicolon;
554 }
555
556 } while (semicolon != NULL);
557
558 if (semicolon != NULL) {
559 *r++ = '\0';
560 } else {
561 r = NULL;
562 }
563
564 cur = mbedtls_calloc(1, sizeof(mbedtls_x509_san_list));
565 if (cur == NULL) {
566 mbedtls_printf("Not enough memory for subjectAltName list\n");
567 goto usage;
568 }
569
570 cur->next = NULL;
571
572 if ((subtype_value = strchr(q, ':')) != NULL) {
573 *subtype_value++ = '\0';
574 } else {
575 mbedtls_printf(
576 "Invalid argument for option SAN: Entry must be of the form TYPE:value\n");
577 goto usage;
578 }
579 if (strcmp(q, "RFC822") == 0) {
580 cur->node.type = MBEDTLS_X509_SAN_RFC822_NAME;
581 } else if (strcmp(q, "URI") == 0) {
582 cur->node.type = MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER;
583 } else if (strcmp(q, "DNS") == 0) {
584 cur->node.type = MBEDTLS_X509_SAN_DNS_NAME;
585 } else if (strcmp(q, "IP") == 0) {
586 size_t ip_addr_len = 0;
587 cur->node.type = MBEDTLS_X509_SAN_IP_ADDRESS;
588 ip_addr_len = mbedtls_x509_crt_parse_cn_inet_pton(subtype_value, ip);
589 if (ip_addr_len == 0) {
590 mbedtls_printf("mbedtls_x509_crt_parse_cn_inet_pton failed to parse %s\n",
591 subtype_value);
592 goto exit;
593 }
594 cur->node.san.unstructured_name.p = (unsigned char *) ip;
595 cur->node.san.unstructured_name.len = sizeof(ip);
596 } else if (strcmp(q, "DN") == 0) {
597 cur->node.type = MBEDTLS_X509_SAN_DIRECTORY_NAME;
598 if ((ret = mbedtls_x509_string_to_names(&ext_san_dirname,
599 subtype_value)) != 0) {
600 mbedtls_strerror(ret, buf, sizeof(buf));
601 mbedtls_printf(
602 " failed\n ! mbedtls_x509_string_to_names "
603 "returned -0x%04x - %s\n\n",
604 (unsigned int) -ret, buf);
605 goto exit;
606 }
607 cur->node.san.directory_name = *ext_san_dirname;
608 } else {
609 mbedtls_free(cur);
610 goto usage;
611 }
612
613 if (cur->node.type == MBEDTLS_X509_SAN_RFC822_NAME ||
614 cur->node.type == MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER ||
615 cur->node.type == MBEDTLS_X509_SAN_DNS_NAME) {
616 q = subtype_value;
617 cur->node.san.unstructured_name.p = (unsigned char *) q;
618 cur->node.san.unstructured_name.len = strlen(q);
619 }
620
621 if (prev == NULL) {
622 opt.san_list = cur;
623 } else {
624 prev->next = cur;
625 }
626
627 prev = cur;
628 q = r;
629 }
630 } else if (strcmp(p, "ns_cert_type") == 0) {
631 while (q != NULL) {
632 if ((r = strchr(q, ',')) != NULL) {
633 *r++ = '\0';
634 }
635
636 if (strcmp(q, "ssl_client") == 0) {
637 opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT;
638 } else if (strcmp(q, "ssl_server") == 0) {
639 opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER;
640 } else if (strcmp(q, "email") == 0) {
641 opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_EMAIL;
642 } else if (strcmp(q, "object_signing") == 0) {
643 opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING;
644 } else if (strcmp(q, "ssl_ca") == 0) {
645 opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_SSL_CA;
646 } else if (strcmp(q, "email_ca") == 0) {
647 opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA;
648 } else if (strcmp(q, "object_signing_ca") == 0) {
649 opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA;
650 } else {
651 mbedtls_printf("Invalid argument for option %s\n", p);
652 goto usage;
653 }
654
655 q = r;
656 }
657 } else if (strcmp(p, "format") == 0) {
658 if (strcmp(q, "der") == 0) {
659 opt.format = FORMAT_DER;
660 } else if (strcmp(q, "pem") == 0) {
661 opt.format = FORMAT_PEM;
662 } else {
663 mbedtls_printf("Invalid argument for option %s\n", p);
664 goto usage;
665 }
666 } else {
667 goto usage;
668 }
669 }
670
671 mbedtls_printf("\n");
672
673 /*
674 * 0. Seed the PRNG
675 */
676 mbedtls_printf(" . Seeding the random number generator...");
677 fflush(stdout);
678
679 if ((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
680 (const unsigned char *) pers,
681 strlen(pers))) != 0) {
682 mbedtls_strerror(ret, buf, sizeof(buf));
683 mbedtls_printf(" failed\n ! mbedtls_ctr_drbg_seed returned %d - %s\n",
684 ret, buf);
685 goto exit;
686 }
687
688 mbedtls_printf(" ok\n");
689
690 // Parse serial to MPI
691 //
692 mbedtls_printf(" . Reading serial number...");
693 fflush(stdout);
694
695 if (serial_frmt == SERIAL_FRMT_HEX) {
696 ret = mbedtls_test_unhexify(serial, sizeof(serial),
697 opt.serial_hex, &serial_len);
698 } else { // SERIAL_FRMT_DEC || SERIAL_FRMT_UNSPEC
699 ret = parse_serial_decimal_format(serial, sizeof(serial),
700 opt.serial, &serial_len);
701 }
702
703 if (ret != 0) {
704 mbedtls_printf(" failed\n ! Unable to parse serial\n");
705 goto exit;
706 }
707
708 mbedtls_printf(" ok\n");
709
710 // Parse issuer certificate if present
711 //
712 if (!opt.selfsign && strlen(opt.issuer_crt)) {
713 /*
714 * 1.0.a. Load the certificates
715 */
716 mbedtls_printf(" . Loading the issuer certificate ...");
717 fflush(stdout);
718
719 if ((ret = mbedtls_x509_crt_parse_file(&issuer_crt, opt.issuer_crt)) != 0) {
720 mbedtls_strerror(ret, buf, sizeof(buf));
721 mbedtls_printf(" failed\n ! mbedtls_x509_crt_parse_file "
722 "returned -0x%04x - %s\n\n", (unsigned int) -ret, buf);
723 goto exit;
724 }
725
726 ret = mbedtls_x509_dn_gets(issuer_name, sizeof(issuer_name),
727 &issuer_crt.subject);
728 if (ret < 0) {
729 mbedtls_strerror(ret, buf, sizeof(buf));
730 mbedtls_printf(" failed\n ! mbedtls_x509_dn_gets "
731 "returned -0x%04x - %s\n\n", (unsigned int) -ret, buf);
732 goto exit;
733 }
734
735 opt.issuer_name = issuer_name;
736
737 mbedtls_printf(" ok\n");
738 }
739
740#if defined(MBEDTLS_X509_CSR_PARSE_C)
741 // Parse certificate request if present
742 //
743 if (!opt.selfsign && strlen(opt.request_file)) {
744 /*
745 * 1.0.b. Load the CSR
746 */
747 mbedtls_printf(" . Loading the certificate request ...");
748 fflush(stdout);
749
750 if ((ret = mbedtls_x509_csr_parse_file(&csr, opt.request_file)) != 0) {
751 mbedtls_strerror(ret, buf, sizeof(buf));
752 mbedtls_printf(" failed\n ! mbedtls_x509_csr_parse_file "
753 "returned -0x%04x - %s\n\n", (unsigned int) -ret, buf);
754 goto exit;
755 }
756
757 ret = mbedtls_x509_dn_gets(subject_name, sizeof(subject_name),
758 &csr.subject);
759 if (ret < 0) {
760 mbedtls_strerror(ret, buf, sizeof(buf));
761 mbedtls_printf(" failed\n ! mbedtls_x509_dn_gets "
762 "returned -0x%04x - %s\n\n", (unsigned int) -ret, buf);
763 goto exit;
764 }
765
766 opt.subject_name = subject_name;
767 subject_key = &csr.pk;
768
769 mbedtls_printf(" ok\n");
770 }
771#endif /* MBEDTLS_X509_CSR_PARSE_C */
772
773 /*
774 * 1.1. Load the keys
775 */
776 if (!opt.selfsign && !strlen(opt.request_file)) {
777 mbedtls_printf(" . Loading the subject key ...");
778 fflush(stdout);
779
780 ret = mbedtls_pk_parse_keyfile(&loaded_subject_key, opt.subject_key,
781 opt.subject_pwd, mbedtls_ctr_drbg_random, &ctr_drbg);
782 if (ret != 0) {
783 mbedtls_strerror(ret, buf, sizeof(buf));
784 mbedtls_printf(" failed\n ! mbedtls_pk_parse_keyfile "
785 "returned -0x%04x - %s\n\n", (unsigned int) -ret, buf);
786 goto exit;
787 }
788
789 mbedtls_printf(" ok\n");
790 }
791
792 mbedtls_printf(" . Loading the issuer key ...");
793 fflush(stdout);
794
795 ret = mbedtls_pk_parse_keyfile(&loaded_issuer_key, opt.issuer_key,
796 opt.issuer_pwd, mbedtls_ctr_drbg_random, &ctr_drbg);
797 if (ret != 0) {
798 mbedtls_strerror(ret, buf, sizeof(buf));
799 mbedtls_printf(" failed\n ! mbedtls_pk_parse_keyfile "
800 "returned -x%02x - %s\n\n", (unsigned int) -ret, buf);
801 goto exit;
802 }
803
804 // Check if key and issuer certificate match
805 //
806 if (strlen(opt.issuer_crt)) {
807 if (mbedtls_pk_check_pair(&issuer_crt.pk, issuer_key,
808 mbedtls_ctr_drbg_random, &ctr_drbg) != 0) {
809 mbedtls_printf(" failed\n ! issuer_key does not match "
810 "issuer certificate\n\n");
811 goto exit;
812 }
813 }
814
815 mbedtls_printf(" ok\n");
816
817 if (opt.selfsign) {
818 opt.subject_name = opt.issuer_name;
819 subject_key = issuer_key;
820 }
821
822 mbedtls_x509write_crt_set_subject_key(&crt, subject_key);
823 mbedtls_x509write_crt_set_issuer_key(&crt, issuer_key);
824
825 /*
826 * 1.0. Check the names for validity
827 */
828 if ((ret = mbedtls_x509write_crt_set_subject_name(&crt, opt.subject_name)) != 0) {
829 mbedtls_strerror(ret, buf, sizeof(buf));
830 mbedtls_printf(" failed\n ! mbedtls_x509write_crt_set_subject_name "
831 "returned -0x%04x - %s\n\n", (unsigned int) -ret, buf);
832 goto exit;
833 }
834
835 if ((ret = mbedtls_x509write_crt_set_issuer_name(&crt, opt.issuer_name)) != 0) {
836 mbedtls_strerror(ret, buf, sizeof(buf));
837 mbedtls_printf(" failed\n ! mbedtls_x509write_crt_set_issuer_name "
838 "returned -0x%04x - %s\n\n", (unsigned int) -ret, buf);
839 goto exit;
840 }
841
842 mbedtls_printf(" . Setting certificate values ...");
843 fflush(stdout);
844
845 mbedtls_x509write_crt_set_version(&crt, opt.version);
846 mbedtls_x509write_crt_set_md_alg(&crt, opt.md);
847
848 ret = mbedtls_x509write_crt_set_serial_raw(&crt, serial, serial_len);
849 if (ret != 0) {
850 mbedtls_strerror(ret, buf, sizeof(buf));
851 mbedtls_printf(" failed\n ! mbedtls_x509write_crt_set_serial_raw "
852 "returned -0x%04x - %s\n\n", (unsigned int) -ret, buf);
853 goto exit;
854 }
855
856 ret = mbedtls_x509write_crt_set_validity(&crt, opt.not_before, opt.not_after);
857 if (ret != 0) {
858 mbedtls_strerror(ret, buf, sizeof(buf));
859 mbedtls_printf(" failed\n ! mbedtls_x509write_crt_set_validity "
860 "returned -0x%04x - %s\n\n", (unsigned int) -ret, buf);
861 goto exit;
862 }
863
864 mbedtls_printf(" ok\n");
865
866 if (opt.version == MBEDTLS_X509_CRT_VERSION_3 &&
867 opt.basic_constraints != 0) {
868 mbedtls_printf(" . Adding the Basic Constraints extension ...");
869 fflush(stdout);
870
871 ret = mbedtls_x509write_crt_set_basic_constraints(&crt, opt.is_ca,
872 opt.max_pathlen);
873 if (ret != 0) {
874 mbedtls_strerror(ret, buf, sizeof(buf));
875 mbedtls_printf(" failed\n ! x509write_crt_set_basic_constraints "
876 "returned -0x%04x - %s\n\n", (unsigned int) -ret, buf);
877 goto exit;
878 }
879
880 mbedtls_printf(" ok\n");
881 }
882
883#if defined(MBEDTLS_MD_CAN_SHA1)
884 if (opt.version == MBEDTLS_X509_CRT_VERSION_3 &&
885 opt.subject_identifier != 0) {
886 mbedtls_printf(" . Adding the Subject Key Identifier ...");
887 fflush(stdout);
888
889 ret = mbedtls_x509write_crt_set_subject_key_identifier(&crt);
890 if (ret != 0) {
891 mbedtls_strerror(ret, buf, sizeof(buf));
892 mbedtls_printf(" failed\n ! mbedtls_x509write_crt_set_subject"
893 "_key_identifier returned -0x%04x - %s\n\n",
894 (unsigned int) -ret, buf);
895 goto exit;
896 }
897
898 mbedtls_printf(" ok\n");
899 }
900
901 if (opt.version == MBEDTLS_X509_CRT_VERSION_3 &&
902 opt.authority_identifier != 0) {
903 mbedtls_printf(" . Adding the Authority Key Identifier ...");
904 fflush(stdout);
905
906 ret = mbedtls_x509write_crt_set_authority_key_identifier(&crt);
907 if (ret != 0) {
908 mbedtls_strerror(ret, buf, sizeof(buf));
909 mbedtls_printf(" failed\n ! mbedtls_x509write_crt_set_authority_"
910 "key_identifier returned -0x%04x - %s\n\n",
911 (unsigned int) -ret, buf);
912 goto exit;
913 }
914
915 mbedtls_printf(" ok\n");
916 }
917#endif /* MBEDTLS_MD_CAN_SHA1 */
918
919 if (opt.version == MBEDTLS_X509_CRT_VERSION_3 &&
920 opt.key_usage != 0) {
921 mbedtls_printf(" . Adding the Key Usage extension ...");
922 fflush(stdout);
923
924 ret = mbedtls_x509write_crt_set_key_usage(&crt, opt.key_usage);
925 if (ret != 0) {
926 mbedtls_strerror(ret, buf, sizeof(buf));
927 mbedtls_printf(" failed\n ! mbedtls_x509write_crt_set_key_usage "
928 "returned -0x%04x - %s\n\n", (unsigned int) -ret, buf);
929 goto exit;
930 }
931
932 mbedtls_printf(" ok\n");
933 }
934
935 if (opt.san_list != NULL) {
936 ret = mbedtls_x509write_crt_set_subject_alternative_name(&crt, opt.san_list);
937
938 if (ret != 0) {
939 mbedtls_printf(
940 " failed\n ! mbedtls_x509write_crt_set_subject_alternative_name returned %d",
941 ret);
942 goto exit;
943 }
944 }
945
946 if (opt.ext_key_usage) {
947 mbedtls_printf(" . Adding the Extended Key Usage extension ...");
948 fflush(stdout);
949
950 ret = mbedtls_x509write_crt_set_ext_key_usage(&crt, opt.ext_key_usage);
951 if (ret != 0) {
952 mbedtls_strerror(ret, buf, sizeof(buf));
953 mbedtls_printf(
954 " failed\n ! mbedtls_x509write_crt_set_ext_key_usage returned -0x%02x - %s\n\n",
955 (unsigned int) -ret,
956 buf);
957 goto exit;
958 }
959
960 mbedtls_printf(" ok\n");
961 }
962
963 if (opt.version == MBEDTLS_X509_CRT_VERSION_3 &&
964 opt.ns_cert_type != 0) {
965 mbedtls_printf(" . Adding the NS Cert Type extension ...");
966 fflush(stdout);
967
968 ret = mbedtls_x509write_crt_set_ns_cert_type(&crt, opt.ns_cert_type);
969 if (ret != 0) {
970 mbedtls_strerror(ret, buf, sizeof(buf));
971 mbedtls_printf(" failed\n ! mbedtls_x509write_crt_set_ns_cert_type "
972 "returned -0x%04x - %s\n\n", (unsigned int) -ret, buf);
973 goto exit;
974 }
975
976 mbedtls_printf(" ok\n");
977 }
978
979 /*
980 * 1.2. Writing the certificate
981 */
982 mbedtls_printf(" . Writing the certificate...");
983 fflush(stdout);
984
985 if ((ret = write_certificate(&crt, opt.output_file,
986 mbedtls_ctr_drbg_random, &ctr_drbg)) != 0) {
987 mbedtls_strerror(ret, buf, sizeof(buf));
988 mbedtls_printf(" failed\n ! write_certificate -0x%04x - %s\n\n",
989 (unsigned int) -ret, buf);
990 goto exit;
991 }
992
993 mbedtls_printf(" ok\n");
994
995 exit_code = MBEDTLS_EXIT_SUCCESS;
996
997exit:
998#if defined(MBEDTLS_X509_CSR_PARSE_C)
999 mbedtls_x509_csr_free(&csr);
1000#endif /* MBEDTLS_X509_CSR_PARSE_C */
1001 mbedtls_asn1_free_named_data_list(&ext_san_dirname);
1002 mbedtls_x509_crt_free(&issuer_crt);
1003 mbedtls_x509write_crt_free(&crt);
1004 mbedtls_pk_free(&loaded_subject_key);
1005 mbedtls_pk_free(&loaded_issuer_key);
1006 mbedtls_ctr_drbg_free(&ctr_drbg);
1007 mbedtls_entropy_free(&entropy);
1008#if defined(MBEDTLS_USE_PSA_CRYPTO)
1009 mbedtls_psa_crypto_free();
1010#endif /* MBEDTLS_USE_PSA_CRYPTO */
1011
1012 mbedtls_exit(exit_code);
1013}
1014#endif /* MBEDTLS_X509_CRT_WRITE_C && MBEDTLS_X509_CRT_PARSE_C &&
1015 MBEDTLS_FS_IO && MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C &&
1016 MBEDTLS_ERROR_C && MBEDTLS_PEM_WRITE_C */