• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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                              is_ca, 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( 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( 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] = {0}, ku[2] = {0};
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     MBEDTLS_PUT_UINT16_LE( key_usage, ku, 0 );
255     ret = mbedtls_asn1_write_named_bitstring( &c, buf, ku, 9 );
256 
257     if( ret < 0 )
258         return( ret );
259     else if( ret < 3 || ret > 5 )
260         return( MBEDTLS_ERR_X509_INVALID_FORMAT );
261 
262     ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_KEY_USAGE,
263                                    MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ),
264                                    1, c, (size_t)ret );
265     if( ret != 0 )
266         return( ret );
267 
268     return( 0 );
269 }
270 
mbedtls_x509write_crt_set_ns_cert_type(mbedtls_x509write_cert * ctx,unsigned char ns_cert_type)271 int mbedtls_x509write_crt_set_ns_cert_type( mbedtls_x509write_cert *ctx,
272                                     unsigned char ns_cert_type )
273 {
274     unsigned char buf[4] = {0};
275     unsigned char *c;
276     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
277 
278     c = buf + 4;
279 
280     ret = mbedtls_asn1_write_named_bitstring( &c, buf, &ns_cert_type, 8 );
281     if( ret < 3 || ret > 4 )
282         return( ret );
283 
284     ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_NS_CERT_TYPE,
285                                    MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ),
286                                    0, c, (size_t)ret );
287     if( ret != 0 )
288         return( ret );
289 
290     return( 0 );
291 }
292 
x509_write_time(unsigned char ** p,unsigned char * start,const char * t,size_t size)293 static int x509_write_time( unsigned char **p, unsigned char *start,
294                             const char *t, size_t size )
295 {
296     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
297     size_t len = 0;
298 
299     /*
300      * write MBEDTLS_ASN1_UTC_TIME if year < 2050 (2 bytes shorter)
301      */
302     if( t[0] == '2' && t[1] == '0' && t[2] < '5' )
303     {
304         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start,
305                                              (const unsigned char *) t + 2,
306                                              size - 2 ) );
307         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
308         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start,
309                                              MBEDTLS_ASN1_UTC_TIME ) );
310     }
311     else
312     {
313         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start,
314                                                   (const unsigned char *) t,
315                                                   size ) );
316         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
317         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start,
318                                              MBEDTLS_ASN1_GENERALIZED_TIME ) );
319     }
320 
321     return( (int) len );
322 }
323 
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)324 int mbedtls_x509write_crt_der( mbedtls_x509write_cert *ctx,
325                                unsigned char *buf, size_t size,
326                                int (*f_rng)(void *, unsigned char *, size_t),
327                                void *p_rng )
328 {
329     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
330     const char *sig_oid;
331     size_t sig_oid_len = 0;
332     unsigned char *c, *c2;
333     unsigned char hash[64];
334     unsigned char sig[MBEDTLS_PK_SIGNATURE_MAX_SIZE];
335     size_t sub_len = 0, pub_len = 0, sig_and_oid_len = 0, sig_len;
336     size_t len = 0;
337     mbedtls_pk_type_t pk_alg;
338 
339     /*
340      * Prepare data to be signed at the end of the target buffer
341      */
342     c = buf + size;
343 
344     /* Signature algorithm needed in TBS, and later for actual signature */
345 
346     /* There's no direct way of extracting a signature algorithm
347      * (represented as an element of mbedtls_pk_type_t) from a PK instance. */
348     if( mbedtls_pk_can_do( ctx->issuer_key, MBEDTLS_PK_RSA ) )
349         pk_alg = MBEDTLS_PK_RSA;
350     else if( mbedtls_pk_can_do( ctx->issuer_key, MBEDTLS_PK_ECDSA ) )
351         pk_alg = MBEDTLS_PK_ECDSA;
352     else
353         return( MBEDTLS_ERR_X509_INVALID_ALG );
354 
355     if( ( ret = mbedtls_oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg,
356                                           &sig_oid, &sig_oid_len ) ) != 0 )
357     {
358         return( ret );
359     }
360 
361     /*
362      *  Extensions  ::=  SEQUENCE SIZE (1..MAX) OF Extension
363      */
364 
365     /* Only for v3 */
366     if( ctx->version == MBEDTLS_X509_CRT_VERSION_3 )
367     {
368         MBEDTLS_ASN1_CHK_ADD( len,
369                               mbedtls_x509_write_extensions( &c,
370                                                       buf, ctx->extensions ) );
371         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
372         MBEDTLS_ASN1_CHK_ADD( len,
373                               mbedtls_asn1_write_tag( &c, buf,
374                                                       MBEDTLS_ASN1_CONSTRUCTED |
375                                                       MBEDTLS_ASN1_SEQUENCE ) );
376         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
377         MBEDTLS_ASN1_CHK_ADD( len,
378                               mbedtls_asn1_write_tag( &c, buf,
379                                                MBEDTLS_ASN1_CONTEXT_SPECIFIC |
380                                                MBEDTLS_ASN1_CONSTRUCTED | 3 ) );
381     }
382 
383     /*
384      *  SubjectPublicKeyInfo
385      */
386     MBEDTLS_ASN1_CHK_ADD( pub_len,
387                           mbedtls_pk_write_pubkey_der( ctx->subject_key,
388                                                        buf, c - buf ) );
389     c -= pub_len;
390     len += pub_len;
391 
392     /*
393      *  Subject  ::=  Name
394      */
395     MBEDTLS_ASN1_CHK_ADD( len,
396                           mbedtls_x509_write_names( &c, buf,
397                                                     ctx->subject ) );
398 
399     /*
400      *  Validity ::= SEQUENCE {
401      *       notBefore      Time,
402      *       notAfter       Time }
403      */
404     sub_len = 0;
405 
406     MBEDTLS_ASN1_CHK_ADD( sub_len,
407                           x509_write_time( &c, buf, ctx->not_after,
408                                         MBEDTLS_X509_RFC5280_UTC_TIME_LEN ) );
409 
410     MBEDTLS_ASN1_CHK_ADD( sub_len,
411                           x509_write_time( &c, buf, ctx->not_before,
412                                         MBEDTLS_X509_RFC5280_UTC_TIME_LEN ) );
413 
414     len += sub_len;
415     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, sub_len ) );
416     MBEDTLS_ASN1_CHK_ADD( len,
417                           mbedtls_asn1_write_tag( &c, buf,
418                                                   MBEDTLS_ASN1_CONSTRUCTED |
419                                                   MBEDTLS_ASN1_SEQUENCE ) );
420 
421     /*
422      *  Issuer  ::=  Name
423      */
424     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, buf,
425                                                          ctx->issuer ) );
426 
427     /*
428      *  Signature   ::=  AlgorithmIdentifier
429      */
430     MBEDTLS_ASN1_CHK_ADD( len,
431                           mbedtls_asn1_write_algorithm_identifier( &c, buf,
432                                               sig_oid, strlen( sig_oid ), 0 ) );
433 
434     /*
435      *  Serial   ::=  INTEGER
436      */
437     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf,
438                                                        &ctx->serial ) );
439 
440     /*
441      *  Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
442      */
443 
444     /* Can be omitted for v1 */
445     if( ctx->version != MBEDTLS_X509_CRT_VERSION_1 )
446     {
447         sub_len = 0;
448         MBEDTLS_ASN1_CHK_ADD( sub_len,
449                               mbedtls_asn1_write_int( &c, buf, ctx->version ) );
450         len += sub_len;
451         MBEDTLS_ASN1_CHK_ADD( len,
452                               mbedtls_asn1_write_len( &c, buf, sub_len ) );
453         MBEDTLS_ASN1_CHK_ADD( len,
454                               mbedtls_asn1_write_tag( &c, buf,
455                                                MBEDTLS_ASN1_CONTEXT_SPECIFIC |
456                                                MBEDTLS_ASN1_CONSTRUCTED | 0 ) );
457     }
458 
459     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
460     MBEDTLS_ASN1_CHK_ADD( len,
461                 mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED |
462                                                      MBEDTLS_ASN1_SEQUENCE ) );
463 
464     /*
465      * Make signature
466      */
467 
468     /* Compute hash of CRT. */
469     if( ( ret = mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c,
470                             len, hash ) ) != 0 )
471     {
472         return( ret );
473     }
474 
475     if( ( ret = mbedtls_pk_sign( ctx->issuer_key, ctx->md_alg,
476                                  hash, 0, sig, sizeof( sig ), &sig_len,
477                                  f_rng, p_rng ) ) != 0 )
478     {
479         return( ret );
480     }
481 
482     /* Move CRT to the front of the buffer to have space
483      * for the signature. */
484     memmove( buf, c, len );
485     c = buf + len;
486 
487     /* Add signature at the end of the buffer,
488      * making sure that it doesn't underflow
489      * into the CRT buffer. */
490     c2 = buf + size;
491     MBEDTLS_ASN1_CHK_ADD( sig_and_oid_len, mbedtls_x509_write_sig( &c2, c,
492                                         sig_oid, sig_oid_len, sig, sig_len ) );
493 
494     /*
495      * Memory layout after this step:
496      *
497      * buf       c=buf+len                c2            buf+size
498      * [CRT0,...,CRTn, UNUSED, ..., UNUSED, SIG0, ..., SIGm]
499      */
500 
501     /* Move raw CRT to just before the signature. */
502     c = c2 - len;
503     memmove( c, buf, len );
504 
505     len += sig_and_oid_len;
506     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
507     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf,
508                                                  MBEDTLS_ASN1_CONSTRUCTED |
509                                                  MBEDTLS_ASN1_SEQUENCE ) );
510 
511     return( (int) len );
512 }
513 
514 #define PEM_BEGIN_CRT           "-----BEGIN CERTIFICATE-----\n"
515 #define PEM_END_CRT             "-----END CERTIFICATE-----\n"
516 
517 #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)518 int mbedtls_x509write_crt_pem( mbedtls_x509write_cert *crt,
519                                unsigned char *buf, size_t size,
520                                int (*f_rng)(void *, unsigned char *, size_t),
521                                void *p_rng )
522 {
523     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
524     size_t olen;
525 
526     if( ( ret = mbedtls_x509write_crt_der( crt, buf, size,
527                                    f_rng, p_rng ) ) < 0 )
528     {
529         return( ret );
530     }
531 
532     if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_CRT, PEM_END_CRT,
533                                           buf + size - ret, ret,
534                                           buf, size, &olen ) ) != 0 )
535     {
536         return( ret );
537     }
538 
539     return( 0 );
540 }
541 #endif /* MBEDTLS_PEM_WRITE_C */
542 
543 #endif /* MBEDTLS_X509_CRT_WRITE_C */
544