1 /*
2 * X.509 certificate writing
3 *
4 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
5 * 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.
18 *
19 * This file is part of mbed TLS (https://tls.mbed.org)
20 */
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
28 #if !defined(MBEDTLS_CONFIG_FILE)
29 #include "mbedtls/config.h"
30 #else
31 #include MBEDTLS_CONFIG_FILE
32 #endif
33
34 #if defined(MBEDTLS_X509_CRT_WRITE_C)
35
36 #include "mbedtls/x509_crt.h"
37 #include "mbedtls/oid.h"
38 #include "mbedtls/asn1write.h"
39 #include "mbedtls/sha1.h"
40
41 #include <string.h>
42
43 #if defined(MBEDTLS_PEM_WRITE_C)
44 #include "mbedtls/pem.h"
45 #endif /* MBEDTLS_PEM_WRITE_C */
46
47 /* Implementation that should never be optimized out by the compiler */
mbedtls_zeroize(void * v,size_t n)48 static void mbedtls_zeroize( void *v, size_t n ) {
49 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
50 }
51
mbedtls_x509write_crt_init(mbedtls_x509write_cert * ctx)52 void mbedtls_x509write_crt_init( mbedtls_x509write_cert *ctx )
53 {
54 memset( ctx, 0, sizeof(mbedtls_x509write_cert) );
55
56 mbedtls_mpi_init( &ctx->serial );
57 ctx->version = MBEDTLS_X509_CRT_VERSION_3;
58 }
59
mbedtls_x509write_crt_free(mbedtls_x509write_cert * ctx)60 void mbedtls_x509write_crt_free( mbedtls_x509write_cert *ctx )
61 {
62 mbedtls_mpi_free( &ctx->serial );
63
64 mbedtls_asn1_free_named_data_list( &ctx->subject );
65 mbedtls_asn1_free_named_data_list( &ctx->issuer );
66 mbedtls_asn1_free_named_data_list( &ctx->extensions );
67
68 mbedtls_zeroize( ctx, sizeof(mbedtls_x509write_cert) );
69 }
70
mbedtls_x509write_crt_set_version(mbedtls_x509write_cert * ctx,int version)71 void mbedtls_x509write_crt_set_version( mbedtls_x509write_cert *ctx, int version )
72 {
73 ctx->version = version;
74 }
75
mbedtls_x509write_crt_set_md_alg(mbedtls_x509write_cert * ctx,mbedtls_md_type_t md_alg)76 void mbedtls_x509write_crt_set_md_alg( mbedtls_x509write_cert *ctx, mbedtls_md_type_t md_alg )
77 {
78 ctx->md_alg = md_alg;
79 }
80
mbedtls_x509write_crt_set_subject_key(mbedtls_x509write_cert * ctx,mbedtls_pk_context * key)81 void mbedtls_x509write_crt_set_subject_key( mbedtls_x509write_cert *ctx, mbedtls_pk_context *key )
82 {
83 ctx->subject_key = key;
84 }
85
mbedtls_x509write_crt_set_issuer_key(mbedtls_x509write_cert * ctx,mbedtls_pk_context * key)86 void mbedtls_x509write_crt_set_issuer_key( mbedtls_x509write_cert *ctx, mbedtls_pk_context *key )
87 {
88 ctx->issuer_key = key;
89 }
90
mbedtls_x509write_crt_set_subject_name(mbedtls_x509write_cert * ctx,const char * subject_name)91 int mbedtls_x509write_crt_set_subject_name( mbedtls_x509write_cert *ctx,
92 const char *subject_name )
93 {
94 return mbedtls_x509_string_to_names( &ctx->subject, subject_name );
95 }
96
mbedtls_x509write_crt_set_issuer_name(mbedtls_x509write_cert * ctx,const char * issuer_name)97 int mbedtls_x509write_crt_set_issuer_name( mbedtls_x509write_cert *ctx,
98 const char *issuer_name )
99 {
100 return mbedtls_x509_string_to_names( &ctx->issuer, issuer_name );
101 }
102
mbedtls_x509write_crt_set_serial(mbedtls_x509write_cert * ctx,const mbedtls_mpi * serial)103 int mbedtls_x509write_crt_set_serial( mbedtls_x509write_cert *ctx, const mbedtls_mpi *serial )
104 {
105 int ret;
106
107 if( ( ret = mbedtls_mpi_copy( &ctx->serial, serial ) ) != 0 )
108 return( ret );
109
110 return( 0 );
111 }
112
mbedtls_x509write_crt_set_validity(mbedtls_x509write_cert * ctx,const char * not_before,const char * not_after)113 int mbedtls_x509write_crt_set_validity( mbedtls_x509write_cert *ctx, const char *not_before,
114 const char *not_after )
115 {
116 if( strlen( not_before ) != MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1 ||
117 strlen( not_after ) != MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1 )
118 {
119 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
120 }
121 strncpy( ctx->not_before, not_before, MBEDTLS_X509_RFC5280_UTC_TIME_LEN );
122 strncpy( ctx->not_after , not_after , MBEDTLS_X509_RFC5280_UTC_TIME_LEN );
123 ctx->not_before[MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1] = 'Z';
124 ctx->not_after[MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1] = 'Z';
125
126 return( 0 );
127 }
128
mbedtls_x509write_crt_set_extension(mbedtls_x509write_cert * ctx,const char * oid,size_t oid_len,int critical,const unsigned char * val,size_t val_len)129 int mbedtls_x509write_crt_set_extension( mbedtls_x509write_cert *ctx,
130 const char *oid, size_t oid_len,
131 int critical,
132 const unsigned char *val, size_t val_len )
133 {
134 return mbedtls_x509_set_extension( &ctx->extensions, oid, oid_len,
135 critical, val, val_len );
136 }
137
mbedtls_x509write_crt_set_basic_constraints(mbedtls_x509write_cert * ctx,int is_ca,int max_pathlen)138 int mbedtls_x509write_crt_set_basic_constraints( mbedtls_x509write_cert *ctx,
139 int is_ca, int max_pathlen )
140 {
141 int ret;
142 unsigned char buf[9];
143 unsigned char *c = buf + sizeof(buf);
144 size_t len = 0;
145
146 memset( buf, 0, sizeof(buf) );
147
148 if( is_ca && max_pathlen > 127 )
149 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
150
151 if( is_ca )
152 {
153 if( max_pathlen >= 0 )
154 {
155 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, max_pathlen ) );
156 }
157 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_bool( &c, buf, 1 ) );
158 }
159
160 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
161 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED |
162 MBEDTLS_ASN1_SEQUENCE ) );
163
164 return mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_BASIC_CONSTRAINTS,
165 MBEDTLS_OID_SIZE( MBEDTLS_OID_BASIC_CONSTRAINTS ),
166 0, buf + sizeof(buf) - len, len );
167 }
168
169 #if defined(MBEDTLS_SHA1_C)
mbedtls_x509write_crt_set_subject_key_identifier(mbedtls_x509write_cert * ctx)170 int mbedtls_x509write_crt_set_subject_key_identifier( mbedtls_x509write_cert *ctx )
171 {
172 int ret;
173 unsigned char buf[MBEDTLS_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
174 unsigned char *c = buf + sizeof(buf);
175 size_t len = 0;
176
177 memset( buf, 0, sizeof(buf) );
178 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, ctx->subject_key ) );
179
180 mbedtls_sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 );
181 c = buf + sizeof(buf) - 20;
182 len = 20;
183
184 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
185 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_OCTET_STRING ) );
186
187 return mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER,
188 MBEDTLS_OID_SIZE( MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER ),
189 0, buf + sizeof(buf) - len, len );
190 }
191
mbedtls_x509write_crt_set_authority_key_identifier(mbedtls_x509write_cert * ctx)192 int mbedtls_x509write_crt_set_authority_key_identifier( mbedtls_x509write_cert *ctx )
193 {
194 int ret;
195 unsigned char buf[MBEDTLS_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
196 unsigned char *c = buf + sizeof(buf);
197 size_t len = 0;
198
199 memset( buf, 0, sizeof(buf) );
200 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, ctx->issuer_key ) );
201
202 mbedtls_sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 );
203 c = buf + sizeof(buf) - 20;
204 len = 20;
205
206 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
207 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | 0 ) );
208
209 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
210 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED |
211 MBEDTLS_ASN1_SEQUENCE ) );
212
213 return mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER,
214 MBEDTLS_OID_SIZE( MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER ),
215 0, buf + sizeof(buf) - len, len );
216 }
217 #endif /* MBEDTLS_SHA1_C */
218
mbedtls_x509write_crt_set_key_usage(mbedtls_x509write_cert * ctx,unsigned int key_usage)219 int mbedtls_x509write_crt_set_key_usage( mbedtls_x509write_cert *ctx,
220 unsigned int key_usage )
221 {
222 unsigned char buf[4], ku;
223 unsigned char *c;
224 int ret;
225
226 /* We currently only support 7 bits, from 0x80 to 0x02 */
227 if( ( key_usage & ~0xfe ) != 0 )
228 return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE );
229
230 c = buf + 4;
231 ku = (unsigned char) key_usage;
232
233 if( ( ret = mbedtls_asn1_write_bitstring( &c, buf, &ku, 7 ) ) != 4 )
234 return( ret );
235
236 ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_KEY_USAGE,
237 MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ),
238 1, buf, 4 );
239 if( ret != 0 )
240 return( ret );
241
242 return( 0 );
243 }
244
mbedtls_x509write_crt_set_ns_cert_type(mbedtls_x509write_cert * ctx,unsigned char ns_cert_type)245 int mbedtls_x509write_crt_set_ns_cert_type( mbedtls_x509write_cert *ctx,
246 unsigned char ns_cert_type )
247 {
248 unsigned char buf[4];
249 unsigned char *c;
250 int ret;
251
252 c = buf + 4;
253
254 if( ( ret = mbedtls_asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 )
255 return( ret );
256
257 ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_NS_CERT_TYPE,
258 MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ),
259 0, buf, 4 );
260 if( ret != 0 )
261 return( ret );
262
263 return( 0 );
264 }
265
x509_write_time(unsigned char ** p,unsigned char * start,const char * time,size_t size)266 static int x509_write_time( unsigned char **p, unsigned char *start,
267 const char *time, size_t size )
268 {
269 int ret;
270 size_t len = 0;
271
272 /*
273 * write MBEDTLS_ASN1_UTC_TIME if year < 2050 (2 bytes shorter)
274 */
275 if( time[0] == '2' && time[1] == '0' && time [2] < '5' )
276 {
277 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start,
278 (const unsigned char *) time + 2,
279 size - 2 ) );
280 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
281 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_UTC_TIME ) );
282 }
283 else
284 {
285 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start,
286 (const unsigned char *) time,
287 size ) );
288 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
289 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_GENERALIZED_TIME ) );
290 }
291
292 return( (int) len );
293 }
294
mbedtls_x509write_crt_der(mbedtls_x509write_cert * ctx,unsigned char * buf,size_t size,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng)295 int mbedtls_x509write_crt_der( mbedtls_x509write_cert *ctx, unsigned char *buf, size_t size,
296 int (*f_rng)(void *, unsigned char *, size_t),
297 void *p_rng )
298 {
299 int ret;
300 const char *sig_oid;
301 size_t sig_oid_len = 0;
302 unsigned char *c, *c2;
303 unsigned char hash[64];
304 unsigned char sig[MBEDTLS_MPI_MAX_SIZE];
305 unsigned char tmp_buf[2048];
306 size_t sub_len = 0, pub_len = 0, sig_and_oid_len = 0, sig_len;
307 size_t len = 0;
308 mbedtls_pk_type_t pk_alg;
309
310 /*
311 * Prepare data to be signed in tmp_buf
312 */
313 c = tmp_buf + sizeof( tmp_buf );
314
315 /* Signature algorithm needed in TBS, and later for actual signature */
316 pk_alg = mbedtls_pk_get_type( ctx->issuer_key );
317 if( pk_alg == MBEDTLS_PK_ECKEY )
318 pk_alg = MBEDTLS_PK_ECDSA;
319
320 if( ( ret = mbedtls_oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg,
321 &sig_oid, &sig_oid_len ) ) != 0 )
322 {
323 return( ret );
324 }
325
326 /*
327 * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
328 */
329 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_extensions( &c, tmp_buf, ctx->extensions ) );
330 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) );
331 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED |
332 MBEDTLS_ASN1_SEQUENCE ) );
333 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) );
334 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC |
335 MBEDTLS_ASN1_CONSTRUCTED | 3 ) );
336
337 /*
338 * SubjectPublicKeyInfo
339 */
340 MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_pk_write_pubkey_der( ctx->subject_key,
341 tmp_buf, c - tmp_buf ) );
342 c -= pub_len;
343 len += pub_len;
344
345 /*
346 * Subject ::= Name
347 */
348 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, tmp_buf, ctx->subject ) );
349
350 /*
351 * Validity ::= SEQUENCE {
352 * notBefore Time,
353 * notAfter Time }
354 */
355 sub_len = 0;
356
357 MBEDTLS_ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_after,
358 MBEDTLS_X509_RFC5280_UTC_TIME_LEN ) );
359
360 MBEDTLS_ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_before,
361 MBEDTLS_X509_RFC5280_UTC_TIME_LEN ) );
362
363 len += sub_len;
364 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, sub_len ) );
365 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED |
366 MBEDTLS_ASN1_SEQUENCE ) );
367
368 /*
369 * Issuer ::= Name
370 */
371 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, tmp_buf, ctx->issuer ) );
372
373 /*
374 * Signature ::= AlgorithmIdentifier
375 */
376 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_algorithm_identifier( &c, tmp_buf,
377 sig_oid, strlen( sig_oid ), 0 ) );
378
379 /*
380 * Serial ::= INTEGER
381 */
382 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, tmp_buf, &ctx->serial ) );
383
384 /*
385 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
386 */
387 sub_len = 0;
388 MBEDTLS_ASN1_CHK_ADD( sub_len, mbedtls_asn1_write_int( &c, tmp_buf, ctx->version ) );
389 len += sub_len;
390 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, sub_len ) );
391 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC |
392 MBEDTLS_ASN1_CONSTRUCTED | 0 ) );
393
394 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) );
395 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED |
396 MBEDTLS_ASN1_SEQUENCE ) );
397
398 /*
399 * Make signature
400 */
401 mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c, len, hash );
402
403 if( ( ret = mbedtls_pk_sign( ctx->issuer_key, ctx->md_alg, hash, 0, sig, &sig_len,
404 f_rng, p_rng ) ) != 0 )
405 {
406 return( ret );
407 }
408
409 /*
410 * Write data to output buffer
411 */
412 c2 = buf + size;
413 MBEDTLS_ASN1_CHK_ADD( sig_and_oid_len, mbedtls_x509_write_sig( &c2, buf,
414 sig_oid, sig_oid_len, sig, sig_len ) );
415
416 if( len > (size_t)( c2 - buf ) )
417 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
418
419 c2 -= len;
420 memcpy( c2, c, len );
421
422 len += sig_and_oid_len;
423 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c2, buf, len ) );
424 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c2, buf, MBEDTLS_ASN1_CONSTRUCTED |
425 MBEDTLS_ASN1_SEQUENCE ) );
426
427 return( (int) len );
428 }
429
430 #define PEM_BEGIN_CRT "-----BEGIN CERTIFICATE-----\n"
431 #define PEM_END_CRT "-----END CERTIFICATE-----\n"
432
433 #if defined(MBEDTLS_PEM_WRITE_C)
mbedtls_x509write_crt_pem(mbedtls_x509write_cert * crt,unsigned char * buf,size_t size,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng)434 int mbedtls_x509write_crt_pem( mbedtls_x509write_cert *crt, unsigned char *buf, size_t size,
435 int (*f_rng)(void *, unsigned char *, size_t),
436 void *p_rng )
437 {
438 int ret;
439 unsigned char output_buf[4096];
440 size_t olen = 0;
441
442 if( ( ret = mbedtls_x509write_crt_der( crt, output_buf, sizeof(output_buf),
443 f_rng, p_rng ) ) < 0 )
444 {
445 return( ret );
446 }
447
448 if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_CRT, PEM_END_CRT,
449 output_buf + sizeof(output_buf) - ret,
450 ret, buf, size, &olen ) ) != 0 )
451 {
452 return( ret );
453 }
454
455 return( 0 );
456 }
457 #endif /* MBEDTLS_PEM_WRITE_C */
458
459 #endif /* MBEDTLS_X509_CRT_WRITE_C */
460