Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers pkwrite.c Source File

pkwrite.c

00001 /*
00002  *  Public Key layer for writing key files and structures
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 #if !defined(MBEDTLS_CONFIG_FILE)
00023 #include "mbedtls/config.h"
00024 #else
00025 #include MBEDTLS_CONFIG_FILE
00026 #endif
00027 
00028 #if defined(MBEDTLS_PK_WRITE_C)
00029 
00030 #include "mbedtls/pk.h"
00031 #include "mbedtls/asn1write.h"
00032 #include "mbedtls/oid.h"
00033 #include "mbedtls/platform_util.h"
00034 
00035 #include <string.h>
00036 
00037 #if defined(MBEDTLS_RSA_C)
00038 #include "mbedtls/rsa.h"
00039 #endif
00040 #if defined(MBEDTLS_ECP_C)
00041 #include "mbedtls/ecp.h"
00042 #endif
00043 #if defined(MBEDTLS_ECDSA_C)
00044 #include "mbedtls/ecdsa.h"
00045 #endif
00046 #if defined(MBEDTLS_PEM_WRITE_C)
00047 #include "mbedtls/pem.h"
00048 #endif
00049 
00050 #if defined(MBEDTLS_USE_PSA_CRYPTO)
00051 #include "psa/crypto.h"
00052 #include "mbedtls/psa_util.h"
00053 #endif
00054 #if defined(MBEDTLS_PLATFORM_C)
00055 #include "mbedtls/platform.h"
00056 #else
00057 #include <stdlib.h>
00058 #define mbedtls_calloc    calloc
00059 #define mbedtls_free       free
00060 #endif
00061 
00062 /* Parameter validation macros based on platform_util.h */
00063 #define PK_VALIDATE_RET( cond )    \
00064     MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_PK_BAD_INPUT_DATA )
00065 #define PK_VALIDATE( cond )        \
00066     MBEDTLS_INTERNAL_VALIDATE( cond )
00067 
00068 #if defined(MBEDTLS_RSA_C)
00069 /*
00070  *  RSAPublicKey ::= SEQUENCE {
00071  *      modulus           INTEGER,  -- n
00072  *      publicExponent    INTEGER   -- e
00073  *  }
00074  */
00075 static int pk_write_rsa_pubkey( unsigned char **p, unsigned char *start,
00076                                 mbedtls_rsa_context *rsa )
00077 {
00078     int ret;
00079     size_t len = 0;
00080     mbedtls_mpi T;
00081 
00082     mbedtls_mpi_init( &T );
00083 
00084     /* Export E */
00085     if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL, NULL, NULL, &T ) ) != 0 ||
00086          ( ret = mbedtls_asn1_write_mpi( p, start, &T ) ) < 0 )
00087         goto end_of_export;
00088     len += ret;
00089 
00090     /* Export N */
00091     if ( ( ret = mbedtls_rsa_export( rsa, &T, NULL, NULL, NULL, NULL ) ) != 0 ||
00092          ( ret = mbedtls_asn1_write_mpi( p, start, &T ) ) < 0 )
00093         goto end_of_export;
00094     len += ret;
00095 
00096 end_of_export:
00097 
00098     mbedtls_mpi_free( &T );
00099     if( ret < 0 )
00100         return( ret );
00101 
00102     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
00103     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED |
00104                                                  MBEDTLS_ASN1_SEQUENCE ) );
00105 
00106     return( (int) len );
00107 }
00108 #endif /* MBEDTLS_RSA_C */
00109 
00110 #if defined(MBEDTLS_ECP_C)
00111 /*
00112  * EC public key is an EC point
00113  */
00114 static int pk_write_ec_pubkey( unsigned char **p, unsigned char *start,
00115                                mbedtls_ecp_keypair *ec )
00116 {
00117     int ret;
00118     size_t len = 0;
00119     unsigned char buf[MBEDTLS_ECP_MAX_PT_LEN];
00120 
00121     if( ( ret = mbedtls_ecp_point_write_binary( &ec->grp , &ec->Q ,
00122                                         MBEDTLS_ECP_PF_UNCOMPRESSED,
00123                                         &len, buf, sizeof( buf ) ) ) != 0 )
00124     {
00125         return( ret );
00126     }
00127 
00128     if( *p < start || (size_t)( *p - start ) < len )
00129         return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
00130 
00131     *p -= len;
00132     memcpy( *p, buf, len );
00133 
00134     return( (int) len );
00135 }
00136 
00137 /*
00138  * ECParameters ::= CHOICE {
00139  *   namedCurve         OBJECT IDENTIFIER
00140  * }
00141  */
00142 static int pk_write_ec_param( unsigned char **p, unsigned char *start,
00143                               mbedtls_ecp_keypair *ec )
00144 {
00145     int ret;
00146     size_t len = 0;
00147     const char *oid;
00148     size_t oid_len;
00149 
00150     if( ( ret = mbedtls_oid_get_oid_by_ec_grp( ec->grp .id , &oid, &oid_len ) ) != 0 )
00151         return( ret );
00152 
00153     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, oid_len ) );
00154 
00155     return( (int) len );
00156 }
00157 #endif /* MBEDTLS_ECP_C */
00158 
00159 int mbedtls_pk_write_pubkey( unsigned char **p, unsigned char *start,
00160                              const mbedtls_pk_context *key )
00161 {
00162     int ret;
00163     size_t len = 0;
00164 
00165     PK_VALIDATE_RET( p != NULL );
00166     PK_VALIDATE_RET( *p != NULL );
00167     PK_VALIDATE_RET( start != NULL );
00168     PK_VALIDATE_RET( key != NULL );
00169 
00170 #if defined(MBEDTLS_RSA_C)
00171     if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA )
00172         MBEDTLS_ASN1_CHK_ADD( len, pk_write_rsa_pubkey( p, start, mbedtls_pk_rsa( *key ) ) );
00173     else
00174 #endif
00175 #if defined(MBEDTLS_ECP_C)
00176     if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY )
00177         MBEDTLS_ASN1_CHK_ADD( len, pk_write_ec_pubkey( p, start, mbedtls_pk_ec( *key ) ) );
00178     else
00179 #endif
00180 #if defined(MBEDTLS_USE_PSA_CRYPTO)
00181     if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_OPAQUE )
00182     {
00183         size_t buffer_size;
00184         psa_key_handle_t* key_slot = (psa_key_handle_t*) key->pk_ctx;
00185 
00186         if ( *p < start )
00187             return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
00188 
00189         buffer_size = (size_t)( *p - start );
00190         if ( psa_export_public_key( *key_slot, start, buffer_size, &len )
00191              != PSA_SUCCESS )
00192         {
00193             return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
00194         }
00195         else
00196         {
00197             *p -= len;
00198             memmove( *p, start, len );
00199         }
00200     }
00201     else
00202 #endif /* MBEDTLS_USE_PSA_CRYPTO */
00203         return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );
00204 
00205     return( (int) len );
00206 }
00207 
00208 int mbedtls_pk_write_pubkey_der( mbedtls_pk_context *key, unsigned char *buf, size_t size )
00209 {
00210     int ret;
00211     unsigned char *c;
00212     size_t len = 0, par_len = 0, oid_len;
00213     mbedtls_pk_type_t pk_type;
00214     const char *oid;
00215 
00216     PK_VALIDATE_RET( key != NULL );
00217     if( size == 0 )
00218         return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
00219     PK_VALIDATE_RET( buf != NULL );
00220 
00221     c = buf + size;
00222 
00223     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, key ) );
00224 
00225     if( c - buf < 1 )
00226         return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
00227 
00228     /*
00229      *  SubjectPublicKeyInfo  ::=  SEQUENCE  {
00230      *       algorithm            AlgorithmIdentifier,
00231      *       subjectPublicKey     BIT STRING }
00232      */
00233     *--c = 0;
00234     len += 1;
00235 
00236     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
00237     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_BIT_STRING ) );
00238 
00239     pk_type = mbedtls_pk_get_type( key );
00240 #if defined(MBEDTLS_ECP_C)
00241     if( pk_type == MBEDTLS_PK_ECKEY )
00242     {
00243         MBEDTLS_ASN1_CHK_ADD( par_len, pk_write_ec_param( &c, buf, mbedtls_pk_ec( *key ) ) );
00244     }
00245 #endif
00246 #if defined(MBEDTLS_USE_PSA_CRYPTO)
00247     if( pk_type == MBEDTLS_PK_OPAQUE )
00248     {
00249         psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
00250         psa_key_type_t key_type;
00251         psa_key_handle_t handle;
00252         psa_ecc_curve_t curve;
00253 
00254         handle = *((psa_key_handle_t*) key->pk_ctx );
00255         if( PSA_SUCCESS != psa_get_key_attributes( handle, &attributes ) )
00256             return( MBEDTLS_ERR_PK_HW_ACCEL_FAILED );
00257         key_type = psa_get_key_type( &attributes );
00258         psa_reset_key_attributes( &attributes );
00259 
00260         curve = PSA_KEY_TYPE_GET_CURVE( key_type );
00261         if( curve == 0 )
00262             return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );
00263 
00264         ret = mbedtls_psa_get_ecc_oid_from_id( curve, &oid, &oid_len );
00265         if( ret != 0 )
00266             return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );
00267 
00268         /* Write EC algorithm parameters; that's akin
00269          * to pk_write_ec_param() above. */
00270         MBEDTLS_ASN1_CHK_ADD( par_len, mbedtls_asn1_write_oid( &c, buf,
00271                                                                oid, oid_len ) );
00272 
00273         /* The rest of the function works as for legacy EC contexts. */
00274         pk_type = MBEDTLS_PK_ECKEY;
00275     }
00276 #endif /* MBEDTLS_USE_PSA_CRYPTO */
00277 
00278     if( ( ret = mbedtls_oid_get_oid_by_pk_alg( pk_type, &oid,
00279                                                &oid_len ) ) != 0 )
00280     {
00281         return( ret );
00282     }
00283 
00284     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_algorithm_identifier( &c, buf, oid, oid_len,
00285                                                         par_len ) );
00286 
00287     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
00288     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED |
00289                                                 MBEDTLS_ASN1_SEQUENCE ) );
00290 
00291     return( (int) len );
00292 }
00293 
00294 int mbedtls_pk_write_key_der( mbedtls_pk_context *key, unsigned char *buf, size_t size )
00295 {
00296     int ret;
00297     unsigned char *c;
00298     size_t len = 0;
00299 
00300     PK_VALIDATE_RET( key != NULL );
00301     if( size == 0 )
00302         return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
00303     PK_VALIDATE_RET( buf != NULL );
00304 
00305     c = buf + size;
00306 
00307 #if defined(MBEDTLS_RSA_C)
00308     if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA )
00309     {
00310         mbedtls_mpi T; /* Temporary holding the exported parameters */
00311         mbedtls_rsa_context *rsa = mbedtls_pk_rsa( *key );
00312 
00313         /*
00314          * Export the parameters one after another to avoid simultaneous copies.
00315          */
00316 
00317         mbedtls_mpi_init( &T );
00318 
00319         /* Export QP */
00320         if( ( ret = mbedtls_rsa_export_crt( rsa, NULL, NULL, &T ) ) != 0 ||
00321             ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )
00322             goto end_of_export;
00323         len += ret;
00324 
00325         /* Export DQ */
00326         if( ( ret = mbedtls_rsa_export_crt( rsa, NULL, &T, NULL ) ) != 0 ||
00327             ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )
00328             goto end_of_export;
00329         len += ret;
00330 
00331         /* Export DP */
00332         if( ( ret = mbedtls_rsa_export_crt( rsa, &T, NULL, NULL ) ) != 0 ||
00333             ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )
00334             goto end_of_export;
00335         len += ret;
00336 
00337         /* Export Q */
00338         if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL,
00339                                          &T, NULL, NULL ) ) != 0 ||
00340              ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )
00341             goto end_of_export;
00342         len += ret;
00343 
00344         /* Export P */
00345         if ( ( ret = mbedtls_rsa_export( rsa, NULL, &T,
00346                                          NULL, NULL, NULL ) ) != 0 ||
00347              ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )
00348             goto end_of_export;
00349         len += ret;
00350 
00351         /* Export D */
00352         if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL,
00353                                          NULL, &T, NULL ) ) != 0 ||
00354              ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )
00355             goto end_of_export;
00356         len += ret;
00357 
00358         /* Export E */
00359         if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL,
00360                                          NULL, NULL, &T ) ) != 0 ||
00361              ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )
00362             goto end_of_export;
00363         len += ret;
00364 
00365         /* Export N */
00366         if ( ( ret = mbedtls_rsa_export( rsa, &T, NULL,
00367                                          NULL, NULL, NULL ) ) != 0 ||
00368              ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )
00369             goto end_of_export;
00370         len += ret;
00371 
00372     end_of_export:
00373 
00374         mbedtls_mpi_free( &T );
00375         if( ret < 0 )
00376             return( ret );
00377 
00378         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, 0 ) );
00379         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
00380         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c,
00381                                                buf, MBEDTLS_ASN1_CONSTRUCTED |
00382                                                MBEDTLS_ASN1_SEQUENCE ) );
00383     }
00384     else
00385 #endif /* MBEDTLS_RSA_C */
00386 #if defined(MBEDTLS_ECP_C)
00387     if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY )
00388     {
00389         mbedtls_ecp_keypair *ec = mbedtls_pk_ec( *key );
00390         size_t pub_len = 0, par_len = 0;
00391 
00392         /*
00393          * RFC 5915, or SEC1 Appendix C.4
00394          *
00395          * ECPrivateKey ::= SEQUENCE {
00396          *      version        INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
00397          *      privateKey     OCTET STRING,
00398          *      parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
00399          *      publicKey  [1] BIT STRING OPTIONAL
00400          *    }
00401          */
00402 
00403         /* publicKey */
00404         MBEDTLS_ASN1_CHK_ADD( pub_len, pk_write_ec_pubkey( &c, buf, ec ) );
00405 
00406         if( c - buf < 1 )
00407             return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
00408         *--c = 0;
00409         pub_len += 1;
00410 
00411         MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_len( &c, buf, pub_len ) );
00412         MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_BIT_STRING ) );
00413 
00414         MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_len( &c, buf, pub_len ) );
00415         MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_tag( &c, buf,
00416                             MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1 ) );
00417         len += pub_len;
00418 
00419         /* parameters */
00420         MBEDTLS_ASN1_CHK_ADD( par_len, pk_write_ec_param( &c, buf, ec ) );
00421 
00422         MBEDTLS_ASN1_CHK_ADD( par_len, mbedtls_asn1_write_len( &c, buf, par_len ) );
00423         MBEDTLS_ASN1_CHK_ADD( par_len, mbedtls_asn1_write_tag( &c, buf,
00424                             MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) );
00425         len += par_len;
00426 
00427         /* privateKey: write as MPI then fix tag */
00428         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &ec->d  ) );
00429         *c = MBEDTLS_ASN1_OCTET_STRING;
00430 
00431         /* version */
00432         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, 1 ) );
00433 
00434         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
00435         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED |
00436                                                     MBEDTLS_ASN1_SEQUENCE ) );
00437     }
00438     else
00439 #endif /* MBEDTLS_ECP_C */
00440         return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );
00441 
00442     return( (int) len );
00443 }
00444 
00445 #if defined(MBEDTLS_PEM_WRITE_C)
00446 
00447 #define PEM_BEGIN_PUBLIC_KEY    "-----BEGIN PUBLIC KEY-----\n"
00448 #define PEM_END_PUBLIC_KEY      "-----END PUBLIC KEY-----\n"
00449 
00450 #define PEM_BEGIN_PRIVATE_KEY_RSA   "-----BEGIN RSA PRIVATE KEY-----\n"
00451 #define PEM_END_PRIVATE_KEY_RSA     "-----END RSA PRIVATE KEY-----\n"
00452 #define PEM_BEGIN_PRIVATE_KEY_EC    "-----BEGIN EC PRIVATE KEY-----\n"
00453 #define PEM_END_PRIVATE_KEY_EC      "-----END EC PRIVATE KEY-----\n"
00454 
00455 /*
00456  * Max sizes of key per types. Shown as tag + len (+ content).
00457  */
00458 
00459 #if defined(MBEDTLS_RSA_C)
00460 /*
00461  * RSA public keys:
00462  *  SubjectPublicKeyInfo  ::=  SEQUENCE  {          1 + 3
00463  *       algorithm            AlgorithmIdentifier,  1 + 1 (sequence)
00464  *                                                + 1 + 1 + 9 (rsa oid)
00465  *                                                + 1 + 1 (params null)
00466  *       subjectPublicKey     BIT STRING }          1 + 3 + (1 + below)
00467  *  RSAPublicKey ::= SEQUENCE {                     1 + 3
00468  *      modulus           INTEGER,  -- n            1 + 3 + MPI_MAX + 1
00469  *      publicExponent    INTEGER   -- e            1 + 3 + MPI_MAX + 1
00470  *  }
00471  */
00472 #define RSA_PUB_DER_MAX_BYTES   38 + 2 * MBEDTLS_MPI_MAX_SIZE
00473 
00474 /*
00475  * RSA private keys:
00476  *  RSAPrivateKey ::= SEQUENCE {                    1 + 3
00477  *      version           Version,                  1 + 1 + 1
00478  *      modulus           INTEGER,                  1 + 3 + MPI_MAX + 1
00479  *      publicExponent    INTEGER,                  1 + 3 + MPI_MAX + 1
00480  *      privateExponent   INTEGER,                  1 + 3 + MPI_MAX + 1
00481  *      prime1            INTEGER,                  1 + 3 + MPI_MAX / 2 + 1
00482  *      prime2            INTEGER,                  1 + 3 + MPI_MAX / 2 + 1
00483  *      exponent1         INTEGER,                  1 + 3 + MPI_MAX / 2 + 1
00484  *      exponent2         INTEGER,                  1 + 3 + MPI_MAX / 2 + 1
00485  *      coefficient       INTEGER,                  1 + 3 + MPI_MAX / 2 + 1
00486  *      otherPrimeInfos   OtherPrimeInfos OPTIONAL  0 (not supported)
00487  *  }
00488  */
00489 #define MPI_MAX_SIZE_2          MBEDTLS_MPI_MAX_SIZE / 2 + \
00490                                 MBEDTLS_MPI_MAX_SIZE % 2
00491 #define RSA_PRV_DER_MAX_BYTES   47 + 3 * MBEDTLS_MPI_MAX_SIZE \
00492                                    + 5 * MPI_MAX_SIZE_2
00493 
00494 #else /* MBEDTLS_RSA_C */
00495 
00496 #define RSA_PUB_DER_MAX_BYTES   0
00497 #define RSA_PRV_DER_MAX_BYTES   0
00498 
00499 #endif /* MBEDTLS_RSA_C */
00500 
00501 #if defined(MBEDTLS_ECP_C)
00502 /*
00503  * EC public keys:
00504  *  SubjectPublicKeyInfo  ::=  SEQUENCE  {      1 + 2
00505  *    algorithm         AlgorithmIdentifier,    1 + 1 (sequence)
00506  *                                            + 1 + 1 + 7 (ec oid)
00507  *                                            + 1 + 1 + 9 (namedCurve oid)
00508  *    subjectPublicKey  BIT STRING              1 + 2 + 1               [1]
00509  *                                            + 1 (point format)        [1]
00510  *                                            + 2 * ECP_MAX (coords)    [1]
00511  *  }
00512  */
00513 #define ECP_PUB_DER_MAX_BYTES   30 + 2 * MBEDTLS_ECP_MAX_BYTES
00514 
00515 /*
00516  * EC private keys:
00517  * ECPrivateKey ::= SEQUENCE {                  1 + 2
00518  *      version        INTEGER ,                1 + 1 + 1
00519  *      privateKey     OCTET STRING,            1 + 1 + ECP_MAX
00520  *      parameters [0] ECParameters OPTIONAL,   1 + 1 + (1 + 1 + 9)
00521  *      publicKey  [1] BIT STRING OPTIONAL      1 + 2 + [1] above
00522  *    }
00523  */
00524 #define ECP_PRV_DER_MAX_BYTES   29 + 3 * MBEDTLS_ECP_MAX_BYTES
00525 
00526 #else /* MBEDTLS_ECP_C */
00527 
00528 #define ECP_PUB_DER_MAX_BYTES   0
00529 #define ECP_PRV_DER_MAX_BYTES   0
00530 
00531 #endif /* MBEDTLS_ECP_C */
00532 
00533 #define PUB_DER_MAX_BYTES   RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \
00534                             RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES
00535 #define PRV_DER_MAX_BYTES   RSA_PRV_DER_MAX_BYTES > ECP_PRV_DER_MAX_BYTES ? \
00536                             RSA_PRV_DER_MAX_BYTES : ECP_PRV_DER_MAX_BYTES
00537 
00538 int mbedtls_pk_write_pubkey_pem( mbedtls_pk_context *key, unsigned char *buf, size_t size )
00539 {
00540     int ret;
00541     unsigned char output_buf[PUB_DER_MAX_BYTES];
00542     size_t olen = 0;
00543 
00544     PK_VALIDATE_RET( key != NULL );
00545     PK_VALIDATE_RET( buf != NULL || size == 0 );
00546 
00547     if( ( ret = mbedtls_pk_write_pubkey_der( key, output_buf,
00548                                      sizeof(output_buf) ) ) < 0 )
00549     {
00550         return( ret );
00551     }
00552 
00553     if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY,
00554                                   output_buf + sizeof(output_buf) - ret,
00555                                   ret, buf, size, &olen ) ) != 0 )
00556     {
00557         return( ret );
00558     }
00559 
00560     return( 0 );
00561 }
00562 
00563 int mbedtls_pk_write_key_pem( mbedtls_pk_context *key, unsigned char *buf, size_t size )
00564 {
00565     int ret;
00566     unsigned char output_buf[PRV_DER_MAX_BYTES];
00567     const char *begin, *end;
00568     size_t olen = 0;
00569 
00570     PK_VALIDATE_RET( key != NULL );
00571     PK_VALIDATE_RET( buf != NULL || size == 0 );
00572 
00573     if( ( ret = mbedtls_pk_write_key_der( key, output_buf, sizeof(output_buf) ) ) < 0 )
00574         return( ret );
00575 
00576 #if defined(MBEDTLS_RSA_C)
00577     if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA )
00578     {
00579         begin = PEM_BEGIN_PRIVATE_KEY_RSA;
00580         end = PEM_END_PRIVATE_KEY_RSA;
00581     }
00582     else
00583 #endif
00584 #if defined(MBEDTLS_ECP_C)
00585     if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY )
00586     {
00587         begin = PEM_BEGIN_PRIVATE_KEY_EC;
00588         end = PEM_END_PRIVATE_KEY_EC;
00589     }
00590     else
00591 #endif
00592         return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );
00593 
00594     if( ( ret = mbedtls_pem_write_buffer( begin, end,
00595                                   output_buf + sizeof(output_buf) - ret,
00596                                   ret, buf, size, &olen ) ) != 0 )
00597     {
00598         return( ret );
00599     }
00600 
00601     return( 0 );
00602 }
00603 #endif /* MBEDTLS_PEM_WRITE_C */
00604 
00605 #endif /* MBEDTLS_PK_WRITE_C */