mbed TLS library

Dependents:   HTTPClient-SSL WS_SERVER

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-2014, ARM Limited, All Rights Reserved
00005  *
00006  *  This file is part of mbed TLS (https://tls.mbed.org)
00007  *
00008  *  This program is free software; you can redistribute it and/or modify
00009  *  it under the terms of the GNU General Public License as published by
00010  *  the Free Software Foundation; either version 2 of the License, or
00011  *  (at your option) any later version.
00012  *
00013  *  This program is distributed in the hope that it will be useful,
00014  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  *  GNU General Public License for more details.
00017  *
00018  *  You should have received a copy of the GNU General Public License along
00019  *  with this program; if not, write to the Free Software Foundation, Inc.,
00020  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00021  */
00022 
00023 /*
00024  * References:
00025  *
00026  * SEC1 http://www.secg.org/index.php?action=secg,docs_secg
00027  * RFC 4492
00028  */
00029 
00030 #if !defined(POLARSSL_CONFIG_FILE)
00031 #include "polarssl/config.h"
00032 #else
00033 #include POLARSSL_CONFIG_FILE
00034 #endif
00035 
00036 #if defined(POLARSSL_ECDH_C)
00037 
00038 #include "polarssl/ecdh.h"
00039 
00040 #include <string.h>
00041 
00042 /*
00043  * Generate public key: simple wrapper around ecp_gen_keypair
00044  */
00045 int ecdh_gen_public( ecp_group *grp, mpi *d, ecp_point *Q,
00046                      int (*f_rng)(void *, unsigned char *, size_t),
00047                      void *p_rng )
00048 {
00049     return ecp_gen_keypair( grp, d, Q, f_rng, p_rng );
00050 }
00051 
00052 /*
00053  * Compute shared secret (SEC1 3.3.1)
00054  */
00055 int ecdh_compute_shared( ecp_group *grp, mpi *z,
00056                          const ecp_point *Q, const mpi *d,
00057                          int (*f_rng)(void *, unsigned char *, size_t),
00058                          void *p_rng )
00059 {
00060     int ret;
00061     ecp_point P;
00062 
00063     ecp_point_init( &P );
00064 
00065     /*
00066      * Make sure Q is a valid pubkey before using it
00067      */
00068     MPI_CHK( ecp_check_pubkey( grp, Q ) );
00069 
00070     MPI_CHK( ecp_mul( grp, &P, d, Q, f_rng, p_rng ) );
00071 
00072     if( ecp_is_zero( &P ) )
00073     {
00074         ret = POLARSSL_ERR_ECP_BAD_INPUT_DATA;
00075         goto cleanup;
00076     }
00077 
00078     MPI_CHK( mpi_copy( z, &P.X  ) );
00079 
00080 cleanup:
00081     ecp_point_free( &P );
00082 
00083     return( ret );
00084 }
00085 
00086 /*
00087  * Initialize context
00088  */
00089 void ecdh_init( ecdh_context *ctx )
00090 {
00091     memset( ctx, 0, sizeof( ecdh_context ) );
00092 }
00093 
00094 /*
00095  * Free context
00096  */
00097 void ecdh_free( ecdh_context *ctx )
00098 {
00099     if( ctx == NULL )
00100         return;
00101 
00102     ecp_group_free( &ctx->grp  );
00103     ecp_point_free( &ctx->Q    );
00104     ecp_point_free( &ctx->Qp   );
00105     ecp_point_free( &ctx->Vi   );
00106     ecp_point_free( &ctx->Vf   );
00107     mpi_free( &ctx->d   );
00108     mpi_free( &ctx->z   );
00109     mpi_free( &ctx->_d  );
00110 }
00111 
00112 /*
00113  * Setup and write the ServerKeyExhange parameters (RFC 4492)
00114  *      struct {
00115  *          ECParameters    curve_params;
00116  *          ECPoint         public;
00117  *      } ServerECDHParams;
00118  */
00119 int ecdh_make_params( ecdh_context *ctx, size_t *olen,
00120                       unsigned char *buf, size_t blen,
00121                       int (*f_rng)(void *, unsigned char *, size_t),
00122                       void *p_rng )
00123 {
00124     int ret;
00125     size_t grp_len, pt_len;
00126 
00127     if( ctx == NULL || ctx->grp .pbits  == 0 )
00128         return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
00129 
00130     if( ( ret = ecdh_gen_public( &ctx->grp , &ctx->d , &ctx->Q , f_rng, p_rng ) )
00131                 != 0 )
00132         return( ret );
00133 
00134     if( ( ret = ecp_tls_write_group( &ctx->grp , &grp_len, buf, blen ) )
00135                 != 0 )
00136         return( ret );
00137 
00138     buf += grp_len;
00139     blen -= grp_len;
00140 
00141     if( ( ret = ecp_tls_write_point( &ctx->grp , &ctx->Q , ctx->point_format ,
00142                                      &pt_len, buf, blen ) ) != 0 )
00143         return( ret );
00144 
00145     *olen = grp_len + pt_len;
00146     return( 0 );
00147 }
00148 
00149 /*
00150  * Read the ServerKeyExhange parameters (RFC 4492)
00151  *      struct {
00152  *          ECParameters    curve_params;
00153  *          ECPoint         public;
00154  *      } ServerECDHParams;
00155  */
00156 int ecdh_read_params( ecdh_context *ctx,
00157                       const unsigned char **buf, const unsigned char *end )
00158 {
00159     int ret;
00160 
00161     if( ( ret = ecp_tls_read_group( &ctx->grp , buf, end - *buf ) ) != 0 )
00162         return( ret );
00163 
00164     if( ( ret = ecp_tls_read_point( &ctx->grp , &ctx->Qp , buf, end - *buf ) )
00165                 != 0 )
00166         return( ret );
00167 
00168     return( 0 );
00169 }
00170 
00171 /*
00172  * Get parameters from a keypair
00173  */
00174 int ecdh_get_params( ecdh_context *ctx, const ecp_keypair *key,
00175                      ecdh_side side )
00176 {
00177     int ret;
00178 
00179     if( ( ret = ecp_group_copy( &ctx->grp , &key->grp  ) ) != 0 )
00180         return( ret );
00181 
00182     /* If it's not our key, just import the public part as Qp */
00183     if( side == POLARSSL_ECDH_THEIRS )
00184         return( ecp_copy( &ctx->Qp , &key->Q  ) );
00185 
00186     /* Our key: import public (as Q) and private parts */
00187     if( side != POLARSSL_ECDH_OURS )
00188         return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
00189 
00190     if( ( ret = ecp_copy( &ctx->Q , &key->Q  ) ) != 0 ||
00191         ( ret = mpi_copy( &ctx->d , &key->d  ) ) != 0 )
00192         return( ret );
00193 
00194     return( 0 );
00195 }
00196 
00197 /*
00198  * Setup and export the client public value
00199  */
00200 int ecdh_make_public( ecdh_context *ctx, size_t *olen,
00201                       unsigned char *buf, size_t blen,
00202                       int (*f_rng)(void *, unsigned char *, size_t),
00203                       void *p_rng )
00204 {
00205     int ret;
00206 
00207     if( ctx == NULL || ctx->grp .pbits  == 0 )
00208         return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
00209 
00210     if( ( ret = ecdh_gen_public( &ctx->grp , &ctx->d , &ctx->Q , f_rng, p_rng ) )
00211                 != 0 )
00212         return( ret );
00213 
00214     return ecp_tls_write_point( &ctx->grp , &ctx->Q , ctx->point_format ,
00215                                 olen, buf, blen );
00216 }
00217 
00218 /*
00219  * Parse and import the client's public value
00220  */
00221 int ecdh_read_public( ecdh_context *ctx,
00222                       const unsigned char *buf, size_t blen )
00223 {
00224     int ret;
00225     const unsigned char *p = buf;
00226 
00227     if( ctx == NULL )
00228         return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
00229 
00230     if( ( ret = ecp_tls_read_point( &ctx->grp , &ctx->Qp , &p, blen ) ) != 0 )
00231         return( ret );
00232 
00233     if( (size_t)( p - buf ) != blen )
00234         return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
00235 
00236     return( 0 );
00237 }
00238 
00239 /*
00240  * Derive and export the shared secret
00241  */
00242 int ecdh_calc_secret( ecdh_context *ctx, size_t *olen,
00243                       unsigned char *buf, size_t blen,
00244                       int (*f_rng)(void *, unsigned char *, size_t),
00245                       void *p_rng )
00246 {
00247     int ret;
00248 
00249     if( ctx == NULL )
00250         return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
00251 
00252     if( ( ret = ecdh_compute_shared( &ctx->grp , &ctx->z , &ctx->Qp , &ctx->d ,
00253                                      f_rng, p_rng ) ) != 0 )
00254     {
00255         return( ret );
00256     }
00257 
00258     if( mpi_size( &ctx->z  ) > blen )
00259         return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
00260 
00261     *olen = ctx->grp .pbits  / 8 + ( ( ctx->grp .pbits  % 8 ) != 0 );
00262     return mpi_write_binary( &ctx->z , buf, *olen );
00263 }
00264 
00265 
00266 #if defined(POLARSSL_SELF_TEST)
00267 
00268 /*
00269  * Checkup routine
00270  */
00271 int ecdh_self_test( int verbose )
00272 {
00273     ((void) verbose );
00274     return( 0 );
00275 }
00276 
00277 #endif /* POLARSSL_SELF_TEST */
00278 
00279 #endif /* POLARSSL_ECDH_C */
00280