blob: 0266cdadd5b30a624b8727b2ac19fd373414f642 [file] [log] [blame]
Paul Bakker9397dcb2013-09-06 09:55:26 +02001/*
2 * Certificate generation and signing
3 *
Manuel Pégourié-Gonnard6fb81872015-07-27 11:11:48 +02004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Paul Bakker9397dcb2013-09-06 09:55:26 +020018 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000019 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker9397dcb2013-09-06 09:55:26 +020020 */
21
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020022#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000023#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020024#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020025#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020026#endif
Paul Bakker9397dcb2013-09-06 09:55:26 +020027
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020028#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000029#include "mbedtls/platform.h"
Rich Evansf90016a2015-01-19 14:26:37 +000030#else
Rich Evans18b78c72015-02-11 14:06:19 +000031#include <stdio.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020032#define mbedtls_printf printf
Rich Evansf90016a2015-01-19 14:26:37 +000033#endif
34
Simon Butcher203a6932016-10-07 15:00:17 +010035#if !defined(MBEDTLS_X509_CRT_WRITE_C) || \
36 !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_FS_IO) || \
37 !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_CTR_DRBG_C) || \
38 !defined(MBEDTLS_ERROR_C) || !defined(MBEDTLS_SHA256_C) || \
39 !defined(MBEDTLS_PEM_WRITE_C)
Manuel Pégourié-Gonnard8d649c62015-03-31 15:10:03 +020040int main( void )
41{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020042 mbedtls_printf( "MBEDTLS_X509_CRT_WRITE_C and/or MBEDTLS_X509_CRT_PARSE_C and/or "
Manuel Pégourié-Gonnardd7389652015-08-06 18:22:26 +020043 "MBEDTLS_FS_IO and/or MBEDTLS_SHA256_C and/or "
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020044 "MBEDTLS_ENTROPY_C and/or MBEDTLS_CTR_DRBG_C and/or "
45 "MBEDTLS_ERROR_C not defined.\n");
Manuel Pégourié-Gonnard8d649c62015-03-31 15:10:03 +020046 return( 0 );
47}
48#else
49
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000050#include "mbedtls/x509_crt.h"
51#include "mbedtls/x509_csr.h"
52#include "mbedtls/entropy.h"
53#include "mbedtls/ctr_drbg.h"
Hanno Becker6c13d372017-09-13 12:49:22 +010054#include "mbedtls/md.h"
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000055#include "mbedtls/error.h"
Azim Khan26a455c2018-02-07 11:11:17 +000056#include "mbedtls/pk_info.h"
Manuel Pégourié-Gonnard7831b0c2013-09-20 12:29:56 +020057
Rich Evans18b78c72015-02-11 14:06:19 +000058#include <stdio.h>
59#include <stdlib.h>
60#include <string.h>
Azim Khan7a339902018-02-21 01:05:21 +000061#if defined(_WIN32)
Azim Khan26a455c2018-02-07 11:11:17 +000062#include <Windows.h>
Azim Khan7a339902018-02-21 01:05:21 +000063#endif
Rich Evans18b78c72015-02-11 14:06:19 +000064
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020065#if defined(MBEDTLS_X509_CSR_PARSE_C)
Rich Evans18b78c72015-02-11 14:06:19 +000066#define USAGE_CSR \
Hanno Becker81535d02017-09-13 15:39:59 +010067 " request_file=%%s default: (empty)\n" \
68 " If request_file is specified, subject_key,\n" \
69 " subject_pwd and subject_name are ignored!\n"
Rich Evans18b78c72015-02-11 14:06:19 +000070#else
71#define USAGE_CSR ""
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020072#endif /* MBEDTLS_X509_CSR_PARSE_C */
Rich Evans18b78c72015-02-11 14:06:19 +000073
Paul Bakker1014e952013-09-09 13:59:42 +020074#define DFL_ISSUER_CRT ""
Paul Bakkere2673fb2013-09-09 15:52:07 +020075#define DFL_REQUEST_FILE ""
Paul Bakker9397dcb2013-09-06 09:55:26 +020076#define DFL_SUBJECT_KEY "subject.key"
77#define DFL_ISSUER_KEY "ca.key"
78#define DFL_SUBJECT_PWD ""
79#define DFL_ISSUER_PWD ""
80#define DFL_OUTPUT_FILENAME "cert.crt"
Manuel Pégourié-Gonnard91699212015-01-22 16:26:39 +000081#define DFL_SUBJECT_NAME "CN=Cert,O=mbed TLS,C=UK"
82#define DFL_ISSUER_NAME "CN=CA,O=mbed TLS,C=UK"
Paul Bakker9397dcb2013-09-06 09:55:26 +020083#define DFL_NOT_BEFORE "20010101000000"
84#define DFL_NOT_AFTER "20301231235959"
85#define DFL_SERIAL "1"
Paul Bakkerb2d7f232013-09-09 16:24:18 +020086#define DFL_SELFSIGN 0
Paul Bakker15162a02013-09-06 19:27:21 +020087#define DFL_IS_CA 0
88#define DFL_MAX_PATHLEN -1
Paul Bakker9397dcb2013-09-06 09:55:26 +020089#define DFL_KEY_USAGE 0
90#define DFL_NS_CERT_TYPE 0
Hanno Becker6c13d372017-09-13 12:49:22 +010091#define DFL_VERSION 3
92#define DFL_AUTH_IDENT 1
93#define DFL_SUBJ_IDENT 1
94#define DFL_CONSTRAINTS 1
95#define DFL_DIGEST MBEDTLS_MD_SHA256
Paul Bakker9397dcb2013-09-06 09:55:26 +020096
Azim Khan26a455c2018-02-07 11:11:17 +000097#define UNUSED(x) ((void)(x))
98
Rich Evans18b78c72015-02-11 14:06:19 +000099#define USAGE \
100 "\n usage: cert_write param=<>...\n" \
101 "\n acceptable parameters:\n" \
102 USAGE_CSR \
Hanno Becker81535d02017-09-13 15:39:59 +0100103 " subject_key=%%s default: subject.key\n" \
104 " subject_pwd=%%s default: (empty)\n" \
105 " subject_name=%%s default: CN=Cert,O=mbed TLS,C=UK\n" \
Rich Evans18b78c72015-02-11 14:06:19 +0000106 "\n" \
Hanno Becker81535d02017-09-13 15:39:59 +0100107 " issuer_crt=%%s default: (empty)\n" \
108 " If issuer_crt is specified, issuer_name is\n" \
109 " ignored!\n" \
110 " issuer_name=%%s default: CN=CA,O=mbed TLS,C=UK\n" \
Rich Evans18b78c72015-02-11 14:06:19 +0000111 "\n" \
Hanno Becker81535d02017-09-13 15:39:59 +0100112 " selfsign=%%d default: 0 (false)\n" \
113 " If selfsign is enabled, issuer_name and\n" \
114 " issuer_key are required (issuer_crt and\n" \
115 " subject_* are ignored\n" \
116 " issuer_key=%%s default: ca.key\n" \
117 " issuer_pwd=%%s default: (empty)\n" \
118 " output_file=%%s default: cert.crt\n" \
119 " serial=%%s default: 1\n" \
120 " not_before=%%s default: 20010101000000\n"\
121 " not_after=%%s default: 20301231235959\n"\
122 " is_ca=%%d default: 0 (disabled)\n" \
123 " max_pathlen=%%d default: -1 (none)\n" \
124 " md=%%s default: SHA256\n" \
125 " Supported values:\n" \
126 " MD5, SHA1, SHA256, SHA512\n"\
127 " version=%%d default: 3\n" \
128 " Possible values: 1, 2, 3\n"\
129 " subject_identifier=%%s default: 1\n" \
130 " Possible values: 0, 1\n" \
131 " (Considered for v3 only)\n"\
132 " authority_identifier=%%s default: 1\n" \
133 " Possible values: 0, 1\n" \
134 " (Considered for v3 only)\n"\
135 " basic_constraints=%%d default: 1\n" \
136 " Possible values: 0, 1\n" \
137 " (Considered for v3 only)\n"\
138 " key_usage=%%s default: (empty)\n" \
139 " Comma-separated-list of values:\n" \
140 " digital_signature\n" \
141 " non_repudiation\n" \
142 " key_encipherment\n" \
143 " data_encipherment\n" \
144 " key_agreement\n" \
145 " key_cert_sign\n" \
146 " crl_sign\n" \
147 " (Considered for v3 only)\n"\
148 " ns_cert_type=%%s default: (empty)\n" \
149 " Comma-separated-list of values:\n" \
150 " ssl_client\n" \
151 " ssl_server\n" \
152 " email\n" \
153 " object_signing\n" \
154 " ssl_ca\n" \
155 " email_ca\n" \
156 " object_signing_ca\n" \
Rich Evans18b78c72015-02-11 14:06:19 +0000157 "\n"
Manuel Pégourié-Gonnard6c5abfa2015-02-13 14:12:07 +0000158
Paul Bakker9397dcb2013-09-06 09:55:26 +0200159/*
160 * global options
161 */
162struct options
163{
Paul Bakker8fc30b12013-11-25 13:29:43 +0100164 const char *issuer_crt; /* filename of the issuer certificate */
165 const char *request_file; /* filename of the certificate request */
166 const char *subject_key; /* filename of the subject key file */
167 const char *issuer_key; /* filename of the issuer key file */
168 const char *subject_pwd; /* password for the subject key file */
169 const char *issuer_pwd; /* password for the issuer key file */
170 const char *output_file; /* where to store the constructed key file */
171 const char *subject_name; /* subject name for certificate */
172 const char *issuer_name; /* issuer name for certificate */
173 const char *not_before; /* validity period not before */
174 const char *not_after; /* validity period not after */
175 const char *serial; /* serial number string */
Paul Bakkerb2d7f232013-09-09 16:24:18 +0200176 int selfsign; /* selfsign the certificate */
Paul Bakker15162a02013-09-06 19:27:21 +0200177 int is_ca; /* is a CA certificate */
178 int max_pathlen; /* maximum CA path length */
Hanno Beckere1b1d0a2017-09-22 15:35:16 +0100179 int authority_identifier; /* add authority identifier to CRT */
180 int subject_identifier; /* add subject identifier to CRT */
Hanno Becker6c13d372017-09-13 12:49:22 +0100181 int basic_constraints; /* add basic constraints ext to CRT */
182 int version; /* CRT version */
183 mbedtls_md_type_t md; /* Hash used for signing */
Paul Bakker9397dcb2013-09-06 09:55:26 +0200184 unsigned char key_usage; /* key usage flags */
185 unsigned char ns_cert_type; /* NS cert type */
186} opt;
187
Azim Khan7a339902018-02-21 01:05:21 +0000188#if defined(_WIN32)
189/** Below are the constants used for remote Opaque key implementation.
190 */
191
192/* Remote cryptoprocessor sync pattern. Sent to sync with the device before
193 * sending commands. */
194#define REMOTE_KEY_MAGIC_PATTERN "rEmOtEkEy"
195#define REMOTE_KEY_CMD_TAG "//opaque_pk/ATCA"
196#define REMOTE_KEY_ID_MIN 0
197#define REMOTE_KEY_ID_MAX 7
198#define REMOTE_KEY_SERIAL_BAUD CBR_9600
199
200#define REMOTE_KEY_FUNC_GET_PUBKEY 0xA
201#define REMOTE_KEY_FUNC_SIGN 0xB
202
203int is_remote_key( const char *remote_info )
204{
205 size_t tag_len = strlen( REMOTE_KEY_CMD_TAG );
206 if ( strlen( remote_info ) > tag_len &&
207 strncmp( remote_info, REMOTE_KEY_CMD_TAG, tag_len ) == 0 )
208 return( 1 );
209 return( 0 );
210}
211
212int parse_remote_info( const char *remote_info, int *key_idx, const char **serial_port )
213{
214 int offset = 0;
215 int remote_info_len = strlen( remote_info );
216
217 if( is_remote_key( remote_info ) == 0 )
218 return( -1 );
219
220 offset = strlen( REMOTE_KEY_CMD_TAG );
221 offset++; // Skip the delimiter. FUTURE: Add validation.
222 if( offset >= remote_info_len )
223 return( -1 );
224 *key_idx = (int) remote_info[offset++];
225 offset++; // Skip the delimiter
226 if( offset >= remote_info_len )
227 return( -1 );
228 *key_idx = *key_idx - 48; // ascii to decimal
229
230 if ( *key_idx < REMOTE_KEY_ID_MIN || *key_idx > REMOTE_KEY_ID_MAX )
231 {
232 mbedtls_printf( " failed\n ! Invalid remote key index %d\n\n", *key_idx );
233 return( -1 );
234 }
235 *serial_port = remote_info + offset;
236 printf( "Got key id %d and com port %s\n", *key_idx, *serial_port );
237 return( 0 );
238}
239
240/**
241 * @brief Send a command to remote cryptoprocessor and receive response.
242 *
243 * It
244 * - first sends a sync pattern 'rEmOtEkEy' and waits for an echo to sync
245 * with the remote.
246 * - Then it sends the tx buf supplied by the caller.
247 * - It waits for a 4 byte length indicator. Value 0 means error.
248 * - Finally it reads no. of bytes specified in received Length indicator
249 * and fills received data in rx_buf and returns.
250 * Note: success is considered when a length indicator > 0 is received and
251 * data size == length indicator is successfully received.
252 *
253 *
254 * @param serial_port Serial port to send & recv data.
255 * @param tx_buf Command Tx buffer
256 * @param tx_buf_len Tx buffer length
257 * @param rx_buf Out response Rx buffer
258 * @param rx_buf_len Rx buffer length
259 * @param rx_len Received data length
260 *
261 * @retval 0 if success, or -1.
262 */
263int serial_xfer( const char * serial_port, const unsigned char * tx_buf,
264 size_t tx_buf_len, unsigned char * rx_buf, size_t rx_buf_len,
265 size_t * rx_len )
266{
267 char c, comm_name[20]; /* \\\\.\\COMxy = 11 characters at least */
268 HANDLE h_comm;
269 DCB dcb_config;
270 COMMTIMEOUTS comm_timeout;
271 DWORD xfer_len;
272 unsigned char len_buf[sizeof(size_t)];
273 int ret = -1;
274 size_t len = 0, sync_pattern_idx = 0;
275
276 do
277 {
278 sprintf( comm_name, "\\\\.\\%s", serial_port );
279
280 h_comm = CreateFile( comm_name, GENERIC_READ | GENERIC_WRITE, 0, 0,
281 OPEN_EXISTING, 0, 0 );
282 if ( h_comm == INVALID_HANDLE_VALUE )
283 {
284 mbedtls_printf( " failed\n ! failed to open port %s %lu\n\n", serial_port, GetLastError() );
285 break;
286 }
287
288 if( GetCommState( h_comm, &dcb_config ) )
289 {
290 dcb_config.BaudRate = REMOTE_KEY_SERIAL_BAUD;
291 dcb_config.Parity = NOPARITY;
292 dcb_config.ByteSize = 8;
293 dcb_config.StopBits = ONESTOPBIT;
294 dcb_config.fOutxCtsFlow = FALSE; // No CTS output flow control
295 dcb_config.fOutxDsrFlow = FALSE; // No DSR output flow control
296 dcb_config.fDtrControl = DTR_CONTROL_DISABLE; // DTR flow control type
297 dcb_config.fDsrSensitivity = FALSE; // DSR sensitivity
298 dcb_config.fTXContinueOnXoff = TRUE; // XOFF continues Tx
299 dcb_config.fOutX = FALSE; // No XON/XOFF out flow control
300 dcb_config.fInX = FALSE; // No XON/XOFF in flow control
301 dcb_config.fErrorChar = FALSE; // Disable error replacement
302 dcb_config.fNull = FALSE; // Disable null stripping
303 dcb_config.fRtsControl = RTS_CONTROL_DISABLE; // RTS flow control
304 dcb_config.fAbortOnError = FALSE; // Do not abort reads/writes on error
305 }
306 else
307 {
308 mbedtls_printf( " failed\n ! GetCommState returned error %lu\n\n", GetLastError() );
309 break;
310 }
311
312 if( !SetCommState( h_comm, &dcb_config ) )
313 {
314 mbedtls_printf( " failed\n ! SetCommState returned error %lu\n\n", GetLastError() );
315 break;
316 }
317
318 if( GetCommTimeouts( h_comm, &comm_timeout ) )
319 {
320 comm_timeout.ReadIntervalTimeout = 1000;
321 comm_timeout.ReadTotalTimeoutMultiplier = 10;
322 comm_timeout.ReadTotalTimeoutConstant = 1000;
323 comm_timeout.WriteTotalTimeoutConstant = 1000;
324 comm_timeout.WriteTotalTimeoutMultiplier = 10;
325 }
326 else
327 {
328 mbedtls_printf( " failed\n ! GetCommTimeouts returned error %lu\n\n", GetLastError() );
329 break;
330 }
331
332 if( !SetCommTimeouts( h_comm, &comm_timeout ) )
333 {
334 mbedtls_printf( " failed\n ! SetCommTimeouts returned error %lu\n\n", GetLastError() );
335 break;
336 }
337
338
339 /* Flush data on serial before sending sync pattern */
340 while( ReadFile( h_comm, &c, sizeof(c), &xfer_len, NULL ) && xfer_len != 0 );
341 /* Sync with peer */
342 if( !WriteFile( h_comm, REMOTE_KEY_MAGIC_PATTERN, strlen(REMOTE_KEY_MAGIC_PATTERN),
343 &xfer_len, NULL ) )
344 {
345 mbedtls_printf( " failed\n ! WriteFile returned error %lu\n\n", GetLastError() );
346 break;
347 }
348
349 while( sync_pattern_idx != strlen(REMOTE_KEY_MAGIC_PATTERN) )
350 {
351 if( !ReadFile( h_comm, &c, sizeof(c), &xfer_len, NULL ) )
352 {
353 mbedtls_printf( " failed\n ! ReadFile returned error %lu\n\n", GetLastError() );
354 break;
355 }
356 if ( c == REMOTE_KEY_MAGIC_PATTERN[sync_pattern_idx] )
357 sync_pattern_idx++;
358 else
359 sync_pattern_idx = 0;
360 }
361
362 /* Exit if there was a read error */
363 if ( sync_pattern_idx != strlen(REMOTE_KEY_MAGIC_PATTERN) )
364 {
365 mbedtls_printf("Failedi to sync!\n");
366 break;
367 }
368
369 {
370 size_t i;
371 printf("Tx: ");
372 for (i = 0; i < tx_buf_len; i++)
373 printf ("0x%02x ", (tx_buf)[i]);
374 printf("\n");
375 }
376 if( !WriteFile( h_comm, tx_buf, tx_buf_len,
377 &xfer_len, NULL ) )
378 {
379 mbedtls_printf( " failed\n ! WriteFile returned error %lu\n\n", GetLastError() );
380 break;
381 }
382
383 /* Read LI (length indicator) */
384 if( !ReadFile( h_comm, len_buf, sizeof(len_buf), &xfer_len, NULL ) ) /* Serial error */
385 {
386 mbedtls_printf( " failed\n ! ReadFile returned error %lu\n\n", GetLastError() );
387 break;
388 }
389
390 *rx_len = ( len_buf[0] << 24 ) | ( len_buf[1] << 16 ) | ( len_buf[2] << 8 ) | len_buf[3];
391 if ( *rx_len == 0 ) /* LI == 0 indicates remote error */
392 {
393 mbedtls_printf( " failed\n ! Received length indicator == 0\n\n" );
394 break;
395 }
396 if ( *rx_len > rx_buf_len ) /* Buffer too small */
397 {
398 mbedtls_printf( " failed\n ! Buffer too small to hold received data\n\n" );
399 break;
400 }
401 /* Read payload */
402 len = 0;
403 while( len < *rx_len )
404 {
405 if( !ReadFile( h_comm, rx_buf + len, *rx_len - len, &xfer_len, NULL ) )
406 {
407 mbedtls_printf( " failed\n ! ReadFile returned error %lu\n\n", GetLastError() );
408 break;
409 }
410 len += xfer_len;
411 }
412 if( len < *rx_len ) /* Serial error */
413 {
414 mbedtls_printf( " failed\n ! ReadFile returned error %lu\n\n", GetLastError() );
415 break;
416 }
417 printf("Received LI 0x%02x 0x%02x 0x%02x 0x%02x \n", len_buf[0], len_buf[1], len_buf[2], len_buf[3]);
418 {
419 size_t i;
420 printf("Rx: ");
421 for (i = 0; i < *rx_len; i++)
422 printf ("0x%02x ", (rx_buf)[i]);
423 printf("\n");
424 }
425
426 ret = 0;
427 } while( 0 );
428
429 if( h_comm != INVALID_HANDLE_VALUE )
430 {
431 CloseHandle( h_comm );
432 h_comm = INVALID_HANDLE_VALUE;
433 }
434
435 return( ret );
436}
437
438/** Load a transparent public key context with public key from remote device
439 * over serial.
440 * This function sends:
441 * rEmOtEkEy<char encoded function code=GetPubKey><char encoded private key ID>
442 * Receives:
443 * <4 bytes length indicator in network order><concatenated public key>
444 */
445int load_pubkey_from_remote( const char * remote_info, mbedtls_pk_context * ctx )
446{
447 int key_idx = 0, offset = 0, ret = 0;
448 const char * serial_port = NULL;
449 unsigned char func_buffer[10];
450 unsigned char pub_key_buf[100];
451 size_t rx_len = 0;
452 static mbedtls_ecp_keypair ecp_key;
453
454 if( parse_remote_info( remote_info, &key_idx, &serial_port ) != 0 )
455 return( -1 );
456
457 /* Prepare command */
458 offset = 0;
459 func_buffer[offset++] = REMOTE_KEY_FUNC_GET_PUBKEY;
460 func_buffer[offset++] = key_idx;
461
462 if( serial_xfer( serial_port, func_buffer, offset, pub_key_buf, sizeof( pub_key_buf ), &rx_len ) != 0 )
463 {
464 mbedtls_printf( " failed\n ! Serial error trying to get pulic key\n\n" );
465 return( -1 );
466 }
467
468 /* Import public key from received binary */
469 mbedtls_ecp_keypair_init(&ecp_key);
470 ret = mbedtls_ecp_group_load(&ecp_key.grp, MBEDTLS_ECP_DP_SECP256R1);
471 if( ret != 0 )
472 {
473 mbedtls_printf( " failed\n ! Failed to load ecp group\n\n" );
474 return( ret );
475 }
476 ret = mbedtls_ecp_point_read_binary(&ecp_key.grp, &ecp_key.Q, pub_key_buf, rx_len );
477 if( ret != 0 )
478 {
479 mbedtls_printf( " failed\n ! Failed to read ecp key from binary\n\n" );
480 return( ret );
481 }
482 ctx->pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY );
483 ctx->pk_ctx = &ecp_key;
484 return( 0 );
485}
486
487/**
488 * @brief Tell if the context can do the operation given by type
489 *
490 * @param ctx PK Context
491 * @param type Target type
492 *
493 * @return 0 if context can't do the operations,
494 * 1 otherwise.
495 */
496static int remote_can_do_func(const void *ctx, mbedtls_pk_type_t type)
497{
498 UNUSED(ctx);
499 /* At the moment only ECDSA is supported */
500 return (MBEDTLS_PK_ECDSA == type);
501}
502
503typedef struct
504{
505 const char *serial_port;
506 unsigned char key_idx;
507} remote_serial_pk_context;
508
509/**
510 * @brief Sign using remote cryptoprocessor accessed over serial.
511 *
512 * @param ctx ECDSA context
513 * @param md_alg Hash Algorithm that was used to hash the message.
514 * Only SHA256 is supported.
515 * @param hash Message hash
516 * @param hash_len Length of hash
517 * @param sig Buffer that will hold the signature
518 * @param sig_len Length of the signature written
519 * @param f_rng RNG function
520 * @param p_rng RNG parameter
521 *
522 * @retval 0 if successful, or 1.
523 */
524static int remote_sign_func(void *ctx, mbedtls_md_type_t md_alg,
525 const unsigned char *hash, size_t hash_len,
526 unsigned char *sig, size_t *sig_len,
527 int (*f_rng)(void *, unsigned char *, size_t),
528 void *p_rng)
529{
530 remote_serial_pk_context * remote_ctx = (remote_serial_pk_context *)ctx;
531 /* Required buffer = func 1 byte + key Id 1 byte + hash len 4 bytes + hash */
532 unsigned char func_buffer[MBEDTLS_MD_MAX_SIZE + 4 + 1 + 1];
533 size_t offset = 0;
534
535 UNUSED( f_rng );
536 UNUSED( p_rng );
537
538 if( md_alg != MBEDTLS_MD_SHA256 )
539 return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
540
541 if( hash_len + 4 + 1 + 1 > sizeof( func_buffer ) )
542 {
543 return( MBEDTLS_ERR_PK_BUFFER_TOO_SMALL );
544 }
545
546 func_buffer[offset++] = REMOTE_KEY_FUNC_SIGN;
547 func_buffer[offset++] = remote_ctx->key_idx;
548 func_buffer[offset++] = hash_len >> 24;
549 func_buffer[offset++] = hash_len >> 16;
550 func_buffer[offset++] = hash_len >> 8;
551 func_buffer[offset++] = hash_len;
552
553 memcpy( func_buffer + offset, hash, hash_len );
554 offset += hash_len;
555
556 if( serial_xfer( remote_ctx->serial_port, func_buffer, offset, sig,
557 100/* FIXME */, sig_len ) != 0 )
558 {
559 mbedtls_printf( " failed\n ! Serial error in signing\n\n" );
560 return( -1 );
561 }
562
563 return( 0 );
564}
565
566void remote_free( void *ctx )
567{
568 /* Nothing to free since remote context is statically allocated.
569 * Within this app there is no need to scrub the memory.
570 */
571 UNUSED( ctx );
572}
573
574int mbedtls_pk_remote_setup( mbedtls_pk_context * ctx, const char * serial_port,
575 unsigned char key_idx )
576{
577 /* allocate remote serial context */
578 static remote_serial_pk_context remote;
579 /* Opaque private key */
580 static const mbedtls_pk_info_t remote_pk_info =
581 {
582 /* MBEDTLS_PK_ECKEY, */
583 MBEDTLS_PK_OPAQUE,
584 "RemoteSerial",
585 NULL,
586 remote_can_do_func,
587 NULL,
588 NULL,
589 remote_sign_func,
590 NULL,
591 NULL,
592 NULL,
593 NULL,
594 remote_free,
595 NULL
596 };
597
598
599 if ( ctx == NULL )
600 return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
601
602 remote.serial_port = serial_port;
603 remote.key_idx = key_idx;
604 ctx->pk_ctx = (void *)&remote;
605 ctx->pk_info = &remote_pk_info;
606
607 return( 0 );
608}
609
610int setup_opaque_privkey( const char * remote_info, mbedtls_pk_context * ctx )
611{
612 int key_idx = 0, ret = 0;
613 const char * serial_port = NULL;
614
615 if( parse_remote_info( remote_info, &key_idx, &serial_port ) != 0 )
616 return( -1 );
617
618 ret = mbedtls_pk_remote_setup( ctx, serial_port, key_idx );
619 if( ret != 0 )
620 {
621 mbedtls_printf( " failed\n ! remote pk setup failure \n\n" );
622 return( ret );
623 }
624
625 return( 0 );
626}
627#endif /* _WIN32 */
628
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200629int write_certificate( mbedtls_x509write_cert *crt, const char *output_file,
Manuel Pégourié-Gonnard31e59402013-09-12 05:59:05 +0200630 int (*f_rng)(void *, unsigned char *, size_t),
631 void *p_rng )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200632{
633 int ret;
634 FILE *f;
635 unsigned char output_buf[4096];
636 size_t len = 0;
637
638 memset( output_buf, 0, 4096 );
Hanno Becker81535d02017-09-13 15:39:59 +0100639 if( ( ret = mbedtls_x509write_crt_pem( crt, output_buf, 4096,
640 f_rng, p_rng ) ) < 0 )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200641 return( ret );
642
643 len = strlen( (char *) output_buf );
644
645 if( ( f = fopen( output_file, "w" ) ) == NULL )
646 return( -1 );
647
648 if( fwrite( output_buf, 1, len, f ) != len )
Paul Bakker0c226102014-04-17 16:02:36 +0200649 {
650 fclose( f );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200651 return( -1 );
Paul Bakker0c226102014-04-17 16:02:36 +0200652 }
Paul Bakker9397dcb2013-09-06 09:55:26 +0200653
Paul Bakker0c226102014-04-17 16:02:36 +0200654 fclose( f );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200655
656 return( 0 );
657}
658
Paul Bakker9397dcb2013-09-06 09:55:26 +0200659int main( int argc, char *argv[] )
660{
661 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200662 mbedtls_x509_crt issuer_crt;
663 mbedtls_pk_context loaded_issuer_key, loaded_subject_key;
664 mbedtls_pk_context *issuer_key = &loaded_issuer_key,
Manuel Pégourié-Gonnardf38e71a2013-09-12 05:21:54 +0200665 *subject_key = &loaded_subject_key;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200666 char buf[1024];
Jonathan Leroybbc75d92015-10-10 21:58:07 +0200667 char issuer_name[256];
Paul Bakkerc97f9f62013-11-30 15:13:02 +0100668 int i;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200669 char *p, *q, *r;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200670#if defined(MBEDTLS_X509_CSR_PARSE_C)
Jonathan Leroybbc75d92015-10-10 21:58:07 +0200671 char subject_name[256];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200672 mbedtls_x509_csr csr;
Paul Bakker7fc7fa62013-09-17 14:44:00 +0200673#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200674 mbedtls_x509write_cert crt;
675 mbedtls_mpi serial;
676 mbedtls_entropy_context entropy;
677 mbedtls_ctr_drbg_context ctr_drbg;
Manuel Pégourié-Gonnard31e59402013-09-12 05:59:05 +0200678 const char *pers = "crt example app";
Paul Bakker9397dcb2013-09-06 09:55:26 +0200679
680 /*
681 * Set to sane values
682 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200683 mbedtls_x509write_crt_init( &crt );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200684 mbedtls_pk_init( &loaded_issuer_key );
685 mbedtls_pk_init( &loaded_subject_key );
686 mbedtls_mpi_init( &serial );
Manuel Pégourié-Gonnardec160c02015-04-28 22:52:30 +0200687 mbedtls_ctr_drbg_init( &ctr_drbg );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200688#if defined(MBEDTLS_X509_CSR_PARSE_C)
689 mbedtls_x509_csr_init( &csr );
Paul Bakker7fc7fa62013-09-17 14:44:00 +0200690#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200691 mbedtls_x509_crt_init( &issuer_crt );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200692 memset( buf, 0, 1024 );
693
694 if( argc == 0 )
695 {
696 usage:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200697 mbedtls_printf( USAGE );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200698 ret = 1;
699 goto exit;
700 }
701
Paul Bakker1014e952013-09-09 13:59:42 +0200702 opt.issuer_crt = DFL_ISSUER_CRT;
Paul Bakkere2673fb2013-09-09 15:52:07 +0200703 opt.request_file = DFL_REQUEST_FILE;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200704 opt.subject_key = DFL_SUBJECT_KEY;
705 opt.issuer_key = DFL_ISSUER_KEY;
706 opt.subject_pwd = DFL_SUBJECT_PWD;
707 opt.issuer_pwd = DFL_ISSUER_PWD;
708 opt.output_file = DFL_OUTPUT_FILENAME;
709 opt.subject_name = DFL_SUBJECT_NAME;
710 opt.issuer_name = DFL_ISSUER_NAME;
711 opt.not_before = DFL_NOT_BEFORE;
712 opt.not_after = DFL_NOT_AFTER;
713 opt.serial = DFL_SERIAL;
Paul Bakkerb2d7f232013-09-09 16:24:18 +0200714 opt.selfsign = DFL_SELFSIGN;
Paul Bakker15162a02013-09-06 19:27:21 +0200715 opt.is_ca = DFL_IS_CA;
716 opt.max_pathlen = DFL_MAX_PATHLEN;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200717 opt.key_usage = DFL_KEY_USAGE;
718 opt.ns_cert_type = DFL_NS_CERT_TYPE;
Hanno Becker38eff432017-09-22 15:38:20 +0100719 opt.version = DFL_VERSION - 1;
Hanno Becker6c13d372017-09-13 12:49:22 +0100720 opt.md = DFL_DIGEST;
721 opt.subject_identifier = DFL_SUBJ_IDENT;
722 opt.authority_identifier = DFL_AUTH_IDENT;
723 opt.basic_constraints = DFL_CONSTRAINTS;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200724
725 for( i = 1; i < argc; i++ )
726 {
727
728 p = argv[i];
729 if( ( q = strchr( p, '=' ) ) == NULL )
730 goto usage;
731 *q++ = '\0';
732
Paul Bakkere2673fb2013-09-09 15:52:07 +0200733 if( strcmp( p, "request_file" ) == 0 )
734 opt.request_file = q;
735 else if( strcmp( p, "subject_key" ) == 0 )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200736 opt.subject_key = q;
737 else if( strcmp( p, "issuer_key" ) == 0 )
738 opt.issuer_key = q;
739 else if( strcmp( p, "subject_pwd" ) == 0 )
740 opt.subject_pwd = q;
741 else if( strcmp( p, "issuer_pwd" ) == 0 )
742 opt.issuer_pwd = q;
Paul Bakker1014e952013-09-09 13:59:42 +0200743 else if( strcmp( p, "issuer_crt" ) == 0 )
744 opt.issuer_crt = q;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200745 else if( strcmp( p, "output_file" ) == 0 )
746 opt.output_file = q;
747 else if( strcmp( p, "subject_name" ) == 0 )
748 {
749 opt.subject_name = q;
750 }
751 else if( strcmp( p, "issuer_name" ) == 0 )
752 {
753 opt.issuer_name = q;
754 }
755 else if( strcmp( p, "not_before" ) == 0 )
756 {
757 opt.not_before = q;
758 }
759 else if( strcmp( p, "not_after" ) == 0 )
760 {
761 opt.not_after = q;
762 }
763 else if( strcmp( p, "serial" ) == 0 )
764 {
765 opt.serial = q;
766 }
Hanno Becker6c13d372017-09-13 12:49:22 +0100767 else if( strcmp( p, "authority_identifier" ) == 0 )
768 {
769 opt.authority_identifier = atoi( q );
770 if( opt.authority_identifier != 0 &&
771 opt.authority_identifier != 1 )
772 {
Hanno Becker17c32762017-10-03 14:56:04 +0100773 mbedtls_printf( "Invalid argument for option %s\n", p );
Hanno Becker6c13d372017-09-13 12:49:22 +0100774 goto usage;
775 }
776 }
777 else if( strcmp( p, "subject_identifier" ) == 0 )
778 {
779 opt.subject_identifier = atoi( q );
780 if( opt.subject_identifier != 0 &&
781 opt.subject_identifier != 1 )
782 {
Hanno Becker17c32762017-10-03 14:56:04 +0100783 mbedtls_printf( "Invalid argument for option %s\n", p );
Hanno Becker6c13d372017-09-13 12:49:22 +0100784 goto usage;
785 }
786 }
787 else if( strcmp( p, "basic_constraints" ) == 0 )
788 {
789 opt.basic_constraints = atoi( q );
790 if( opt.basic_constraints != 0 &&
791 opt.basic_constraints != 1 )
792 {
Hanno Becker17c32762017-10-03 14:56:04 +0100793 mbedtls_printf( "Invalid argument for option %s\n", p );
Hanno Becker6c13d372017-09-13 12:49:22 +0100794 goto usage;
795 }
796 }
797 else if( strcmp( p, "md" ) == 0 )
798 {
799 if( strcmp( q, "SHA1" ) == 0 )
800 opt.md = MBEDTLS_MD_SHA1;
801 else if( strcmp( q, "SHA256" ) == 0 )
802 opt.md = MBEDTLS_MD_SHA256;
803 else if( strcmp( q, "SHA512" ) == 0 )
804 opt.md = MBEDTLS_MD_SHA512;
805 else if( strcmp( q, "MD5" ) == 0 )
806 opt.md = MBEDTLS_MD_MD5;
807 else
Hanno Becker17c32762017-10-03 14:56:04 +0100808 {
809 mbedtls_printf( "Invalid argument for option %s\n", p );
Hanno Becker6c13d372017-09-13 12:49:22 +0100810 goto usage;
Hanno Becker17c32762017-10-03 14:56:04 +0100811 }
Hanno Becker6c13d372017-09-13 12:49:22 +0100812 }
813 else if( strcmp( p, "version" ) == 0 )
814 {
815 opt.version = atoi( q );
816 if( opt.version < 1 || opt.version > 3 )
Hanno Becker17c32762017-10-03 14:56:04 +0100817 {
818 mbedtls_printf( "Invalid argument for option %s\n", p );
Hanno Becker6c13d372017-09-13 12:49:22 +0100819 goto usage;
Hanno Becker17c32762017-10-03 14:56:04 +0100820 }
Hanno Becker38eff432017-09-22 15:38:20 +0100821 opt.version--;
Hanno Becker6c13d372017-09-13 12:49:22 +0100822 }
Paul Bakkerb2d7f232013-09-09 16:24:18 +0200823 else if( strcmp( p, "selfsign" ) == 0 )
824 {
825 opt.selfsign = atoi( q );
826 if( opt.selfsign < 0 || opt.selfsign > 1 )
Hanno Becker17c32762017-10-03 14:56:04 +0100827 {
828 mbedtls_printf( "Invalid argument for option %s\n", p );
Paul Bakkerb2d7f232013-09-09 16:24:18 +0200829 goto usage;
Hanno Becker17c32762017-10-03 14:56:04 +0100830 }
Paul Bakkerb2d7f232013-09-09 16:24:18 +0200831 }
Paul Bakker15162a02013-09-06 19:27:21 +0200832 else if( strcmp( p, "is_ca" ) == 0 )
833 {
834 opt.is_ca = atoi( q );
835 if( opt.is_ca < 0 || opt.is_ca > 1 )
Hanno Becker17c32762017-10-03 14:56:04 +0100836 {
837 mbedtls_printf( "Invalid argument for option %s\n", p );
Paul Bakker15162a02013-09-06 19:27:21 +0200838 goto usage;
Hanno Becker17c32762017-10-03 14:56:04 +0100839 }
Paul Bakker15162a02013-09-06 19:27:21 +0200840 }
841 else if( strcmp( p, "max_pathlen" ) == 0 )
842 {
843 opt.max_pathlen = atoi( q );
844 if( opt.max_pathlen < -1 || opt.max_pathlen > 127 )
Hanno Becker17c32762017-10-03 14:56:04 +0100845 {
846 mbedtls_printf( "Invalid argument for option %s\n", p );
Paul Bakker15162a02013-09-06 19:27:21 +0200847 goto usage;
Hanno Becker17c32762017-10-03 14:56:04 +0100848 }
Paul Bakker15162a02013-09-06 19:27:21 +0200849 }
Paul Bakker9397dcb2013-09-06 09:55:26 +0200850 else if( strcmp( p, "key_usage" ) == 0 )
851 {
852 while( q != NULL )
853 {
854 if( ( r = strchr( q, ',' ) ) != NULL )
855 *r++ = '\0';
856
857 if( strcmp( q, "digital_signature" ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200858 opt.key_usage |= MBEDTLS_X509_KU_DIGITAL_SIGNATURE;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200859 else if( strcmp( q, "non_repudiation" ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200860 opt.key_usage |= MBEDTLS_X509_KU_NON_REPUDIATION;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200861 else if( strcmp( q, "key_encipherment" ) == 0 )
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +0100862 opt.key_usage |= MBEDTLS_X509_KU_KEY_ENCIPHERMENT;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200863 else if( strcmp( q, "data_encipherment" ) == 0 )
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +0100864 opt.key_usage |= MBEDTLS_X509_KU_DATA_ENCIPHERMENT;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200865 else if( strcmp( q, "key_agreement" ) == 0 )
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +0100866 opt.key_usage |= MBEDTLS_X509_KU_KEY_AGREEMENT;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200867 else if( strcmp( q, "key_cert_sign" ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200868 opt.key_usage |= MBEDTLS_X509_KU_KEY_CERT_SIGN;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200869 else if( strcmp( q, "crl_sign" ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200870 opt.key_usage |= MBEDTLS_X509_KU_CRL_SIGN;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200871 else
Hanno Becker17c32762017-10-03 14:56:04 +0100872 {
873 mbedtls_printf( "Invalid argument for option %s\n", p );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200874 goto usage;
Hanno Becker17c32762017-10-03 14:56:04 +0100875 }
Paul Bakker9397dcb2013-09-06 09:55:26 +0200876
877 q = r;
878 }
879 }
880 else if( strcmp( p, "ns_cert_type" ) == 0 )
881 {
882 while( q != NULL )
883 {
884 if( ( r = strchr( q, ',' ) ) != NULL )
885 *r++ = '\0';
886
887 if( strcmp( q, "ssl_client" ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200888 opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200889 else if( strcmp( q, "ssl_server" ) == 0 )
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +0100890 opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200891 else if( strcmp( q, "email" ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200892 opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_EMAIL;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200893 else if( strcmp( q, "object_signing" ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200894 opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200895 else if( strcmp( q, "ssl_ca" ) == 0 )
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +0100896 opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_SSL_CA;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200897 else if( strcmp( q, "email_ca" ) == 0 )
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +0100898 opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200899 else if( strcmp( q, "object_signing_ca" ) == 0 )
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +0100900 opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200901 else
Hanno Becker17c32762017-10-03 14:56:04 +0100902 {
903 mbedtls_printf( "Invalid argument for option %s\n", p );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200904 goto usage;
Hanno Becker17c32762017-10-03 14:56:04 +0100905 }
Paul Bakker9397dcb2013-09-06 09:55:26 +0200906
907 q = r;
908 }
909 }
910 else
911 goto usage;
912 }
913
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200914 mbedtls_printf("\n");
Paul Bakker1014e952013-09-09 13:59:42 +0200915
Manuel Pégourié-Gonnard31e59402013-09-12 05:59:05 +0200916 /*
917 * 0. Seed the PRNG
918 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200919 mbedtls_printf( " . Seeding the random number generator..." );
Manuel Pégourié-Gonnard31e59402013-09-12 05:59:05 +0200920 fflush( stdout );
921
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200922 mbedtls_entropy_init( &entropy );
Manuel Pégourié-Gonnardec160c02015-04-28 22:52:30 +0200923 if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy,
Manuel Pégourié-Gonnard31e59402013-09-12 05:59:05 +0200924 (const unsigned char *) pers,
925 strlen( pers ) ) ) != 0 )
926 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200927 mbedtls_strerror( ret, buf, 1024 );
Hanno Becker81535d02017-09-13 15:39:59 +0100928 mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned %d - %s\n",
929 ret, buf );
Manuel Pégourié-Gonnard31e59402013-09-12 05:59:05 +0200930 goto exit;
931 }
932
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200933 mbedtls_printf( " ok\n" );
Manuel Pégourié-Gonnard31e59402013-09-12 05:59:05 +0200934
Paul Bakker9397dcb2013-09-06 09:55:26 +0200935 // Parse serial to MPI
936 //
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200937 mbedtls_printf( " . Reading serial number..." );
Manuel Pégourié-Gonnard31e59402013-09-12 05:59:05 +0200938 fflush( stdout );
939
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200940 if( ( ret = mbedtls_mpi_read_string( &serial, 10, opt.serial ) ) != 0 )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200941 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200942 mbedtls_strerror( ret, buf, 1024 );
Hanno Becker81535d02017-09-13 15:39:59 +0100943 mbedtls_printf( " failed\n ! mbedtls_mpi_read_string "
Hanno Becker7f3652d2017-09-22 15:39:02 +0100944 "returned -0x%04x - %s\n\n", -ret, buf );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200945 goto exit;
946 }
947
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200948 mbedtls_printf( " ok\n" );
Manuel Pégourié-Gonnard31e59402013-09-12 05:59:05 +0200949
Paul Bakker1014e952013-09-09 13:59:42 +0200950 // Parse issuer certificate if present
951 //
Paul Bakkerb2d7f232013-09-09 16:24:18 +0200952 if( !opt.selfsign && strlen( opt.issuer_crt ) )
Paul Bakker1014e952013-09-09 13:59:42 +0200953 {
954 /*
Paul Bakkere2673fb2013-09-09 15:52:07 +0200955 * 1.0.a. Load the certificates
Paul Bakker1014e952013-09-09 13:59:42 +0200956 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200957 mbedtls_printf( " . Loading the issuer certificate ..." );
Paul Bakker1014e952013-09-09 13:59:42 +0200958 fflush( stdout );
959
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200960 if( ( ret = mbedtls_x509_crt_parse_file( &issuer_crt, opt.issuer_crt ) ) != 0 )
Paul Bakker1014e952013-09-09 13:59:42 +0200961 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200962 mbedtls_strerror( ret, buf, 1024 );
Hanno Becker81535d02017-09-13 15:39:59 +0100963 mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse_file "
Hanno Becker7f3652d2017-09-22 15:39:02 +0100964 "returned -0x%04x - %s\n\n", -ret, buf );
Paul Bakker1014e952013-09-09 13:59:42 +0200965 goto exit;
966 }
967
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200968 ret = mbedtls_x509_dn_gets( issuer_name, sizeof(issuer_name),
Paul Bakkerfdba4682014-04-25 11:48:35 +0200969 &issuer_crt.subject );
Paul Bakker1014e952013-09-09 13:59:42 +0200970 if( ret < 0 )
971 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200972 mbedtls_strerror( ret, buf, 1024 );
Hanno Becker81535d02017-09-13 15:39:59 +0100973 mbedtls_printf( " failed\n ! mbedtls_x509_dn_gets "
Hanno Becker7f3652d2017-09-22 15:39:02 +0100974 "returned -0x%04x - %s\n\n", -ret, buf );
Paul Bakker1014e952013-09-09 13:59:42 +0200975 goto exit;
976 }
977
Paul Bakkere2673fb2013-09-09 15:52:07 +0200978 opt.issuer_name = issuer_name;
979
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200980 mbedtls_printf( " ok\n" );
Paul Bakkere2673fb2013-09-09 15:52:07 +0200981 }
982
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200983#if defined(MBEDTLS_X509_CSR_PARSE_C)
Paul Bakkere2673fb2013-09-09 15:52:07 +0200984 // Parse certificate request if present
985 //
Paul Bakkerb2d7f232013-09-09 16:24:18 +0200986 if( !opt.selfsign && strlen( opt.request_file ) )
Paul Bakkere2673fb2013-09-09 15:52:07 +0200987 {
988 /*
989 * 1.0.b. Load the CSR
990 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200991 mbedtls_printf( " . Loading the certificate request ..." );
Paul Bakkere2673fb2013-09-09 15:52:07 +0200992 fflush( stdout );
993
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200994 if( ( ret = mbedtls_x509_csr_parse_file( &csr, opt.request_file ) ) != 0 )
Paul Bakkere2673fb2013-09-09 15:52:07 +0200995 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200996 mbedtls_strerror( ret, buf, 1024 );
Hanno Becker81535d02017-09-13 15:39:59 +0100997 mbedtls_printf( " failed\n ! mbedtls_x509_csr_parse_file "
Hanno Becker7f3652d2017-09-22 15:39:02 +0100998 "returned -0x%04x - %s\n\n", -ret, buf );
Paul Bakkere2673fb2013-09-09 15:52:07 +0200999 goto exit;
1000 }
1001
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001002 ret = mbedtls_x509_dn_gets( subject_name, sizeof(subject_name),
Paul Bakkere2673fb2013-09-09 15:52:07 +02001003 &csr.subject );
1004 if( ret < 0 )
1005 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001006 mbedtls_strerror( ret, buf, 1024 );
Hanno Becker81535d02017-09-13 15:39:59 +01001007 mbedtls_printf( " failed\n ! mbedtls_x509_dn_gets "
Hanno Becker7f3652d2017-09-22 15:39:02 +01001008 "returned -0x%04x - %s\n\n", -ret, buf );
Paul Bakkere2673fb2013-09-09 15:52:07 +02001009 goto exit;
1010 }
1011
1012 opt.subject_name = subject_name;
Manuel Pégourié-Gonnardf38e71a2013-09-12 05:21:54 +02001013 subject_key = &csr.pk;
Paul Bakkere2673fb2013-09-09 15:52:07 +02001014
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001015 mbedtls_printf( " ok\n" );
Paul Bakkerb2d7f232013-09-09 16:24:18 +02001016 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001017#endif /* MBEDTLS_X509_CSR_PARSE_C */
Paul Bakkerb2d7f232013-09-09 16:24:18 +02001018
1019 /*
1020 * 1.1. Load the keys
1021 */
1022 if( !opt.selfsign && !strlen( opt.request_file ) )
1023 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001024 mbedtls_printf( " . Loading the subject key ..." );
Paul Bakkerb2d7f232013-09-09 16:24:18 +02001025 fflush( stdout );
1026
Azim Khan7a339902018-02-21 01:05:21 +00001027#if defined(_WIN32)
Azim Khan26a455c2018-02-07 11:11:17 +00001028 if ( is_remote_key( opt.subject_key ) )
Paul Bakkere2673fb2013-09-09 15:52:07 +02001029 {
Azim Khan26a455c2018-02-07 11:11:17 +00001030 ret = load_pubkey_from_remote( opt.subject_key, &loaded_subject_key );
1031 if ( ret != 0 )
1032 goto exit;
1033 }
1034 else
Azim Khan7a339902018-02-21 01:05:21 +00001035#endif
Azim Khan26a455c2018-02-07 11:11:17 +00001036 {
1037 ret = mbedtls_pk_parse_keyfile( &loaded_subject_key, opt.subject_key,
1038 opt.subject_pwd );
1039 if( ret != 0 )
1040 {
1041 mbedtls_strerror( ret, buf, 1024 );
1042 mbedtls_printf( " failed\n ! mbedtls_pk_parse_keyfile "
1043 "returned -0x%04x - %s\n\n", -ret, buf );
1044 goto exit;
1045 }
Paul Bakkere2673fb2013-09-09 15:52:07 +02001046 }
Paul Bakker1014e952013-09-09 13:59:42 +02001047
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001048 mbedtls_printf( " ok\n" );
Paul Bakker1014e952013-09-09 13:59:42 +02001049 }
1050
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001051 mbedtls_printf( " . Loading the issuer key ..." );
Paul Bakkerb2d7f232013-09-09 16:24:18 +02001052 fflush( stdout );
1053
Azim Khan7a339902018-02-21 01:05:21 +00001054#if defined(_WIN32)
Azim Khan26a455c2018-02-07 11:11:17 +00001055 if ( is_remote_key( opt.issuer_key ) )
1056 {
1057 ret = setup_opaque_privkey( opt.issuer_key, &loaded_issuer_key );
1058 if ( ret != 0 )
1059 goto exit;
1060 }
1061 else
Azim Khan7a339902018-02-21 01:05:21 +00001062#endif
Azim Khan26a455c2018-02-07 11:11:17 +00001063 {
1064 ret = mbedtls_pk_parse_keyfile( &loaded_issuer_key, opt.issuer_key,
1065 opt.issuer_pwd );
1066 }
1067
Paul Bakkerb2d7f232013-09-09 16:24:18 +02001068 if( ret != 0 )
1069 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001070 mbedtls_strerror( ret, buf, 1024 );
Hanno Becker81535d02017-09-13 15:39:59 +01001071 mbedtls_printf( " failed\n ! mbedtls_pk_parse_keyfile "
1072 "returned -x%02x - %s\n\n", -ret, buf );
Paul Bakkerb2d7f232013-09-09 16:24:18 +02001073 goto exit;
1074 }
1075
1076 // Check if key and issuer certificate match
1077 //
1078 if( strlen( opt.issuer_crt ) )
1079 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001080 if( !mbedtls_pk_can_do( &issuer_crt.pk, MBEDTLS_PK_RSA ) ||
1081 mbedtls_mpi_cmp_mpi( &mbedtls_pk_rsa( issuer_crt.pk )->N,
1082 &mbedtls_pk_rsa( *issuer_key )->N ) != 0 ||
1083 mbedtls_mpi_cmp_mpi( &mbedtls_pk_rsa( issuer_crt.pk )->E,
1084 &mbedtls_pk_rsa( *issuer_key )->E ) != 0 )
Paul Bakkerb2d7f232013-09-09 16:24:18 +02001085 {
Hanno Becker81535d02017-09-13 15:39:59 +01001086 mbedtls_printf( " failed\n ! issuer_key does not match "
1087 "issuer certificate\n\n" );
Paul Bakkerb2d7f232013-09-09 16:24:18 +02001088 ret = -1;
1089 goto exit;
1090 }
1091 }
1092
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001093 mbedtls_printf( " ok\n" );
Paul Bakkerb2d7f232013-09-09 16:24:18 +02001094
1095 if( opt.selfsign )
1096 {
Paul Bakker93c6aa42013-10-28 22:28:09 +01001097 opt.subject_name = opt.issuer_name;
Manuel Pégourié-Gonnardf38e71a2013-09-12 05:21:54 +02001098 subject_key = issuer_key;
Paul Bakkerb2d7f232013-09-09 16:24:18 +02001099 }
1100
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001101 mbedtls_x509write_crt_set_subject_key( &crt, subject_key );
1102 mbedtls_x509write_crt_set_issuer_key( &crt, issuer_key );
Paul Bakkerb2d7f232013-09-09 16:24:18 +02001103
Paul Bakker9397dcb2013-09-06 09:55:26 +02001104 /*
1105 * 1.0. Check the names for validity
1106 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001107 if( ( ret = mbedtls_x509write_crt_set_subject_name( &crt, opt.subject_name ) ) != 0 )
Paul Bakker9397dcb2013-09-06 09:55:26 +02001108 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001109 mbedtls_strerror( ret, buf, 1024 );
Hanno Becker81535d02017-09-13 15:39:59 +01001110 mbedtls_printf( " failed\n ! mbedtls_x509write_crt_set_subject_name "
Hanno Becker7f3652d2017-09-22 15:39:02 +01001111 "returned -0x%04x - %s\n\n", -ret, buf );
Paul Bakker9397dcb2013-09-06 09:55:26 +02001112 goto exit;
1113 }
1114
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001115 if( ( ret = mbedtls_x509write_crt_set_issuer_name( &crt, opt.issuer_name ) ) != 0 )
Paul Bakker9397dcb2013-09-06 09:55:26 +02001116 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001117 mbedtls_strerror( ret, buf, 1024 );
Hanno Becker81535d02017-09-13 15:39:59 +01001118 mbedtls_printf( " failed\n ! mbedtls_x509write_crt_set_issuer_name "
Hanno Becker7f3652d2017-09-22 15:39:02 +01001119 "returned -0x%04x - %s\n\n", -ret, buf );
Paul Bakker9397dcb2013-09-06 09:55:26 +02001120 goto exit;
1121 }
1122
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001123 mbedtls_printf( " . Setting certificate values ..." );
Paul Bakker9397dcb2013-09-06 09:55:26 +02001124 fflush( stdout );
1125
Hanno Becker38eff432017-09-22 15:38:20 +01001126 mbedtls_x509write_crt_set_version( &crt, opt.version );
Hanno Becker6c13d372017-09-13 12:49:22 +01001127 mbedtls_x509write_crt_set_md_alg( &crt, opt.md );
1128
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001129 ret = mbedtls_x509write_crt_set_serial( &crt, &serial );
Paul Bakker9397dcb2013-09-06 09:55:26 +02001130 if( ret != 0 )
1131 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001132 mbedtls_strerror( ret, buf, 1024 );
Hanno Becker81535d02017-09-13 15:39:59 +01001133 mbedtls_printf( " failed\n ! mbedtls_x509write_crt_set_serial "
Hanno Becker7f3652d2017-09-22 15:39:02 +01001134 "returned -0x%04x - %s\n\n", -ret, buf );
Paul Bakker9397dcb2013-09-06 09:55:26 +02001135 goto exit;
1136 }
1137
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001138 ret = mbedtls_x509write_crt_set_validity( &crt, opt.not_before, opt.not_after );
Paul Bakker9397dcb2013-09-06 09:55:26 +02001139 if( ret != 0 )
1140 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001141 mbedtls_strerror( ret, buf, 1024 );
Hanno Becker81535d02017-09-13 15:39:59 +01001142 mbedtls_printf( " failed\n ! mbedtls_x509write_crt_set_validity "
Hanno Becker7f3652d2017-09-22 15:39:02 +01001143 "returned -0x%04x - %s\n\n", -ret, buf );
Paul Bakker9397dcb2013-09-06 09:55:26 +02001144 goto exit;
1145 }
1146
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001147 mbedtls_printf( " ok\n" );
Paul Bakker9397dcb2013-09-06 09:55:26 +02001148
Hanno Becker38eff432017-09-22 15:38:20 +01001149 if( opt.version == MBEDTLS_X509_CRT_VERSION_3 &&
1150 opt.basic_constraints != 0 )
Paul Bakker15162a02013-09-06 19:27:21 +02001151 {
Hanno Becker6c13d372017-09-13 12:49:22 +01001152 mbedtls_printf( " . Adding the Basic Constraints extension ..." );
1153 fflush( stdout );
Paul Bakker15162a02013-09-06 19:27:21 +02001154
Hanno Becker6c13d372017-09-13 12:49:22 +01001155 ret = mbedtls_x509write_crt_set_basic_constraints( &crt, opt.is_ca,
1156 opt.max_pathlen );
1157 if( ret != 0 )
1158 {
1159 mbedtls_strerror( ret, buf, 1024 );
1160 mbedtls_printf( " failed\n ! x509write_crt_set_basic_contraints "
Hanno Becker7f3652d2017-09-22 15:39:02 +01001161 "returned -0x%04x - %s\n\n", -ret, buf );
Hanno Becker6c13d372017-09-13 12:49:22 +01001162 goto exit;
1163 }
1164
1165 mbedtls_printf( " ok\n" );
1166 }
Paul Bakker15162a02013-09-06 19:27:21 +02001167
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001168#if defined(MBEDTLS_SHA1_C)
Hanno Becker38eff432017-09-22 15:38:20 +01001169 if( opt.version == MBEDTLS_X509_CRT_VERSION_3 &&
1170 opt.subject_identifier != 0 )
Paul Bakker15162a02013-09-06 19:27:21 +02001171 {
Hanno Becker6c13d372017-09-13 12:49:22 +01001172 mbedtls_printf( " . Adding the Subject Key Identifier ..." );
1173 fflush( stdout );
1174
1175 ret = mbedtls_x509write_crt_set_subject_key_identifier( &crt );
1176 if( ret != 0 )
1177 {
1178 mbedtls_strerror( ret, buf, 1024 );
1179 mbedtls_printf( " failed\n ! mbedtls_x509write_crt_set_subject"
Hanno Becker7f3652d2017-09-22 15:39:02 +01001180 "_key_identifier returned -0x%04x - %s\n\n",
Hanno Becker6c13d372017-09-13 12:49:22 +01001181 -ret, buf );
1182 goto exit;
1183 }
1184
1185 mbedtls_printf( " ok\n" );
Paul Bakker15162a02013-09-06 19:27:21 +02001186 }
1187
Hanno Becker38eff432017-09-22 15:38:20 +01001188 if( opt.version == MBEDTLS_X509_CRT_VERSION_3 &&
1189 opt.authority_identifier != 0 )
Paul Bakker15162a02013-09-06 19:27:21 +02001190 {
Hanno Becker6c13d372017-09-13 12:49:22 +01001191 mbedtls_printf( " . Adding the Authority Key Identifier ..." );
1192 fflush( stdout );
Paul Bakker15162a02013-09-06 19:27:21 +02001193
Hanno Becker6c13d372017-09-13 12:49:22 +01001194 ret = mbedtls_x509write_crt_set_authority_key_identifier( &crt );
1195 if( ret != 0 )
1196 {
1197 mbedtls_strerror( ret, buf, 1024 );
1198 mbedtls_printf( " failed\n ! mbedtls_x509write_crt_set_authority_"
Hanno Becker7f3652d2017-09-22 15:39:02 +01001199 "key_identifier returned -0x%04x - %s\n\n",
Hanno Becker6c13d372017-09-13 12:49:22 +01001200 -ret, buf );
1201 goto exit;
1202 }
1203
1204 mbedtls_printf( " ok\n" );
1205 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001206#endif /* MBEDTLS_SHA1_C */
Paul Bakker15162a02013-09-06 19:27:21 +02001207
Hanno Becker38eff432017-09-22 15:38:20 +01001208 if( opt.version == MBEDTLS_X509_CRT_VERSION_3 &&
1209 opt.key_usage != 0 )
Paul Bakker52be08c2013-09-09 12:37:54 +02001210 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001211 mbedtls_printf( " . Adding the Key Usage extension ..." );
Paul Bakker52be08c2013-09-09 12:37:54 +02001212 fflush( stdout );
1213
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001214 ret = mbedtls_x509write_crt_set_key_usage( &crt, opt.key_usage );
Paul Bakker52be08c2013-09-09 12:37:54 +02001215 if( ret != 0 )
1216 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001217 mbedtls_strerror( ret, buf, 1024 );
Hanno Becker81535d02017-09-13 15:39:59 +01001218 mbedtls_printf( " failed\n ! mbedtls_x509write_crt_set_key_usage "
Hanno Becker7f3652d2017-09-22 15:39:02 +01001219 "returned -0x%04x - %s\n\n", -ret, buf );
Paul Bakker52be08c2013-09-09 12:37:54 +02001220 goto exit;
1221 }
1222
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001223 mbedtls_printf( " ok\n" );
Paul Bakker52be08c2013-09-09 12:37:54 +02001224 }
1225
Hanno Becker38eff432017-09-22 15:38:20 +01001226 if( opt.version == MBEDTLS_X509_CRT_VERSION_3 &&
1227 opt.ns_cert_type != 0 )
Paul Bakker52be08c2013-09-09 12:37:54 +02001228 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001229 mbedtls_printf( " . Adding the NS Cert Type extension ..." );
Paul Bakker52be08c2013-09-09 12:37:54 +02001230 fflush( stdout );
1231
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001232 ret = mbedtls_x509write_crt_set_ns_cert_type( &crt, opt.ns_cert_type );
Paul Bakker52be08c2013-09-09 12:37:54 +02001233 if( ret != 0 )
1234 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001235 mbedtls_strerror( ret, buf, 1024 );
Hanno Becker81535d02017-09-13 15:39:59 +01001236 mbedtls_printf( " failed\n ! mbedtls_x509write_crt_set_ns_cert_type "
Hanno Becker7f3652d2017-09-22 15:39:02 +01001237 "returned -0x%04x - %s\n\n", -ret, buf );
Paul Bakker52be08c2013-09-09 12:37:54 +02001238 goto exit;
1239 }
1240
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001241 mbedtls_printf( " ok\n" );
Paul Bakker52be08c2013-09-09 12:37:54 +02001242 }
1243
Paul Bakker9397dcb2013-09-06 09:55:26 +02001244 /*
1245 * 1.2. Writing the request
1246 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001247 mbedtls_printf( " . Writing the certificate..." );
Paul Bakker9397dcb2013-09-06 09:55:26 +02001248 fflush( stdout );
1249
Manuel Pégourié-Gonnard31e59402013-09-12 05:59:05 +02001250 if( ( ret = write_certificate( &crt, opt.output_file,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001251 mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 )
Paul Bakker9397dcb2013-09-06 09:55:26 +02001252 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001253 mbedtls_strerror( ret, buf, 1024 );
Hanno Becker7f3652d2017-09-22 15:39:02 +01001254 mbedtls_printf( " failed\n ! write_certificate -0x%04x - %s\n\n",
Hanno Becker81535d02017-09-13 15:39:59 +01001255 -ret, buf );
Paul Bakker9397dcb2013-09-06 09:55:26 +02001256 goto exit;
1257 }
1258
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001259 mbedtls_printf( " ok\n" );
Paul Bakker9397dcb2013-09-06 09:55:26 +02001260
1261exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001262 mbedtls_x509write_crt_free( &crt );
1263 mbedtls_pk_free( &loaded_subject_key );
Azim Khan7a339902018-02-21 01:05:21 +00001264 mbedtls_pk_free( &loaded_issuer_key );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001265 mbedtls_mpi_free( &serial );
1266 mbedtls_ctr_drbg_free( &ctr_drbg );
1267 mbedtls_entropy_free( &entropy );
Paul Bakker9397dcb2013-09-06 09:55:26 +02001268
1269#if defined(_WIN32)
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001270 mbedtls_printf( " + Press Enter to exit this program.\n" );
Paul Bakker9397dcb2013-09-06 09:55:26 +02001271 fflush( stdout ); getchar();
1272#endif
1273
1274 return( ret );
1275}
Azim Khan26a455c2018-02-07 11:11:17 +00001276
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001277#endif /* MBEDTLS_X509_CRT_WRITE_C && MBEDTLS_X509_CRT_PARSE_C &&
1278 MBEDTLS_FS_IO && MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C &&
Simon Butcher203a6932016-10-07 15:00:17 +01001279 MBEDTLS_ERROR_C && MBEDTLS_PEM_WRITE_C */