Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

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