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