1 /*
2  *  X.509 certificate writing
3  *
4  *  Copyright The Mbed TLS Contributors
5  *  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:
12  *
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.
24  *
25  *  **********
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  */
46 /*
47  * References:
48  * - certificates: RFC 5280, updated by RFC 6818
49  * - CSRs: PKCS#10 v1.7 aka RFC 2986
50  * - attributes: PKCS#9 v2.0 aka RFC 2985
51  */
52 
53 #if !defined(MBEDTLS_CONFIG_FILE)
54 #include "mbedtls/config.h"
55 #else
56 #include MBEDTLS_CONFIG_FILE
57 #endif
58 
59 #if defined(MBEDTLS_X509_CRT_WRITE_C)
60 
61 #include "mbedtls/x509_crt.h"
62 #include "mbedtls/oid.h"
63 #include "mbedtls/asn1write.h"
64 #include "mbedtls/sha1.h"
65 #include "mbedtls/platform_util.h"
66 
67 #include <string.h>
68 
69 #if defined(MBEDTLS_PEM_WRITE_C)
70 #include "mbedtls/pem.h"
71 #endif /* MBEDTLS_PEM_WRITE_C */
72 
73 /*
74  * For the currently used signature algorithms the buffer to store any signature
75  * must be at least of size MAX(MBEDTLS_ECDSA_MAX_LEN, MBEDTLS_MPI_MAX_SIZE)
76  */
77 #if MBEDTLS_ECDSA_MAX_LEN > MBEDTLS_MPI_MAX_SIZE
78 #define SIGNATURE_MAX_SIZE MBEDTLS_ECDSA_MAX_LEN
79 #else
80 #define SIGNATURE_MAX_SIZE MBEDTLS_MPI_MAX_SIZE
81 #endif
82 
mbedtls_x509write_crt_init(mbedtls_x509write_cert * ctx)83 void mbedtls_x509write_crt_init( mbedtls_x509write_cert *ctx )
84 {
85     memset( ctx, 0, sizeof( mbedtls_x509write_cert ) );
86 
87     mbedtls_mpi_init( &ctx->serial );
88     ctx->version = MBEDTLS_X509_CRT_VERSION_3;
89 }
90 
mbedtls_x509write_crt_free(mbedtls_x509write_cert * ctx)91 void mbedtls_x509write_crt_free( mbedtls_x509write_cert *ctx )
92 {
93     mbedtls_mpi_free( &ctx->serial );
94 
95     mbedtls_asn1_free_named_data_list( &ctx->subject );
96     mbedtls_asn1_free_named_data_list( &ctx->issuer );
97     mbedtls_asn1_free_named_data_list( &ctx->extensions );
98 
99     mbedtls_platform_zeroize( ctx, sizeof( mbedtls_x509write_cert ) );
100 }
101 
mbedtls_x509write_crt_set_version(mbedtls_x509write_cert * ctx,int version)102 void mbedtls_x509write_crt_set_version( mbedtls_x509write_cert *ctx,
103                                         int version )
104 {
105     ctx->version = version;
106 }
107 
mbedtls_x509write_crt_set_md_alg(mbedtls_x509write_cert * ctx,mbedtls_md_type_t md_alg)108 void mbedtls_x509write_crt_set_md_alg( mbedtls_x509write_cert *ctx,
109                                        mbedtls_md_type_t md_alg )
110 {
111     ctx->md_alg = md_alg;
112 }
113 
mbedtls_x509write_crt_set_subject_key(mbedtls_x509write_cert * ctx,mbedtls_pk_context * key)114 void mbedtls_x509write_crt_set_subject_key( mbedtls_x509write_cert *ctx,
115                                             mbedtls_pk_context *key )
116 {
117     ctx->subject_key = key;
118 }
119 
mbedtls_x509write_crt_set_issuer_key(mbedtls_x509write_cert * ctx,mbedtls_pk_context * key)120 void mbedtls_x509write_crt_set_issuer_key( mbedtls_x509write_cert *ctx,
121                                            mbedtls_pk_context *key )
122 {
123     ctx->issuer_key = key;
124 }
125 
mbedtls_x509write_crt_set_subject_name(mbedtls_x509write_cert * ctx,const char * subject_name)126 int mbedtls_x509write_crt_set_subject_name( mbedtls_x509write_cert *ctx,
127                                             const char *subject_name )
128 {
129     return mbedtls_x509_string_to_names( &ctx->subject, subject_name );
130 }
131 
mbedtls_x509write_crt_set_issuer_name(mbedtls_x509write_cert * ctx,const char * issuer_name)132 int mbedtls_x509write_crt_set_issuer_name( mbedtls_x509write_cert *ctx,
133                                            const char *issuer_name )
134 {
135     return mbedtls_x509_string_to_names( &ctx->issuer, issuer_name );
136 }
137 
mbedtls_x509write_crt_set_serial(mbedtls_x509write_cert * ctx,const mbedtls_mpi * serial)138 int mbedtls_x509write_crt_set_serial( mbedtls_x509write_cert *ctx,
139                                       const mbedtls_mpi *serial )
140 {
141     int ret;
142 
143     if( ( ret = mbedtls_mpi_copy( &ctx->serial, serial ) ) != 0 )
144         return( ret );
145 
146     return( 0 );
147 }
148 
mbedtls_x509write_crt_set_validity(mbedtls_x509write_cert * ctx,const char * not_before,const char * not_after)149 int mbedtls_x509write_crt_set_validity( mbedtls_x509write_cert *ctx,
150                                         const char *not_before,
151                                         const char *not_after )
152 {
153     if( strlen( not_before ) != MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1 ||
154         strlen( not_after )  != MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1 )
155     {
156         return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
157     }
158     strncpy( ctx->not_before, not_before, MBEDTLS_X509_RFC5280_UTC_TIME_LEN );
159     strncpy( ctx->not_after , not_after , MBEDTLS_X509_RFC5280_UTC_TIME_LEN );
160     ctx->not_before[MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1] = 'Z';
161     ctx->not_after[MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1] = 'Z';
162 
163     return( 0 );
164 }
165 
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)166 int mbedtls_x509write_crt_set_extension( mbedtls_x509write_cert *ctx,
167                                  const char *oid, size_t oid_len,
168                                  int critical,
169                                  const unsigned char *val, size_t val_len )
170 {
171     return( mbedtls_x509_set_extension( &ctx->extensions, oid, oid_len,
172                                         critical, val, val_len ) );
173 }
174 
mbedtls_x509write_crt_set_basic_constraints(mbedtls_x509write_cert * ctx,int is_ca,int max_pathlen)175 int mbedtls_x509write_crt_set_basic_constraints( mbedtls_x509write_cert *ctx,
176                                                  int is_ca, int max_pathlen )
177 {
178     int ret;
179     unsigned char buf[9];
180     unsigned char *c = buf + sizeof(buf);
181     size_t len = 0;
182 
183     memset( buf, 0, sizeof(buf) );
184 
185     if( is_ca && max_pathlen > 127 )
186         return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
187 
188     if( is_ca )
189     {
190         if( max_pathlen >= 0 )
191         {
192             MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf,
193                                                                max_pathlen ) );
194         }
195         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_bool( &c, buf, 1 ) );
196     }
197 
198     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
199     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf,
200                                                 MBEDTLS_ASN1_CONSTRUCTED |
201                                                 MBEDTLS_ASN1_SEQUENCE ) );
202 
203     return(
204         mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_BASIC_CONSTRAINTS,
205                              MBEDTLS_OID_SIZE( MBEDTLS_OID_BASIC_CONSTRAINTS ),
206                              is_ca, buf + sizeof(buf) - len, len ) );
207 }
208 
209 #if defined(MBEDTLS_SHA1_C)
mbedtls_x509write_crt_set_subject_key_identifier(mbedtls_x509write_cert * ctx)210 int mbedtls_x509write_crt_set_subject_key_identifier( mbedtls_x509write_cert *ctx )
211 {
212     int ret;
213     unsigned char buf[MBEDTLS_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
214     unsigned char *c = buf + sizeof(buf);
215     size_t len = 0;
216 
217     memset( buf, 0, sizeof(buf) );
218     MBEDTLS_ASN1_CHK_ADD( len,
219                 mbedtls_pk_write_pubkey( &c, buf, ctx->subject_key ) );
220 
221     ret = mbedtls_sha1_ret( buf + sizeof( buf ) - len, len,
222                             buf + sizeof( buf ) - 20 );
223     if( ret != 0 )
224         return( ret );
225     c = buf + sizeof( buf ) - 20;
226     len = 20;
227 
228     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
229     MBEDTLS_ASN1_CHK_ADD( len,
230             mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_OCTET_STRING ) );
231 
232     return mbedtls_x509write_crt_set_extension( ctx,
233                  MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER,
234                  MBEDTLS_OID_SIZE( MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER ),
235                  0, buf + sizeof(buf) - len, len );
236 }
237 
mbedtls_x509write_crt_set_authority_key_identifier(mbedtls_x509write_cert * ctx)238 int mbedtls_x509write_crt_set_authority_key_identifier( mbedtls_x509write_cert *ctx )
239 {
240     int ret;
241     unsigned char buf[MBEDTLS_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
242     unsigned char *c = buf + sizeof( buf );
243     size_t len = 0;
244 
245     memset( buf, 0, sizeof(buf) );
246     MBEDTLS_ASN1_CHK_ADD( len,
247                           mbedtls_pk_write_pubkey( &c, buf, ctx->issuer_key ) );
248 
249     ret = mbedtls_sha1_ret( buf + sizeof( buf ) - len, len,
250                             buf + sizeof( buf ) - 20 );
251     if( ret != 0 )
252         return( ret );
253     c = buf + sizeof( buf ) - 20;
254     len = 20;
255 
256     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
257     MBEDTLS_ASN1_CHK_ADD( len,
258         mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | 0 ) );
259 
260     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
261     MBEDTLS_ASN1_CHK_ADD( len,
262                           mbedtls_asn1_write_tag( &c, buf,
263                                                   MBEDTLS_ASN1_CONSTRUCTED |
264                                                   MBEDTLS_ASN1_SEQUENCE ) );
265 
266     return mbedtls_x509write_crt_set_extension(
267         ctx, MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER,
268         MBEDTLS_OID_SIZE( MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER ),
269         0, buf + sizeof( buf ) - len, len );
270 }
271 #endif /* MBEDTLS_SHA1_C */
272 
crt_get_unused_bits_for_named_bitstring(unsigned char bitstring,size_t bit_offset)273 static size_t crt_get_unused_bits_for_named_bitstring( unsigned char bitstring,
274                                                        size_t bit_offset )
275 {
276     size_t unused_bits;
277 
278      /* Count the unused bits removing trailing 0s */
279     for( unused_bits = bit_offset; unused_bits < 8; unused_bits++ )
280         if( ( ( bitstring >> unused_bits ) & 0x1 ) != 0 )
281             break;
282 
283      return( unused_bits );
284 }
285 
mbedtls_x509write_crt_set_key_usage(mbedtls_x509write_cert * ctx,unsigned int key_usage)286 int mbedtls_x509write_crt_set_key_usage( mbedtls_x509write_cert *ctx,
287                                          unsigned int key_usage )
288 {
289     unsigned char buf[4], ku;
290     unsigned char *c;
291     int ret;
292     size_t unused_bits;
293     const unsigned int allowed_bits = MBEDTLS_X509_KU_DIGITAL_SIGNATURE |
294         MBEDTLS_X509_KU_NON_REPUDIATION   |
295         MBEDTLS_X509_KU_KEY_ENCIPHERMENT  |
296         MBEDTLS_X509_KU_DATA_ENCIPHERMENT |
297         MBEDTLS_X509_KU_KEY_AGREEMENT     |
298         MBEDTLS_X509_KU_KEY_CERT_SIGN     |
299         MBEDTLS_X509_KU_CRL_SIGN;
300 
301     /* Check that nothing other than the allowed flags is set */
302     if( ( key_usage & ~allowed_bits ) != 0 )
303         return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE );
304 
305     c = buf + 4;
306     ku = (unsigned char)key_usage;
307     unused_bits = crt_get_unused_bits_for_named_bitstring( ku, 1 );
308     ret = mbedtls_asn1_write_bitstring( &c, buf, &ku, 8 - unused_bits );
309 
310     if( ret < 0 )
311         return( ret );
312     else if( ret < 3 || ret > 4 )
313         return( MBEDTLS_ERR_X509_INVALID_FORMAT );
314 
315     ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_KEY_USAGE,
316                                    MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ),
317                                    1, c, (size_t)ret );
318     if( ret != 0 )
319         return( ret );
320 
321     return( 0 );
322 }
323 
mbedtls_x509write_crt_set_ns_cert_type(mbedtls_x509write_cert * ctx,unsigned char ns_cert_type)324 int mbedtls_x509write_crt_set_ns_cert_type( mbedtls_x509write_cert *ctx,
325                                     unsigned char ns_cert_type )
326 {
327     unsigned char buf[4];
328     unsigned char *c;
329     size_t unused_bits;
330     int ret;
331 
332     c = buf + 4;
333 
334     unused_bits = crt_get_unused_bits_for_named_bitstring( ns_cert_type, 0 );
335     ret = mbedtls_asn1_write_bitstring( &c,
336                                         buf,
337                                         &ns_cert_type,
338                                         8 - unused_bits );
339     if( ret < 3 || ret > 4 )
340         return( ret );
341 
342     ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_NS_CERT_TYPE,
343                                    MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ),
344                                    0, c, (size_t)ret );
345     if( ret != 0 )
346         return( ret );
347 
348     return( 0 );
349 }
350 
x509_write_time(unsigned char ** p,unsigned char * start,const char * t,size_t size)351 static int x509_write_time( unsigned char **p, unsigned char *start,
352                             const char *t, size_t size )
353 {
354     int ret;
355     size_t len = 0;
356 
357     /*
358      * write MBEDTLS_ASN1_UTC_TIME if year < 2050 (2 bytes shorter)
359      */
360     if( t[0] == '2' && t[1] == '0' && t[2] < '5' )
361     {
362         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start,
363                                              (const unsigned char *) t + 2,
364                                              size - 2 ) );
365         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
366         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start,
367                                              MBEDTLS_ASN1_UTC_TIME ) );
368     }
369     else
370     {
371         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start,
372                                                   (const unsigned char *) t,
373                                                   size ) );
374         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
375         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start,
376                                              MBEDTLS_ASN1_GENERALIZED_TIME ) );
377     }
378 
379     return( (int) len );
380 }
381 
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)382 int mbedtls_x509write_crt_der( mbedtls_x509write_cert *ctx,
383                                unsigned char *buf, size_t size,
384                                int (*f_rng)(void *, unsigned char *, size_t),
385                                void *p_rng )
386 {
387     int ret;
388     const char *sig_oid;
389     size_t sig_oid_len = 0;
390     unsigned char *c, *c2;
391     unsigned char hash[64];
392     unsigned char sig[SIGNATURE_MAX_SIZE];
393     size_t sub_len = 0, pub_len = 0, sig_and_oid_len = 0, sig_len;
394     size_t len = 0;
395     mbedtls_pk_type_t pk_alg;
396 
397     /*
398      * Prepare data to be signed at the end of the target buffer
399      */
400     c = buf + size;
401 
402     /* Signature algorithm needed in TBS, and later for actual signature */
403 
404     /* There's no direct way of extracting a signature algorithm
405      * (represented as an element of mbedtls_pk_type_t) from a PK instance. */
406     if( mbedtls_pk_can_do( ctx->issuer_key, MBEDTLS_PK_RSA ) )
407         pk_alg = MBEDTLS_PK_RSA;
408     else if( mbedtls_pk_can_do( ctx->issuer_key, MBEDTLS_PK_ECDSA ) )
409         pk_alg = MBEDTLS_PK_ECDSA;
410     else
411         return( MBEDTLS_ERR_X509_INVALID_ALG );
412 
413     if( ( ret = mbedtls_oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg,
414                                           &sig_oid, &sig_oid_len ) ) != 0 )
415     {
416         return( ret );
417     }
418 
419     /*
420      *  Extensions  ::=  SEQUENCE SIZE (1..MAX) OF Extension
421      */
422 
423     /* Only for v3 */
424     if( ctx->version == MBEDTLS_X509_CRT_VERSION_3 )
425     {
426         MBEDTLS_ASN1_CHK_ADD( len,
427                               mbedtls_x509_write_extensions( &c,
428                                                       buf, ctx->extensions ) );
429         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
430         MBEDTLS_ASN1_CHK_ADD( len,
431                               mbedtls_asn1_write_tag( &c, buf,
432                                                       MBEDTLS_ASN1_CONSTRUCTED |
433                                                       MBEDTLS_ASN1_SEQUENCE ) );
434         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
435         MBEDTLS_ASN1_CHK_ADD( len,
436                               mbedtls_asn1_write_tag( &c, buf,
437                                                MBEDTLS_ASN1_CONTEXT_SPECIFIC |
438                                                MBEDTLS_ASN1_CONSTRUCTED | 3 ) );
439     }
440 
441     /*
442      *  SubjectPublicKeyInfo
443      */
444     MBEDTLS_ASN1_CHK_ADD( pub_len,
445                           mbedtls_pk_write_pubkey_der( ctx->subject_key,
446                                                        buf, c - buf ) );
447     c -= pub_len;
448     len += pub_len;
449 
450     /*
451      *  Subject  ::=  Name
452      */
453     MBEDTLS_ASN1_CHK_ADD( len,
454                           mbedtls_x509_write_names( &c, buf,
455                                                     ctx->subject ) );
456 
457     /*
458      *  Validity ::= SEQUENCE {
459      *       notBefore      Time,
460      *       notAfter       Time }
461      */
462     sub_len = 0;
463 
464     MBEDTLS_ASN1_CHK_ADD( sub_len,
465                           x509_write_time( &c, buf, ctx->not_after,
466                                         MBEDTLS_X509_RFC5280_UTC_TIME_LEN ) );
467 
468     MBEDTLS_ASN1_CHK_ADD( sub_len,
469                           x509_write_time( &c, buf, ctx->not_before,
470                                         MBEDTLS_X509_RFC5280_UTC_TIME_LEN ) );
471 
472     len += sub_len;
473     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, sub_len ) );
474     MBEDTLS_ASN1_CHK_ADD( len,
475                           mbedtls_asn1_write_tag( &c, buf,
476                                                   MBEDTLS_ASN1_CONSTRUCTED |
477                                                   MBEDTLS_ASN1_SEQUENCE ) );
478 
479     /*
480      *  Issuer  ::=  Name
481      */
482     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, buf,
483                                                          ctx->issuer ) );
484 
485     /*
486      *  Signature   ::=  AlgorithmIdentifier
487      */
488     MBEDTLS_ASN1_CHK_ADD( len,
489                           mbedtls_asn1_write_algorithm_identifier( &c, buf,
490                                               sig_oid, strlen( sig_oid ), 0 ) );
491 
492     /*
493      *  Serial   ::=  INTEGER
494      */
495     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf,
496                                                        &ctx->serial ) );
497 
498     /*
499      *  Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
500      */
501 
502     /* Can be omitted for v1 */
503     if( ctx->version != MBEDTLS_X509_CRT_VERSION_1 )
504     {
505         sub_len = 0;
506         MBEDTLS_ASN1_CHK_ADD( sub_len,
507                               mbedtls_asn1_write_int( &c, buf, ctx->version ) );
508         len += sub_len;
509         MBEDTLS_ASN1_CHK_ADD( len,
510                               mbedtls_asn1_write_len( &c, buf, sub_len ) );
511         MBEDTLS_ASN1_CHK_ADD( len,
512                               mbedtls_asn1_write_tag( &c, buf,
513                                                MBEDTLS_ASN1_CONTEXT_SPECIFIC |
514                                                MBEDTLS_ASN1_CONSTRUCTED | 0 ) );
515     }
516 
517     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
518     MBEDTLS_ASN1_CHK_ADD( len,
519                 mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED |
520                                                      MBEDTLS_ASN1_SEQUENCE ) );
521 
522     /*
523      * Make signature
524      */
525 
526     /* Compute hash of CRT. */
527     if( ( ret = mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c,
528                             len, hash ) ) != 0 )
529     {
530         return( ret );
531     }
532 
533     if( ( ret = mbedtls_pk_sign( ctx->issuer_key, ctx->md_alg,
534                                  hash, 0, sig, &sig_len,
535                                  f_rng, p_rng ) ) != 0 )
536     {
537         return( ret );
538     }
539 
540     /* Move CRT to the front of the buffer to have space
541      * for the signature. */
542     memmove( buf, c, len );
543     c = buf + len;
544 
545     /* Add signature at the end of the buffer,
546      * making sure that it doesn't underflow
547      * into the CRT buffer. */
548     c2 = buf + size;
549     MBEDTLS_ASN1_CHK_ADD( sig_and_oid_len, mbedtls_x509_write_sig( &c2, c,
550                                         sig_oid, sig_oid_len, sig, sig_len ) );
551 
552     /*
553      * Memory layout after this step:
554      *
555      * buf       c=buf+len                c2            buf+size
556      * [CRT0,...,CRTn, UNUSED, ..., UNUSED, SIG0, ..., SIGm]
557      */
558 
559     /* Move raw CRT to just before the signature. */
560     c = c2 - len;
561     memmove( c, buf, len );
562 
563     len += sig_and_oid_len;
564     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
565     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf,
566                                                  MBEDTLS_ASN1_CONSTRUCTED |
567                                                  MBEDTLS_ASN1_SEQUENCE ) );
568 
569     return( (int) len );
570 }
571 
572 #define PEM_BEGIN_CRT           "-----BEGIN CERTIFICATE-----\n"
573 #define PEM_END_CRT             "-----END CERTIFICATE-----\n"
574 
575 #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)576 int mbedtls_x509write_crt_pem( mbedtls_x509write_cert *crt,
577                                unsigned char *buf, size_t size,
578                                int (*f_rng)(void *, unsigned char *, size_t),
579                                void *p_rng )
580 {
581     int ret;
582     size_t olen;
583 
584     if( ( ret = mbedtls_x509write_crt_der( crt, buf, size,
585                                    f_rng, p_rng ) ) < 0 )
586     {
587         return( ret );
588     }
589 
590     if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_CRT, PEM_END_CRT,
591                                           buf + size - ret, ret,
592                                           buf, size, &olen ) ) != 0 )
593     {
594         return( ret );
595     }
596 
597     return( 0 );
598 }
599 #endif /* MBEDTLS_PEM_WRITE_C */
600 
601 #endif /* MBEDTLS_X509_CRT_WRITE_C */
602