blob: 7d6885877df6ff6123655591f00b7c7cbb1665de [file] [log] [blame]
Paul Bakker9397dcb2013-09-06 09:55:26 +02001/*
2 * Certificate generation and signing
3 *
Manuel Pégourié-Gonnarda658a402015-01-23 09:45:19 +00004 * Copyright (C) 2006-2013, ARM Limited, All Rights Reserved
Paul Bakker9397dcb2013-09-06 09:55:26 +02005 *
Manuel Pégourié-Gonnard860b5162015-01-28 17:12:07 +00006 * This file is part of mbed TLS (https://polarssl.org)
Paul Bakker9397dcb2013-09-06 09:55:26 +02007 *
Paul Bakker9397dcb2013-09-06 09:55:26 +02008 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020023#if !defined(POLARSSL_CONFIG_FILE)
Manuel Pégourié-Gonnardabd6e022013-09-20 13:30:43 +020024#include "polarssl/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020025#else
26#include POLARSSL_CONFIG_FILE
27#endif
Paul Bakker9397dcb2013-09-06 09:55:26 +020028
Rich Evansf90016a2015-01-19 14:26:37 +000029#if defined(POLARSSL_PLATFORM_C)
30#include "polarssl/platform.h"
31#else
32#define polarssl_printf printf
Rich Evansf90016a2015-01-19 14:26:37 +000033#endif
34
Paul Bakker9397dcb2013-09-06 09:55:26 +020035#include <string.h>
36#include <stdlib.h>
37#include <stdio.h>
38
Paul Bakker7c6b2c32013-09-16 13:49:26 +020039#if !defined(POLARSSL_X509_CRT_WRITE_C) || \
40 !defined(POLARSSL_X509_CRT_PARSE_C) || !defined(POLARSSL_FS_IO) || \
Manuel Pégourié-Gonnard31e59402013-09-12 05:59:05 +020041 !defined(POLARSSL_ENTROPY_C) || !defined(POLARSSL_CTR_DRBG_C) || \
Paul Bakker4122f3e2013-09-09 16:01:46 +020042 !defined(POLARSSL_ERROR_C)
Paul Bakker9397dcb2013-09-06 09:55:26 +020043int main( int argc, char *argv[] )
44{
45 ((void) argc);
46 ((void) argv);
47
Rich Evansf90016a2015-01-19 14:26:37 +000048 polarssl_printf( "POLARSSL_X509_CRT_WRITE_C and/or POLARSSL_X509_CRT_PARSE_C and/or "
Manuel Pégourié-Gonnard31e59402013-09-12 05:59:05 +020049 "POLARSSL_FS_IO and/or "
50 "POLARSSL_ENTROPY_C and/or POLARSSL_CTR_DRBG_C and/or "
51 "POLARSSL_ERROR_C not defined.\n");
Paul Bakker9397dcb2013-09-06 09:55:26 +020052 return( 0 );
53}
54#else
55
Manuel Pégourié-Gonnard7831b0c2013-09-20 12:29:56 +020056#include "polarssl/x509_crt.h"
57#include "polarssl/x509_csr.h"
58#include "polarssl/entropy.h"
59#include "polarssl/ctr_drbg.h"
60#include "polarssl/error.h"
61
Paul Bakker1014e952013-09-09 13:59:42 +020062#define DFL_ISSUER_CRT ""
Paul Bakkere2673fb2013-09-09 15:52:07 +020063#define DFL_REQUEST_FILE ""
Paul Bakker9397dcb2013-09-06 09:55:26 +020064#define DFL_SUBJECT_KEY "subject.key"
65#define DFL_ISSUER_KEY "ca.key"
66#define DFL_SUBJECT_PWD ""
67#define DFL_ISSUER_PWD ""
68#define DFL_OUTPUT_FILENAME "cert.crt"
Manuel Pégourié-Gonnard91699212015-01-22 16:26:39 +000069#define DFL_SUBJECT_NAME "CN=Cert,O=mbed TLS,C=UK"
70#define DFL_ISSUER_NAME "CN=CA,O=mbed TLS,C=UK"
Paul Bakker9397dcb2013-09-06 09:55:26 +020071#define DFL_NOT_BEFORE "20010101000000"
72#define DFL_NOT_AFTER "20301231235959"
73#define DFL_SERIAL "1"
Paul Bakkerb2d7f232013-09-09 16:24:18 +020074#define DFL_SELFSIGN 0
Paul Bakker15162a02013-09-06 19:27:21 +020075#define DFL_IS_CA 0
76#define DFL_MAX_PATHLEN -1
Paul Bakker9397dcb2013-09-06 09:55:26 +020077#define DFL_KEY_USAGE 0
78#define DFL_NS_CERT_TYPE 0
79
80/*
81 * global options
82 */
83struct options
84{
Paul Bakker8fc30b12013-11-25 13:29:43 +010085 const char *issuer_crt; /* filename of the issuer certificate */
86 const char *request_file; /* filename of the certificate request */
87 const char *subject_key; /* filename of the subject key file */
88 const char *issuer_key; /* filename of the issuer key file */
89 const char *subject_pwd; /* password for the subject key file */
90 const char *issuer_pwd; /* password for the issuer key file */
91 const char *output_file; /* where to store the constructed key file */
92 const char *subject_name; /* subject name for certificate */
93 const char *issuer_name; /* issuer name for certificate */
94 const char *not_before; /* validity period not before */
95 const char *not_after; /* validity period not after */
96 const char *serial; /* serial number string */
Paul Bakkerb2d7f232013-09-09 16:24:18 +020097 int selfsign; /* selfsign the certificate */
Paul Bakker15162a02013-09-06 19:27:21 +020098 int is_ca; /* is a CA certificate */
99 int max_pathlen; /* maximum CA path length */
Paul Bakker9397dcb2013-09-06 09:55:26 +0200100 unsigned char key_usage; /* key usage flags */
101 unsigned char ns_cert_type; /* NS cert type */
102} opt;
103
Paul Bakker8fc30b12013-11-25 13:29:43 +0100104int write_certificate( x509write_cert *crt, const char *output_file,
Manuel Pégourié-Gonnard31e59402013-09-12 05:59:05 +0200105 int (*f_rng)(void *, unsigned char *, size_t),
106 void *p_rng )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200107{
108 int ret;
109 FILE *f;
110 unsigned char output_buf[4096];
111 size_t len = 0;
112
113 memset( output_buf, 0, 4096 );
Manuel Pégourié-Gonnard31e59402013-09-12 05:59:05 +0200114 if( ( ret = x509write_crt_pem( crt, output_buf, 4096, f_rng, p_rng ) ) < 0 )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200115 return( ret );
116
117 len = strlen( (char *) output_buf );
118
119 if( ( f = fopen( output_file, "w" ) ) == NULL )
120 return( -1 );
121
122 if( fwrite( output_buf, 1, len, f ) != len )
Paul Bakker0c226102014-04-17 16:02:36 +0200123 {
124 fclose( f );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200125 return( -1 );
Paul Bakker0c226102014-04-17 16:02:36 +0200126 }
Paul Bakker9397dcb2013-09-06 09:55:26 +0200127
Paul Bakker0c226102014-04-17 16:02:36 +0200128 fclose( f );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200129
130 return( 0 );
131}
132
Paul Bakker7fc7fa62013-09-17 14:44:00 +0200133#if defined(POLARSSL_X509_CSR_PARSE_C)
134#define USAGE_CSR \
135 " request_file=%%s default: (empty)\n" \
136 " If request_file is specified, subject_key,\n" \
137 " subject_pwd and subject_name are ignored!\n"
138#else
139#define USAGE_CSR ""
140#endif /* POLARSSL_X509_CSR_PARSE_C */
141
Paul Bakker9397dcb2013-09-06 09:55:26 +0200142#define USAGE \
143 "\n usage: cert_write param=<>...\n" \
144 "\n acceptable parameters:\n" \
Paul Bakker7fc7fa62013-09-17 14:44:00 +0200145 USAGE_CSR \
Paul Bakker9397dcb2013-09-06 09:55:26 +0200146 " subject_key=%%s default: subject.key\n" \
147 " subject_pwd=%%s default: (empty)\n" \
Manuel Pégourié-Gonnard91699212015-01-22 16:26:39 +0000148 " subject_name=%%s default: CN=Cert,O=mbed TLS,C=UK\n" \
Paul Bakkerb2d7f232013-09-09 16:24:18 +0200149 "\n" \
Paul Bakker1014e952013-09-09 13:59:42 +0200150 " issuer_crt=%%s default: (empty)\n" \
151 " If issuer_crt is specified, issuer_name is\n" \
152 " ignored!\n" \
Manuel Pégourié-Gonnard91699212015-01-22 16:26:39 +0000153 " issuer_name=%%s default: CN=CA,O=mbed TLS,C=UK\n" \
Paul Bakkerb2d7f232013-09-09 16:24:18 +0200154 "\n" \
155 " selfsign=%%d default: 0 (false)\n" \
156 " If selfsign is enabled, issuer_name and\n" \
157 " issuer_key are required (issuer_crt and\n" \
158 " subject_* are ignored\n" \
Paul Bakker9397dcb2013-09-06 09:55:26 +0200159 " issuer_key=%%s default: ca.key\n" \
160 " issuer_pwd=%%s default: (empty)\n" \
161 " output_file=%%s default: cert.crt\n" \
Paul Bakker9397dcb2013-09-06 09:55:26 +0200162 " serial=%%s default: 1\n" \
163 " not_before=%%s default: 20010101000000\n"\
164 " not_after=%%s default: 20301231235959\n"\
Paul Bakker15162a02013-09-06 19:27:21 +0200165 " is_ca=%%d default: 0 (disabled)\n" \
166 " max_pathlen=%%d default: -1 (none)\n" \
Paul Bakker9397dcb2013-09-06 09:55:26 +0200167 " key_usage=%%s default: (empty)\n" \
168 " Comma-separated-list of values:\n" \
169 " digital_signature\n" \
170 " non_repudiation\n" \
171 " key_encipherment\n" \
172 " data_encipherment\n" \
173 " key_agreement\n" \
174 " key_certificate_sign\n" \
175 " crl_sign\n" \
176 " ns_cert_type=%%s default: (empty)\n" \
177 " Comma-separated-list of values:\n" \
178 " ssl_client\n" \
179 " ssl_server\n" \
180 " email\n" \
181 " object_signing\n" \
182 " ssl_ca\n" \
183 " email_ca\n" \
184 " object_signing_ca\n" \
185 "\n"
186
187int main( int argc, char *argv[] )
188{
189 int ret = 0;
Paul Bakkerc559c7a2013-09-18 14:13:26 +0200190 x509_crt issuer_crt;
Manuel Pégourié-Gonnardf38e71a2013-09-12 05:21:54 +0200191 pk_context loaded_issuer_key, loaded_subject_key;
192 pk_context *issuer_key = &loaded_issuer_key,
193 *subject_key = &loaded_subject_key;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200194 char buf[1024];
Paul Bakkere2673fb2013-09-09 15:52:07 +0200195 char issuer_name[128];
Paul Bakkerc97f9f62013-11-30 15:13:02 +0100196 int i;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200197 char *p, *q, *r;
Paul Bakker7fc7fa62013-09-17 14:44:00 +0200198#if defined(POLARSSL_X509_CSR_PARSE_C)
199 char subject_name[128];
Paul Bakkere2673fb2013-09-09 15:52:07 +0200200 x509_csr csr;
Paul Bakker7fc7fa62013-09-17 14:44:00 +0200201#endif
Paul Bakker9397dcb2013-09-06 09:55:26 +0200202 x509write_cert crt;
203 mpi serial;
Manuel Pégourié-Gonnard31e59402013-09-12 05:59:05 +0200204 entropy_context entropy;
205 ctr_drbg_context ctr_drbg;
206 const char *pers = "crt example app";
Paul Bakker9397dcb2013-09-06 09:55:26 +0200207
208 /*
209 * Set to sane values
210 */
211 x509write_crt_init( &crt );
Manuel Pégourié-Gonnard6f60cd82015-02-10 10:47:03 +0000212 x509write_crt_set_md_alg( &crt, POLARSSL_MD_SHA256 );
Manuel Pégourié-Gonnardf38e71a2013-09-12 05:21:54 +0200213 pk_init( &loaded_issuer_key );
214 pk_init( &loaded_subject_key );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200215 mpi_init( &serial );
Paul Bakker7fc7fa62013-09-17 14:44:00 +0200216#if defined(POLARSSL_X509_CSR_PARSE_C)
Paul Bakker369d2eb2013-09-18 11:58:25 +0200217 x509_csr_init( &csr );
Paul Bakker7fc7fa62013-09-17 14:44:00 +0200218#endif
Paul Bakker369d2eb2013-09-18 11:58:25 +0200219 x509_crt_init( &issuer_crt );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200220 memset( buf, 0, 1024 );
221
222 if( argc == 0 )
223 {
224 usage:
Rich Evansf90016a2015-01-19 14:26:37 +0000225 polarssl_printf( USAGE );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200226 ret = 1;
227 goto exit;
228 }
229
Paul Bakker1014e952013-09-09 13:59:42 +0200230 opt.issuer_crt = DFL_ISSUER_CRT;
Paul Bakkere2673fb2013-09-09 15:52:07 +0200231 opt.request_file = DFL_REQUEST_FILE;
232 opt.request_file = DFL_REQUEST_FILE;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200233 opt.subject_key = DFL_SUBJECT_KEY;
234 opt.issuer_key = DFL_ISSUER_KEY;
235 opt.subject_pwd = DFL_SUBJECT_PWD;
236 opt.issuer_pwd = DFL_ISSUER_PWD;
237 opt.output_file = DFL_OUTPUT_FILENAME;
238 opt.subject_name = DFL_SUBJECT_NAME;
239 opt.issuer_name = DFL_ISSUER_NAME;
240 opt.not_before = DFL_NOT_BEFORE;
241 opt.not_after = DFL_NOT_AFTER;
242 opt.serial = DFL_SERIAL;
Paul Bakkerb2d7f232013-09-09 16:24:18 +0200243 opt.selfsign = DFL_SELFSIGN;
Paul Bakker15162a02013-09-06 19:27:21 +0200244 opt.is_ca = DFL_IS_CA;
245 opt.max_pathlen = DFL_MAX_PATHLEN;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200246 opt.key_usage = DFL_KEY_USAGE;
247 opt.ns_cert_type = DFL_NS_CERT_TYPE;
248
249 for( i = 1; i < argc; i++ )
250 {
251
252 p = argv[i];
253 if( ( q = strchr( p, '=' ) ) == NULL )
254 goto usage;
255 *q++ = '\0';
256
Paul Bakkere2673fb2013-09-09 15:52:07 +0200257 if( strcmp( p, "request_file" ) == 0 )
258 opt.request_file = q;
259 else if( strcmp( p, "subject_key" ) == 0 )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200260 opt.subject_key = q;
261 else if( strcmp( p, "issuer_key" ) == 0 )
262 opt.issuer_key = q;
263 else if( strcmp( p, "subject_pwd" ) == 0 )
264 opt.subject_pwd = q;
265 else if( strcmp( p, "issuer_pwd" ) == 0 )
266 opt.issuer_pwd = q;
Paul Bakker1014e952013-09-09 13:59:42 +0200267 else if( strcmp( p, "issuer_crt" ) == 0 )
268 opt.issuer_crt = q;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200269 else if( strcmp( p, "output_file" ) == 0 )
270 opt.output_file = q;
271 else if( strcmp( p, "subject_name" ) == 0 )
272 {
273 opt.subject_name = q;
274 }
275 else if( strcmp( p, "issuer_name" ) == 0 )
276 {
277 opt.issuer_name = q;
278 }
279 else if( strcmp( p, "not_before" ) == 0 )
280 {
281 opt.not_before = q;
282 }
283 else if( strcmp( p, "not_after" ) == 0 )
284 {
285 opt.not_after = q;
286 }
287 else if( strcmp( p, "serial" ) == 0 )
288 {
289 opt.serial = q;
290 }
Paul Bakkerb2d7f232013-09-09 16:24:18 +0200291 else if( strcmp( p, "selfsign" ) == 0 )
292 {
293 opt.selfsign = atoi( q );
294 if( opt.selfsign < 0 || opt.selfsign > 1 )
295 goto usage;
296 }
Paul Bakker15162a02013-09-06 19:27:21 +0200297 else if( strcmp( p, "is_ca" ) == 0 )
298 {
299 opt.is_ca = atoi( q );
300 if( opt.is_ca < 0 || opt.is_ca > 1 )
301 goto usage;
302 }
303 else if( strcmp( p, "max_pathlen" ) == 0 )
304 {
305 opt.max_pathlen = atoi( q );
306 if( opt.max_pathlen < -1 || opt.max_pathlen > 127 )
307 goto usage;
308 }
Paul Bakker9397dcb2013-09-06 09:55:26 +0200309 else if( strcmp( p, "key_usage" ) == 0 )
310 {
311 while( q != NULL )
312 {
313 if( ( r = strchr( q, ',' ) ) != NULL )
314 *r++ = '\0';
315
316 if( strcmp( q, "digital_signature" ) == 0 )
317 opt.key_usage |= KU_DIGITAL_SIGNATURE;
318 else if( strcmp( q, "non_repudiation" ) == 0 )
319 opt.key_usage |= KU_NON_REPUDIATION;
320 else if( strcmp( q, "key_encipherment" ) == 0 )
321 opt.key_usage |= KU_KEY_ENCIPHERMENT;
322 else if( strcmp( q, "data_encipherment" ) == 0 )
323 opt.key_usage |= KU_DATA_ENCIPHERMENT;
324 else if( strcmp( q, "key_agreement" ) == 0 )
325 opt.key_usage |= KU_KEY_AGREEMENT;
326 else if( strcmp( q, "key_cert_sign" ) == 0 )
327 opt.key_usage |= KU_KEY_CERT_SIGN;
328 else if( strcmp( q, "crl_sign" ) == 0 )
329 opt.key_usage |= KU_CRL_SIGN;
330 else
331 goto usage;
332
333 q = r;
334 }
335 }
336 else if( strcmp( p, "ns_cert_type" ) == 0 )
337 {
338 while( q != NULL )
339 {
340 if( ( r = strchr( q, ',' ) ) != NULL )
341 *r++ = '\0';
342
343 if( strcmp( q, "ssl_client" ) == 0 )
344 opt.ns_cert_type |= NS_CERT_TYPE_SSL_CLIENT;
345 else if( strcmp( q, "ssl_server" ) == 0 )
346 opt.ns_cert_type |= NS_CERT_TYPE_SSL_SERVER;
347 else if( strcmp( q, "email" ) == 0 )
348 opt.ns_cert_type |= NS_CERT_TYPE_EMAIL;
349 else if( strcmp( q, "object_signing" ) == 0 )
350 opt.ns_cert_type |= NS_CERT_TYPE_OBJECT_SIGNING;
351 else if( strcmp( q, "ssl_ca" ) == 0 )
352 opt.ns_cert_type |= NS_CERT_TYPE_SSL_CA;
353 else if( strcmp( q, "email_ca" ) == 0 )
354 opt.ns_cert_type |= NS_CERT_TYPE_EMAIL_CA;
355 else if( strcmp( q, "object_signing_ca" ) == 0 )
356 opt.ns_cert_type |= NS_CERT_TYPE_OBJECT_SIGNING_CA;
357 else
358 goto usage;
359
360 q = r;
361 }
362 }
363 else
364 goto usage;
365 }
366
Rich Evansf90016a2015-01-19 14:26:37 +0000367 polarssl_printf("\n");
Paul Bakker1014e952013-09-09 13:59:42 +0200368
Manuel Pégourié-Gonnard31e59402013-09-12 05:59:05 +0200369 /*
370 * 0. Seed the PRNG
371 */
Rich Evansf90016a2015-01-19 14:26:37 +0000372 polarssl_printf( " . Seeding the random number generator..." );
Manuel Pégourié-Gonnard31e59402013-09-12 05:59:05 +0200373 fflush( stdout );
374
375 entropy_init( &entropy );
376 if( ( ret = ctr_drbg_init( &ctr_drbg, entropy_func, &entropy,
377 (const unsigned char *) pers,
378 strlen( pers ) ) ) != 0 )
379 {
Shuo Chen95a0d112014-04-04 21:04:40 -0700380 polarssl_strerror( ret, buf, 1024 );
Rich Evansf90016a2015-01-19 14:26:37 +0000381 polarssl_printf( " failed\n ! ctr_drbg_init returned %d - %s\n", ret, buf );
Manuel Pégourié-Gonnard31e59402013-09-12 05:59:05 +0200382 goto exit;
383 }
384
Rich Evansf90016a2015-01-19 14:26:37 +0000385 polarssl_printf( " ok\n" );
Manuel Pégourié-Gonnard31e59402013-09-12 05:59:05 +0200386
Paul Bakker9397dcb2013-09-06 09:55:26 +0200387 // Parse serial to MPI
388 //
Rich Evansf90016a2015-01-19 14:26:37 +0000389 polarssl_printf( " . Reading serial number..." );
Manuel Pégourié-Gonnard31e59402013-09-12 05:59:05 +0200390 fflush( stdout );
391
Paul Bakker9397dcb2013-09-06 09:55:26 +0200392 if( ( ret = mpi_read_string( &serial, 10, opt.serial ) ) != 0 )
393 {
Shuo Chen95a0d112014-04-04 21:04:40 -0700394 polarssl_strerror( ret, buf, 1024 );
Rich Evansf90016a2015-01-19 14:26:37 +0000395 polarssl_printf( " failed\n ! mpi_read_string returned -0x%02x - %s\n\n", -ret, buf );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200396 goto exit;
397 }
398
Rich Evansf90016a2015-01-19 14:26:37 +0000399 polarssl_printf( " ok\n" );
Manuel Pégourié-Gonnard31e59402013-09-12 05:59:05 +0200400
Paul Bakker1014e952013-09-09 13:59:42 +0200401 // Parse issuer certificate if present
402 //
Paul Bakkerb2d7f232013-09-09 16:24:18 +0200403 if( !opt.selfsign && strlen( opt.issuer_crt ) )
Paul Bakker1014e952013-09-09 13:59:42 +0200404 {
405 /*
Paul Bakkere2673fb2013-09-09 15:52:07 +0200406 * 1.0.a. Load the certificates
Paul Bakker1014e952013-09-09 13:59:42 +0200407 */
Rich Evansf90016a2015-01-19 14:26:37 +0000408 polarssl_printf( " . Loading the issuer certificate ..." );
Paul Bakker1014e952013-09-09 13:59:42 +0200409 fflush( stdout );
410
Paul Bakkerddf26b42013-09-18 13:46:23 +0200411 if( ( ret = x509_crt_parse_file( &issuer_crt, opt.issuer_crt ) ) != 0 )
Paul Bakker1014e952013-09-09 13:59:42 +0200412 {
Shuo Chen95a0d112014-04-04 21:04:40 -0700413 polarssl_strerror( ret, buf, 1024 );
Rich Evansf90016a2015-01-19 14:26:37 +0000414 polarssl_printf( " failed\n ! x509_crt_parse_file returned -0x%02x - %s\n\n", -ret, buf );
Paul Bakker1014e952013-09-09 13:59:42 +0200415 goto exit;
416 }
417
Paul Bakker86d0c192013-09-18 11:11:02 +0200418 ret = x509_dn_gets( issuer_name, sizeof(issuer_name),
Paul Bakkerfdba4682014-04-25 11:48:35 +0200419 &issuer_crt.subject );
Paul Bakker1014e952013-09-09 13:59:42 +0200420 if( ret < 0 )
421 {
Shuo Chen95a0d112014-04-04 21:04:40 -0700422 polarssl_strerror( ret, buf, 1024 );
Rich Evansf90016a2015-01-19 14:26:37 +0000423 polarssl_printf( " failed\n ! x509_dn_gets returned -0x%02x - %s\n\n", -ret, buf );
Paul Bakker1014e952013-09-09 13:59:42 +0200424 goto exit;
425 }
426
Paul Bakkere2673fb2013-09-09 15:52:07 +0200427 opt.issuer_name = issuer_name;
428
Rich Evansf90016a2015-01-19 14:26:37 +0000429 polarssl_printf( " ok\n" );
Paul Bakkere2673fb2013-09-09 15:52:07 +0200430 }
431
Paul Bakker7fc7fa62013-09-17 14:44:00 +0200432#if defined(POLARSSL_X509_CSR_PARSE_C)
Paul Bakkere2673fb2013-09-09 15:52:07 +0200433 // Parse certificate request if present
434 //
Paul Bakkerb2d7f232013-09-09 16:24:18 +0200435 if( !opt.selfsign && strlen( opt.request_file ) )
Paul Bakkere2673fb2013-09-09 15:52:07 +0200436 {
437 /*
438 * 1.0.b. Load the CSR
439 */
Rich Evansf90016a2015-01-19 14:26:37 +0000440 polarssl_printf( " . Loading the certificate request ..." );
Paul Bakkere2673fb2013-09-09 15:52:07 +0200441 fflush( stdout );
442
Paul Bakkerddf26b42013-09-18 13:46:23 +0200443 if( ( ret = x509_csr_parse_file( &csr, opt.request_file ) ) != 0 )
Paul Bakkere2673fb2013-09-09 15:52:07 +0200444 {
Shuo Chen95a0d112014-04-04 21:04:40 -0700445 polarssl_strerror( ret, buf, 1024 );
Rich Evansf90016a2015-01-19 14:26:37 +0000446 polarssl_printf( " failed\n ! x509_csr_parse_file returned -0x%02x - %s\n\n", -ret, buf );
Paul Bakkere2673fb2013-09-09 15:52:07 +0200447 goto exit;
448 }
449
Paul Bakker86d0c192013-09-18 11:11:02 +0200450 ret = x509_dn_gets( subject_name, sizeof(subject_name),
Paul Bakkere2673fb2013-09-09 15:52:07 +0200451 &csr.subject );
452 if( ret < 0 )
453 {
Shuo Chen95a0d112014-04-04 21:04:40 -0700454 polarssl_strerror( ret, buf, 1024 );
Rich Evansf90016a2015-01-19 14:26:37 +0000455 polarssl_printf( " failed\n ! x509_dn_gets returned -0x%02x - %s\n\n", -ret, buf );
Paul Bakkere2673fb2013-09-09 15:52:07 +0200456 goto exit;
457 }
458
459 opt.subject_name = subject_name;
Manuel Pégourié-Gonnardf38e71a2013-09-12 05:21:54 +0200460 subject_key = &csr.pk;
Paul Bakkere2673fb2013-09-09 15:52:07 +0200461
Rich Evansf90016a2015-01-19 14:26:37 +0000462 polarssl_printf( " ok\n" );
Paul Bakkerb2d7f232013-09-09 16:24:18 +0200463 }
Paul Bakker7fc7fa62013-09-17 14:44:00 +0200464#endif /* POLARSSL_X509_CSR_PARSE_C */
Paul Bakkerb2d7f232013-09-09 16:24:18 +0200465
466 /*
467 * 1.1. Load the keys
468 */
469 if( !opt.selfsign && !strlen( opt.request_file ) )
470 {
Rich Evansf90016a2015-01-19 14:26:37 +0000471 polarssl_printf( " . Loading the subject key ..." );
Paul Bakkerb2d7f232013-09-09 16:24:18 +0200472 fflush( stdout );
473
Paul Bakker1a7550a2013-09-15 13:01:22 +0200474 ret = pk_parse_keyfile( &loaded_subject_key, opt.subject_key,
Manuel Pégourié-Gonnardf38e71a2013-09-12 05:21:54 +0200475 opt.subject_pwd );
Paul Bakkerb2d7f232013-09-09 16:24:18 +0200476 if( ret != 0 )
Paul Bakkere2673fb2013-09-09 15:52:07 +0200477 {
Shuo Chen95a0d112014-04-04 21:04:40 -0700478 polarssl_strerror( ret, buf, 1024 );
Rich Evansf90016a2015-01-19 14:26:37 +0000479 polarssl_printf( " failed\n ! pk_parse_keyfile returned -0x%02x - %s\n\n", -ret, buf );
Paul Bakkere2673fb2013-09-09 15:52:07 +0200480 goto exit;
481 }
Paul Bakker1014e952013-09-09 13:59:42 +0200482
Rich Evansf90016a2015-01-19 14:26:37 +0000483 polarssl_printf( " ok\n" );
Paul Bakker1014e952013-09-09 13:59:42 +0200484 }
485
Rich Evansf90016a2015-01-19 14:26:37 +0000486 polarssl_printf( " . Loading the issuer key ..." );
Paul Bakkerb2d7f232013-09-09 16:24:18 +0200487 fflush( stdout );
488
Paul Bakker1a7550a2013-09-15 13:01:22 +0200489 ret = pk_parse_keyfile( &loaded_issuer_key, opt.issuer_key,
490 opt.issuer_pwd );
Paul Bakkerb2d7f232013-09-09 16:24:18 +0200491 if( ret != 0 )
492 {
Shuo Chen95a0d112014-04-04 21:04:40 -0700493 polarssl_strerror( ret, buf, 1024 );
Rich Evansf90016a2015-01-19 14:26:37 +0000494 polarssl_printf( " failed\n ! pk_parse_keyfile returned -x%02x - %s\n\n", -ret, buf );
Paul Bakkerb2d7f232013-09-09 16:24:18 +0200495 goto exit;
496 }
497
498 // Check if key and issuer certificate match
499 //
500 if( strlen( opt.issuer_crt ) )
501 {
502 if( !pk_can_do( &issuer_crt.pk, POLARSSL_PK_RSA ) ||
Manuel Pégourié-Gonnardf38e71a2013-09-12 05:21:54 +0200503 mpi_cmp_mpi( &pk_rsa( issuer_crt.pk )->N,
504 &pk_rsa( *issuer_key )->N ) != 0 ||
505 mpi_cmp_mpi( &pk_rsa( issuer_crt.pk )->E,
506 &pk_rsa( *issuer_key )->E ) != 0 )
Paul Bakkerb2d7f232013-09-09 16:24:18 +0200507 {
Rich Evansf90016a2015-01-19 14:26:37 +0000508 polarssl_printf( " failed\n ! issuer_key does not match issuer certificate\n\n" );
Paul Bakkerb2d7f232013-09-09 16:24:18 +0200509 ret = -1;
510 goto exit;
511 }
512 }
513
Rich Evansf90016a2015-01-19 14:26:37 +0000514 polarssl_printf( " ok\n" );
Paul Bakkerb2d7f232013-09-09 16:24:18 +0200515
516 if( opt.selfsign )
517 {
Paul Bakker93c6aa42013-10-28 22:28:09 +0100518 opt.subject_name = opt.issuer_name;
Manuel Pégourié-Gonnardf38e71a2013-09-12 05:21:54 +0200519 subject_key = issuer_key;
Paul Bakkerb2d7f232013-09-09 16:24:18 +0200520 }
521
Manuel Pégourié-Gonnardf38e71a2013-09-12 05:21:54 +0200522 x509write_crt_set_subject_key( &crt, subject_key );
523 x509write_crt_set_issuer_key( &crt, issuer_key );
Paul Bakkerb2d7f232013-09-09 16:24:18 +0200524
Paul Bakker9397dcb2013-09-06 09:55:26 +0200525 /*
526 * 1.0. Check the names for validity
527 */
528 if( ( ret = x509write_crt_set_subject_name( &crt, opt.subject_name ) ) != 0 )
529 {
Shuo Chen95a0d112014-04-04 21:04:40 -0700530 polarssl_strerror( ret, buf, 1024 );
Rich Evansf90016a2015-01-19 14:26:37 +0000531 polarssl_printf( " failed\n ! x509write_crt_set_subject_name returned -0x%02x - %s\n\n", -ret, buf );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200532 goto exit;
533 }
534
535 if( ( ret = x509write_crt_set_issuer_name( &crt, opt.issuer_name ) ) != 0 )
536 {
Shuo Chen95a0d112014-04-04 21:04:40 -0700537 polarssl_strerror( ret, buf, 1024 );
Rich Evansf90016a2015-01-19 14:26:37 +0000538 polarssl_printf( " failed\n ! x509write_crt_set_issuer_name returned -0x%02x - %s\n\n", -ret, buf );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200539 goto exit;
540 }
541
Rich Evansf90016a2015-01-19 14:26:37 +0000542 polarssl_printf( " . Setting certificate values ..." );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200543 fflush( stdout );
544
545 ret = x509write_crt_set_serial( &crt, &serial );
546 if( ret != 0 )
547 {
Shuo Chen95a0d112014-04-04 21:04:40 -0700548 polarssl_strerror( ret, buf, 1024 );
Rich Evansf90016a2015-01-19 14:26:37 +0000549 polarssl_printf( " failed\n ! x509write_crt_set_serial returned -0x%02x - %s\n\n", -ret, buf );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200550 goto exit;
551 }
552
553 ret = x509write_crt_set_validity( &crt, opt.not_before, opt.not_after );
554 if( ret != 0 )
555 {
Shuo Chen95a0d112014-04-04 21:04:40 -0700556 polarssl_strerror( ret, buf, 1024 );
Rich Evansf90016a2015-01-19 14:26:37 +0000557 polarssl_printf( " failed\n ! x509write_crt_set_validity returned -0x%02x - %s\n\n", -ret, buf );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200558 goto exit;
559 }
560
Rich Evansf90016a2015-01-19 14:26:37 +0000561 polarssl_printf( " ok\n" );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200562
Rich Evansf90016a2015-01-19 14:26:37 +0000563 polarssl_printf( " . Adding the Basic Constraints extension ..." );
Paul Bakker15162a02013-09-06 19:27:21 +0200564 fflush( stdout );
565
566 ret = x509write_crt_set_basic_constraints( &crt, opt.is_ca,
567 opt.max_pathlen );
568 if( ret != 0 )
569 {
Shuo Chen95a0d112014-04-04 21:04:40 -0700570 polarssl_strerror( ret, buf, 1024 );
Rich Evansf90016a2015-01-19 14:26:37 +0000571 polarssl_printf( " failed\n ! x509write_crt_set_basic_contraints returned -0x%02x - %s\n\n", -ret, buf );
Paul Bakker15162a02013-09-06 19:27:21 +0200572 goto exit;
573 }
574
Rich Evansf90016a2015-01-19 14:26:37 +0000575 polarssl_printf( " ok\n" );
Paul Bakker15162a02013-09-06 19:27:21 +0200576
Manuel Pégourié-Gonnard3daaf3d2013-10-27 14:22:02 +0100577#if defined(POLARSSL_SHA1_C)
Rich Evansf90016a2015-01-19 14:26:37 +0000578 polarssl_printf( " . Adding the Subject Key Identifier ..." );
Paul Bakker15162a02013-09-06 19:27:21 +0200579 fflush( stdout );
580
581 ret = x509write_crt_set_subject_key_identifier( &crt );
582 if( ret != 0 )
583 {
Shuo Chen95a0d112014-04-04 21:04:40 -0700584 polarssl_strerror( ret, buf, 1024 );
Rich Evansf90016a2015-01-19 14:26:37 +0000585 polarssl_printf( " failed\n ! x509write_crt_set_subject_key_identifier returned -0x%02x - %s\n\n", -ret, buf );
Paul Bakker15162a02013-09-06 19:27:21 +0200586 goto exit;
587 }
588
Rich Evansf90016a2015-01-19 14:26:37 +0000589 polarssl_printf( " ok\n" );
Paul Bakker15162a02013-09-06 19:27:21 +0200590
Rich Evansf90016a2015-01-19 14:26:37 +0000591 polarssl_printf( " . Adding the Authority Key Identifier ..." );
Paul Bakker15162a02013-09-06 19:27:21 +0200592 fflush( stdout );
593
594 ret = x509write_crt_set_authority_key_identifier( &crt );
595 if( ret != 0 )
596 {
Shuo Chen95a0d112014-04-04 21:04:40 -0700597 polarssl_strerror( ret, buf, 1024 );
Rich Evansf90016a2015-01-19 14:26:37 +0000598 polarssl_printf( " failed\n ! x509write_crt_set_authority_key_identifier returned -0x%02x - %s\n\n", -ret, buf );
Paul Bakker15162a02013-09-06 19:27:21 +0200599 goto exit;
600 }
601
Rich Evansf90016a2015-01-19 14:26:37 +0000602 polarssl_printf( " ok\n" );
Manuel Pégourié-Gonnard3daaf3d2013-10-27 14:22:02 +0100603#endif /* POLARSSL_SHA1_C */
Paul Bakker15162a02013-09-06 19:27:21 +0200604
Paul Bakker52be08c2013-09-09 12:37:54 +0200605 if( opt.key_usage )
606 {
Rich Evansf90016a2015-01-19 14:26:37 +0000607 polarssl_printf( " . Adding the Key Usage extension ..." );
Paul Bakker52be08c2013-09-09 12:37:54 +0200608 fflush( stdout );
609
610 ret = x509write_crt_set_key_usage( &crt, opt.key_usage );
611 if( ret != 0 )
612 {
Shuo Chen95a0d112014-04-04 21:04:40 -0700613 polarssl_strerror( ret, buf, 1024 );
Rich Evansf90016a2015-01-19 14:26:37 +0000614 polarssl_printf( " failed\n ! x509write_crt_set_key_usage returned -0x%02x - %s\n\n", -ret, buf );
Paul Bakker52be08c2013-09-09 12:37:54 +0200615 goto exit;
616 }
617
Rich Evansf90016a2015-01-19 14:26:37 +0000618 polarssl_printf( " ok\n" );
Paul Bakker52be08c2013-09-09 12:37:54 +0200619 }
620
621 if( opt.ns_cert_type )
622 {
Rich Evansf90016a2015-01-19 14:26:37 +0000623 polarssl_printf( " . Adding the NS Cert Type extension ..." );
Paul Bakker52be08c2013-09-09 12:37:54 +0200624 fflush( stdout );
625
626 ret = x509write_crt_set_ns_cert_type( &crt, opt.ns_cert_type );
627 if( ret != 0 )
628 {
Shuo Chen95a0d112014-04-04 21:04:40 -0700629 polarssl_strerror( ret, buf, 1024 );
Rich Evansf90016a2015-01-19 14:26:37 +0000630 polarssl_printf( " failed\n ! x509write_crt_set_ns_cert_type returned -0x%02x - %s\n\n", -ret, buf );
Paul Bakker52be08c2013-09-09 12:37:54 +0200631 goto exit;
632 }
633
Rich Evansf90016a2015-01-19 14:26:37 +0000634 polarssl_printf( " ok\n" );
Paul Bakker52be08c2013-09-09 12:37:54 +0200635 }
636
Paul Bakker9397dcb2013-09-06 09:55:26 +0200637 /*
638 * 1.2. Writing the request
639 */
Rich Evansf90016a2015-01-19 14:26:37 +0000640 polarssl_printf( " . Writing the certificate..." );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200641 fflush( stdout );
642
Manuel Pégourié-Gonnard31e59402013-09-12 05:59:05 +0200643 if( ( ret = write_certificate( &crt, opt.output_file,
644 ctr_drbg_random, &ctr_drbg ) ) != 0 )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200645 {
Shuo Chen95a0d112014-04-04 21:04:40 -0700646 polarssl_strerror( ret, buf, 1024 );
Rich Evansf90016a2015-01-19 14:26:37 +0000647 polarssl_printf( " failed\n ! write_certifcate -0x%02x - %s\n\n", -ret, buf );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200648 goto exit;
649 }
650
Rich Evansf90016a2015-01-19 14:26:37 +0000651 polarssl_printf( " ok\n" );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200652
653exit:
654 x509write_crt_free( &crt );
Manuel Pégourié-Gonnardf38e71a2013-09-12 05:21:54 +0200655 pk_free( &loaded_subject_key );
656 pk_free( &loaded_issuer_key );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200657 mpi_free( &serial );
Paul Bakkera317a982014-06-18 16:44:11 +0200658 ctr_drbg_free( &ctr_drbg );
Paul Bakker1ffefac2013-09-28 15:23:03 +0200659 entropy_free( &entropy );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200660
661#if defined(_WIN32)
Rich Evansf90016a2015-01-19 14:26:37 +0000662 polarssl_printf( " + Press Enter to exit this program.\n" );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200663 fflush( stdout ); getchar();
664#endif
665
666 return( ret );
667}
Paul Bakker36713e82013-09-17 13:25:29 +0200668#endif /* POLARSSL_X509_CRT_WRITE_C && POLARSSL_X509_CRT_PARSE_C &&
669 POLARSSL_FS_IO && POLARSSL_ENTROPY_C && POLARSSL_CTR_DRBG_C &&
Manuel Pégourié-Gonnard31e59402013-09-12 05:59:05 +0200670 POLARSSL_ERROR_C */