Example program to test AES-GCM functionality. Used for a workshop

Dependencies:   mbed

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