Subversion Repositories Kolibri OS

Rev

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

  1. /*
  2.  *  Public Key layer for writing key files and structures
  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. #if !defined(MBEDTLS_CONFIG_FILE)
  25. #include "mbedtls/config.h"
  26. #else
  27. #include MBEDTLS_CONFIG_FILE
  28. #endif
  29.  
  30. #if defined(MBEDTLS_PK_WRITE_C)
  31.  
  32. #include "mbedtls/pk.h"
  33. #include "mbedtls/asn1write.h"
  34. #include "mbedtls/oid.h"
  35. #include "mbedtls/platform_util.h"
  36.  
  37. #include <string.h>
  38.  
  39. #if defined(MBEDTLS_RSA_C)
  40. #include "mbedtls/rsa.h"
  41. #endif
  42. #if defined(MBEDTLS_ECP_C)
  43. #include "mbedtls/bignum.h"
  44. #include "mbedtls/ecp.h"
  45. #include "mbedtls/platform_util.h"
  46. #endif
  47. #if defined(MBEDTLS_ECDSA_C)
  48. #include "mbedtls/ecdsa.h"
  49. #endif
  50. #if defined(MBEDTLS_PEM_WRITE_C)
  51. #include "mbedtls/pem.h"
  52. #endif
  53.  
  54. #if defined(MBEDTLS_PLATFORM_C)
  55. #include "mbedtls/platform.h"
  56. #else
  57. #include <stdlib.h>
  58. #define mbedtls_calloc    calloc
  59. #define mbedtls_free       free
  60. #endif
  61.  
  62. /* Parameter validation macros based on platform_util.h */
  63. #define PK_VALIDATE_RET( cond )    \
  64.     MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_PK_BAD_INPUT_DATA )
  65. #define PK_VALIDATE( cond )        \
  66.     MBEDTLS_INTERNAL_VALIDATE( cond )
  67.  
  68. #if defined(MBEDTLS_RSA_C)
  69. /*
  70.  *  RSAPublicKey ::= SEQUENCE {
  71.  *      modulus           INTEGER,  -- n
  72.  *      publicExponent    INTEGER   -- e
  73.  *  }
  74.  */
  75. static int pk_write_rsa_pubkey( unsigned char **p, unsigned char *start,
  76.                                 mbedtls_rsa_context *rsa )
  77. {
  78.     int ret;
  79.     size_t len = 0;
  80.     mbedtls_mpi T;
  81.  
  82.     mbedtls_mpi_init( &T );
  83.  
  84.     /* Export E */
  85.     if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL, NULL, NULL, &T ) ) != 0 ||
  86.          ( ret = mbedtls_asn1_write_mpi( p, start, &T ) ) < 0 )
  87.         goto end_of_export;
  88.     len += ret;
  89.  
  90.     /* Export N */
  91.     if ( ( ret = mbedtls_rsa_export( rsa, &T, NULL, NULL, NULL, NULL ) ) != 0 ||
  92.          ( ret = mbedtls_asn1_write_mpi( p, start, &T ) ) < 0 )
  93.         goto end_of_export;
  94.     len += ret;
  95.  
  96. end_of_export:
  97.  
  98.     mbedtls_mpi_free( &T );
  99.     if( ret < 0 )
  100.         return( ret );
  101.  
  102.     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
  103.     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED |
  104.                                                  MBEDTLS_ASN1_SEQUENCE ) );
  105.  
  106.     return( (int) len );
  107. }
  108. #endif /* MBEDTLS_RSA_C */
  109.  
  110. #if defined(MBEDTLS_ECP_C)
  111. /*
  112.  * EC public key is an EC point
  113.  */
  114. static int pk_write_ec_pubkey( unsigned char **p, unsigned char *start,
  115.                                mbedtls_ecp_keypair *ec )
  116. {
  117.     int ret;
  118.     size_t len = 0;
  119.     unsigned char buf[MBEDTLS_ECP_MAX_PT_LEN];
  120.  
  121.     if( ( ret = mbedtls_ecp_point_write_binary( &ec->grp, &ec->Q,
  122.                                         MBEDTLS_ECP_PF_UNCOMPRESSED,
  123.                                         &len, buf, sizeof( buf ) ) ) != 0 )
  124.     {
  125.         return( ret );
  126.     }
  127.  
  128.     if( *p < start || (size_t)( *p - start ) < len )
  129.         return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
  130.  
  131.     *p -= len;
  132.     memcpy( *p, buf, len );
  133.  
  134.     return( (int) len );
  135. }
  136.  
  137. /*
  138.  * ECParameters ::= CHOICE {
  139.  *   namedCurve         OBJECT IDENTIFIER
  140.  * }
  141.  */
  142. static int pk_write_ec_param( unsigned char **p, unsigned char *start,
  143.                               mbedtls_ecp_keypair *ec )
  144. {
  145.     int ret;
  146.     size_t len = 0;
  147.     const char *oid;
  148.     size_t oid_len;
  149.  
  150.     if( ( ret = mbedtls_oid_get_oid_by_ec_grp( ec->grp.id, &oid, &oid_len ) ) != 0 )
  151.         return( ret );
  152.  
  153.     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, oid_len ) );
  154.  
  155.     return( (int) len );
  156. }
  157.  
  158. /*
  159.  * privateKey  OCTET STRING -- always of length ceil(log2(n)/8)
  160.  */
  161. static int pk_write_ec_private( unsigned char **p, unsigned char *start,
  162.                                 mbedtls_ecp_keypair *ec )
  163. {
  164.     int ret;
  165.     size_t byte_length = ( ec->grp.pbits + 7 ) / 8;
  166.     unsigned char tmp[MBEDTLS_ECP_MAX_BYTES];
  167.  
  168.     ret = mbedtls_mpi_write_binary( &ec->d, tmp, byte_length );
  169.     if( ret != 0 )
  170.         goto exit;
  171.     ret = mbedtls_asn1_write_octet_string( p, start, tmp, byte_length );
  172.  
  173. exit:
  174.     mbedtls_platform_zeroize( tmp, byte_length );
  175.     return( ret );
  176. }
  177. #endif /* MBEDTLS_ECP_C */
  178.  
  179. int mbedtls_pk_write_pubkey( unsigned char **p, unsigned char *start,
  180.                              const mbedtls_pk_context *key )
  181. {
  182.     int ret;
  183.     size_t len = 0;
  184.  
  185.     PK_VALIDATE_RET( p != NULL );
  186.     PK_VALIDATE_RET( *p != NULL );
  187.     PK_VALIDATE_RET( start != NULL );
  188.     PK_VALIDATE_RET( key != NULL );
  189.  
  190. #if defined(MBEDTLS_RSA_C)
  191.     if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA )
  192.         MBEDTLS_ASN1_CHK_ADD( len, pk_write_rsa_pubkey( p, start, mbedtls_pk_rsa( *key ) ) );
  193.     else
  194. #endif
  195. #if defined(MBEDTLS_ECP_C)
  196.     if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY )
  197.         MBEDTLS_ASN1_CHK_ADD( len, pk_write_ec_pubkey( p, start, mbedtls_pk_ec( *key ) ) );
  198.     else
  199. #endif
  200.         return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );
  201.  
  202.     return( (int) len );
  203. }
  204.  
  205. int mbedtls_pk_write_pubkey_der( mbedtls_pk_context *key, unsigned char *buf, size_t size )
  206. {
  207.     int ret;
  208.     unsigned char *c;
  209.     size_t len = 0, par_len = 0, oid_len;
  210.     const char *oid;
  211.  
  212.     PK_VALIDATE_RET( key != NULL );
  213.     if( size == 0 )
  214.         return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
  215.     PK_VALIDATE_RET( buf != NULL );
  216.  
  217.     c = buf + size;
  218.  
  219.     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, key ) );
  220.  
  221.     if( c - buf < 1 )
  222.         return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
  223.  
  224.     /*
  225.      *  SubjectPublicKeyInfo  ::=  SEQUENCE  {
  226.      *       algorithm            AlgorithmIdentifier,
  227.      *       subjectPublicKey     BIT STRING }
  228.      */
  229.     *--c = 0;
  230.     len += 1;
  231.  
  232.     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
  233.     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_BIT_STRING ) );
  234.  
  235.     if( ( ret = mbedtls_oid_get_oid_by_pk_alg( mbedtls_pk_get_type( key ),
  236.                                        &oid, &oid_len ) ) != 0 )
  237.     {
  238.         return( ret );
  239.     }
  240.  
  241. #if defined(MBEDTLS_ECP_C)
  242.     if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY )
  243.     {
  244.         MBEDTLS_ASN1_CHK_ADD( par_len, pk_write_ec_param( &c, buf, mbedtls_pk_ec( *key ) ) );
  245.     }
  246. #endif
  247.  
  248.     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_algorithm_identifier( &c, buf, oid, oid_len,
  249.                                                         par_len ) );
  250.  
  251.     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
  252.     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED |
  253.                                                 MBEDTLS_ASN1_SEQUENCE ) );
  254.  
  255.     return( (int) len );
  256. }
  257.  
  258. int mbedtls_pk_write_key_der( mbedtls_pk_context *key, unsigned char *buf, size_t size )
  259. {
  260.     int ret;
  261.     unsigned char *c;
  262.     size_t len = 0;
  263.  
  264.     PK_VALIDATE_RET( key != NULL );
  265.     if( size == 0 )
  266.         return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
  267.     PK_VALIDATE_RET( buf != NULL );
  268.  
  269.     c = buf + size;
  270.  
  271. #if defined(MBEDTLS_RSA_C)
  272.     if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA )
  273.     {
  274.         mbedtls_mpi T; /* Temporary holding the exported parameters */
  275.         mbedtls_rsa_context *rsa = mbedtls_pk_rsa( *key );
  276.  
  277.         /*
  278.          * Export the parameters one after another to avoid simultaneous copies.
  279.          */
  280.  
  281.         mbedtls_mpi_init( &T );
  282.  
  283.         /* Export QP */
  284.         if( ( ret = mbedtls_rsa_export_crt( rsa, NULL, NULL, &T ) ) != 0 ||
  285.             ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )
  286.             goto end_of_export;
  287.         len += ret;
  288.  
  289.         /* Export DQ */
  290.         if( ( ret = mbedtls_rsa_export_crt( rsa, NULL, &T, NULL ) ) != 0 ||
  291.             ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )
  292.             goto end_of_export;
  293.         len += ret;
  294.  
  295.         /* Export DP */
  296.         if( ( ret = mbedtls_rsa_export_crt( rsa, &T, NULL, NULL ) ) != 0 ||
  297.             ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )
  298.             goto end_of_export;
  299.         len += ret;
  300.  
  301.         /* Export Q */
  302.         if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL,
  303.                                          &T, NULL, NULL ) ) != 0 ||
  304.              ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )
  305.             goto end_of_export;
  306.         len += ret;
  307.  
  308.         /* Export P */
  309.         if ( ( ret = mbedtls_rsa_export( rsa, NULL, &T,
  310.                                          NULL, NULL, NULL ) ) != 0 ||
  311.              ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )
  312.             goto end_of_export;
  313.         len += ret;
  314.  
  315.         /* Export D */
  316.         if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL,
  317.                                          NULL, &T, NULL ) ) != 0 ||
  318.              ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )
  319.             goto end_of_export;
  320.         len += ret;
  321.  
  322.         /* Export E */
  323.         if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL,
  324.                                          NULL, NULL, &T ) ) != 0 ||
  325.              ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )
  326.             goto end_of_export;
  327.         len += ret;
  328.  
  329.         /* Export N */
  330.         if ( ( ret = mbedtls_rsa_export( rsa, &T, NULL,
  331.                                          NULL, NULL, NULL ) ) != 0 ||
  332.              ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )
  333.             goto end_of_export;
  334.         len += ret;
  335.  
  336.     end_of_export:
  337.  
  338.         mbedtls_mpi_free( &T );
  339.         if( ret < 0 )
  340.             return( ret );
  341.  
  342.         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, 0 ) );
  343.         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
  344.         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c,
  345.                                                buf, MBEDTLS_ASN1_CONSTRUCTED |
  346.                                                MBEDTLS_ASN1_SEQUENCE ) );
  347.     }
  348.     else
  349. #endif /* MBEDTLS_RSA_C */
  350. #if defined(MBEDTLS_ECP_C)
  351.     if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY )
  352.     {
  353.         mbedtls_ecp_keypair *ec = mbedtls_pk_ec( *key );
  354.         size_t pub_len = 0, par_len = 0;
  355.  
  356.         /*
  357.          * RFC 5915, or SEC1 Appendix C.4
  358.          *
  359.          * ECPrivateKey ::= SEQUENCE {
  360.          *      version        INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
  361.          *      privateKey     OCTET STRING,
  362.          *      parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
  363.          *      publicKey  [1] BIT STRING OPTIONAL
  364.          *    }
  365.          */
  366.  
  367.         /* publicKey */
  368.         MBEDTLS_ASN1_CHK_ADD( pub_len, pk_write_ec_pubkey( &c, buf, ec ) );
  369.  
  370.         if( c - buf < 1 )
  371.             return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
  372.         *--c = 0;
  373.         pub_len += 1;
  374.  
  375.         MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_len( &c, buf, pub_len ) );
  376.         MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_BIT_STRING ) );
  377.  
  378.         MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_len( &c, buf, pub_len ) );
  379.         MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_tag( &c, buf,
  380.                             MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1 ) );
  381.         len += pub_len;
  382.  
  383.         /* parameters */
  384.         MBEDTLS_ASN1_CHK_ADD( par_len, pk_write_ec_param( &c, buf, ec ) );
  385.  
  386.         MBEDTLS_ASN1_CHK_ADD( par_len, mbedtls_asn1_write_len( &c, buf, par_len ) );
  387.         MBEDTLS_ASN1_CHK_ADD( par_len, mbedtls_asn1_write_tag( &c, buf,
  388.                             MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) );
  389.         len += par_len;
  390.  
  391.         /* privateKey */
  392.         MBEDTLS_ASN1_CHK_ADD( len, pk_write_ec_private( &c, buf, ec ) );
  393.  
  394.         /* version */
  395.         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, 1 ) );
  396.  
  397.         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
  398.         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED |
  399.                                                     MBEDTLS_ASN1_SEQUENCE ) );
  400.     }
  401.     else
  402. #endif /* MBEDTLS_ECP_C */
  403.         return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );
  404.  
  405.     return( (int) len );
  406. }
  407.  
  408. #if defined(MBEDTLS_PEM_WRITE_C)
  409.  
  410. #define PEM_BEGIN_PUBLIC_KEY    "-----BEGIN PUBLIC KEY-----\n"
  411. #define PEM_END_PUBLIC_KEY      "-----END PUBLIC KEY-----\n"
  412.  
  413. #define PEM_BEGIN_PRIVATE_KEY_RSA   "-----BEGIN RSA PRIVATE KEY-----\n"
  414. #define PEM_END_PRIVATE_KEY_RSA     "-----END RSA PRIVATE KEY-----\n"
  415. #define PEM_BEGIN_PRIVATE_KEY_EC    "-----BEGIN EC PRIVATE KEY-----\n"
  416. #define PEM_END_PRIVATE_KEY_EC      "-----END EC PRIVATE KEY-----\n"
  417.  
  418. /*
  419.  * Max sizes of key per types. Shown as tag + len (+ content).
  420.  */
  421.  
  422. #if defined(MBEDTLS_RSA_C)
  423. /*
  424.  * RSA public keys:
  425.  *  SubjectPublicKeyInfo  ::=  SEQUENCE  {          1 + 3
  426.  *       algorithm            AlgorithmIdentifier,  1 + 1 (sequence)
  427.  *                                                + 1 + 1 + 9 (rsa oid)
  428.  *                                                + 1 + 1 (params null)
  429.  *       subjectPublicKey     BIT STRING }          1 + 3 + (1 + below)
  430.  *  RSAPublicKey ::= SEQUENCE {                     1 + 3
  431.  *      modulus           INTEGER,  -- n            1 + 3 + MPI_MAX + 1
  432.  *      publicExponent    INTEGER   -- e            1 + 3 + MPI_MAX + 1
  433.  *  }
  434.  */
  435. #define RSA_PUB_DER_MAX_BYTES   38 + 2 * MBEDTLS_MPI_MAX_SIZE
  436.  
  437. /*
  438.  * RSA private keys:
  439.  *  RSAPrivateKey ::= SEQUENCE {                    1 + 3
  440.  *      version           Version,                  1 + 1 + 1
  441.  *      modulus           INTEGER,                  1 + 3 + MPI_MAX + 1
  442.  *      publicExponent    INTEGER,                  1 + 3 + MPI_MAX + 1
  443.  *      privateExponent   INTEGER,                  1 + 3 + MPI_MAX + 1
  444.  *      prime1            INTEGER,                  1 + 3 + MPI_MAX / 2 + 1
  445.  *      prime2            INTEGER,                  1 + 3 + MPI_MAX / 2 + 1
  446.  *      exponent1         INTEGER,                  1 + 3 + MPI_MAX / 2 + 1
  447.  *      exponent2         INTEGER,                  1 + 3 + MPI_MAX / 2 + 1
  448.  *      coefficient       INTEGER,                  1 + 3 + MPI_MAX / 2 + 1
  449.  *      otherPrimeInfos   OtherPrimeInfos OPTIONAL  0 (not supported)
  450.  *  }
  451.  */
  452. #define MPI_MAX_SIZE_2          MBEDTLS_MPI_MAX_SIZE / 2 + \
  453.                                 MBEDTLS_MPI_MAX_SIZE % 2
  454. #define RSA_PRV_DER_MAX_BYTES   47 + 3 * MBEDTLS_MPI_MAX_SIZE \
  455.                                    + 5 * MPI_MAX_SIZE_2
  456.  
  457. #else /* MBEDTLS_RSA_C */
  458.  
  459. #define RSA_PUB_DER_MAX_BYTES   0
  460. #define RSA_PRV_DER_MAX_BYTES   0
  461.  
  462. #endif /* MBEDTLS_RSA_C */
  463.  
  464. #if defined(MBEDTLS_ECP_C)
  465. /*
  466.  * EC public keys:
  467.  *  SubjectPublicKeyInfo  ::=  SEQUENCE  {      1 + 2
  468.  *    algorithm         AlgorithmIdentifier,    1 + 1 (sequence)
  469.  *                                            + 1 + 1 + 7 (ec oid)
  470.  *                                            + 1 + 1 + 9 (namedCurve oid)
  471.  *    subjectPublicKey  BIT STRING              1 + 2 + 1               [1]
  472.  *                                            + 1 (point format)        [1]
  473.  *                                            + 2 * ECP_MAX (coords)    [1]
  474.  *  }
  475.  */
  476. #define ECP_PUB_DER_MAX_BYTES   30 + 2 * MBEDTLS_ECP_MAX_BYTES
  477.  
  478. /*
  479.  * EC private keys:
  480.  * ECPrivateKey ::= SEQUENCE {                  1 + 2
  481.  *      version        INTEGER ,                1 + 1 + 1
  482.  *      privateKey     OCTET STRING,            1 + 1 + ECP_MAX
  483.  *      parameters [0] ECParameters OPTIONAL,   1 + 1 + (1 + 1 + 9)
  484.  *      publicKey  [1] BIT STRING OPTIONAL      1 + 2 + [1] above
  485.  *    }
  486.  */
  487. #define ECP_PRV_DER_MAX_BYTES   29 + 3 * MBEDTLS_ECP_MAX_BYTES
  488.  
  489. #else /* MBEDTLS_ECP_C */
  490.  
  491. #define ECP_PUB_DER_MAX_BYTES   0
  492. #define ECP_PRV_DER_MAX_BYTES   0
  493.  
  494. #endif /* MBEDTLS_ECP_C */
  495.  
  496. #define PUB_DER_MAX_BYTES   RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \
  497.                             RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES
  498. #define PRV_DER_MAX_BYTES   RSA_PRV_DER_MAX_BYTES > ECP_PRV_DER_MAX_BYTES ? \
  499.                             RSA_PRV_DER_MAX_BYTES : ECP_PRV_DER_MAX_BYTES
  500.  
  501. int mbedtls_pk_write_pubkey_pem( mbedtls_pk_context *key, unsigned char *buf, size_t size )
  502. {
  503.     int ret;
  504.     unsigned char output_buf[PUB_DER_MAX_BYTES];
  505.     size_t olen = 0;
  506.  
  507.     PK_VALIDATE_RET( key != NULL );
  508.     PK_VALIDATE_RET( buf != NULL || size == 0 );
  509.  
  510.     if( ( ret = mbedtls_pk_write_pubkey_der( key, output_buf,
  511.                                      sizeof(output_buf) ) ) < 0 )
  512.     {
  513.         return( ret );
  514.     }
  515.  
  516.     if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY,
  517.                                   output_buf + sizeof(output_buf) - ret,
  518.                                   ret, buf, size, &olen ) ) != 0 )
  519.     {
  520.         return( ret );
  521.     }
  522.  
  523.     return( 0 );
  524. }
  525.  
  526. int mbedtls_pk_write_key_pem( mbedtls_pk_context *key, unsigned char *buf, size_t size )
  527. {
  528.     int ret;
  529.     unsigned char output_buf[PRV_DER_MAX_BYTES];
  530.     const char *begin, *end;
  531.     size_t olen = 0;
  532.  
  533.     PK_VALIDATE_RET( key != NULL );
  534.     PK_VALIDATE_RET( buf != NULL || size == 0 );
  535.  
  536.     if( ( ret = mbedtls_pk_write_key_der( key, output_buf, sizeof(output_buf) ) ) < 0 )
  537.         return( ret );
  538.  
  539. #if defined(MBEDTLS_RSA_C)
  540.     if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA )
  541.     {
  542.         begin = PEM_BEGIN_PRIVATE_KEY_RSA;
  543.         end = PEM_END_PRIVATE_KEY_RSA;
  544.     }
  545.     else
  546. #endif
  547. #if defined(MBEDTLS_ECP_C)
  548.     if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY )
  549.     {
  550.         begin = PEM_BEGIN_PRIVATE_KEY_EC;
  551.         end = PEM_END_PRIVATE_KEY_EC;
  552.     }
  553.     else
  554. #endif
  555.         return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );
  556.  
  557.     if( ( ret = mbedtls_pem_write_buffer( begin, end,
  558.                                   output_buf + sizeof(output_buf) - ret,
  559.                                   ret, buf, size, &olen ) ) != 0 )
  560.     {
  561.         return( ret );
  562.     }
  563.  
  564.     return( 0 );
  565. }
  566. #endif /* MBEDTLS_PEM_WRITE_C */
  567.  
  568. #endif /* MBEDTLS_PK_WRITE_C */
  569.