Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ecdh.c Source File

ecdh.c

00001 /*
00002  *  Elliptic curve Diffie-Hellman
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 /*
00023  * References:
00024  *
00025  * SEC1 http://www.secg.org/index.php?action=secg,docs_secg
00026  * RFC 4492
00027  */
00028 
00029 #if !defined(MBEDTLS_CONFIG_FILE)
00030 #include "mbedtls/config.h"
00031 #else
00032 #include MBEDTLS_CONFIG_FILE
00033 #endif
00034 
00035 #if defined(MBEDTLS_ECDH_C)
00036 
00037 #include "mbedtls/ecdh.h"
00038 #include "mbedtls/platform_util.h"
00039 
00040 #include <string.h>
00041 
00042 /* Parameter validation macros based on platform_util.h */
00043 #define ECDH_VALIDATE_RET( cond )    \
00044     MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA )
00045 #define ECDH_VALIDATE( cond )        \
00046     MBEDTLS_INTERNAL_VALIDATE( cond )
00047 
00048 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
00049 typedef mbedtls_ecdh_context mbedtls_ecdh_context_mbed;
00050 #endif
00051 
00052 static mbedtls_ecp_group_id mbedtls_ecdh_grp_id(
00053     const mbedtls_ecdh_context *ctx )
00054 {
00055 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
00056     return( ctx->grp .id  );
00057 #else
00058     return( ctx->grp_id  );
00059 #endif
00060 }
00061 
00062 int mbedtls_ecdh_can_do( mbedtls_ecp_group_id gid )
00063 {
00064     /* At this time, all groups support ECDH. */
00065     (void) gid;
00066     return( 1 );
00067 }
00068 
00069 #if !defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT)
00070 /*
00071  * Generate public key (restartable version)
00072  *
00073  * Note: this internal function relies on its caller preserving the value of
00074  * the output parameter 'd' across continuation calls. This would not be
00075  * acceptable for a public function but is OK here as we control call sites.
00076  */
00077 static int ecdh_gen_public_restartable( mbedtls_ecp_group *grp,
00078                     mbedtls_mpi *d, mbedtls_ecp_point *Q,
00079                     int (*f_rng)(void *, unsigned char *, size_t),
00080                     void *p_rng,
00081                     mbedtls_ecp_restart_ctx *rs_ctx )
00082 {
00083     int ret;
00084 
00085     /* If multiplication is in progress, we already generated a privkey */
00086 #if defined(MBEDTLS_ECP_RESTARTABLE)
00087     if( rs_ctx == NULL || rs_ctx->rsm  == NULL )
00088 #endif
00089         MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) );
00090 
00091     MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, Q, d, &grp->G ,
00092                                                   f_rng, p_rng, rs_ctx ) );
00093 
00094 cleanup:
00095     return( ret );
00096 }
00097 
00098 /*
00099  * Generate public key
00100  */
00101 int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q,
00102                      int (*f_rng)(void *, unsigned char *, size_t),
00103                      void *p_rng )
00104 {
00105     ECDH_VALIDATE_RET( grp != NULL );
00106     ECDH_VALIDATE_RET( d != NULL );
00107     ECDH_VALIDATE_RET( Q != NULL );
00108     ECDH_VALIDATE_RET( f_rng != NULL );
00109     return( ecdh_gen_public_restartable( grp, d, Q, f_rng, p_rng, NULL ) );
00110 }
00111 #endif /* !MBEDTLS_ECDH_GEN_PUBLIC_ALT */
00112 
00113 #if !defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT)
00114 /*
00115  * Compute shared secret (SEC1 3.3.1)
00116  */
00117 static int ecdh_compute_shared_restartable( mbedtls_ecp_group *grp,
00118                          mbedtls_mpi *z,
00119                          const mbedtls_ecp_point *Q, const mbedtls_mpi *d,
00120                          int (*f_rng)(void *, unsigned char *, size_t),
00121                          void *p_rng,
00122                          mbedtls_ecp_restart_ctx *rs_ctx )
00123 {
00124     int ret;
00125     mbedtls_ecp_point P;
00126 
00127     mbedtls_ecp_point_init( &P );
00128 
00129     MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, &P, d, Q,
00130                                                   f_rng, p_rng, rs_ctx ) );
00131 
00132     if( mbedtls_ecp_is_zero( &P ) )
00133     {
00134         ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
00135         goto cleanup;
00136     }
00137 
00138     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( z, &P.X  ) );
00139 
00140 cleanup:
00141     mbedtls_ecp_point_free( &P );
00142 
00143     return( ret );
00144 }
00145 
00146 /*
00147  * Compute shared secret (SEC1 3.3.1)
00148  */
00149 int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z,
00150                          const mbedtls_ecp_point *Q, const mbedtls_mpi *d,
00151                          int (*f_rng)(void *, unsigned char *, size_t),
00152                          void *p_rng )
00153 {
00154     ECDH_VALIDATE_RET( grp != NULL );
00155     ECDH_VALIDATE_RET( Q != NULL );
00156     ECDH_VALIDATE_RET( d != NULL );
00157     ECDH_VALIDATE_RET( z != NULL );
00158     return( ecdh_compute_shared_restartable( grp, z, Q, d,
00159                                              f_rng, p_rng, NULL ) );
00160 }
00161 #endif /* !MBEDTLS_ECDH_COMPUTE_SHARED_ALT */
00162 
00163 static void ecdh_init_internal( mbedtls_ecdh_context_mbed *ctx )
00164 {
00165     mbedtls_ecp_group_init( &ctx->grp  );
00166     mbedtls_mpi_init( &ctx->d   );
00167     mbedtls_ecp_point_init( &ctx->Q    );
00168     mbedtls_ecp_point_init( &ctx->Qp   );
00169     mbedtls_mpi_init( &ctx->z   );
00170 
00171 #if defined(MBEDTLS_ECP_RESTARTABLE)
00172     mbedtls_ecp_restart_init( &ctx->rs  );
00173 #endif
00174 }
00175 
00176 /*
00177  * Initialize context
00178  */
00179 void mbedtls_ecdh_init( mbedtls_ecdh_context *ctx )
00180 {
00181     ECDH_VALIDATE( ctx != NULL );
00182 
00183 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
00184     ecdh_init_internal( ctx );
00185     mbedtls_ecp_point_init( &ctx->Vi   );
00186     mbedtls_ecp_point_init( &ctx->Vf   );
00187     mbedtls_mpi_init( &ctx->_d  );
00188 #else
00189     memset( ctx, 0, sizeof( mbedtls_ecdh_context ) );
00190 
00191     ctx->var  = MBEDTLS_ECDH_VARIANT_NONE ;
00192 #endif
00193     ctx->point_format  = MBEDTLS_ECP_PF_UNCOMPRESSED;
00194 #if defined(MBEDTLS_ECP_RESTARTABLE)
00195     ctx->restart_enabled  = 0;
00196 #endif
00197 }
00198 
00199 static int ecdh_setup_internal( mbedtls_ecdh_context_mbed *ctx,
00200                                 mbedtls_ecp_group_id grp_id )
00201 {
00202     int ret;
00203 
00204     ret = mbedtls_ecp_group_load( &ctx->grp , grp_id );
00205     if( ret != 0 )
00206     {
00207         return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
00208     }
00209 
00210     return( 0 );
00211 }
00212 
00213 /*
00214  * Setup context
00215  */
00216 int mbedtls_ecdh_setup( mbedtls_ecdh_context *ctx, mbedtls_ecp_group_id grp_id )
00217 {
00218     ECDH_VALIDATE_RET( ctx != NULL );
00219 
00220 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
00221     return( ecdh_setup_internal( ctx, grp_id ) );
00222 #else
00223     switch( grp_id )
00224     {
00225 #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
00226         case MBEDTLS_ECP_DP_CURVE25519:
00227             ctx->point_format  = MBEDTLS_ECP_PF_COMPRESSED;
00228             ctx->var  = MBEDTLS_ECDH_VARIANT_EVEREST ;
00229             ctx->grp_id  = grp_id;
00230             return( mbedtls_everest_setup( &ctx->ctx .everest_ecdh, grp_id ) );
00231 #endif
00232         default:
00233             ctx->point_format  = MBEDTLS_ECP_PF_UNCOMPRESSED;
00234             ctx->var  = MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0 ;
00235             ctx->grp_id  = grp_id;
00236             ecdh_init_internal( &ctx->ctx .mbed_ecdh );
00237             return( ecdh_setup_internal( &ctx->ctx .mbed_ecdh, grp_id ) );
00238     }
00239 #endif
00240 }
00241 
00242 static void ecdh_free_internal( mbedtls_ecdh_context_mbed *ctx )
00243 {
00244     mbedtls_ecp_group_free( &ctx->grp  );
00245     mbedtls_mpi_free( &ctx->d   );
00246     mbedtls_ecp_point_free( &ctx->Q    );
00247     mbedtls_ecp_point_free( &ctx->Qp   );
00248     mbedtls_mpi_free( &ctx->z   );
00249 
00250 #if defined(MBEDTLS_ECP_RESTARTABLE)
00251     mbedtls_ecp_restart_free( &ctx->rs  );
00252 #endif
00253 }
00254 
00255 #if defined(MBEDTLS_ECP_RESTARTABLE)
00256 /*
00257  * Enable restartable operations for context
00258  */
00259 void mbedtls_ecdh_enable_restart( mbedtls_ecdh_context *ctx )
00260 {
00261     ECDH_VALIDATE( ctx != NULL );
00262 
00263     ctx->restart_enabled  = 1;
00264 }
00265 #endif
00266 
00267 /*
00268  * Free context
00269  */
00270 void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx )
00271 {
00272     if( ctx == NULL )
00273         return;
00274 
00275 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
00276     mbedtls_ecp_point_free( &ctx->Vi  );
00277     mbedtls_ecp_point_free( &ctx->Vf  );
00278     mbedtls_mpi_free( &ctx->_d  );
00279     ecdh_free_internal( ctx );
00280 #else
00281     switch( ctx->var  )
00282     {
00283 #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
00284         case MBEDTLS_ECDH_VARIANT_EVEREST :
00285             mbedtls_everest_free( &ctx->ctx .everest_ecdh );
00286             break;
00287 #endif
00288         case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0 :
00289             ecdh_free_internal( &ctx->ctx .mbed_ecdh );
00290             break;
00291         default:
00292             break;
00293     }
00294 
00295     ctx->point_format  = MBEDTLS_ECP_PF_UNCOMPRESSED;
00296     ctx->var  = MBEDTLS_ECDH_VARIANT_NONE ;
00297     ctx->grp_id  = MBEDTLS_ECP_DP_NONE;
00298 #endif
00299 }
00300 
00301 static int ecdh_make_params_internal( mbedtls_ecdh_context_mbed *ctx,
00302                                       size_t *olen, int point_format,
00303                                       unsigned char *buf, size_t blen,
00304                                       int (*f_rng)(void *,
00305                                                    unsigned char *,
00306                                                    size_t),
00307                                       void *p_rng,
00308                                       int restart_enabled )
00309 {
00310     int ret;
00311     size_t grp_len, pt_len;
00312 #if defined(MBEDTLS_ECP_RESTARTABLE)
00313     mbedtls_ecp_restart_ctx *rs_ctx = NULL;
00314 #endif
00315 
00316     if( ctx->grp .pbits  == 0 )
00317         return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
00318 
00319 #if defined(MBEDTLS_ECP_RESTARTABLE)
00320     if( restart_enabled )
00321         rs_ctx = &ctx->rs ;
00322 #else
00323     (void) restart_enabled;
00324 #endif
00325 
00326 
00327 #if defined(MBEDTLS_ECP_RESTARTABLE)
00328     if( ( ret = ecdh_gen_public_restartable( &ctx->grp , &ctx->d , &ctx->Q ,
00329                                              f_rng, p_rng, rs_ctx ) ) != 0 )
00330         return( ret );
00331 #else
00332     if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp , &ctx->d , &ctx->Q ,
00333                                          f_rng, p_rng ) ) != 0 )
00334         return( ret );
00335 #endif /* MBEDTLS_ECP_RESTARTABLE */
00336 
00337     if( ( ret = mbedtls_ecp_tls_write_group( &ctx->grp , &grp_len, buf,
00338                                              blen ) ) != 0 )
00339         return( ret );
00340 
00341     buf += grp_len;
00342     blen -= grp_len;
00343 
00344     if( ( ret = mbedtls_ecp_tls_write_point( &ctx->grp , &ctx->Q , point_format,
00345                                              &pt_len, buf, blen ) ) != 0 )
00346         return( ret );
00347 
00348     *olen = grp_len + pt_len;
00349     return( 0 );
00350 }
00351 
00352 /*
00353  * Setup and write the ServerKeyExchange parameters (RFC 4492)
00354  *      struct {
00355  *          ECParameters    curve_params;
00356  *          ECPoint         public;
00357  *      } ServerECDHParams;
00358  */
00359 int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen,
00360                               unsigned char *buf, size_t blen,
00361                               int (*f_rng)(void *, unsigned char *, size_t),
00362                               void *p_rng )
00363 {
00364     int restart_enabled = 0;
00365     ECDH_VALIDATE_RET( ctx != NULL );
00366     ECDH_VALIDATE_RET( olen != NULL );
00367     ECDH_VALIDATE_RET( buf != NULL );
00368     ECDH_VALIDATE_RET( f_rng != NULL );
00369 
00370 #if defined(MBEDTLS_ECP_RESTARTABLE)
00371     restart_enabled = ctx->restart_enabled ;
00372 #else
00373     (void) restart_enabled;
00374 #endif
00375 
00376 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
00377     return( ecdh_make_params_internal( ctx, olen, ctx->point_format , buf, blen,
00378                                        f_rng, p_rng, restart_enabled ) );
00379 #else
00380     switch( ctx->var  )
00381     {
00382 #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
00383         case MBEDTLS_ECDH_VARIANT_EVEREST :
00384             return( mbedtls_everest_make_params( &ctx->ctx .everest_ecdh, olen,
00385                                                  buf, blen, f_rng, p_rng ) );
00386 #endif
00387         case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0 :
00388             return( ecdh_make_params_internal( &ctx->ctx .mbed_ecdh, olen,
00389                                                ctx->point_format , buf, blen,
00390                                                f_rng, p_rng,
00391                                                restart_enabled ) );
00392         default:
00393             return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
00394     }
00395 #endif
00396 }
00397 
00398 static int ecdh_read_params_internal( mbedtls_ecdh_context_mbed *ctx,
00399                                       const unsigned char **buf,
00400                                       const unsigned char *end )
00401 {
00402     return( mbedtls_ecp_tls_read_point( &ctx->grp , &ctx->Qp , buf,
00403                                         end - *buf ) );
00404 }
00405 
00406 /*
00407  * Read the ServerKeyExhange parameters (RFC 4492)
00408  *      struct {
00409  *          ECParameters    curve_params;
00410  *          ECPoint         public;
00411  *      } ServerECDHParams;
00412  */
00413 int mbedtls_ecdh_read_params( mbedtls_ecdh_context *ctx,
00414                               const unsigned char **buf,
00415                               const unsigned char *end )
00416 {
00417     int ret;
00418     mbedtls_ecp_group_id grp_id;
00419     ECDH_VALIDATE_RET( ctx != NULL );
00420     ECDH_VALIDATE_RET( buf != NULL );
00421     ECDH_VALIDATE_RET( *buf != NULL );
00422     ECDH_VALIDATE_RET( end != NULL );
00423 
00424     if( ( ret = mbedtls_ecp_tls_read_group_id( &grp_id, buf, end - *buf ) )
00425             != 0 )
00426         return( ret );
00427 
00428     if( ( ret = mbedtls_ecdh_setup( ctx, grp_id ) ) != 0 )
00429         return( ret );
00430 
00431 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
00432     return( ecdh_read_params_internal( ctx, buf, end ) );
00433 #else
00434     switch( ctx->var  )
00435     {
00436 #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
00437         case MBEDTLS_ECDH_VARIANT_EVEREST :
00438             return( mbedtls_everest_read_params( &ctx->ctx .everest_ecdh,
00439                                                  buf, end) );
00440 #endif
00441         case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0 :
00442             return( ecdh_read_params_internal( &ctx->ctx .mbed_ecdh,
00443                                                buf, end ) );
00444         default:
00445             return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
00446     }
00447 #endif
00448 }
00449 
00450 static int ecdh_get_params_internal( mbedtls_ecdh_context_mbed *ctx,
00451                                      const mbedtls_ecp_keypair *key,
00452                                      mbedtls_ecdh_side side )
00453 {
00454     int ret;
00455 
00456     /* If it's not our key, just import the public part as Qp */
00457     if( side == MBEDTLS_ECDH_THEIRS )
00458         return( mbedtls_ecp_copy( &ctx->Qp , &key->Q  ) );
00459 
00460     /* Our key: import public (as Q) and private parts */
00461     if( side != MBEDTLS_ECDH_OURS )
00462         return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
00463 
00464     if( ( ret = mbedtls_ecp_copy( &ctx->Q , &key->Q  ) ) != 0 ||
00465         ( ret = mbedtls_mpi_copy( &ctx->d , &key->d  ) ) != 0 )
00466         return( ret );
00467 
00468     return( 0 );
00469 }
00470 
00471 /*
00472  * Get parameters from a keypair
00473  */
00474 int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx,
00475                              const mbedtls_ecp_keypair *key,
00476                              mbedtls_ecdh_side side )
00477 {
00478     int ret;
00479     ECDH_VALIDATE_RET( ctx != NULL );
00480     ECDH_VALIDATE_RET( key != NULL );
00481     ECDH_VALIDATE_RET( side == MBEDTLS_ECDH_OURS ||
00482                        side == MBEDTLS_ECDH_THEIRS );
00483 
00484     if( mbedtls_ecdh_grp_id( ctx ) == MBEDTLS_ECP_DP_NONE )
00485     {
00486         /* This is the first call to get_params(). Set up the context
00487          * for use with the group. */
00488         if( ( ret = mbedtls_ecdh_setup( ctx, key->grp .id  ) ) != 0 )
00489             return( ret );
00490     }
00491     else
00492     {
00493         /* This is not the first call to get_params(). Check that the
00494          * current key's group is the same as the context's, which was set
00495          * from the first key's group. */
00496         if( mbedtls_ecdh_grp_id( ctx ) != key->grp .id  )
00497             return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
00498     }
00499 
00500 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
00501     return( ecdh_get_params_internal( ctx, key, side ) );
00502 #else
00503     switch( ctx->var  )
00504     {
00505 #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
00506         case MBEDTLS_ECDH_VARIANT_EVEREST :
00507         {
00508             mbedtls_everest_ecdh_side s = side == MBEDTLS_ECDH_OURS ?
00509                                                    MBEDTLS_EVEREST_ECDH_OURS :
00510                                                    MBEDTLS_EVEREST_ECDH_THEIRS;
00511             return( mbedtls_everest_get_params( &ctx->ctx .everest_ecdh,
00512                                                 key, s) );
00513         }
00514 #endif
00515         case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0 :
00516             return( ecdh_get_params_internal( &ctx->ctx .mbed_ecdh,
00517                                               key, side ) );
00518         default:
00519             return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
00520     }
00521 #endif
00522 }
00523 
00524 static int ecdh_make_public_internal( mbedtls_ecdh_context_mbed *ctx,
00525                                       size_t *olen, int point_format,
00526                                       unsigned char *buf, size_t blen,
00527                                       int (*f_rng)(void *,
00528                                                    unsigned char *,
00529                                                    size_t),
00530                                       void *p_rng,
00531                                       int restart_enabled )
00532 {
00533     int ret;
00534 #if defined(MBEDTLS_ECP_RESTARTABLE)
00535     mbedtls_ecp_restart_ctx *rs_ctx = NULL;
00536 #endif
00537 
00538     if( ctx->grp .pbits  == 0 )
00539         return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
00540 
00541 #if defined(MBEDTLS_ECP_RESTARTABLE)
00542     if( restart_enabled )
00543         rs_ctx = &ctx->rs ;
00544 #else
00545     (void) restart_enabled;
00546 #endif
00547 
00548 #if defined(MBEDTLS_ECP_RESTARTABLE)
00549     if( ( ret = ecdh_gen_public_restartable( &ctx->grp , &ctx->d , &ctx->Q ,
00550                                              f_rng, p_rng, rs_ctx ) ) != 0 )
00551         return( ret );
00552 #else
00553     if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp , &ctx->d , &ctx->Q ,
00554                                          f_rng, p_rng ) ) != 0 )
00555         return( ret );
00556 #endif /* MBEDTLS_ECP_RESTARTABLE */
00557 
00558     return mbedtls_ecp_tls_write_point( &ctx->grp , &ctx->Q , point_format, olen,
00559                                         buf, blen );
00560 }
00561 
00562 /*
00563  * Setup and export the client public value
00564  */
00565 int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen,
00566                               unsigned char *buf, size_t blen,
00567                               int (*f_rng)(void *, unsigned char *, size_t),
00568                               void *p_rng )
00569 {
00570     int restart_enabled = 0;
00571     ECDH_VALIDATE_RET( ctx != NULL );
00572     ECDH_VALIDATE_RET( olen != NULL );
00573     ECDH_VALIDATE_RET( buf != NULL );
00574     ECDH_VALIDATE_RET( f_rng != NULL );
00575 
00576 #if defined(MBEDTLS_ECP_RESTARTABLE)
00577     restart_enabled = ctx->restart_enabled ;
00578 #endif
00579 
00580 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
00581     return( ecdh_make_public_internal( ctx, olen, ctx->point_format , buf, blen,
00582                                        f_rng, p_rng, restart_enabled ) );
00583 #else
00584     switch( ctx->var  )
00585     {
00586 #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
00587         case MBEDTLS_ECDH_VARIANT_EVEREST :
00588             return( mbedtls_everest_make_public( &ctx->ctx .everest_ecdh, olen,
00589                                                  buf, blen, f_rng, p_rng ) );
00590 #endif
00591         case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0 :
00592             return( ecdh_make_public_internal( &ctx->ctx .mbed_ecdh, olen,
00593                                                ctx->point_format , buf, blen,
00594                                                f_rng, p_rng,
00595                                                restart_enabled ) );
00596         default:
00597             return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
00598     }
00599 #endif
00600 }
00601 
00602 static int ecdh_read_public_internal( mbedtls_ecdh_context_mbed *ctx,
00603                                       const unsigned char *buf, size_t blen )
00604 {
00605     int ret;
00606     const unsigned char *p = buf;
00607 
00608     if( ( ret = mbedtls_ecp_tls_read_point( &ctx->grp , &ctx->Qp , &p,
00609                                             blen ) ) != 0 )
00610         return( ret );
00611 
00612     if( (size_t)( p - buf ) != blen )
00613         return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
00614 
00615     return( 0 );
00616 }
00617 
00618 /*
00619  * Parse and import the client's public value
00620  */
00621 int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx,
00622                               const unsigned char *buf, size_t blen )
00623 {
00624     ECDH_VALIDATE_RET( ctx != NULL );
00625     ECDH_VALIDATE_RET( buf != NULL );
00626 
00627 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
00628     return( ecdh_read_public_internal( ctx, buf, blen ) );
00629 #else
00630     switch( ctx->var  )
00631     {
00632 #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
00633         case MBEDTLS_ECDH_VARIANT_EVEREST :
00634             return( mbedtls_everest_read_public( &ctx->ctx .everest_ecdh,
00635                                                  buf, blen ) );
00636 #endif
00637         case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0 :
00638             return( ecdh_read_public_internal( &ctx->ctx .mbed_ecdh,
00639                                                        buf, blen ) );
00640         default:
00641             return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
00642     }
00643 #endif
00644 }
00645 
00646 static int ecdh_calc_secret_internal( mbedtls_ecdh_context_mbed *ctx,
00647                                       size_t *olen, unsigned char *buf,
00648                                       size_t blen,
00649                                       int (*f_rng)(void *,
00650                                                    unsigned char *,
00651                                                    size_t),
00652                                       void *p_rng,
00653                                       int restart_enabled )
00654 {
00655     int ret;
00656 #if defined(MBEDTLS_ECP_RESTARTABLE)
00657     mbedtls_ecp_restart_ctx *rs_ctx = NULL;
00658 #endif
00659 
00660     if( ctx == NULL || ctx->grp .pbits  == 0 )
00661         return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
00662 
00663 #if defined(MBEDTLS_ECP_RESTARTABLE)
00664     if( restart_enabled )
00665         rs_ctx = &ctx->rs ;
00666 #else
00667     (void) restart_enabled;
00668 #endif
00669 
00670 #if defined(MBEDTLS_ECP_RESTARTABLE)
00671     if( ( ret = ecdh_compute_shared_restartable( &ctx->grp , &ctx->z , &ctx->Qp ,
00672                                                  &ctx->d , f_rng, p_rng,
00673                                                  rs_ctx ) ) != 0 )
00674     {
00675         return( ret );
00676     }
00677 #else
00678     if( ( ret = mbedtls_ecdh_compute_shared( &ctx->grp , &ctx->z , &ctx->Qp ,
00679                                              &ctx->d , f_rng, p_rng ) ) != 0 )
00680     {
00681         return( ret );
00682     }
00683 #endif /* MBEDTLS_ECP_RESTARTABLE */
00684 
00685     if( mbedtls_mpi_size( &ctx->z  ) > blen )
00686         return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
00687 
00688     *olen = ctx->grp .pbits  / 8 + ( ( ctx->grp .pbits  % 8 ) != 0 );
00689 
00690     if( mbedtls_ecp_get_type( &ctx->grp  ) == MBEDTLS_ECP_TYPE_MONTGOMERY )
00691         return mbedtls_mpi_write_binary_le( &ctx->z , buf, *olen );
00692 
00693     return mbedtls_mpi_write_binary( &ctx->z , buf, *olen );
00694 }
00695 
00696 /*
00697  * Derive and export the shared secret
00698  */
00699 int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen,
00700                               unsigned char *buf, size_t blen,
00701                               int (*f_rng)(void *, unsigned char *, size_t),
00702                               void *p_rng )
00703 {
00704     int restart_enabled = 0;
00705     ECDH_VALIDATE_RET( ctx != NULL );
00706     ECDH_VALIDATE_RET( olen != NULL );
00707     ECDH_VALIDATE_RET( buf != NULL );
00708 
00709 #if defined(MBEDTLS_ECP_RESTARTABLE)
00710     restart_enabled = ctx->restart_enabled ;
00711 #endif
00712 
00713 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
00714     return( ecdh_calc_secret_internal( ctx, olen, buf, blen, f_rng, p_rng,
00715                                        restart_enabled ) );
00716 #else
00717     switch( ctx->var  )
00718     {
00719 #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
00720         case MBEDTLS_ECDH_VARIANT_EVEREST :
00721             return( mbedtls_everest_calc_secret( &ctx->ctx .everest_ecdh, olen,
00722                                                  buf, blen, f_rng, p_rng ) );
00723 #endif
00724         case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0 :
00725             return( ecdh_calc_secret_internal( &ctx->ctx .mbed_ecdh, olen, buf,
00726                                                blen, f_rng, p_rng,
00727                                                restart_enabled ) );
00728         default:
00729             return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
00730     }
00731 #endif
00732 }
00733 
00734 #endif /* MBEDTLS_ECDH_C */