blob: 7a74a1fecf7f46bae753b1f9b15800d1c37ae604 [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
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 Bakker7c6b2c32013-09-16 13:49:26 +020018 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000019 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker7c6b2c32013-09-16 13:49:26 +020020 */
21/*
22 * References:
23 * - certificates: RFC 5280, updated by RFC 6818
24 * - CSRs: PKCS#10 v1.7 aka RFC 2986
25 * - attributes: PKCS#9 v2.0 aka RFC 2985
26 */
27
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020028#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000029#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020030#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020031#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020032#endif
Paul Bakker7c6b2c32013-09-16 13:49:26 +020033
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020034#if defined(MBEDTLS_X509_CRT_WRITE_C)
Paul Bakker7c6b2c32013-09-16 13:49:26 +020035
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000036#include "mbedtls/x509_crt.h"
Hanno Beckerf6bc8882019-05-02 13:05:58 +010037#include "mbedtls/x509_internal.h"
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000038#include "mbedtls/oid.h"
39#include "mbedtls/asn1write.h"
40#include "mbedtls/sha1.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050041#include "mbedtls/platform_util.h"
Paul Bakker7c6b2c32013-09-16 13:49:26 +020042
Rich Evans00ab4702015-02-06 13:43:58 +000043#include <string.h>
44
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020045#if defined(MBEDTLS_PEM_WRITE_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000046#include "mbedtls/pem.h"
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020047#endif /* MBEDTLS_PEM_WRITE_C */
Paul Bakker7c6b2c32013-09-16 13:49:26 +020048
k-stachowiake79c9392019-05-31 20:11:26 +020049/*
50 * For the currently used signature algorithms the buffer to store any signature
51 * must be at least of size MAX(MBEDTLS_ECDSA_MAX_LEN, MBEDTLS_MPI_MAX_SIZE)
52 */
53#if MBEDTLS_ECDSA_MAX_LEN > MBEDTLS_MPI_MAX_SIZE
54#define SIGNATURE_MAX_SIZE MBEDTLS_ECDSA_MAX_LEN
55#else
56#define SIGNATURE_MAX_SIZE MBEDTLS_MPI_MAX_SIZE
57#endif
58
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020059void mbedtls_x509write_crt_init( mbedtls_x509write_cert *ctx )
Paul Bakker7c6b2c32013-09-16 13:49:26 +020060{
Manuel Pégourié-Gonnard7a346b82019-10-02 14:47:01 +020061 mbedtls_platform_memset( ctx, 0, sizeof( mbedtls_x509write_cert ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +020062
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020063 mbedtls_mpi_init( &ctx->serial );
64 ctx->version = MBEDTLS_X509_CRT_VERSION_3;
Paul Bakker7c6b2c32013-09-16 13:49:26 +020065}
66
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020067void mbedtls_x509write_crt_free( mbedtls_x509write_cert *ctx )
Paul Bakker7c6b2c32013-09-16 13:49:26 +020068{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020069 mbedtls_mpi_free( &ctx->serial );
Paul Bakker7c6b2c32013-09-16 13:49:26 +020070
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020071 mbedtls_asn1_free_named_data_list( &ctx->subject );
72 mbedtls_asn1_free_named_data_list( &ctx->issuer );
73 mbedtls_asn1_free_named_data_list( &ctx->extensions );
Paul Bakker7c6b2c32013-09-16 13:49:26 +020074
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050075 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_x509write_cert ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +020076}
77
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020078void mbedtls_x509write_crt_set_version( mbedtls_x509write_cert *ctx, int version )
Paul Bakker5191e922013-10-11 10:54:28 +020079{
80 ctx->version = version;
81}
82
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020083void mbedtls_x509write_crt_set_md_alg( mbedtls_x509write_cert *ctx, mbedtls_md_type_t md_alg )
Paul Bakker7c6b2c32013-09-16 13:49:26 +020084{
85 ctx->md_alg = md_alg;
86}
87
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020088void mbedtls_x509write_crt_set_subject_key( mbedtls_x509write_cert *ctx, mbedtls_pk_context *key )
Paul Bakker7c6b2c32013-09-16 13:49:26 +020089{
90 ctx->subject_key = key;
91}
92
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020093void mbedtls_x509write_crt_set_issuer_key( mbedtls_x509write_cert *ctx, mbedtls_pk_context *key )
Paul Bakker7c6b2c32013-09-16 13:49:26 +020094{
95 ctx->issuer_key = key;
96}
97
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020098int mbedtls_x509write_crt_set_subject_name( mbedtls_x509write_cert *ctx,
Paul Bakker50dc8502013-10-28 21:19:10 +010099 const char *subject_name )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200100{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200101 return mbedtls_x509_string_to_names( &ctx->subject, subject_name );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200102}
103
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200104int mbedtls_x509write_crt_set_issuer_name( mbedtls_x509write_cert *ctx,
Paul Bakker50dc8502013-10-28 21:19:10 +0100105 const char *issuer_name )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200106{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200107 return mbedtls_x509_string_to_names( &ctx->issuer, issuer_name );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200108}
109
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200110int mbedtls_x509write_crt_set_serial( mbedtls_x509write_cert *ctx, const mbedtls_mpi *serial )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200111{
112 int ret;
113
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200114 if( ( ret = mbedtls_mpi_copy( &ctx->serial, serial ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200115 return( ret );
116
117 return( 0 );
118}
119
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200120int mbedtls_x509write_crt_set_validity( mbedtls_x509write_cert *ctx, const char *not_before,
Paul Bakker50dc8502013-10-28 21:19:10 +0100121 const char *not_after )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200122{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200123 if( strlen( not_before ) != MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1 ||
124 strlen( not_after ) != MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200125 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200126 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200127 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200128 strncpy( ctx->not_before, not_before, MBEDTLS_X509_RFC5280_UTC_TIME_LEN );
129 strncpy( ctx->not_after , not_after , MBEDTLS_X509_RFC5280_UTC_TIME_LEN );
130 ctx->not_before[MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1] = 'Z';
131 ctx->not_after[MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1] = 'Z';
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200132
133 return( 0 );
134}
135
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200136int mbedtls_x509write_crt_set_extension( mbedtls_x509write_cert *ctx,
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200137 const char *oid, size_t oid_len,
138 int critical,
139 const unsigned char *val, size_t val_len )
140{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200141 return mbedtls_x509_set_extension( &ctx->extensions, oid, oid_len,
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200142 critical, val, val_len );
143}
144
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200145int mbedtls_x509write_crt_set_basic_constraints( mbedtls_x509write_cert *ctx,
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200146 int is_ca, int max_pathlen )
147{
148 int ret;
149 unsigned char buf[9];
150 unsigned char *c = buf + sizeof(buf);
151 size_t len = 0;
152
Manuel Pégourié-Gonnard7a346b82019-10-02 14:47:01 +0200153 mbedtls_platform_memset( buf, 0, sizeof(buf) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200154
155 if( is_ca && max_pathlen > 127 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200156 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200157
158 if( is_ca )
159 {
160 if( max_pathlen >= 0 )
161 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200162 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, max_pathlen ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200163 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200164 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_bool( &c, buf, 1 ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200165 }
166
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200167 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
168 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED |
169 MBEDTLS_ASN1_SEQUENCE ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200170
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200171 return mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_BASIC_CONSTRAINTS,
172 MBEDTLS_OID_SIZE( MBEDTLS_OID_BASIC_CONSTRAINTS ),
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200173 0, buf + sizeof(buf) - len, len );
174}
175
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200176#if defined(MBEDTLS_SHA1_C)
177int mbedtls_x509write_crt_set_subject_key_identifier( mbedtls_x509write_cert *ctx )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200178{
179 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200180 unsigned char buf[MBEDTLS_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200181 unsigned char *c = buf + sizeof(buf);
182 size_t len = 0;
183
Manuel Pégourié-Gonnard7a346b82019-10-02 14:47:01 +0200184 mbedtls_platform_memset( buf, 0, sizeof(buf) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200185 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, ctx->subject_key ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200186
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100187 ret = mbedtls_sha1_ret( buf + sizeof( buf ) - len, len,
Andres Amaya Garcia8d8204f2017-06-28 11:07:30 +0100188 buf + sizeof( buf ) - 20 );
189 if( ret != 0 )
190 return( ret );
191 c = buf + sizeof( buf ) - 20;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200192 len = 20;
193
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200194 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
195 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_OCTET_STRING ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200196
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200197 return mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER,
198 MBEDTLS_OID_SIZE( MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER ),
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200199 0, buf + sizeof(buf) - len, len );
200}
201
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200202int mbedtls_x509write_crt_set_authority_key_identifier( mbedtls_x509write_cert *ctx )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200203{
204 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200205 unsigned char buf[MBEDTLS_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
Hanno Becker81535d02017-09-13 15:39:59 +0100206 unsigned char *c = buf + sizeof( buf );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200207 size_t len = 0;
208
Manuel Pégourié-Gonnard7a346b82019-10-02 14:47:01 +0200209 mbedtls_platform_memset( buf, 0, sizeof(buf) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200210 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, ctx->issuer_key ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200211
Gilles Peskine9e4f77c2018-01-22 11:48:08 +0100212 ret = mbedtls_sha1_ret( buf + sizeof( buf ) - len, len,
Andres Amaya Garcia8d8204f2017-06-28 11:07:30 +0100213 buf + sizeof( buf ) - 20 );
214 if( ret != 0 )
215 return( ret );
216 c = buf + sizeof( buf ) - 20;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200217 len = 20;
218
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200219 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
220 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | 0 ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200221
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200222 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
223 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED |
224 MBEDTLS_ASN1_SEQUENCE ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200225
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200226 return mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER,
227 MBEDTLS_OID_SIZE( MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER ),
Hanno Becker81535d02017-09-13 15:39:59 +0100228 0, buf + sizeof( buf ) - len, len );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200229}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200230#endif /* MBEDTLS_SHA1_C */
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200231
Andres Amaya Garciad60e3782018-09-26 10:48:24 +0100232static size_t crt_get_unused_bits_for_named_bitstring( unsigned char bitstring,
233 size_t bit_offset )
234{
235 size_t unused_bits;
236
237 /* Count the unused bits removing trailing 0s */
238 for( unused_bits = bit_offset; unused_bits < 8; unused_bits++ )
239 if( ( ( bitstring >> unused_bits ) & 0x1 ) != 0 )
240 break;
241
242 return( unused_bits );
243}
244
Manuel Pégourié-Gonnard1cd10ad2015-06-23 11:07:37 +0200245int mbedtls_x509write_crt_set_key_usage( mbedtls_x509write_cert *ctx,
246 unsigned int key_usage )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200247{
Manuel Pégourié-Gonnard1cd10ad2015-06-23 11:07:37 +0200248 unsigned char buf[4], ku;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200249 unsigned char *c;
250 int ret;
Andres Amaya Garciad60e3782018-09-26 10:48:24 +0100251 size_t unused_bits;
252 const unsigned int allowed_bits = MBEDTLS_X509_KU_DIGITAL_SIGNATURE |
253 MBEDTLS_X509_KU_NON_REPUDIATION |
254 MBEDTLS_X509_KU_KEY_ENCIPHERMENT |
255 MBEDTLS_X509_KU_DATA_ENCIPHERMENT |
256 MBEDTLS_X509_KU_KEY_AGREEMENT |
257 MBEDTLS_X509_KU_KEY_CERT_SIGN |
258 MBEDTLS_X509_KU_CRL_SIGN;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200259
Andres Amaya Garciad60e3782018-09-26 10:48:24 +0100260 /* Check that nothing other than the allowed flags is set */
261 if( ( key_usage & ~allowed_bits ) != 0 )
Manuel Pégourié-Gonnard1cd10ad2015-06-23 11:07:37 +0200262 return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200263
Manuel Pégourié-Gonnard1cd10ad2015-06-23 11:07:37 +0200264 c = buf + 4;
Andres Amaya Garciad60e3782018-09-26 10:48:24 +0100265 ku = (unsigned char)key_usage;
266 unused_bits = crt_get_unused_bits_for_named_bitstring( ku, 1 );
267 ret = mbedtls_asn1_write_bitstring( &c, buf, &ku, 8 - unused_bits );
Manuel Pégourié-Gonnard1cd10ad2015-06-23 11:07:37 +0200268
Andres Amaya Garciad60e3782018-09-26 10:48:24 +0100269 if( ret < 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200270 return( ret );
Andres Amaya Garciad60e3782018-09-26 10:48:24 +0100271 else if( ret < 3 || ret > 4 )
272 return( MBEDTLS_ERR_X509_INVALID_FORMAT );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200273
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200274 ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_KEY_USAGE,
275 MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ),
Andres Amaya Garciad60e3782018-09-26 10:48:24 +0100276 1, c, (size_t)ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200277 if( ret != 0 )
278 return( ret );
279
280 return( 0 );
281}
282
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200283int mbedtls_x509write_crt_set_ns_cert_type( mbedtls_x509write_cert *ctx,
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200284 unsigned char ns_cert_type )
285{
286 unsigned char buf[4];
287 unsigned char *c;
Andres Amaya Garciad60e3782018-09-26 10:48:24 +0100288 size_t unused_bits;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200289 int ret;
290
291 c = buf + 4;
292
Andres Amaya Garciad60e3782018-09-26 10:48:24 +0100293 unused_bits = crt_get_unused_bits_for_named_bitstring( ns_cert_type, 0 );
294 ret = mbedtls_asn1_write_bitstring( &c,
295 buf,
296 &ns_cert_type,
297 8 - unused_bits );
298 if( ret < 3 || ret > 4 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200299 return( ret );
300
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200301 ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_NS_CERT_TYPE,
302 MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ),
Andres Amaya Garciad60e3782018-09-26 10:48:24 +0100303 0, c, (size_t)ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200304 if( ret != 0 )
305 return( ret );
306
307 return( 0 );
308}
309
310static int x509_write_time( unsigned char **p, unsigned char *start,
Hanno Becker61937d42017-04-26 15:01:23 +0100311 const char *t, size_t size )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200312{
313 int ret;
314 size_t len = 0;
315
316 /*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200317 * write MBEDTLS_ASN1_UTC_TIME if year < 2050 (2 bytes shorter)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200318 */
Hanno Becker61937d42017-04-26 15:01:23 +0100319 if( t[0] == '2' && t[1] == '0' && t[2] < '5' )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200320 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200321 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start,
Hanno Becker61937d42017-04-26 15:01:23 +0100322 (const unsigned char *) t + 2,
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200323 size - 2 ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200324 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
325 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_UTC_TIME ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200326 }
327 else
328 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200329 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start,
Hanno Becker61937d42017-04-26 15:01:23 +0100330 (const unsigned char *) t,
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200331 size ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200332 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
333 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_GENERALIZED_TIME ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200334 }
335
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200336 return( (int) len );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200337}
338
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200339int mbedtls_x509write_crt_der( mbedtls_x509write_cert *ctx, unsigned char *buf, size_t size,
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200340 int (*f_rng)(void *, unsigned char *, size_t),
341 void *p_rng )
342{
343 int ret;
344 const char *sig_oid;
345 size_t sig_oid_len = 0;
346 unsigned char *c, *c2;
347 unsigned char hash[64];
k-stachowiake79c9392019-05-31 20:11:26 +0200348 unsigned char sig[SIGNATURE_MAX_SIZE];
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200349 unsigned char tmp_buf[2048];
350 size_t sub_len = 0, pub_len = 0, sig_and_oid_len = 0, sig_len;
351 size_t len = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200352 mbedtls_pk_type_t pk_alg;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200353
354 /*
355 * Prepare data to be signed in tmp_buf
356 */
357 c = tmp_buf + sizeof( tmp_buf );
358
359 /* Signature algorithm needed in TBS, and later for actual signature */
Hanno Beckerfc771442017-09-13 08:45:48 +0100360
361 /* There's no direct way of extracting a signature algorithm
362 * (represented as an element of mbedtls_pk_type_t) from a PK instance. */
363 if( mbedtls_pk_can_do( ctx->issuer_key, MBEDTLS_PK_RSA ) )
364 pk_alg = MBEDTLS_PK_RSA;
365 else if( mbedtls_pk_can_do( ctx->issuer_key, MBEDTLS_PK_ECDSA ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200366 pk_alg = MBEDTLS_PK_ECDSA;
Hanno Beckerfc771442017-09-13 08:45:48 +0100367 else
Hanno Beckerd8a6f7c2017-09-22 16:05:43 +0100368 return( MBEDTLS_ERR_X509_INVALID_ALG );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200369
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200370 if( ( ret = mbedtls_oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg,
Hanno Becker81535d02017-09-13 15:39:59 +0100371 &sig_oid, &sig_oid_len ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200372 {
373 return( ret );
374 }
375
376 /*
377 * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
378 */
Hanno Beckerd7f35202017-09-13 12:00:15 +0100379
380 /* Only for v3 */
Hanno Beckera20e33a2017-09-22 15:40:01 +0100381 if( ctx->version == MBEDTLS_X509_CRT_VERSION_3 )
Hanno Beckerd7f35202017-09-13 12:00:15 +0100382 {
383 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_extensions( &c, tmp_buf, ctx->extensions ) );
384 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) );
385 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED |
386 MBEDTLS_ASN1_SEQUENCE ) );
387 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) );
388 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC |
389 MBEDTLS_ASN1_CONSTRUCTED | 3 ) );
390 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200391
392 /*
393 * SubjectPublicKeyInfo
394 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200395 MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_pk_write_pubkey_der( ctx->subject_key,
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200396 tmp_buf, c - tmp_buf ) );
397 c -= pub_len;
398 len += pub_len;
399
400 /*
401 * Subject ::= Name
402 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200403 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, tmp_buf, ctx->subject ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200404
405 /*
406 * Validity ::= SEQUENCE {
407 * notBefore Time,
408 * notAfter Time }
409 */
410 sub_len = 0;
411
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200412 MBEDTLS_ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_after,
413 MBEDTLS_X509_RFC5280_UTC_TIME_LEN ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200414
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200415 MBEDTLS_ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_before,
416 MBEDTLS_X509_RFC5280_UTC_TIME_LEN ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200417
418 len += sub_len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200419 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, sub_len ) );
420 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED |
421 MBEDTLS_ASN1_SEQUENCE ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200422
423 /*
424 * Issuer ::= Name
425 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200426 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, tmp_buf, ctx->issuer ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200427
428 /*
429 * Signature ::= AlgorithmIdentifier
430 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200431 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_algorithm_identifier( &c, tmp_buf,
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200432 sig_oid, strlen( sig_oid ), 0 ) );
433
434 /*
435 * Serial ::= INTEGER
436 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200437 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, tmp_buf, &ctx->serial ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200438
439 /*
440 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
441 */
Hanno Becker47698652017-09-13 11:59:26 +0100442
443 /* Can be omitted for v1 */
Hanno Beckera20e33a2017-09-22 15:40:01 +0100444 if( ctx->version != MBEDTLS_X509_CRT_VERSION_1 )
Hanno Becker47698652017-09-13 11:59:26 +0100445 {
446 sub_len = 0;
447 MBEDTLS_ASN1_CHK_ADD( sub_len, mbedtls_asn1_write_int( &c, tmp_buf, ctx->version ) );
448 len += sub_len;
449 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, sub_len ) );
450 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC |
451 MBEDTLS_ASN1_CONSTRUCTED | 0 ) );
452 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200453
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200454 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) );
455 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED |
Hanno Becker47698652017-09-13 11:59:26 +0100456 MBEDTLS_ASN1_SEQUENCE ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200457
458 /*
459 * Make signature
460 */
Andres Amaya Garcia8d8204f2017-06-28 11:07:30 +0100461 if( ( ret = mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c,
462 len, hash ) ) != 0 )
463 {
464 return( ret );
465 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200466
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200467 if( ( ret = mbedtls_pk_sign( ctx->issuer_key, ctx->md_alg, hash, 0, sig, &sig_len,
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200468 f_rng, p_rng ) ) != 0 )
469 {
470 return( ret );
471 }
472
473 /*
474 * Write data to output buffer
475 */
476 c2 = buf + size;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200477 MBEDTLS_ASN1_CHK_ADD( sig_and_oid_len, mbedtls_x509_write_sig( &c2, buf,
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200478 sig_oid, sig_oid_len, sig, sig_len ) );
479
Andres AG60dbc932016-09-02 15:23:48 +0100480 if( len > (size_t)( c2 - buf ) )
481 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
482
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200483 c2 -= len;
Teppo Järvelin91d79382019-10-02 09:09:31 +0300484 mbedtls_platform_memcpy( c2, c, len );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200485
486 len += sig_and_oid_len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200487 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c2, buf, len ) );
488 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c2, buf, MBEDTLS_ASN1_CONSTRUCTED |
489 MBEDTLS_ASN1_SEQUENCE ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200490
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200491 return( (int) len );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200492}
493
494#define PEM_BEGIN_CRT "-----BEGIN CERTIFICATE-----\n"
495#define PEM_END_CRT "-----END CERTIFICATE-----\n"
496
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200497#if defined(MBEDTLS_PEM_WRITE_C)
498int mbedtls_x509write_crt_pem( mbedtls_x509write_cert *crt, unsigned char *buf, size_t size,
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200499 int (*f_rng)(void *, unsigned char *, size_t),
500 void *p_rng )
501{
502 int ret;
503 unsigned char output_buf[4096];
504 size_t olen = 0;
505
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200506 if( ( ret = mbedtls_x509write_crt_der( crt, output_buf, sizeof(output_buf),
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200507 f_rng, p_rng ) ) < 0 )
508 {
509 return( ret );
510 }
511
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200512 if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_CRT, PEM_END_CRT,
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200513 output_buf + sizeof(output_buf) - ret,
514 ret, buf, size, &olen ) ) != 0 )
515 {
516 return( ret );
517 }
518
519 return( 0 );
520}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200521#endif /* MBEDTLS_PEM_WRITE_C */
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200522
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200523#endif /* MBEDTLS_X509_CRT_WRITE_C */