blob: 68a9523e01ded08752d70954eab7a869dd5c4189 [file] [log] [blame]
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001/*
2 * X.509 certificate writing
3 *
Manuel Pégourié-Gonnard6fb81872015-07-27 11:11:48 +02004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Bence Szépkútif744bd72020-06-05 13:02:18 +02005 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6 *
7 * This file is provided under the Apache License 2.0, or the
8 * GNU General Public License v2.0 or later.
9 *
10 * **********
11 * Apache License 2.0:
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +020012 *
13 * Licensed under the Apache License, Version 2.0 (the "License"); you may
14 * not use this file except in compliance with the License.
15 * You may obtain a copy of the License at
16 *
17 * http://www.apache.org/licenses/LICENSE-2.0
18 *
19 * Unless required by applicable law or agreed to in writing, software
20 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
21 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 * See the License for the specific language governing permissions and
23 * limitations under the License.
Paul Bakker7c6b2c32013-09-16 13:49:26 +020024 *
Bence Szépkútif744bd72020-06-05 13:02:18 +020025 * **********
26 *
27 * **********
28 * GNU General Public License v2.0 or later:
29 *
30 * This program is free software; you can redistribute it and/or modify
31 * it under the terms of the GNU General Public License as published by
32 * the Free Software Foundation; either version 2 of the License, or
33 * (at your option) any later version.
34 *
35 * This program is distributed in the hope that it will be useful,
36 * but WITHOUT ANY WARRANTY; without even the implied warranty of
37 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38 * GNU General Public License for more details.
39 *
40 * You should have received a copy of the GNU General Public License along
41 * with this program; if not, write to the Free Software Foundation, Inc.,
42 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
43 *
44 * **********
45 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000046 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker7c6b2c32013-09-16 13:49:26 +020047 */
48/*
49 * References:
50 * - certificates: RFC 5280, updated by RFC 6818
51 * - CSRs: PKCS#10 v1.7 aka RFC 2986
52 * - attributes: PKCS#9 v2.0 aka RFC 2985
53 */
54
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020055#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000056#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020057#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020058#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020059#endif
Paul Bakker7c6b2c32013-09-16 13:49:26 +020060
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020061#if defined(MBEDTLS_X509_CRT_WRITE_C)
Paul Bakker7c6b2c32013-09-16 13:49:26 +020062
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000063#include "mbedtls/x509_crt.h"
64#include "mbedtls/oid.h"
65#include "mbedtls/asn1write.h"
66#include "mbedtls/sha1.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050067#include "mbedtls/platform_util.h"
Paul Bakker7c6b2c32013-09-16 13:49:26 +020068
Rich Evans00ab4702015-02-06 13:43:58 +000069#include <string.h>
70
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020071#if defined(MBEDTLS_PEM_WRITE_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000072#include "mbedtls/pem.h"
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020073#endif /* MBEDTLS_PEM_WRITE_C */
Paul Bakker7c6b2c32013-09-16 13:49:26 +020074
k-stachowiake79c9392019-05-31 20:11:26 +020075/*
76 * For the currently used signature algorithms the buffer to store any signature
77 * must be at least of size MAX(MBEDTLS_ECDSA_MAX_LEN, MBEDTLS_MPI_MAX_SIZE)
78 */
79#if MBEDTLS_ECDSA_MAX_LEN > MBEDTLS_MPI_MAX_SIZE
80#define SIGNATURE_MAX_SIZE MBEDTLS_ECDSA_MAX_LEN
81#else
82#define SIGNATURE_MAX_SIZE MBEDTLS_MPI_MAX_SIZE
83#endif
84
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020085void mbedtls_x509write_crt_init( mbedtls_x509write_cert *ctx )
Paul Bakker7c6b2c32013-09-16 13:49:26 +020086{
Hanno Becker81535d02017-09-13 15:39:59 +010087 memset( ctx, 0, sizeof( mbedtls_x509write_cert ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +020088
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020089 mbedtls_mpi_init( &ctx->serial );
90 ctx->version = MBEDTLS_X509_CRT_VERSION_3;
Paul Bakker7c6b2c32013-09-16 13:49:26 +020091}
92
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020093void mbedtls_x509write_crt_free( mbedtls_x509write_cert *ctx )
Paul Bakker7c6b2c32013-09-16 13:49:26 +020094{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020095 mbedtls_mpi_free( &ctx->serial );
Paul Bakker7c6b2c32013-09-16 13:49:26 +020096
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020097 mbedtls_asn1_free_named_data_list( &ctx->subject );
98 mbedtls_asn1_free_named_data_list( &ctx->issuer );
99 mbedtls_asn1_free_named_data_list( &ctx->extensions );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200100
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500101 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_x509write_cert ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200102}
103
Hanno Beckerbeaf3962019-05-04 07:37:58 +0100104void mbedtls_x509write_crt_set_version( mbedtls_x509write_cert *ctx,
105 int version )
Paul Bakker5191e922013-10-11 10:54:28 +0200106{
107 ctx->version = version;
108}
109
Hanno Beckerbeaf3962019-05-04 07:37:58 +0100110void mbedtls_x509write_crt_set_md_alg( mbedtls_x509write_cert *ctx,
111 mbedtls_md_type_t md_alg )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200112{
113 ctx->md_alg = md_alg;
114}
115
Hanno Beckerbeaf3962019-05-04 07:37:58 +0100116void mbedtls_x509write_crt_set_subject_key( mbedtls_x509write_cert *ctx,
117 mbedtls_pk_context *key )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200118{
119 ctx->subject_key = key;
120}
121
Hanno Beckerbeaf3962019-05-04 07:37:58 +0100122void mbedtls_x509write_crt_set_issuer_key( mbedtls_x509write_cert *ctx,
123 mbedtls_pk_context *key )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200124{
125 ctx->issuer_key = key;
126}
127
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200128int mbedtls_x509write_crt_set_subject_name( mbedtls_x509write_cert *ctx,
Hanno Beckerbeaf3962019-05-04 07:37:58 +0100129 const char *subject_name )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200130{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200131 return mbedtls_x509_string_to_names( &ctx->subject, subject_name );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200132}
133
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200134int mbedtls_x509write_crt_set_issuer_name( mbedtls_x509write_cert *ctx,
Hanno Beckerbeaf3962019-05-04 07:37:58 +0100135 const char *issuer_name )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200136{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200137 return mbedtls_x509_string_to_names( &ctx->issuer, issuer_name );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200138}
139
Hanno Beckerbeaf3962019-05-04 07:37:58 +0100140int mbedtls_x509write_crt_set_serial( mbedtls_x509write_cert *ctx,
141 const mbedtls_mpi *serial )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200142{
143 int ret;
144
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200145 if( ( ret = mbedtls_mpi_copy( &ctx->serial, serial ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200146 return( ret );
147
148 return( 0 );
149}
150
Hanno Beckerbeaf3962019-05-04 07:37:58 +0100151int mbedtls_x509write_crt_set_validity( mbedtls_x509write_cert *ctx,
152 const char *not_before,
153 const char *not_after )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200154{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200155 if( strlen( not_before ) != MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1 ||
156 strlen( not_after ) != MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200157 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200158 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200159 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200160 strncpy( ctx->not_before, not_before, MBEDTLS_X509_RFC5280_UTC_TIME_LEN );
161 strncpy( ctx->not_after , not_after , MBEDTLS_X509_RFC5280_UTC_TIME_LEN );
162 ctx->not_before[MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1] = 'Z';
163 ctx->not_after[MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1] = 'Z';
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200164
165 return( 0 );
166}
167
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200168int mbedtls_x509write_crt_set_extension( mbedtls_x509write_cert *ctx,
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200169 const char *oid, size_t oid_len,
170 int critical,
171 const unsigned char *val, size_t val_len )
172{
Hanno Beckerbeaf3962019-05-04 07:37:58 +0100173 return( mbedtls_x509_set_extension( &ctx->extensions, oid, oid_len,
174 critical, val, val_len ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200175}
176
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200177int mbedtls_x509write_crt_set_basic_constraints( mbedtls_x509write_cert *ctx,
Hanno Beckerbeaf3962019-05-04 07:37:58 +0100178 int is_ca, int max_pathlen )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200179{
180 int ret;
181 unsigned char buf[9];
182 unsigned char *c = buf + sizeof(buf);
183 size_t len = 0;
184
185 memset( buf, 0, sizeof(buf) );
186
187 if( is_ca && max_pathlen > 127 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200188 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200189
190 if( is_ca )
191 {
192 if( max_pathlen >= 0 )
193 {
Hanno Beckerbeaf3962019-05-04 07:37:58 +0100194 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf,
195 max_pathlen ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200196 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200197 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_bool( &c, buf, 1 ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200198 }
199
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200200 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
Hanno Beckerbeaf3962019-05-04 07:37:58 +0100201 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf,
202 MBEDTLS_ASN1_CONSTRUCTED |
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200203 MBEDTLS_ASN1_SEQUENCE ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200204
Hanno Beckerbeaf3962019-05-04 07:37:58 +0100205 return(
206 mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_BASIC_CONSTRAINTS,
207 MBEDTLS_OID_SIZE( MBEDTLS_OID_BASIC_CONSTRAINTS ),
208 0, buf + sizeof(buf) - len, len ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200209}
210
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200211#if defined(MBEDTLS_SHA1_C)
212int mbedtls_x509write_crt_set_subject_key_identifier( mbedtls_x509write_cert *ctx )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200213{
214 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200215 unsigned char buf[MBEDTLS_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200216 unsigned char *c = buf + sizeof(buf);
217 size_t len = 0;
218
Paul Bakker66d5d072014-06-17 16:39:18 +0200219 memset( buf, 0, sizeof(buf) );
Hanno Beckerbeaf3962019-05-04 07:37:58 +0100220 MBEDTLS_ASN1_CHK_ADD( len,
221 mbedtls_pk_write_pubkey( &c, buf, ctx->subject_key ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200222
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100223 ret = mbedtls_sha1_ret( buf + sizeof( buf ) - len, len,
Andres Amaya Garcia8d8204f2017-06-28 11:07:30 +0100224 buf + sizeof( buf ) - 20 );
225 if( ret != 0 )
226 return( ret );
227 c = buf + sizeof( buf ) - 20;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200228 len = 20;
229
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200230 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
Hanno Beckerbeaf3962019-05-04 07:37:58 +0100231 MBEDTLS_ASN1_CHK_ADD( len,
232 mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_OCTET_STRING ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200233
Hanno Beckerbeaf3962019-05-04 07:37:58 +0100234 return mbedtls_x509write_crt_set_extension( ctx,
235 MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER,
236 MBEDTLS_OID_SIZE( MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER ),
237 0, buf + sizeof(buf) - len, len );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200238}
239
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200240int mbedtls_x509write_crt_set_authority_key_identifier( mbedtls_x509write_cert *ctx )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200241{
242 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200243 unsigned char buf[MBEDTLS_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
Hanno Becker81535d02017-09-13 15:39:59 +0100244 unsigned char *c = buf + sizeof( buf );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200245 size_t len = 0;
246
Paul Bakker66d5d072014-06-17 16:39:18 +0200247 memset( buf, 0, sizeof(buf) );
Hanno Beckerbeaf3962019-05-04 07:37:58 +0100248 MBEDTLS_ASN1_CHK_ADD( len,
249 mbedtls_pk_write_pubkey( &c, buf, ctx->issuer_key ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200250
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100251 ret = mbedtls_sha1_ret( buf + sizeof( buf ) - len, len,
Andres Amaya Garcia8d8204f2017-06-28 11:07:30 +0100252 buf + sizeof( buf ) - 20 );
253 if( ret != 0 )
254 return( ret );
255 c = buf + sizeof( buf ) - 20;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200256 len = 20;
257
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200258 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
Hanno Beckerbeaf3962019-05-04 07:37:58 +0100259 MBEDTLS_ASN1_CHK_ADD( len,
260 mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | 0 ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200261
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200262 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
Hanno Beckerbeaf3962019-05-04 07:37:58 +0100263 MBEDTLS_ASN1_CHK_ADD( len,
264 mbedtls_asn1_write_tag( &c, buf,
265 MBEDTLS_ASN1_CONSTRUCTED |
266 MBEDTLS_ASN1_SEQUENCE ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200267
Hanno Beckerbeaf3962019-05-04 07:37:58 +0100268 return mbedtls_x509write_crt_set_extension(
269 ctx, MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER,
270 MBEDTLS_OID_SIZE( MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER ),
271 0, buf + sizeof( buf ) - len, len );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200272}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200273#endif /* MBEDTLS_SHA1_C */
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200274
Andres Amaya Garciad60e3782018-09-26 10:48:24 +0100275static size_t crt_get_unused_bits_for_named_bitstring( unsigned char bitstring,
276 size_t bit_offset )
277{
278 size_t unused_bits;
279
280 /* Count the unused bits removing trailing 0s */
281 for( unused_bits = bit_offset; unused_bits < 8; unused_bits++ )
282 if( ( ( bitstring >> unused_bits ) & 0x1 ) != 0 )
283 break;
284
285 return( unused_bits );
286}
287
Manuel Pégourié-Gonnard1cd10ad2015-06-23 11:07:37 +0200288int mbedtls_x509write_crt_set_key_usage( mbedtls_x509write_cert *ctx,
289 unsigned int key_usage )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200290{
Manuel Pégourié-Gonnard1cd10ad2015-06-23 11:07:37 +0200291 unsigned char buf[4], ku;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200292 unsigned char *c;
293 int ret;
Andres Amaya Garciad60e3782018-09-26 10:48:24 +0100294 size_t unused_bits;
295 const unsigned int allowed_bits = MBEDTLS_X509_KU_DIGITAL_SIGNATURE |
296 MBEDTLS_X509_KU_NON_REPUDIATION |
297 MBEDTLS_X509_KU_KEY_ENCIPHERMENT |
298 MBEDTLS_X509_KU_DATA_ENCIPHERMENT |
299 MBEDTLS_X509_KU_KEY_AGREEMENT |
300 MBEDTLS_X509_KU_KEY_CERT_SIGN |
301 MBEDTLS_X509_KU_CRL_SIGN;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200302
Andres Amaya Garciad60e3782018-09-26 10:48:24 +0100303 /* Check that nothing other than the allowed flags is set */
304 if( ( key_usage & ~allowed_bits ) != 0 )
Manuel Pégourié-Gonnard1cd10ad2015-06-23 11:07:37 +0200305 return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200306
Manuel Pégourié-Gonnard1cd10ad2015-06-23 11:07:37 +0200307 c = buf + 4;
Andres Amaya Garciad60e3782018-09-26 10:48:24 +0100308 ku = (unsigned char)key_usage;
309 unused_bits = crt_get_unused_bits_for_named_bitstring( ku, 1 );
310 ret = mbedtls_asn1_write_bitstring( &c, buf, &ku, 8 - unused_bits );
Manuel Pégourié-Gonnard1cd10ad2015-06-23 11:07:37 +0200311
Andres Amaya Garciad60e3782018-09-26 10:48:24 +0100312 if( ret < 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200313 return( ret );
Andres Amaya Garciad60e3782018-09-26 10:48:24 +0100314 else if( ret < 3 || ret > 4 )
315 return( MBEDTLS_ERR_X509_INVALID_FORMAT );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200316
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200317 ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_KEY_USAGE,
Hanno Beckerbeaf3962019-05-04 07:37:58 +0100318 MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ),
319 1, c, (size_t)ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200320 if( ret != 0 )
321 return( ret );
322
323 return( 0 );
324}
325
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200326int mbedtls_x509write_crt_set_ns_cert_type( mbedtls_x509write_cert *ctx,
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200327 unsigned char ns_cert_type )
328{
329 unsigned char buf[4];
330 unsigned char *c;
Andres Amaya Garciad60e3782018-09-26 10:48:24 +0100331 size_t unused_bits;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200332 int ret;
333
334 c = buf + 4;
335
Andres Amaya Garciad60e3782018-09-26 10:48:24 +0100336 unused_bits = crt_get_unused_bits_for_named_bitstring( ns_cert_type, 0 );
337 ret = mbedtls_asn1_write_bitstring( &c,
338 buf,
339 &ns_cert_type,
340 8 - unused_bits );
341 if( ret < 3 || ret > 4 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200342 return( ret );
343
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200344 ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_NS_CERT_TYPE,
Hanno Beckerbeaf3962019-05-04 07:37:58 +0100345 MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ),
346 0, c, (size_t)ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200347 if( ret != 0 )
348 return( ret );
349
350 return( 0 );
351}
352
353static int x509_write_time( unsigned char **p, unsigned char *start,
Hanno Becker61937d42017-04-26 15:01:23 +0100354 const char *t, size_t size )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200355{
356 int ret;
357 size_t len = 0;
358
359 /*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200360 * write MBEDTLS_ASN1_UTC_TIME if year < 2050 (2 bytes shorter)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200361 */
Hanno Becker61937d42017-04-26 15:01:23 +0100362 if( t[0] == '2' && t[1] == '0' && t[2] < '5' )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200363 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200364 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start,
Hanno Becker61937d42017-04-26 15:01:23 +0100365 (const unsigned char *) t + 2,
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200366 size - 2 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200367 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
Hanno Beckerbeaf3962019-05-04 07:37:58 +0100368 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start,
369 MBEDTLS_ASN1_UTC_TIME ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200370 }
371 else
372 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200373 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start,
Hanno Becker61937d42017-04-26 15:01:23 +0100374 (const unsigned char *) t,
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200375 size ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200376 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
Hanno Beckerbeaf3962019-05-04 07:37:58 +0100377 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start,
378 MBEDTLS_ASN1_GENERALIZED_TIME ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200379 }
380
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200381 return( (int) len );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200382}
383
Hanno Beckerbeaf3962019-05-04 07:37:58 +0100384int mbedtls_x509write_crt_der( mbedtls_x509write_cert *ctx,
385 unsigned char *buf, size_t size,
386 int (*f_rng)(void *, unsigned char *, size_t),
387 void *p_rng )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200388{
389 int ret;
390 const char *sig_oid;
391 size_t sig_oid_len = 0;
392 unsigned char *c, *c2;
393 unsigned char hash[64];
k-stachowiake79c9392019-05-31 20:11:26 +0200394 unsigned char sig[SIGNATURE_MAX_SIZE];
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200395 unsigned char tmp_buf[2048];
396 size_t sub_len = 0, pub_len = 0, sig_and_oid_len = 0, sig_len;
397 size_t len = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200398 mbedtls_pk_type_t pk_alg;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200399
400 /*
401 * Prepare data to be signed in tmp_buf
402 */
403 c = tmp_buf + sizeof( tmp_buf );
404
405 /* Signature algorithm needed in TBS, and later for actual signature */
Hanno Beckerfc771442017-09-13 08:45:48 +0100406
407 /* There's no direct way of extracting a signature algorithm
408 * (represented as an element of mbedtls_pk_type_t) from a PK instance. */
409 if( mbedtls_pk_can_do( ctx->issuer_key, MBEDTLS_PK_RSA ) )
410 pk_alg = MBEDTLS_PK_RSA;
411 else if( mbedtls_pk_can_do( ctx->issuer_key, MBEDTLS_PK_ECDSA ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200412 pk_alg = MBEDTLS_PK_ECDSA;
Hanno Beckerfc771442017-09-13 08:45:48 +0100413 else
Hanno Beckerd8a6f7c2017-09-22 16:05:43 +0100414 return( MBEDTLS_ERR_X509_INVALID_ALG );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200415
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200416 if( ( ret = mbedtls_oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg,
Hanno Becker81535d02017-09-13 15:39:59 +0100417 &sig_oid, &sig_oid_len ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200418 {
419 return( ret );
420 }
421
422 /*
423 * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
424 */
Hanno Beckerd7f35202017-09-13 12:00:15 +0100425
426 /* Only for v3 */
Hanno Beckera20e33a2017-09-22 15:40:01 +0100427 if( ctx->version == MBEDTLS_X509_CRT_VERSION_3 )
Hanno Beckerd7f35202017-09-13 12:00:15 +0100428 {
Hanno Beckerbeaf3962019-05-04 07:37:58 +0100429 MBEDTLS_ASN1_CHK_ADD( len,
430 mbedtls_x509_write_extensions( &c,
431 tmp_buf, ctx->extensions ) );
Hanno Beckerd7f35202017-09-13 12:00:15 +0100432 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) );
Hanno Beckerbeaf3962019-05-04 07:37:58 +0100433 MBEDTLS_ASN1_CHK_ADD( len,
434 mbedtls_asn1_write_tag( &c, tmp_buf,
435 MBEDTLS_ASN1_CONSTRUCTED |
436 MBEDTLS_ASN1_SEQUENCE ) );
Hanno Beckerd7f35202017-09-13 12:00:15 +0100437 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) );
Hanno Beckerbeaf3962019-05-04 07:37:58 +0100438 MBEDTLS_ASN1_CHK_ADD( len,
439 mbedtls_asn1_write_tag( &c, tmp_buf,
440 MBEDTLS_ASN1_CONTEXT_SPECIFIC |
441 MBEDTLS_ASN1_CONSTRUCTED | 3 ) );
Hanno Beckerd7f35202017-09-13 12:00:15 +0100442 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200443
444 /*
445 * SubjectPublicKeyInfo
446 */
Hanno Beckerbeaf3962019-05-04 07:37:58 +0100447 MBEDTLS_ASN1_CHK_ADD( pub_len,
448 mbedtls_pk_write_pubkey_der( ctx->subject_key,
449 tmp_buf, c - tmp_buf ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200450 c -= pub_len;
451 len += pub_len;
452
453 /*
454 * Subject ::= Name
455 */
Hanno Beckerbeaf3962019-05-04 07:37:58 +0100456 MBEDTLS_ASN1_CHK_ADD( len,
457 mbedtls_x509_write_names( &c, tmp_buf,
458 ctx->subject ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200459
460 /*
461 * Validity ::= SEQUENCE {
462 * notBefore Time,
463 * notAfter Time }
464 */
465 sub_len = 0;
466
Hanno Beckerbeaf3962019-05-04 07:37:58 +0100467 MBEDTLS_ASN1_CHK_ADD( sub_len,
468 x509_write_time( &c, tmp_buf, ctx->not_after,
469 MBEDTLS_X509_RFC5280_UTC_TIME_LEN ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200470
Hanno Beckerbeaf3962019-05-04 07:37:58 +0100471 MBEDTLS_ASN1_CHK_ADD( sub_len,
472 x509_write_time( &c, tmp_buf, ctx->not_before,
473 MBEDTLS_X509_RFC5280_UTC_TIME_LEN ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200474
475 len += sub_len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200476 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, sub_len ) );
Hanno Beckerbeaf3962019-05-04 07:37:58 +0100477 MBEDTLS_ASN1_CHK_ADD( len,
478 mbedtls_asn1_write_tag( &c, tmp_buf,
479 MBEDTLS_ASN1_CONSTRUCTED |
480 MBEDTLS_ASN1_SEQUENCE ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200481
482 /*
483 * Issuer ::= Name
484 */
Hanno Beckerbeaf3962019-05-04 07:37:58 +0100485 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c,
486 tmp_buf,
487 ctx->issuer ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200488
489 /*
490 * Signature ::= AlgorithmIdentifier
491 */
Hanno Beckerbeaf3962019-05-04 07:37:58 +0100492 MBEDTLS_ASN1_CHK_ADD( len,
493 mbedtls_asn1_write_algorithm_identifier( &c, tmp_buf,
494 sig_oid, strlen( sig_oid ), 0 ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200495
496 /*
497 * Serial ::= INTEGER
498 */
Hanno Beckerbeaf3962019-05-04 07:37:58 +0100499 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c,
500 tmp_buf,
501 &ctx->serial ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200502
503 /*
504 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
505 */
Hanno Becker47698652017-09-13 11:59:26 +0100506
507 /* Can be omitted for v1 */
Hanno Beckera20e33a2017-09-22 15:40:01 +0100508 if( ctx->version != MBEDTLS_X509_CRT_VERSION_1 )
Hanno Becker47698652017-09-13 11:59:26 +0100509 {
510 sub_len = 0;
Hanno Beckerbeaf3962019-05-04 07:37:58 +0100511 MBEDTLS_ASN1_CHK_ADD( sub_len,
512 mbedtls_asn1_write_int( &c, tmp_buf,
513 ctx->version ) );
Hanno Becker47698652017-09-13 11:59:26 +0100514 len += sub_len;
Hanno Beckerbeaf3962019-05-04 07:37:58 +0100515 MBEDTLS_ASN1_CHK_ADD( len,
516 mbedtls_asn1_write_len( &c, tmp_buf, sub_len ) );
517 MBEDTLS_ASN1_CHK_ADD( len,
518 mbedtls_asn1_write_tag( &c, tmp_buf,
519 MBEDTLS_ASN1_CONTEXT_SPECIFIC |
520 MBEDTLS_ASN1_CONSTRUCTED | 0 ) );
Hanno Becker47698652017-09-13 11:59:26 +0100521 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200522
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200523 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) );
Hanno Beckerbeaf3962019-05-04 07:37:58 +0100524 MBEDTLS_ASN1_CHK_ADD( len,
525 mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED |
526 MBEDTLS_ASN1_SEQUENCE ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200527
528 /*
529 * Make signature
530 */
Andres Amaya Garcia8d8204f2017-06-28 11:07:30 +0100531 if( ( ret = mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c,
532 len, hash ) ) != 0 )
533 {
534 return( ret );
535 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200536
Hanno Beckerbeaf3962019-05-04 07:37:58 +0100537 if( ( ret = mbedtls_pk_sign( ctx->issuer_key, ctx->md_alg,
538 hash, 0, sig, &sig_len,
539 f_rng, p_rng ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200540 {
541 return( ret );
542 }
543
544 /*
545 * Write data to output buffer
546 */
547 c2 = buf + size;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200548 MBEDTLS_ASN1_CHK_ADD( sig_and_oid_len, mbedtls_x509_write_sig( &c2, buf,
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200549 sig_oid, sig_oid_len, sig, sig_len ) );
550
Andres AG60dbc932016-09-02 15:23:48 +0100551 if( len > (size_t)( c2 - buf ) )
552 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
553
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200554 c2 -= len;
555 memcpy( c2, c, len );
556
557 len += sig_and_oid_len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200558 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c2, buf, len ) );
Hanno Beckerbeaf3962019-05-04 07:37:58 +0100559 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c2, buf,
560 MBEDTLS_ASN1_CONSTRUCTED |
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200561 MBEDTLS_ASN1_SEQUENCE ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200562
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200563 return( (int) len );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200564}
565
566#define PEM_BEGIN_CRT "-----BEGIN CERTIFICATE-----\n"
567#define PEM_END_CRT "-----END CERTIFICATE-----\n"
568
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200569#if defined(MBEDTLS_PEM_WRITE_C)
Hanno Beckerbeaf3962019-05-04 07:37:58 +0100570int mbedtls_x509write_crt_pem( mbedtls_x509write_cert *crt,
571 unsigned char *buf, size_t size,
572 int (*f_rng)(void *, unsigned char *, size_t),
573 void *p_rng )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200574{
575 int ret;
576 unsigned char output_buf[4096];
577 size_t olen = 0;
578
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200579 if( ( ret = mbedtls_x509write_crt_der( crt, output_buf, sizeof(output_buf),
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200580 f_rng, p_rng ) ) < 0 )
581 {
582 return( ret );
583 }
584
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200585 if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_CRT, PEM_END_CRT,
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200586 output_buf + sizeof(output_buf) - ret,
587 ret, buf, size, &olen ) ) != 0 )
588 {
589 return( ret );
590 }
591
592 return( 0 );
593}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200594#endif /* MBEDTLS_PEM_WRITE_C */
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200595
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200596#endif /* MBEDTLS_X509_CRT_WRITE_C */