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