blob: 2dca1a1801a66a837807b17b211df565289f38e3 [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{
Azim Khan969191f2018-02-22 11:09:40 +0000214 size_t offset = 0;
215 size_t remote_info_len = strlen( remote_info );
Azim Khan7a339902018-02-21 01:05:21 +0000216
Azim Khan0f9708f2018-02-22 13:24:16 +0000217 if( !is_remote_key( remote_info ) )
Azim Khan7a339902018-02-21 01:05:21 +0000218 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 */
Azim Khan969191f2018-02-22 11:09:40 +0000342 if( !WriteFile( h_comm, REMOTE_KEY_MAGIC_PATTERN, (DWORD)strlen(REMOTE_KEY_MAGIC_PATTERN),
Azim Khan7a339902018-02-21 01:05:21 +0000343 &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 {
Azim Khan969191f2018-02-22 11:09:40 +0000365 mbedtls_printf("Failed to sync!\n");
Azim Khan7a339902018-02-21 01:05:21 +0000366 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 }
Azim Khan969191f2018-02-22 11:09:40 +0000376 if( !WriteFile( h_comm, tx_buf, (DWORD)tx_buf_len,
Azim Khan7a339902018-02-21 01:05:21 +0000377 &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 {
Azim Khan969191f2018-02-22 11:09:40 +0000405 if( !ReadFile( h_comm, rx_buf + len, (DWORD)(*rx_len - len), &xfer_len, NULL ) )
Azim Khan7a339902018-02-21 01:05:21 +0000406 {
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;
Azim Khan0f9708f2018-02-22 13:24:16 +0000449 unsigned char func_buffer[2]; /* Op code: 1 + key Id: 1 */
Azim Khan88953b62018-02-22 17:46:48 +0000450 unsigned char pub_key_buf[65]; /* ECDSA Pub key: 64 + EC octet string format tag: 1 */
Azim Khan7a339902018-02-21 01:05:21 +0000451 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
Azim Khan0f9708f2018-02-22 13:24:16 +0000462 if( serial_xfer( serial_port, func_buffer, offset, pub_key_buf,
463 sizeof( pub_key_buf ), &rx_len ) != 0 )
Azim Khan7a339902018-02-21 01:05:21 +0000464 {
465 mbedtls_printf( " failed\n ! Serial error trying to get pulic key\n\n" );
466 return( -1 );
467 }
468
469 /* Import public key from received binary */
470 mbedtls_ecp_keypair_init(&ecp_key);
471 ret = mbedtls_ecp_group_load(&ecp_key.grp, MBEDTLS_ECP_DP_SECP256R1);
472 if( ret != 0 )
473 {
474 mbedtls_printf( " failed\n ! Failed to load ecp group\n\n" );
475 return( ret );
476 }
477 ret = mbedtls_ecp_point_read_binary(&ecp_key.grp, &ecp_key.Q, pub_key_buf, rx_len );
478 if( ret != 0 )
479 {
480 mbedtls_printf( " failed\n ! Failed to read ecp key from binary\n\n" );
481 return( ret );
482 }
Azim Khan0f9708f2018-02-22 13:24:16 +0000483 mbedtls_pk_setup( ctx, mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY ) );
Azim Khan7a339902018-02-21 01:05:21 +0000484 ctx->pk_ctx = &ecp_key;
485 return( 0 );
486}
487
488/**
489 * @brief Tell if the context can do the operation given by type
490 *
491 * @param ctx PK Context
492 * @param type Target type
493 *
494 * @return 0 if context can't do the operations,
495 * 1 otherwise.
496 */
497static int remote_can_do_func(const void *ctx, mbedtls_pk_type_t type)
498{
499 UNUSED(ctx);
500 /* At the moment only ECDSA is supported */
501 return (MBEDTLS_PK_ECDSA == type);
502}
503
504typedef struct
505{
506 const char *serial_port;
507 unsigned char key_idx;
508} remote_serial_pk_context;
509
510/**
511 * @brief Sign using remote cryptoprocessor accessed over serial.
512 *
513 * @param ctx ECDSA context
514 * @param md_alg Hash Algorithm that was used to hash the message.
515 * Only SHA256 is supported.
516 * @param hash Message hash
517 * @param hash_len Length of hash
518 * @param sig Buffer that will hold the signature
519 * @param sig_len Length of the signature written
520 * @param f_rng RNG function
521 * @param p_rng RNG parameter
522 *
523 * @retval 0 if successful, or 1.
524 */
525static int remote_sign_func(void *ctx, mbedtls_md_type_t md_alg,
526 const unsigned char *hash, size_t hash_len,
527 unsigned char *sig, size_t *sig_len,
528 int (*f_rng)(void *, unsigned char *, size_t),
529 void *p_rng)
530{
531 remote_serial_pk_context * remote_ctx = (remote_serial_pk_context *)ctx;
532 /* Required buffer = func 1 byte + key Id 1 byte + hash len 4 bytes + hash */
533 unsigned char func_buffer[MBEDTLS_MD_MAX_SIZE + 4 + 1 + 1];
534 size_t offset = 0;
535
536 UNUSED( f_rng );
537 UNUSED( p_rng );
538
Azim Khan0f9708f2018-02-22 13:24:16 +0000539 /* Currently this feature only supports Crypto chip ATCAECC508A that only
540 * supports SHA256. */
Azim Khan7a339902018-02-21 01:05:21 +0000541 if( md_alg != MBEDTLS_MD_SHA256 )
542 return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
543
544 if( hash_len + 4 + 1 + 1 > sizeof( func_buffer ) )
545 {
546 return( MBEDTLS_ERR_PK_BUFFER_TOO_SMALL );
547 }
548
549 func_buffer[offset++] = REMOTE_KEY_FUNC_SIGN;
550 func_buffer[offset++] = remote_ctx->key_idx;
Azim Khan969191f2018-02-22 11:09:40 +0000551 func_buffer[offset++] = (unsigned char)(hash_len >> 24);
552 func_buffer[offset++] = (unsigned char)(hash_len >> 16);
553 func_buffer[offset++] = (unsigned char)(hash_len >> 8);
554 func_buffer[offset++] = (unsigned char)(hash_len);
Azim Khan7a339902018-02-21 01:05:21 +0000555
556 memcpy( func_buffer + offset, hash, hash_len );
557 offset += hash_len;
558
559 if( serial_xfer( remote_ctx->serial_port, func_buffer, offset, sig,
Azim Khaneda800f2018-02-21 10:39:44 +0000560 MBEDTLS_ECDSA_MAX_SIG_LEN(256), sig_len ) != 0 )
Azim Khan7a339902018-02-21 01:05:21 +0000561 {
562 mbedtls_printf( " failed\n ! Serial error in signing\n\n" );
563 return( -1 );
564 }
565
566 return( 0 );
567}
568
569void remote_free( void *ctx )
570{
571 /* Nothing to free since remote context is statically allocated.
572 * Within this app there is no need to scrub the memory.
573 */
574 UNUSED( ctx );
575}
576
577int mbedtls_pk_remote_setup( mbedtls_pk_context * ctx, const char * serial_port,
578 unsigned char key_idx )
579{
580 /* allocate remote serial context */
581 static remote_serial_pk_context remote;
582 /* Opaque private key */
583 static const mbedtls_pk_info_t remote_pk_info =
Azim Khan0f9708f2018-02-22 13:24:16 +0000584 MBEDTLS_PK_OPAQUE_INFO_1(
585 "RemoteSerial",
586 NULL,
587 remote_can_do_func,
588 NULL,
589 NULL,
590 remote_sign_func,
591 NULL,
592 NULL,
593 NULL,
594 NULL,
595 remote_free,
596 NULL
597 );
Azim Khan7a339902018-02-21 01:05:21 +0000598
599
600 if ( ctx == NULL )
601 return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
602
603 remote.serial_port = serial_port;
604 remote.key_idx = key_idx;
Azim Khan0f9708f2018-02-22 13:24:16 +0000605 mbedtls_pk_setup( ctx, &remote_pk_info );
Azim Khan7a339902018-02-21 01:05:21 +0000606 ctx->pk_ctx = (void *)&remote;
Azim Khan7a339902018-02-21 01:05:21 +0000607
608 return( 0 );
609}
610
611int setup_opaque_privkey( const char * remote_info, mbedtls_pk_context * ctx )
612{
613 int key_idx = 0, ret = 0;
614 const char * serial_port = NULL;
615
616 if( parse_remote_info( remote_info, &key_idx, &serial_port ) != 0 )
617 return( -1 );
618
619 ret = mbedtls_pk_remote_setup( ctx, serial_port, key_idx );
620 if( ret != 0 )
621 {
622 mbedtls_printf( " failed\n ! remote pk setup failure \n\n" );
623 return( ret );
624 }
625
626 return( 0 );
627}
628#endif /* _WIN32 */
629
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200630int write_certificate( mbedtls_x509write_cert *crt, const char *output_file,
Manuel Pégourié-Gonnard31e59402013-09-12 05:59:05 +0200631 int (*f_rng)(void *, unsigned char *, size_t),
632 void *p_rng )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200633{
634 int ret;
635 FILE *f;
636 unsigned char output_buf[4096];
637 size_t len = 0;
638
639 memset( output_buf, 0, 4096 );
Hanno Becker81535d02017-09-13 15:39:59 +0100640 if( ( ret = mbedtls_x509write_crt_pem( crt, output_buf, 4096,
641 f_rng, p_rng ) ) < 0 )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200642 return( ret );
643
644 len = strlen( (char *) output_buf );
645
646 if( ( f = fopen( output_file, "w" ) ) == NULL )
647 return( -1 );
648
649 if( fwrite( output_buf, 1, len, f ) != len )
Paul Bakker0c226102014-04-17 16:02:36 +0200650 {
651 fclose( f );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200652 return( -1 );
Paul Bakker0c226102014-04-17 16:02:36 +0200653 }
Paul Bakker9397dcb2013-09-06 09:55:26 +0200654
Paul Bakker0c226102014-04-17 16:02:36 +0200655 fclose( f );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200656
657 return( 0 );
658}
659
Paul Bakker9397dcb2013-09-06 09:55:26 +0200660int main( int argc, char *argv[] )
661{
662 int ret = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200663 mbedtls_x509_crt issuer_crt;
664 mbedtls_pk_context loaded_issuer_key, loaded_subject_key;
665 mbedtls_pk_context *issuer_key = &loaded_issuer_key,
Manuel Pégourié-Gonnardf38e71a2013-09-12 05:21:54 +0200666 *subject_key = &loaded_subject_key;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200667 char buf[1024];
Jonathan Leroybbc75d92015-10-10 21:58:07 +0200668 char issuer_name[256];
Paul Bakkerc97f9f62013-11-30 15:13:02 +0100669 int i;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200670 char *p, *q, *r;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200671#if defined(MBEDTLS_X509_CSR_PARSE_C)
Jonathan Leroybbc75d92015-10-10 21:58:07 +0200672 char subject_name[256];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200673 mbedtls_x509_csr csr;
Paul Bakker7fc7fa62013-09-17 14:44:00 +0200674#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200675 mbedtls_x509write_cert crt;
676 mbedtls_mpi serial;
677 mbedtls_entropy_context entropy;
678 mbedtls_ctr_drbg_context ctr_drbg;
Manuel Pégourié-Gonnard31e59402013-09-12 05:59:05 +0200679 const char *pers = "crt example app";
Paul Bakker9397dcb2013-09-06 09:55:26 +0200680
681 /*
682 * Set to sane values
683 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200684 mbedtls_x509write_crt_init( &crt );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200685 mbedtls_pk_init( &loaded_issuer_key );
686 mbedtls_pk_init( &loaded_subject_key );
687 mbedtls_mpi_init( &serial );
Manuel Pégourié-Gonnardec160c02015-04-28 22:52:30 +0200688 mbedtls_ctr_drbg_init( &ctr_drbg );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200689#if defined(MBEDTLS_X509_CSR_PARSE_C)
690 mbedtls_x509_csr_init( &csr );
Paul Bakker7fc7fa62013-09-17 14:44:00 +0200691#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200692 mbedtls_x509_crt_init( &issuer_crt );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200693 memset( buf, 0, 1024 );
694
695 if( argc == 0 )
696 {
697 usage:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200698 mbedtls_printf( USAGE );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200699 ret = 1;
700 goto exit;
701 }
702
Paul Bakker1014e952013-09-09 13:59:42 +0200703 opt.issuer_crt = DFL_ISSUER_CRT;
Paul Bakkere2673fb2013-09-09 15:52:07 +0200704 opt.request_file = DFL_REQUEST_FILE;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200705 opt.subject_key = DFL_SUBJECT_KEY;
706 opt.issuer_key = DFL_ISSUER_KEY;
707 opt.subject_pwd = DFL_SUBJECT_PWD;
708 opt.issuer_pwd = DFL_ISSUER_PWD;
709 opt.output_file = DFL_OUTPUT_FILENAME;
710 opt.subject_name = DFL_SUBJECT_NAME;
711 opt.issuer_name = DFL_ISSUER_NAME;
712 opt.not_before = DFL_NOT_BEFORE;
713 opt.not_after = DFL_NOT_AFTER;
714 opt.serial = DFL_SERIAL;
Paul Bakkerb2d7f232013-09-09 16:24:18 +0200715 opt.selfsign = DFL_SELFSIGN;
Paul Bakker15162a02013-09-06 19:27:21 +0200716 opt.is_ca = DFL_IS_CA;
717 opt.max_pathlen = DFL_MAX_PATHLEN;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200718 opt.key_usage = DFL_KEY_USAGE;
719 opt.ns_cert_type = DFL_NS_CERT_TYPE;
Hanno Becker38eff432017-09-22 15:38:20 +0100720 opt.version = DFL_VERSION - 1;
Hanno Becker6c13d372017-09-13 12:49:22 +0100721 opt.md = DFL_DIGEST;
722 opt.subject_identifier = DFL_SUBJ_IDENT;
723 opt.authority_identifier = DFL_AUTH_IDENT;
724 opt.basic_constraints = DFL_CONSTRAINTS;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200725
726 for( i = 1; i < argc; i++ )
727 {
728
729 p = argv[i];
730 if( ( q = strchr( p, '=' ) ) == NULL )
731 goto usage;
732 *q++ = '\0';
733
Paul Bakkere2673fb2013-09-09 15:52:07 +0200734 if( strcmp( p, "request_file" ) == 0 )
735 opt.request_file = q;
736 else if( strcmp( p, "subject_key" ) == 0 )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200737 opt.subject_key = q;
738 else if( strcmp( p, "issuer_key" ) == 0 )
739 opt.issuer_key = q;
740 else if( strcmp( p, "subject_pwd" ) == 0 )
741 opt.subject_pwd = q;
742 else if( strcmp( p, "issuer_pwd" ) == 0 )
743 opt.issuer_pwd = q;
Paul Bakker1014e952013-09-09 13:59:42 +0200744 else if( strcmp( p, "issuer_crt" ) == 0 )
745 opt.issuer_crt = q;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200746 else if( strcmp( p, "output_file" ) == 0 )
747 opt.output_file = q;
748 else if( strcmp( p, "subject_name" ) == 0 )
749 {
750 opt.subject_name = q;
751 }
752 else if( strcmp( p, "issuer_name" ) == 0 )
753 {
754 opt.issuer_name = q;
755 }
756 else if( strcmp( p, "not_before" ) == 0 )
757 {
758 opt.not_before = q;
759 }
760 else if( strcmp( p, "not_after" ) == 0 )
761 {
762 opt.not_after = q;
763 }
764 else if( strcmp( p, "serial" ) == 0 )
765 {
766 opt.serial = q;
767 }
Hanno Becker6c13d372017-09-13 12:49:22 +0100768 else if( strcmp( p, "authority_identifier" ) == 0 )
769 {
770 opt.authority_identifier = atoi( q );
771 if( opt.authority_identifier != 0 &&
772 opt.authority_identifier != 1 )
773 {
Hanno Becker17c32762017-10-03 14:56:04 +0100774 mbedtls_printf( "Invalid argument for option %s\n", p );
Hanno Becker6c13d372017-09-13 12:49:22 +0100775 goto usage;
776 }
777 }
778 else if( strcmp( p, "subject_identifier" ) == 0 )
779 {
780 opt.subject_identifier = atoi( q );
781 if( opt.subject_identifier != 0 &&
782 opt.subject_identifier != 1 )
783 {
Hanno Becker17c32762017-10-03 14:56:04 +0100784 mbedtls_printf( "Invalid argument for option %s\n", p );
Hanno Becker6c13d372017-09-13 12:49:22 +0100785 goto usage;
786 }
787 }
788 else if( strcmp( p, "basic_constraints" ) == 0 )
789 {
790 opt.basic_constraints = atoi( q );
791 if( opt.basic_constraints != 0 &&
792 opt.basic_constraints != 1 )
793 {
Hanno Becker17c32762017-10-03 14:56:04 +0100794 mbedtls_printf( "Invalid argument for option %s\n", p );
Hanno Becker6c13d372017-09-13 12:49:22 +0100795 goto usage;
796 }
797 }
798 else if( strcmp( p, "md" ) == 0 )
799 {
800 if( strcmp( q, "SHA1" ) == 0 )
801 opt.md = MBEDTLS_MD_SHA1;
802 else if( strcmp( q, "SHA256" ) == 0 )
803 opt.md = MBEDTLS_MD_SHA256;
804 else if( strcmp( q, "SHA512" ) == 0 )
805 opt.md = MBEDTLS_MD_SHA512;
806 else if( strcmp( q, "MD5" ) == 0 )
807 opt.md = MBEDTLS_MD_MD5;
808 else
Hanno Becker17c32762017-10-03 14:56:04 +0100809 {
810 mbedtls_printf( "Invalid argument for option %s\n", p );
Hanno Becker6c13d372017-09-13 12:49:22 +0100811 goto usage;
Hanno Becker17c32762017-10-03 14:56:04 +0100812 }
Hanno Becker6c13d372017-09-13 12:49:22 +0100813 }
814 else if( strcmp( p, "version" ) == 0 )
815 {
816 opt.version = atoi( q );
817 if( opt.version < 1 || opt.version > 3 )
Hanno Becker17c32762017-10-03 14:56:04 +0100818 {
819 mbedtls_printf( "Invalid argument for option %s\n", p );
Hanno Becker6c13d372017-09-13 12:49:22 +0100820 goto usage;
Hanno Becker17c32762017-10-03 14:56:04 +0100821 }
Hanno Becker38eff432017-09-22 15:38:20 +0100822 opt.version--;
Hanno Becker6c13d372017-09-13 12:49:22 +0100823 }
Paul Bakkerb2d7f232013-09-09 16:24:18 +0200824 else if( strcmp( p, "selfsign" ) == 0 )
825 {
826 opt.selfsign = atoi( q );
827 if( opt.selfsign < 0 || opt.selfsign > 1 )
Hanno Becker17c32762017-10-03 14:56:04 +0100828 {
829 mbedtls_printf( "Invalid argument for option %s\n", p );
Paul Bakkerb2d7f232013-09-09 16:24:18 +0200830 goto usage;
Hanno Becker17c32762017-10-03 14:56:04 +0100831 }
Paul Bakkerb2d7f232013-09-09 16:24:18 +0200832 }
Paul Bakker15162a02013-09-06 19:27:21 +0200833 else if( strcmp( p, "is_ca" ) == 0 )
834 {
835 opt.is_ca = atoi( q );
836 if( opt.is_ca < 0 || opt.is_ca > 1 )
Hanno Becker17c32762017-10-03 14:56:04 +0100837 {
838 mbedtls_printf( "Invalid argument for option %s\n", p );
Paul Bakker15162a02013-09-06 19:27:21 +0200839 goto usage;
Hanno Becker17c32762017-10-03 14:56:04 +0100840 }
Paul Bakker15162a02013-09-06 19:27:21 +0200841 }
842 else if( strcmp( p, "max_pathlen" ) == 0 )
843 {
844 opt.max_pathlen = atoi( q );
845 if( opt.max_pathlen < -1 || opt.max_pathlen > 127 )
Hanno Becker17c32762017-10-03 14:56:04 +0100846 {
847 mbedtls_printf( "Invalid argument for option %s\n", p );
Paul Bakker15162a02013-09-06 19:27:21 +0200848 goto usage;
Hanno Becker17c32762017-10-03 14:56:04 +0100849 }
Paul Bakker15162a02013-09-06 19:27:21 +0200850 }
Paul Bakker9397dcb2013-09-06 09:55:26 +0200851 else if( strcmp( p, "key_usage" ) == 0 )
852 {
853 while( q != NULL )
854 {
855 if( ( r = strchr( q, ',' ) ) != NULL )
856 *r++ = '\0';
857
858 if( strcmp( q, "digital_signature" ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200859 opt.key_usage |= MBEDTLS_X509_KU_DIGITAL_SIGNATURE;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200860 else if( strcmp( q, "non_repudiation" ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200861 opt.key_usage |= MBEDTLS_X509_KU_NON_REPUDIATION;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200862 else if( strcmp( q, "key_encipherment" ) == 0 )
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +0100863 opt.key_usage |= MBEDTLS_X509_KU_KEY_ENCIPHERMENT;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200864 else if( strcmp( q, "data_encipherment" ) == 0 )
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +0100865 opt.key_usage |= MBEDTLS_X509_KU_DATA_ENCIPHERMENT;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200866 else if( strcmp( q, "key_agreement" ) == 0 )
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +0100867 opt.key_usage |= MBEDTLS_X509_KU_KEY_AGREEMENT;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200868 else if( strcmp( q, "key_cert_sign" ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200869 opt.key_usage |= MBEDTLS_X509_KU_KEY_CERT_SIGN;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200870 else if( strcmp( q, "crl_sign" ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200871 opt.key_usage |= MBEDTLS_X509_KU_CRL_SIGN;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200872 else
Hanno Becker17c32762017-10-03 14:56:04 +0100873 {
874 mbedtls_printf( "Invalid argument for option %s\n", p );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200875 goto usage;
Hanno Becker17c32762017-10-03 14:56:04 +0100876 }
Paul Bakker9397dcb2013-09-06 09:55:26 +0200877
878 q = r;
879 }
880 }
881 else if( strcmp( p, "ns_cert_type" ) == 0 )
882 {
883 while( q != NULL )
884 {
885 if( ( r = strchr( q, ',' ) ) != NULL )
886 *r++ = '\0';
887
888 if( strcmp( q, "ssl_client" ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200889 opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200890 else if( strcmp( q, "ssl_server" ) == 0 )
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +0100891 opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200892 else if( strcmp( q, "email" ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200893 opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_EMAIL;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200894 else if( strcmp( q, "object_signing" ) == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200895 opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200896 else if( strcmp( q, "ssl_ca" ) == 0 )
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +0100897 opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_SSL_CA;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200898 else if( strcmp( q, "email_ca" ) == 0 )
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +0100899 opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200900 else if( strcmp( q, "object_signing_ca" ) == 0 )
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +0100901 opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA;
Paul Bakker9397dcb2013-09-06 09:55:26 +0200902 else
Hanno Becker17c32762017-10-03 14:56:04 +0100903 {
904 mbedtls_printf( "Invalid argument for option %s\n", p );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200905 goto usage;
Hanno Becker17c32762017-10-03 14:56:04 +0100906 }
Paul Bakker9397dcb2013-09-06 09:55:26 +0200907
908 q = r;
909 }
910 }
911 else
912 goto usage;
913 }
914
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200915 mbedtls_printf("\n");
Paul Bakker1014e952013-09-09 13:59:42 +0200916
Manuel Pégourié-Gonnard31e59402013-09-12 05:59:05 +0200917 /*
918 * 0. Seed the PRNG
919 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200920 mbedtls_printf( " . Seeding the random number generator..." );
Manuel Pégourié-Gonnard31e59402013-09-12 05:59:05 +0200921 fflush( stdout );
922
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200923 mbedtls_entropy_init( &entropy );
Manuel Pégourié-Gonnardec160c02015-04-28 22:52:30 +0200924 if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy,
Manuel Pégourié-Gonnard31e59402013-09-12 05:59:05 +0200925 (const unsigned char *) pers,
926 strlen( pers ) ) ) != 0 )
927 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200928 mbedtls_strerror( ret, buf, 1024 );
Hanno Becker81535d02017-09-13 15:39:59 +0100929 mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned %d - %s\n",
930 ret, buf );
Manuel Pégourié-Gonnard31e59402013-09-12 05:59:05 +0200931 goto exit;
932 }
933
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200934 mbedtls_printf( " ok\n" );
Manuel Pégourié-Gonnard31e59402013-09-12 05:59:05 +0200935
Paul Bakker9397dcb2013-09-06 09:55:26 +0200936 // Parse serial to MPI
937 //
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200938 mbedtls_printf( " . Reading serial number..." );
Manuel Pégourié-Gonnard31e59402013-09-12 05:59:05 +0200939 fflush( stdout );
940
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200941 if( ( ret = mbedtls_mpi_read_string( &serial, 10, opt.serial ) ) != 0 )
Paul Bakker9397dcb2013-09-06 09:55:26 +0200942 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200943 mbedtls_strerror( ret, buf, 1024 );
Hanno Becker81535d02017-09-13 15:39:59 +0100944 mbedtls_printf( " failed\n ! mbedtls_mpi_read_string "
Hanno Becker7f3652d2017-09-22 15:39:02 +0100945 "returned -0x%04x - %s\n\n", -ret, buf );
Paul Bakker9397dcb2013-09-06 09:55:26 +0200946 goto exit;
947 }
948
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200949 mbedtls_printf( " ok\n" );
Manuel Pégourié-Gonnard31e59402013-09-12 05:59:05 +0200950
Paul Bakker1014e952013-09-09 13:59:42 +0200951 // Parse issuer certificate if present
952 //
Paul Bakkerb2d7f232013-09-09 16:24:18 +0200953 if( !opt.selfsign && strlen( opt.issuer_crt ) )
Paul Bakker1014e952013-09-09 13:59:42 +0200954 {
955 /*
Paul Bakkere2673fb2013-09-09 15:52:07 +0200956 * 1.0.a. Load the certificates
Paul Bakker1014e952013-09-09 13:59:42 +0200957 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200958 mbedtls_printf( " . Loading the issuer certificate ..." );
Paul Bakker1014e952013-09-09 13:59:42 +0200959 fflush( stdout );
960
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200961 if( ( ret = mbedtls_x509_crt_parse_file( &issuer_crt, opt.issuer_crt ) ) != 0 )
Paul Bakker1014e952013-09-09 13:59:42 +0200962 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200963 mbedtls_strerror( ret, buf, 1024 );
Hanno Becker81535d02017-09-13 15:39:59 +0100964 mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse_file "
Hanno Becker7f3652d2017-09-22 15:39:02 +0100965 "returned -0x%04x - %s\n\n", -ret, buf );
Paul Bakker1014e952013-09-09 13:59:42 +0200966 goto exit;
967 }
968
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200969 ret = mbedtls_x509_dn_gets( issuer_name, sizeof(issuer_name),
Paul Bakkerfdba4682014-04-25 11:48:35 +0200970 &issuer_crt.subject );
Paul Bakker1014e952013-09-09 13:59:42 +0200971 if( ret < 0 )
972 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200973 mbedtls_strerror( ret, buf, 1024 );
Hanno Becker81535d02017-09-13 15:39:59 +0100974 mbedtls_printf( " failed\n ! mbedtls_x509_dn_gets "
Hanno Becker7f3652d2017-09-22 15:39:02 +0100975 "returned -0x%04x - %s\n\n", -ret, buf );
Paul Bakker1014e952013-09-09 13:59:42 +0200976 goto exit;
977 }
978
Paul Bakkere2673fb2013-09-09 15:52:07 +0200979 opt.issuer_name = issuer_name;
980
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200981 mbedtls_printf( " ok\n" );
Paul Bakkere2673fb2013-09-09 15:52:07 +0200982 }
983
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200984#if defined(MBEDTLS_X509_CSR_PARSE_C)
Paul Bakkere2673fb2013-09-09 15:52:07 +0200985 // Parse certificate request if present
986 //
Paul Bakkerb2d7f232013-09-09 16:24:18 +0200987 if( !opt.selfsign && strlen( opt.request_file ) )
Paul Bakkere2673fb2013-09-09 15:52:07 +0200988 {
989 /*
990 * 1.0.b. Load the CSR
991 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200992 mbedtls_printf( " . Loading the certificate request ..." );
Paul Bakkere2673fb2013-09-09 15:52:07 +0200993 fflush( stdout );
994
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200995 if( ( ret = mbedtls_x509_csr_parse_file( &csr, opt.request_file ) ) != 0 )
Paul Bakkere2673fb2013-09-09 15:52:07 +0200996 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200997 mbedtls_strerror( ret, buf, 1024 );
Hanno Becker81535d02017-09-13 15:39:59 +0100998 mbedtls_printf( " failed\n ! mbedtls_x509_csr_parse_file "
Hanno Becker7f3652d2017-09-22 15:39:02 +0100999 "returned -0x%04x - %s\n\n", -ret, buf );
Paul Bakkere2673fb2013-09-09 15:52:07 +02001000 goto exit;
1001 }
1002
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001003 ret = mbedtls_x509_dn_gets( subject_name, sizeof(subject_name),
Paul Bakkere2673fb2013-09-09 15:52:07 +02001004 &csr.subject );
1005 if( ret < 0 )
1006 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001007 mbedtls_strerror( ret, buf, 1024 );
Hanno Becker81535d02017-09-13 15:39:59 +01001008 mbedtls_printf( " failed\n ! mbedtls_x509_dn_gets "
Hanno Becker7f3652d2017-09-22 15:39:02 +01001009 "returned -0x%04x - %s\n\n", -ret, buf );
Paul Bakkere2673fb2013-09-09 15:52:07 +02001010 goto exit;
1011 }
1012
1013 opt.subject_name = subject_name;
Manuel Pégourié-Gonnardf38e71a2013-09-12 05:21:54 +02001014 subject_key = &csr.pk;
Paul Bakkere2673fb2013-09-09 15:52:07 +02001015
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001016 mbedtls_printf( " ok\n" );
Paul Bakkerb2d7f232013-09-09 16:24:18 +02001017 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001018#endif /* MBEDTLS_X509_CSR_PARSE_C */
Paul Bakkerb2d7f232013-09-09 16:24:18 +02001019
1020 /*
1021 * 1.1. Load the keys
1022 */
1023 if( !opt.selfsign && !strlen( opt.request_file ) )
1024 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001025 mbedtls_printf( " . Loading the subject key ..." );
Paul Bakkerb2d7f232013-09-09 16:24:18 +02001026 fflush( stdout );
1027
Azim Khan7a339902018-02-21 01:05:21 +00001028#if defined(_WIN32)
Azim Khan26a455c2018-02-07 11:11:17 +00001029 if ( is_remote_key( opt.subject_key ) )
Paul Bakkere2673fb2013-09-09 15:52:07 +02001030 {
Azim Khan26a455c2018-02-07 11:11:17 +00001031 ret = load_pubkey_from_remote( opt.subject_key, &loaded_subject_key );
1032 if ( ret != 0 )
1033 goto exit;
1034 }
1035 else
Azim Khan7a339902018-02-21 01:05:21 +00001036#endif
Azim Khan26a455c2018-02-07 11:11:17 +00001037 {
1038 ret = mbedtls_pk_parse_keyfile( &loaded_subject_key, opt.subject_key,
1039 opt.subject_pwd );
1040 if( ret != 0 )
1041 {
1042 mbedtls_strerror( ret, buf, 1024 );
1043 mbedtls_printf( " failed\n ! mbedtls_pk_parse_keyfile "
1044 "returned -0x%04x - %s\n\n", -ret, buf );
1045 goto exit;
1046 }
Paul Bakkere2673fb2013-09-09 15:52:07 +02001047 }
Paul Bakker1014e952013-09-09 13:59:42 +02001048
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001049 mbedtls_printf( " ok\n" );
Paul Bakker1014e952013-09-09 13:59:42 +02001050 }
1051
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001052 mbedtls_printf( " . Loading the issuer key ..." );
Paul Bakkerb2d7f232013-09-09 16:24:18 +02001053 fflush( stdout );
1054
Azim Khan7a339902018-02-21 01:05:21 +00001055#if defined(_WIN32)
Azim Khan26a455c2018-02-07 11:11:17 +00001056 if ( is_remote_key( opt.issuer_key ) )
1057 {
1058 ret = setup_opaque_privkey( opt.issuer_key, &loaded_issuer_key );
1059 if ( ret != 0 )
1060 goto exit;
1061 }
1062 else
Azim Khan7a339902018-02-21 01:05:21 +00001063#endif
Azim Khan26a455c2018-02-07 11:11:17 +00001064 {
1065 ret = mbedtls_pk_parse_keyfile( &loaded_issuer_key, opt.issuer_key,
1066 opt.issuer_pwd );
1067 }
1068
Paul Bakkerb2d7f232013-09-09 16:24:18 +02001069 if( ret != 0 )
1070 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001071 mbedtls_strerror( ret, buf, 1024 );
Hanno Becker81535d02017-09-13 15:39:59 +01001072 mbedtls_printf( " failed\n ! mbedtls_pk_parse_keyfile "
1073 "returned -x%02x - %s\n\n", -ret, buf );
Paul Bakkerb2d7f232013-09-09 16:24:18 +02001074 goto exit;
1075 }
1076
1077 // Check if key and issuer certificate match
1078 //
1079 if( strlen( opt.issuer_crt ) )
1080 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001081 if( !mbedtls_pk_can_do( &issuer_crt.pk, MBEDTLS_PK_RSA ) ||
1082 mbedtls_mpi_cmp_mpi( &mbedtls_pk_rsa( issuer_crt.pk )->N,
1083 &mbedtls_pk_rsa( *issuer_key )->N ) != 0 ||
1084 mbedtls_mpi_cmp_mpi( &mbedtls_pk_rsa( issuer_crt.pk )->E,
1085 &mbedtls_pk_rsa( *issuer_key )->E ) != 0 )
Paul Bakkerb2d7f232013-09-09 16:24:18 +02001086 {
Hanno Becker81535d02017-09-13 15:39:59 +01001087 mbedtls_printf( " failed\n ! issuer_key does not match "
1088 "issuer certificate\n\n" );
Paul Bakkerb2d7f232013-09-09 16:24:18 +02001089 ret = -1;
1090 goto exit;
1091 }
1092 }
1093
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001094 mbedtls_printf( " ok\n" );
Paul Bakkerb2d7f232013-09-09 16:24:18 +02001095
1096 if( opt.selfsign )
1097 {
Paul Bakker93c6aa42013-10-28 22:28:09 +01001098 opt.subject_name = opt.issuer_name;
Manuel Pégourié-Gonnardf38e71a2013-09-12 05:21:54 +02001099 subject_key = issuer_key;
Paul Bakkerb2d7f232013-09-09 16:24:18 +02001100 }
1101
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001102 mbedtls_x509write_crt_set_subject_key( &crt, subject_key );
1103 mbedtls_x509write_crt_set_issuer_key( &crt, issuer_key );
Paul Bakkerb2d7f232013-09-09 16:24:18 +02001104
Paul Bakker9397dcb2013-09-06 09:55:26 +02001105 /*
1106 * 1.0. Check the names for validity
1107 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001108 if( ( ret = mbedtls_x509write_crt_set_subject_name( &crt, opt.subject_name ) ) != 0 )
Paul Bakker9397dcb2013-09-06 09:55:26 +02001109 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001110 mbedtls_strerror( ret, buf, 1024 );
Hanno Becker81535d02017-09-13 15:39:59 +01001111 mbedtls_printf( " failed\n ! mbedtls_x509write_crt_set_subject_name "
Hanno Becker7f3652d2017-09-22 15:39:02 +01001112 "returned -0x%04x - %s\n\n", -ret, buf );
Paul Bakker9397dcb2013-09-06 09:55:26 +02001113 goto exit;
1114 }
1115
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001116 if( ( ret = mbedtls_x509write_crt_set_issuer_name( &crt, opt.issuer_name ) ) != 0 )
Paul Bakker9397dcb2013-09-06 09:55:26 +02001117 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001118 mbedtls_strerror( ret, buf, 1024 );
Hanno Becker81535d02017-09-13 15:39:59 +01001119 mbedtls_printf( " failed\n ! mbedtls_x509write_crt_set_issuer_name "
Hanno Becker7f3652d2017-09-22 15:39:02 +01001120 "returned -0x%04x - %s\n\n", -ret, buf );
Paul Bakker9397dcb2013-09-06 09:55:26 +02001121 goto exit;
1122 }
1123
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001124 mbedtls_printf( " . Setting certificate values ..." );
Paul Bakker9397dcb2013-09-06 09:55:26 +02001125 fflush( stdout );
1126
Hanno Becker38eff432017-09-22 15:38:20 +01001127 mbedtls_x509write_crt_set_version( &crt, opt.version );
Hanno Becker6c13d372017-09-13 12:49:22 +01001128 mbedtls_x509write_crt_set_md_alg( &crt, opt.md );
1129
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001130 ret = mbedtls_x509write_crt_set_serial( &crt, &serial );
Paul Bakker9397dcb2013-09-06 09:55:26 +02001131 if( ret != 0 )
1132 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001133 mbedtls_strerror( ret, buf, 1024 );
Hanno Becker81535d02017-09-13 15:39:59 +01001134 mbedtls_printf( " failed\n ! mbedtls_x509write_crt_set_serial "
Hanno Becker7f3652d2017-09-22 15:39:02 +01001135 "returned -0x%04x - %s\n\n", -ret, buf );
Paul Bakker9397dcb2013-09-06 09:55:26 +02001136 goto exit;
1137 }
1138
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001139 ret = mbedtls_x509write_crt_set_validity( &crt, opt.not_before, opt.not_after );
Paul Bakker9397dcb2013-09-06 09:55:26 +02001140 if( ret != 0 )
1141 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001142 mbedtls_strerror( ret, buf, 1024 );
Hanno Becker81535d02017-09-13 15:39:59 +01001143 mbedtls_printf( " failed\n ! mbedtls_x509write_crt_set_validity "
Hanno Becker7f3652d2017-09-22 15:39:02 +01001144 "returned -0x%04x - %s\n\n", -ret, buf );
Paul Bakker9397dcb2013-09-06 09:55:26 +02001145 goto exit;
1146 }
1147
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001148 mbedtls_printf( " ok\n" );
Paul Bakker9397dcb2013-09-06 09:55:26 +02001149
Hanno Becker38eff432017-09-22 15:38:20 +01001150 if( opt.version == MBEDTLS_X509_CRT_VERSION_3 &&
1151 opt.basic_constraints != 0 )
Paul Bakker15162a02013-09-06 19:27:21 +02001152 {
Hanno Becker6c13d372017-09-13 12:49:22 +01001153 mbedtls_printf( " . Adding the Basic Constraints extension ..." );
1154 fflush( stdout );
Paul Bakker15162a02013-09-06 19:27:21 +02001155
Hanno Becker6c13d372017-09-13 12:49:22 +01001156 ret = mbedtls_x509write_crt_set_basic_constraints( &crt, opt.is_ca,
1157 opt.max_pathlen );
1158 if( ret != 0 )
1159 {
1160 mbedtls_strerror( ret, buf, 1024 );
1161 mbedtls_printf( " failed\n ! x509write_crt_set_basic_contraints "
Hanno Becker7f3652d2017-09-22 15:39:02 +01001162 "returned -0x%04x - %s\n\n", -ret, buf );
Hanno Becker6c13d372017-09-13 12:49:22 +01001163 goto exit;
1164 }
1165
1166 mbedtls_printf( " ok\n" );
1167 }
Paul Bakker15162a02013-09-06 19:27:21 +02001168
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001169#if defined(MBEDTLS_SHA1_C)
Hanno Becker38eff432017-09-22 15:38:20 +01001170 if( opt.version == MBEDTLS_X509_CRT_VERSION_3 &&
1171 opt.subject_identifier != 0 )
Paul Bakker15162a02013-09-06 19:27:21 +02001172 {
Hanno Becker6c13d372017-09-13 12:49:22 +01001173 mbedtls_printf( " . Adding the Subject Key Identifier ..." );
1174 fflush( stdout );
1175
1176 ret = mbedtls_x509write_crt_set_subject_key_identifier( &crt );
1177 if( ret != 0 )
1178 {
1179 mbedtls_strerror( ret, buf, 1024 );
1180 mbedtls_printf( " failed\n ! mbedtls_x509write_crt_set_subject"
Hanno Becker7f3652d2017-09-22 15:39:02 +01001181 "_key_identifier returned -0x%04x - %s\n\n",
Hanno Becker6c13d372017-09-13 12:49:22 +01001182 -ret, buf );
1183 goto exit;
1184 }
1185
1186 mbedtls_printf( " ok\n" );
Paul Bakker15162a02013-09-06 19:27:21 +02001187 }
1188
Hanno Becker38eff432017-09-22 15:38:20 +01001189 if( opt.version == MBEDTLS_X509_CRT_VERSION_3 &&
1190 opt.authority_identifier != 0 )
Paul Bakker15162a02013-09-06 19:27:21 +02001191 {
Hanno Becker6c13d372017-09-13 12:49:22 +01001192 mbedtls_printf( " . Adding the Authority Key Identifier ..." );
1193 fflush( stdout );
Paul Bakker15162a02013-09-06 19:27:21 +02001194
Hanno Becker6c13d372017-09-13 12:49:22 +01001195 ret = mbedtls_x509write_crt_set_authority_key_identifier( &crt );
1196 if( ret != 0 )
1197 {
1198 mbedtls_strerror( ret, buf, 1024 );
1199 mbedtls_printf( " failed\n ! mbedtls_x509write_crt_set_authority_"
Hanno Becker7f3652d2017-09-22 15:39:02 +01001200 "key_identifier returned -0x%04x - %s\n\n",
Hanno Becker6c13d372017-09-13 12:49:22 +01001201 -ret, buf );
1202 goto exit;
1203 }
1204
1205 mbedtls_printf( " ok\n" );
1206 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001207#endif /* MBEDTLS_SHA1_C */
Paul Bakker15162a02013-09-06 19:27:21 +02001208
Hanno Becker38eff432017-09-22 15:38:20 +01001209 if( opt.version == MBEDTLS_X509_CRT_VERSION_3 &&
1210 opt.key_usage != 0 )
Paul Bakker52be08c2013-09-09 12:37:54 +02001211 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001212 mbedtls_printf( " . Adding the Key Usage extension ..." );
Paul Bakker52be08c2013-09-09 12:37:54 +02001213 fflush( stdout );
1214
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001215 ret = mbedtls_x509write_crt_set_key_usage( &crt, opt.key_usage );
Paul Bakker52be08c2013-09-09 12:37:54 +02001216 if( ret != 0 )
1217 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001218 mbedtls_strerror( ret, buf, 1024 );
Hanno Becker81535d02017-09-13 15:39:59 +01001219 mbedtls_printf( " failed\n ! mbedtls_x509write_crt_set_key_usage "
Hanno Becker7f3652d2017-09-22 15:39:02 +01001220 "returned -0x%04x - %s\n\n", -ret, buf );
Paul Bakker52be08c2013-09-09 12:37:54 +02001221 goto exit;
1222 }
1223
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001224 mbedtls_printf( " ok\n" );
Paul Bakker52be08c2013-09-09 12:37:54 +02001225 }
1226
Hanno Becker38eff432017-09-22 15:38:20 +01001227 if( opt.version == MBEDTLS_X509_CRT_VERSION_3 &&
1228 opt.ns_cert_type != 0 )
Paul Bakker52be08c2013-09-09 12:37:54 +02001229 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001230 mbedtls_printf( " . Adding the NS Cert Type extension ..." );
Paul Bakker52be08c2013-09-09 12:37:54 +02001231 fflush( stdout );
1232
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001233 ret = mbedtls_x509write_crt_set_ns_cert_type( &crt, opt.ns_cert_type );
Paul Bakker52be08c2013-09-09 12:37:54 +02001234 if( ret != 0 )
1235 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001236 mbedtls_strerror( ret, buf, 1024 );
Hanno Becker81535d02017-09-13 15:39:59 +01001237 mbedtls_printf( " failed\n ! mbedtls_x509write_crt_set_ns_cert_type "
Hanno Becker7f3652d2017-09-22 15:39:02 +01001238 "returned -0x%04x - %s\n\n", -ret, buf );
Paul Bakker52be08c2013-09-09 12:37:54 +02001239 goto exit;
1240 }
1241
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001242 mbedtls_printf( " ok\n" );
Paul Bakker52be08c2013-09-09 12:37:54 +02001243 }
1244
Paul Bakker9397dcb2013-09-06 09:55:26 +02001245 /*
1246 * 1.2. Writing the request
1247 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001248 mbedtls_printf( " . Writing the certificate..." );
Paul Bakker9397dcb2013-09-06 09:55:26 +02001249 fflush( stdout );
1250
Manuel Pégourié-Gonnard31e59402013-09-12 05:59:05 +02001251 if( ( ret = write_certificate( &crt, opt.output_file,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001252 mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 )
Paul Bakker9397dcb2013-09-06 09:55:26 +02001253 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001254 mbedtls_strerror( ret, buf, 1024 );
Hanno Becker7f3652d2017-09-22 15:39:02 +01001255 mbedtls_printf( " failed\n ! write_certificate -0x%04x - %s\n\n",
Hanno Becker81535d02017-09-13 15:39:59 +01001256 -ret, buf );
Paul Bakker9397dcb2013-09-06 09:55:26 +02001257 goto exit;
1258 }
1259
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001260 mbedtls_printf( " ok\n" );
Paul Bakker9397dcb2013-09-06 09:55:26 +02001261
1262exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001263 mbedtls_x509write_crt_free( &crt );
1264 mbedtls_pk_free( &loaded_subject_key );
Azim Khan7a339902018-02-21 01:05:21 +00001265 mbedtls_pk_free( &loaded_issuer_key );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001266 mbedtls_mpi_free( &serial );
1267 mbedtls_ctr_drbg_free( &ctr_drbg );
1268 mbedtls_entropy_free( &entropy );
Paul Bakker9397dcb2013-09-06 09:55:26 +02001269
1270#if defined(_WIN32)
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001271 mbedtls_printf( " + Press Enter to exit this program.\n" );
Paul Bakker9397dcb2013-09-06 09:55:26 +02001272 fflush( stdout ); getchar();
1273#endif
1274
1275 return( ret );
1276}
Azim Khan26a455c2018-02-07 11:11:17 +00001277
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001278#endif /* MBEDTLS_X509_CRT_WRITE_C && MBEDTLS_X509_CRT_PARSE_C &&
1279 MBEDTLS_FS_IO && MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C &&
Simon Butcher203a6932016-10-07 15:00:17 +01001280 MBEDTLS_ERROR_C && MBEDTLS_PEM_WRITE_C */