Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers x509write_crt.c Source File

x509write_crt.c

00001 /*
00002  *  X.509 certificate writing
00003  *
00004  *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
00005  *  SPDX-License-Identifier: Apache-2.0
00006  *
00007  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
00008  *  not use this file except in compliance with the License.
00009  *  You may obtain a copy of the License at
00010  *
00011  *  http://www.apache.org/licenses/LICENSE-2.0
00012  *
00013  *  Unless required by applicable law or agreed to in writing, software
00014  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
00015  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00016  *  See the License for the specific language governing permissions and
00017  *  limitations under the License.
00018  *
00019  *  This file is part of mbed TLS (https://tls.mbed.org)
00020  */
00021 /*
00022  * References:
00023  * - certificates: RFC 5280, updated by RFC 6818
00024  * - CSRs: PKCS#10 v1.7 aka RFC 2986
00025  * - attributes: PKCS#9 v2.0 aka RFC 2985
00026  */
00027 
00028 #if !defined(MBEDTLS_CONFIG_FILE)
00029 #include "mbedtls/config.h"
00030 #else
00031 #include MBEDTLS_CONFIG_FILE
00032 #endif
00033 
00034 #if defined(MBEDTLS_X509_CRT_WRITE_C)
00035 
00036 #include "mbedtls/x509_crt.h"
00037 #include "mbedtls/oid.h"
00038 #include "mbedtls/asn1write.h"
00039 #include "mbedtls/sha1.h"
00040 #include "mbedtls/platform_util.h"
00041 
00042 #include <string.h>
00043 
00044 #if defined(MBEDTLS_PEM_WRITE_C)
00045 #include "mbedtls/pem.h"
00046 #endif /* MBEDTLS_PEM_WRITE_C */
00047 
00048 /*
00049  * For the currently used signature algorithms the buffer to store any signature
00050  * must be at least of size MAX(MBEDTLS_ECDSA_MAX_LEN, MBEDTLS_MPI_MAX_SIZE)
00051  */
00052 #if MBEDTLS_ECDSA_MAX_LEN > MBEDTLS_MPI_MAX_SIZE
00053 #define SIGNATURE_MAX_SIZE MBEDTLS_ECDSA_MAX_LEN
00054 #else
00055 #define SIGNATURE_MAX_SIZE MBEDTLS_MPI_MAX_SIZE
00056 #endif
00057 
00058 void mbedtls_x509write_crt_init( mbedtls_x509write_cert *ctx )
00059 {
00060     memset( ctx, 0, sizeof( mbedtls_x509write_cert ) );
00061 
00062     mbedtls_mpi_init( &ctx->serial );
00063     ctx->version = MBEDTLS_X509_CRT_VERSION_3;
00064 }
00065 
00066 void mbedtls_x509write_crt_free( mbedtls_x509write_cert *ctx )
00067 {
00068     mbedtls_mpi_free( &ctx->serial );
00069 
00070     mbedtls_asn1_free_named_data_list( &ctx->subject );
00071     mbedtls_asn1_free_named_data_list( &ctx->issuer );
00072     mbedtls_asn1_free_named_data_list( &ctx->extensions );
00073 
00074     mbedtls_platform_zeroize( ctx, sizeof( mbedtls_x509write_cert ) );
00075 }
00076 
00077 void mbedtls_x509write_crt_set_version( mbedtls_x509write_cert *ctx,
00078                                         int version )
00079 {
00080     ctx->version = version;
00081 }
00082 
00083 void mbedtls_x509write_crt_set_md_alg( mbedtls_x509write_cert *ctx,
00084                                        mbedtls_md_type_t md_alg )
00085 {
00086     ctx->md_alg = md_alg;
00087 }
00088 
00089 void mbedtls_x509write_crt_set_subject_key( mbedtls_x509write_cert *ctx,
00090                                             mbedtls_pk_context *key )
00091 {
00092     ctx->subject_key = key;
00093 }
00094 
00095 void mbedtls_x509write_crt_set_issuer_key( mbedtls_x509write_cert *ctx,
00096                                            mbedtls_pk_context *key )
00097 {
00098     ctx->issuer_key = key;
00099 }
00100 
00101 int mbedtls_x509write_crt_set_subject_name( mbedtls_x509write_cert *ctx,
00102                                             const char *subject_name )
00103 {
00104     return mbedtls_x509_string_to_names( &ctx->subject, subject_name );
00105 }
00106 
00107 int mbedtls_x509write_crt_set_issuer_name( mbedtls_x509write_cert *ctx,
00108                                            const char *issuer_name )
00109 {
00110     return mbedtls_x509_string_to_names( &ctx->issuer, issuer_name );
00111 }
00112 
00113 int mbedtls_x509write_crt_set_serial( mbedtls_x509write_cert *ctx,
00114                                       const mbedtls_mpi *serial )
00115 {
00116     int ret;
00117 
00118     if( ( ret = mbedtls_mpi_copy( &ctx->serial, serial ) ) != 0 )
00119         return( ret );
00120 
00121     return( 0 );
00122 }
00123 
00124 int mbedtls_x509write_crt_set_validity( mbedtls_x509write_cert *ctx,
00125                                         const char *not_before,
00126                                         const char *not_after )
00127 {
00128     if( strlen( not_before ) != MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1 ||
00129         strlen( not_after )  != MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1 )
00130     {
00131         return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
00132     }
00133     strncpy( ctx->not_before, not_before, MBEDTLS_X509_RFC5280_UTC_TIME_LEN );
00134     strncpy( ctx->not_after , not_after , MBEDTLS_X509_RFC5280_UTC_TIME_LEN );
00135     ctx->not_before[MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1] = 'Z';
00136     ctx->not_after[MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1] = 'Z';
00137 
00138     return( 0 );
00139 }
00140 
00141 int mbedtls_x509write_crt_set_extension( mbedtls_x509write_cert *ctx,
00142                                  const char *oid, size_t oid_len,
00143                                  int critical,
00144                                  const unsigned char *val, size_t val_len )
00145 {
00146     return( mbedtls_x509_set_extension( &ctx->extensions, oid, oid_len,
00147                                         critical, val, val_len ) );
00148 }
00149 
00150 int mbedtls_x509write_crt_set_basic_constraints( mbedtls_x509write_cert *ctx,
00151                                                  int is_ca, int max_pathlen )
00152 {
00153     int ret;
00154     unsigned char buf[9];
00155     unsigned char *c = buf + sizeof(buf);
00156     size_t len = 0;
00157 
00158     memset( buf, 0, sizeof(buf) );
00159 
00160     if( is_ca && max_pathlen > 127 )
00161         return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
00162 
00163     if( is_ca )
00164     {
00165         if( max_pathlen >= 0 )
00166         {
00167             MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf,
00168                                                                max_pathlen ) );
00169         }
00170         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_bool( &c, buf, 1 ) );
00171     }
00172 
00173     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
00174     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf,
00175                                                 MBEDTLS_ASN1_CONSTRUCTED |
00176                                                 MBEDTLS_ASN1_SEQUENCE ) );
00177 
00178     return(
00179         mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_BASIC_CONSTRAINTS,
00180                              MBEDTLS_OID_SIZE( MBEDTLS_OID_BASIC_CONSTRAINTS ),
00181                              0, buf + sizeof(buf) - len, len ) );
00182 }
00183 
00184 #if defined(MBEDTLS_SHA1_C)
00185 int mbedtls_x509write_crt_set_subject_key_identifier( mbedtls_x509write_cert *ctx )
00186 {
00187     int ret;
00188     unsigned char buf[MBEDTLS_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
00189     unsigned char *c = buf + sizeof(buf);
00190     size_t len = 0;
00191 
00192     memset( buf, 0, sizeof(buf) );
00193     MBEDTLS_ASN1_CHK_ADD( len,
00194                 mbedtls_pk_write_pubkey( &c, buf, ctx->subject_key ) );
00195 
00196     ret = mbedtls_sha1_ret( buf + sizeof( buf ) - len, len,
00197                             buf + sizeof( buf ) - 20 );
00198     if( ret != 0 )
00199         return( ret );
00200     c = buf + sizeof( buf ) - 20;
00201     len = 20;
00202 
00203     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
00204     MBEDTLS_ASN1_CHK_ADD( len,
00205             mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_OCTET_STRING ) );
00206 
00207     return mbedtls_x509write_crt_set_extension( ctx,
00208                  MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER,
00209                  MBEDTLS_OID_SIZE( MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER ),
00210                  0, buf + sizeof(buf) - len, len );
00211 }
00212 
00213 int mbedtls_x509write_crt_set_authority_key_identifier( mbedtls_x509write_cert *ctx )
00214 {
00215     int ret;
00216     unsigned char buf[MBEDTLS_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
00217     unsigned char *c = buf + sizeof( buf );
00218     size_t len = 0;
00219 
00220     memset( buf, 0, sizeof(buf) );
00221     MBEDTLS_ASN1_CHK_ADD( len,
00222                           mbedtls_pk_write_pubkey( &c, buf, ctx->issuer_key ) );
00223 
00224     ret = mbedtls_sha1_ret( buf + sizeof( buf ) - len, len,
00225                             buf + sizeof( buf ) - 20 );
00226     if( ret != 0 )
00227         return( ret );
00228     c = buf + sizeof( buf ) - 20;
00229     len = 20;
00230 
00231     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
00232     MBEDTLS_ASN1_CHK_ADD( len,
00233         mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | 0 ) );
00234 
00235     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
00236     MBEDTLS_ASN1_CHK_ADD( len,
00237                           mbedtls_asn1_write_tag( &c, buf,
00238                                                   MBEDTLS_ASN1_CONSTRUCTED |
00239                                                   MBEDTLS_ASN1_SEQUENCE ) );
00240 
00241     return mbedtls_x509write_crt_set_extension(
00242         ctx, MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER,
00243         MBEDTLS_OID_SIZE( MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER ),
00244         0, buf + sizeof( buf ) - len, len );
00245 }
00246 #endif /* MBEDTLS_SHA1_C */
00247 
00248 int mbedtls_x509write_crt_set_key_usage( mbedtls_x509write_cert *ctx,
00249                                          unsigned int key_usage )
00250 {
00251     unsigned char buf[5], ku[2];
00252     unsigned char *c;
00253     int ret;
00254     const unsigned int allowed_bits = MBEDTLS_X509_KU_DIGITAL_SIGNATURE |
00255         MBEDTLS_X509_KU_NON_REPUDIATION   |
00256         MBEDTLS_X509_KU_KEY_ENCIPHERMENT  |
00257         MBEDTLS_X509_KU_DATA_ENCIPHERMENT |
00258         MBEDTLS_X509_KU_KEY_AGREEMENT     |
00259         MBEDTLS_X509_KU_KEY_CERT_SIGN     |
00260         MBEDTLS_X509_KU_CRL_SIGN          |
00261         MBEDTLS_X509_KU_ENCIPHER_ONLY     |
00262         MBEDTLS_X509_KU_DECIPHER_ONLY;
00263 
00264     /* Check that nothing other than the allowed flags is set */
00265     if( ( key_usage & ~allowed_bits ) != 0 )
00266         return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE );
00267 
00268     c = buf + 5;
00269     ku[0] = (unsigned char)( key_usage      );
00270     ku[1] = (unsigned char)( key_usage >> 8 );
00271     ret = mbedtls_asn1_write_named_bitstring( &c, buf, ku, 9 );
00272 
00273     if( ret < 0 )
00274         return( ret );
00275     else if( ret < 3 || ret > 5 )
00276         return( MBEDTLS_ERR_X509_INVALID_FORMAT );
00277 
00278     ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_KEY_USAGE,
00279                                    MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ),
00280                                    1, c, (size_t)ret );
00281     if( ret != 0 )
00282         return( ret );
00283 
00284     return( 0 );
00285 }
00286 
00287 int mbedtls_x509write_crt_set_ns_cert_type( mbedtls_x509write_cert *ctx,
00288                                     unsigned char ns_cert_type )
00289 {
00290     unsigned char buf[4];
00291     unsigned char *c;
00292     int ret;
00293 
00294     c = buf + 4;
00295 
00296     ret = mbedtls_asn1_write_named_bitstring( &c, buf, &ns_cert_type, 8 );
00297     if( ret < 3 || ret > 4 )
00298         return( ret );
00299 
00300     ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_NS_CERT_TYPE,
00301                                    MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ),
00302                                    0, c, (size_t)ret );
00303     if( ret != 0 )
00304         return( ret );
00305 
00306     return( 0 );
00307 }
00308 
00309 static int x509_write_time( unsigned char **p, unsigned char *start,
00310                             const char *t, size_t size )
00311 {
00312     int ret;
00313     size_t len = 0;
00314 
00315     /*
00316      * write MBEDTLS_ASN1_UTC_TIME if year < 2050 (2 bytes shorter)
00317      */
00318     if( t[0] == '2' && t[1] == '0' && t[2] < '5' )
00319     {
00320         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start,
00321                                              (const unsigned char *) t + 2,
00322                                              size - 2 ) );
00323         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
00324         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start,
00325                                              MBEDTLS_ASN1_UTC_TIME ) );
00326     }
00327     else
00328     {
00329         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start,
00330                                                   (const unsigned char *) t,
00331                                                   size ) );
00332         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
00333         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start,
00334                                              MBEDTLS_ASN1_GENERALIZED_TIME ) );
00335     }
00336 
00337     return( (int) len );
00338 }
00339 
00340 int mbedtls_x509write_crt_der( mbedtls_x509write_cert *ctx,
00341                                unsigned char *buf, size_t size,
00342                                int (*f_rng)(void *, unsigned char *, size_t),
00343                                void *p_rng )
00344 {
00345     int ret;
00346     const char *sig_oid;
00347     size_t sig_oid_len = 0;
00348     unsigned char *c, *c2;
00349     unsigned char hash[64];
00350     unsigned char sig[SIGNATURE_MAX_SIZE];
00351     size_t sub_len = 0, pub_len = 0, sig_and_oid_len = 0, sig_len;
00352     size_t len = 0;
00353     mbedtls_pk_type_t pk_alg;
00354 
00355     /*
00356      * Prepare data to be signed at the end of the target buffer
00357      */
00358     c = buf + size;
00359 
00360     /* Signature algorithm needed in TBS, and later for actual signature */
00361 
00362     /* There's no direct way of extracting a signature algorithm
00363      * (represented as an element of mbedtls_pk_type_t) from a PK instance. */
00364     if( mbedtls_pk_can_do( ctx->issuer_key, MBEDTLS_PK_RSA ) )
00365         pk_alg = MBEDTLS_PK_RSA;
00366     else if( mbedtls_pk_can_do( ctx->issuer_key, MBEDTLS_PK_ECDSA ) )
00367         pk_alg = MBEDTLS_PK_ECDSA;
00368     else
00369         return( MBEDTLS_ERR_X509_INVALID_ALG );
00370 
00371     if( ( ret = mbedtls_oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg,
00372                                           &sig_oid, &sig_oid_len ) ) != 0 )
00373     {
00374         return( ret );
00375     }
00376 
00377     /*
00378      *  Extensions  ::=  SEQUENCE SIZE (1..MAX) OF Extension
00379      */
00380 
00381     /* Only for v3 */
00382     if( ctx->version == MBEDTLS_X509_CRT_VERSION_3 )
00383     {
00384         MBEDTLS_ASN1_CHK_ADD( len,
00385                               mbedtls_x509_write_extensions( &c,
00386                                                       buf, ctx->extensions ) );
00387         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
00388         MBEDTLS_ASN1_CHK_ADD( len,
00389                               mbedtls_asn1_write_tag( &c, buf,
00390                                                       MBEDTLS_ASN1_CONSTRUCTED |
00391                                                       MBEDTLS_ASN1_SEQUENCE ) );
00392         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
00393         MBEDTLS_ASN1_CHK_ADD( len,
00394                               mbedtls_asn1_write_tag( &c, buf,
00395                                                MBEDTLS_ASN1_CONTEXT_SPECIFIC |
00396                                                MBEDTLS_ASN1_CONSTRUCTED | 3 ) );
00397     }
00398 
00399     /*
00400      *  SubjectPublicKeyInfo
00401      */
00402     MBEDTLS_ASN1_CHK_ADD( pub_len,
00403                           mbedtls_pk_write_pubkey_der( ctx->subject_key,
00404                                                        buf, c - buf ) );
00405     c -= pub_len;
00406     len += pub_len;
00407 
00408     /*
00409      *  Subject  ::=  Name
00410      */
00411     MBEDTLS_ASN1_CHK_ADD( len,
00412                           mbedtls_x509_write_names( &c, buf,
00413                                                     ctx->subject ) );
00414 
00415     /*
00416      *  Validity ::= SEQUENCE {
00417      *       notBefore      Time,
00418      *       notAfter       Time }
00419      */
00420     sub_len = 0;
00421 
00422     MBEDTLS_ASN1_CHK_ADD( sub_len,
00423                           x509_write_time( &c, buf, ctx->not_after,
00424                                         MBEDTLS_X509_RFC5280_UTC_TIME_LEN ) );
00425 
00426     MBEDTLS_ASN1_CHK_ADD( sub_len,
00427                           x509_write_time( &c, buf, ctx->not_before,
00428                                         MBEDTLS_X509_RFC5280_UTC_TIME_LEN ) );
00429 
00430     len += sub_len;
00431     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, sub_len ) );
00432     MBEDTLS_ASN1_CHK_ADD( len,
00433                           mbedtls_asn1_write_tag( &c, buf,
00434                                                   MBEDTLS_ASN1_CONSTRUCTED |
00435                                                   MBEDTLS_ASN1_SEQUENCE ) );
00436 
00437     /*
00438      *  Issuer  ::=  Name
00439      */
00440     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, buf,
00441                                                          ctx->issuer ) );
00442 
00443     /*
00444      *  Signature   ::=  AlgorithmIdentifier
00445      */
00446     MBEDTLS_ASN1_CHK_ADD( len,
00447                           mbedtls_asn1_write_algorithm_identifier( &c, buf,
00448                                               sig_oid, strlen( sig_oid ), 0 ) );
00449 
00450     /*
00451      *  Serial   ::=  INTEGER
00452      */
00453     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf,
00454                                                        &ctx->serial ) );
00455 
00456     /*
00457      *  Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
00458      */
00459 
00460     /* Can be omitted for v1 */
00461     if( ctx->version != MBEDTLS_X509_CRT_VERSION_1 )
00462     {
00463         sub_len = 0;
00464         MBEDTLS_ASN1_CHK_ADD( sub_len,
00465                               mbedtls_asn1_write_int( &c, buf, ctx->version ) );
00466         len += sub_len;
00467         MBEDTLS_ASN1_CHK_ADD( len,
00468                               mbedtls_asn1_write_len( &c, buf, sub_len ) );
00469         MBEDTLS_ASN1_CHK_ADD( len,
00470                               mbedtls_asn1_write_tag( &c, buf,
00471                                                MBEDTLS_ASN1_CONTEXT_SPECIFIC |
00472                                                MBEDTLS_ASN1_CONSTRUCTED | 0 ) );
00473     }
00474 
00475     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
00476     MBEDTLS_ASN1_CHK_ADD( len,
00477                 mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED |
00478                                                      MBEDTLS_ASN1_SEQUENCE ) );
00479 
00480     /*
00481      * Make signature
00482      */
00483 
00484     /* Compute hash of CRT. */
00485     if( ( ret = mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c,
00486                             len, hash ) ) != 0 )
00487     {
00488         return( ret );
00489     }
00490 
00491     if( ( ret = mbedtls_pk_sign( ctx->issuer_key, ctx->md_alg,
00492                                  hash, 0, sig, &sig_len,
00493                                  f_rng, p_rng ) ) != 0 )
00494     {
00495         return( ret );
00496     }
00497 
00498     /* Move CRT to the front of the buffer to have space
00499      * for the signature. */
00500     memmove( buf, c, len );
00501     c = buf + len;
00502 
00503     /* Add signature at the end of the buffer,
00504      * making sure that it doesn't underflow
00505      * into the CRT buffer. */
00506     c2 = buf + size;
00507     MBEDTLS_ASN1_CHK_ADD( sig_and_oid_len, mbedtls_x509_write_sig( &c2, c,
00508                                         sig_oid, sig_oid_len, sig, sig_len ) );
00509 
00510     /*
00511      * Memory layout after this step:
00512      *
00513      * buf       c=buf+len                c2            buf+size
00514      * [CRT0,...,CRTn, UNUSED, ..., UNUSED, SIG0, ..., SIGm]
00515      */
00516 
00517     /* Move raw CRT to just before the signature. */
00518     c = c2 - len;
00519     memmove( c, buf, len );
00520 
00521     len += sig_and_oid_len;
00522     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
00523     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf,
00524                                                  MBEDTLS_ASN1_CONSTRUCTED |
00525                                                  MBEDTLS_ASN1_SEQUENCE ) );
00526 
00527     return( (int) len );
00528 }
00529 
00530 #define PEM_BEGIN_CRT           "-----BEGIN CERTIFICATE-----\n"
00531 #define PEM_END_CRT             "-----END CERTIFICATE-----\n"
00532 
00533 #if defined(MBEDTLS_PEM_WRITE_C)
00534 int mbedtls_x509write_crt_pem( mbedtls_x509write_cert *crt,
00535                                unsigned char *buf, size_t size,
00536                                int (*f_rng)(void *, unsigned char *, size_t),
00537                                void *p_rng )
00538 {
00539     int ret;
00540     size_t olen;
00541 
00542     if( ( ret = mbedtls_x509write_crt_der( crt, buf, size,
00543                                    f_rng, p_rng ) ) < 0 )
00544     {
00545         return( ret );
00546     }
00547 
00548     if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_CRT, PEM_END_CRT,
00549                                           buf + size - ret, ret,
00550                                           buf, size, &olen ) ) != 0 )
00551     {
00552         return( ret );
00553     }
00554 
00555     return( 0 );
00556 }
00557 #endif /* MBEDTLS_PEM_WRITE_C */
00558 
00559 #endif /* MBEDTLS_X509_CRT_WRITE_C */