1 /*
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)
main(void)19 int 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
169 typedef enum {
170 SERIAL_FRMT_UNSPEC,
171 SERIAL_FRMT_DEC,
172 SERIAL_FRMT_HEX
173 } serial_format_t;
174
175 /*
176 * global options
177 */
178 struct 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
write_certificate(mbedtls_x509write_cert * crt,const char * output_file,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng)207 int 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
parse_serial_decimal_format(unsigned char * obuf,size_t obufmax,const char * ibuf,size_t * len)252 int 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
main(int argc,char * argv[])290 int 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) {
342 usage:
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 }
575 if (strcmp(q, "RFC822") == 0) {
576 cur->node.type = MBEDTLS_X509_SAN_RFC822_NAME;
577 } else if (strcmp(q, "URI") == 0) {
578 cur->node.type = MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER;
579 } else if (strcmp(q, "DNS") == 0) {
580 cur->node.type = MBEDTLS_X509_SAN_DNS_NAME;
581 } else if (strcmp(q, "IP") == 0) {
582 size_t ip_len = 0;
583 cur->node.type = MBEDTLS_X509_SAN_IP_ADDRESS;
584 ip_len = mbedtls_x509_crt_parse_cn_inet_pton(subtype_value, ip);
585 if (ip_len == 0) {
586 mbedtls_printf("mbedtls_x509_crt_parse_cn_inet_pton failed to parse %s\n",
587 subtype_value);
588 goto exit;
589 }
590 cur->node.san.unstructured_name.p = (unsigned char *) ip;
591 cur->node.san.unstructured_name.len = sizeof(ip);
592 } else if (strcmp(q, "DN") == 0) {
593 cur->node.type = MBEDTLS_X509_SAN_DIRECTORY_NAME;
594 if ((ret = mbedtls_x509_string_to_names(&ext_san_dirname,
595 subtype_value)) != 0) {
596 mbedtls_strerror(ret, buf, sizeof(buf));
597 mbedtls_printf(
598 " failed\n ! mbedtls_x509_string_to_names "
599 "returned -0x%04x - %s\n\n",
600 (unsigned int) -ret, buf);
601 goto exit;
602 }
603 cur->node.san.directory_name = *ext_san_dirname;
604 } else {
605 mbedtls_free(cur);
606 goto usage;
607 }
608
609 if (cur->node.type == MBEDTLS_X509_SAN_RFC822_NAME ||
610 cur->node.type == MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER ||
611 cur->node.type == MBEDTLS_X509_SAN_DNS_NAME) {
612 q = subtype_value;
613 cur->node.san.unstructured_name.p = (unsigned char *) q;
614 cur->node.san.unstructured_name.len = strlen(q);
615 }
616
617 if (prev == NULL) {
618 opt.san_list = cur;
619 } else {
620 prev->next = cur;
621 }
622
623 prev = cur;
624 q = r;
625 }
626 } else if (strcmp(p, "ns_cert_type") == 0) {
627 while (q != NULL) {
628 if ((r = strchr(q, ',')) != NULL) {
629 *r++ = '\0';
630 }
631
632 if (strcmp(q, "ssl_client") == 0) {
633 opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT;
634 } else if (strcmp(q, "ssl_server") == 0) {
635 opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER;
636 } else if (strcmp(q, "email") == 0) {
637 opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_EMAIL;
638 } else if (strcmp(q, "object_signing") == 0) {
639 opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING;
640 } else if (strcmp(q, "ssl_ca") == 0) {
641 opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_SSL_CA;
642 } else if (strcmp(q, "email_ca") == 0) {
643 opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA;
644 } else if (strcmp(q, "object_signing_ca") == 0) {
645 opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA;
646 } else {
647 mbedtls_printf("Invalid argument for option %s\n", p);
648 goto usage;
649 }
650
651 q = r;
652 }
653 } else if (strcmp(p, "format") == 0) {
654 if (strcmp(q, "der") == 0) {
655 opt.format = FORMAT_DER;
656 } else if (strcmp(q, "pem") == 0) {
657 opt.format = FORMAT_PEM;
658 } else {
659 mbedtls_printf("Invalid argument for option %s\n", p);
660 goto usage;
661 }
662 } else {
663 goto usage;
664 }
665 }
666
667 mbedtls_printf("\n");
668
669 /*
670 * 0. Seed the PRNG
671 */
672 mbedtls_printf(" . Seeding the random number generator...");
673 fflush(stdout);
674
675 if ((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
676 (const unsigned char *) pers,
677 strlen(pers))) != 0) {
678 mbedtls_strerror(ret, buf, sizeof(buf));
679 mbedtls_printf(" failed\n ! mbedtls_ctr_drbg_seed returned %d - %s\n",
680 ret, buf);
681 goto exit;
682 }
683
684 mbedtls_printf(" ok\n");
685
686 // Parse serial to MPI
687 //
688 mbedtls_printf(" . Reading serial number...");
689 fflush(stdout);
690
691 if (serial_frmt == SERIAL_FRMT_HEX) {
692 ret = mbedtls_test_unhexify(serial, sizeof(serial),
693 opt.serial_hex, &serial_len);
694 } else { // SERIAL_FRMT_DEC || SERIAL_FRMT_UNSPEC
695 ret = parse_serial_decimal_format(serial, sizeof(serial),
696 opt.serial, &serial_len);
697 }
698
699 if (ret != 0) {
700 mbedtls_printf(" failed\n ! Unable to parse serial\n");
701 goto exit;
702 }
703
704 mbedtls_printf(" ok\n");
705
706 // Parse issuer certificate if present
707 //
708 if (!opt.selfsign && strlen(opt.issuer_crt)) {
709 /*
710 * 1.0.a. Load the certificates
711 */
712 mbedtls_printf(" . Loading the issuer certificate ...");
713 fflush(stdout);
714
715 if ((ret = mbedtls_x509_crt_parse_file(&issuer_crt, opt.issuer_crt)) != 0) {
716 mbedtls_strerror(ret, buf, sizeof(buf));
717 mbedtls_printf(" failed\n ! mbedtls_x509_crt_parse_file "
718 "returned -0x%04x - %s\n\n", (unsigned int) -ret, buf);
719 goto exit;
720 }
721
722 ret = mbedtls_x509_dn_gets(issuer_name, sizeof(issuer_name),
723 &issuer_crt.subject);
724 if (ret < 0) {
725 mbedtls_strerror(ret, buf, sizeof(buf));
726 mbedtls_printf(" failed\n ! mbedtls_x509_dn_gets "
727 "returned -0x%04x - %s\n\n", (unsigned int) -ret, buf);
728 goto exit;
729 }
730
731 opt.issuer_name = issuer_name;
732
733 mbedtls_printf(" ok\n");
734 }
735
736 #if defined(MBEDTLS_X509_CSR_PARSE_C)
737 // Parse certificate request if present
738 //
739 if (!opt.selfsign && strlen(opt.request_file)) {
740 /*
741 * 1.0.b. Load the CSR
742 */
743 mbedtls_printf(" . Loading the certificate request ...");
744 fflush(stdout);
745
746 if ((ret = mbedtls_x509_csr_parse_file(&csr, opt.request_file)) != 0) {
747 mbedtls_strerror(ret, buf, sizeof(buf));
748 mbedtls_printf(" failed\n ! mbedtls_x509_csr_parse_file "
749 "returned -0x%04x - %s\n\n", (unsigned int) -ret, buf);
750 goto exit;
751 }
752
753 ret = mbedtls_x509_dn_gets(subject_name, sizeof(subject_name),
754 &csr.subject);
755 if (ret < 0) {
756 mbedtls_strerror(ret, buf, sizeof(buf));
757 mbedtls_printf(" failed\n ! mbedtls_x509_dn_gets "
758 "returned -0x%04x - %s\n\n", (unsigned int) -ret, buf);
759 goto exit;
760 }
761
762 opt.subject_name = subject_name;
763 subject_key = &csr.pk;
764
765 mbedtls_printf(" ok\n");
766 }
767 #endif /* MBEDTLS_X509_CSR_PARSE_C */
768
769 /*
770 * 1.1. Load the keys
771 */
772 if (!opt.selfsign && !strlen(opt.request_file)) {
773 mbedtls_printf(" . Loading the subject key ...");
774 fflush(stdout);
775
776 ret = mbedtls_pk_parse_keyfile(&loaded_subject_key, opt.subject_key,
777 opt.subject_pwd, mbedtls_ctr_drbg_random, &ctr_drbg);
778 if (ret != 0) {
779 mbedtls_strerror(ret, buf, sizeof(buf));
780 mbedtls_printf(" failed\n ! mbedtls_pk_parse_keyfile "
781 "returned -0x%04x - %s\n\n", (unsigned int) -ret, buf);
782 goto exit;
783 }
784
785 mbedtls_printf(" ok\n");
786 }
787
788 mbedtls_printf(" . Loading the issuer key ...");
789 fflush(stdout);
790
791 ret = mbedtls_pk_parse_keyfile(&loaded_issuer_key, opt.issuer_key,
792 opt.issuer_pwd, mbedtls_ctr_drbg_random, &ctr_drbg);
793 if (ret != 0) {
794 mbedtls_strerror(ret, buf, sizeof(buf));
795 mbedtls_printf(" failed\n ! mbedtls_pk_parse_keyfile "
796 "returned -x%02x - %s\n\n", (unsigned int) -ret, buf);
797 goto exit;
798 }
799
800 // Check if key and issuer certificate match
801 //
802 if (strlen(opt.issuer_crt)) {
803 if (mbedtls_pk_check_pair(&issuer_crt.pk, issuer_key,
804 mbedtls_ctr_drbg_random, &ctr_drbg) != 0) {
805 mbedtls_printf(" failed\n ! issuer_key does not match "
806 "issuer certificate\n\n");
807 goto exit;
808 }
809 }
810
811 mbedtls_printf(" ok\n");
812
813 if (opt.selfsign) {
814 opt.subject_name = opt.issuer_name;
815 subject_key = issuer_key;
816 }
817
818 mbedtls_x509write_crt_set_subject_key(&crt, subject_key);
819 mbedtls_x509write_crt_set_issuer_key(&crt, issuer_key);
820
821 /*
822 * 1.0. Check the names for validity
823 */
824 if ((ret = mbedtls_x509write_crt_set_subject_name(&crt, opt.subject_name)) != 0) {
825 mbedtls_strerror(ret, buf, sizeof(buf));
826 mbedtls_printf(" failed\n ! mbedtls_x509write_crt_set_subject_name "
827 "returned -0x%04x - %s\n\n", (unsigned int) -ret, buf);
828 goto exit;
829 }
830
831 if ((ret = mbedtls_x509write_crt_set_issuer_name(&crt, opt.issuer_name)) != 0) {
832 mbedtls_strerror(ret, buf, sizeof(buf));
833 mbedtls_printf(" failed\n ! mbedtls_x509write_crt_set_issuer_name "
834 "returned -0x%04x - %s\n\n", (unsigned int) -ret, buf);
835 goto exit;
836 }
837
838 mbedtls_printf(" . Setting certificate values ...");
839 fflush(stdout);
840
841 mbedtls_x509write_crt_set_version(&crt, opt.version);
842 mbedtls_x509write_crt_set_md_alg(&crt, opt.md);
843
844 ret = mbedtls_x509write_crt_set_serial_raw(&crt, serial, serial_len);
845 if (ret != 0) {
846 mbedtls_strerror(ret, buf, sizeof(buf));
847 mbedtls_printf(" failed\n ! mbedtls_x509write_crt_set_serial_raw "
848 "returned -0x%04x - %s\n\n", (unsigned int) -ret, buf);
849 goto exit;
850 }
851
852 ret = mbedtls_x509write_crt_set_validity(&crt, opt.not_before, opt.not_after);
853 if (ret != 0) {
854 mbedtls_strerror(ret, buf, sizeof(buf));
855 mbedtls_printf(" failed\n ! mbedtls_x509write_crt_set_validity "
856 "returned -0x%04x - %s\n\n", (unsigned int) -ret, buf);
857 goto exit;
858 }
859
860 mbedtls_printf(" ok\n");
861
862 if (opt.version == MBEDTLS_X509_CRT_VERSION_3 &&
863 opt.basic_constraints != 0) {
864 mbedtls_printf(" . Adding the Basic Constraints extension ...");
865 fflush(stdout);
866
867 ret = mbedtls_x509write_crt_set_basic_constraints(&crt, opt.is_ca,
868 opt.max_pathlen);
869 if (ret != 0) {
870 mbedtls_strerror(ret, buf, sizeof(buf));
871 mbedtls_printf(" failed\n ! x509write_crt_set_basic_constraints "
872 "returned -0x%04x - %s\n\n", (unsigned int) -ret, buf);
873 goto exit;
874 }
875
876 mbedtls_printf(" ok\n");
877 }
878
879 #if defined(MBEDTLS_MD_CAN_SHA1)
880 if (opt.version == MBEDTLS_X509_CRT_VERSION_3 &&
881 opt.subject_identifier != 0) {
882 mbedtls_printf(" . Adding the Subject Key Identifier ...");
883 fflush(stdout);
884
885 ret = mbedtls_x509write_crt_set_subject_key_identifier(&crt);
886 if (ret != 0) {
887 mbedtls_strerror(ret, buf, sizeof(buf));
888 mbedtls_printf(" failed\n ! mbedtls_x509write_crt_set_subject"
889 "_key_identifier returned -0x%04x - %s\n\n",
890 (unsigned int) -ret, buf);
891 goto exit;
892 }
893
894 mbedtls_printf(" ok\n");
895 }
896
897 if (opt.version == MBEDTLS_X509_CRT_VERSION_3 &&
898 opt.authority_identifier != 0) {
899 mbedtls_printf(" . Adding the Authority Key Identifier ...");
900 fflush(stdout);
901
902 ret = mbedtls_x509write_crt_set_authority_key_identifier(&crt);
903 if (ret != 0) {
904 mbedtls_strerror(ret, buf, sizeof(buf));
905 mbedtls_printf(" failed\n ! mbedtls_x509write_crt_set_authority_"
906 "key_identifier returned -0x%04x - %s\n\n",
907 (unsigned int) -ret, buf);
908 goto exit;
909 }
910
911 mbedtls_printf(" ok\n");
912 }
913 #endif /* MBEDTLS_MD_CAN_SHA1 */
914
915 if (opt.version == MBEDTLS_X509_CRT_VERSION_3 &&
916 opt.key_usage != 0) {
917 mbedtls_printf(" . Adding the Key Usage extension ...");
918 fflush(stdout);
919
920 ret = mbedtls_x509write_crt_set_key_usage(&crt, opt.key_usage);
921 if (ret != 0) {
922 mbedtls_strerror(ret, buf, sizeof(buf));
923 mbedtls_printf(" failed\n ! mbedtls_x509write_crt_set_key_usage "
924 "returned -0x%04x - %s\n\n", (unsigned int) -ret, buf);
925 goto exit;
926 }
927
928 mbedtls_printf(" ok\n");
929 }
930
931 if (opt.san_list != NULL) {
932 ret = mbedtls_x509write_crt_set_subject_alternative_name(&crt, opt.san_list);
933
934 if (ret != 0) {
935 mbedtls_printf(
936 " failed\n ! mbedtls_x509write_crt_set_subject_alternative_name returned %d",
937 ret);
938 goto exit;
939 }
940 }
941
942 if (opt.ext_key_usage) {
943 mbedtls_printf(" . Adding the Extended Key Usage extension ...");
944 fflush(stdout);
945
946 ret = mbedtls_x509write_crt_set_ext_key_usage(&crt, opt.ext_key_usage);
947 if (ret != 0) {
948 mbedtls_strerror(ret, buf, sizeof(buf));
949 mbedtls_printf(
950 " failed\n ! mbedtls_x509write_crt_set_ext_key_usage returned -0x%02x - %s\n\n",
951 (unsigned int) -ret,
952 buf);
953 goto exit;
954 }
955
956 mbedtls_printf(" ok\n");
957 }
958
959 if (opt.version == MBEDTLS_X509_CRT_VERSION_3 &&
960 opt.ns_cert_type != 0) {
961 mbedtls_printf(" . Adding the NS Cert Type extension ...");
962 fflush(stdout);
963
964 ret = mbedtls_x509write_crt_set_ns_cert_type(&crt, opt.ns_cert_type);
965 if (ret != 0) {
966 mbedtls_strerror(ret, buf, sizeof(buf));
967 mbedtls_printf(" failed\n ! mbedtls_x509write_crt_set_ns_cert_type "
968 "returned -0x%04x - %s\n\n", (unsigned int) -ret, buf);
969 goto exit;
970 }
971
972 mbedtls_printf(" ok\n");
973 }
974
975 /*
976 * 1.2. Writing the certificate
977 */
978 mbedtls_printf(" . Writing the certificate...");
979 fflush(stdout);
980
981 if ((ret = write_certificate(&crt, opt.output_file,
982 mbedtls_ctr_drbg_random, &ctr_drbg)) != 0) {
983 mbedtls_strerror(ret, buf, sizeof(buf));
984 mbedtls_printf(" failed\n ! write_certificate -0x%04x - %s\n\n",
985 (unsigned int) -ret, buf);
986 goto exit;
987 }
988
989 mbedtls_printf(" ok\n");
990
991 exit_code = MBEDTLS_EXIT_SUCCESS;
992
993 exit:
994 #if defined(MBEDTLS_X509_CSR_PARSE_C)
995 mbedtls_x509_csr_free(&csr);
996 #endif /* MBEDTLS_X509_CSR_PARSE_C */
997 mbedtls_asn1_free_named_data_list(&ext_san_dirname);
998 mbedtls_x509_crt_free(&issuer_crt);
999 mbedtls_x509write_crt_free(&crt);
1000 mbedtls_pk_free(&loaded_subject_key);
1001 mbedtls_pk_free(&loaded_issuer_key);
1002 mbedtls_ctr_drbg_free(&ctr_drbg);
1003 mbedtls_entropy_free(&entropy);
1004 #if defined(MBEDTLS_USE_PSA_CRYPTO)
1005 mbedtls_psa_crypto_free();
1006 #endif /* MBEDTLS_USE_PSA_CRYPTO */
1007
1008 mbedtls_exit(exit_code);
1009 }
1010 #endif /* MBEDTLS_X509_CRT_WRITE_C && MBEDTLS_X509_CRT_PARSE_C &&
1011 MBEDTLS_FS_IO && MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C &&
1012 MBEDTLS_ERROR_C && MBEDTLS_PEM_WRITE_C */
1013