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