mbedtls ported to mbed-classic

Fork of mbedtls by Christopher Haster

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 
00039 #include <string.h>
00040 
00041 /*
00042  * Generate public key: simple wrapper around mbedtls_ecp_gen_keypair
00043  */
00044 int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q,
00045                      int (*f_rng)(void *, unsigned char *, size_t),
00046                      void *p_rng )
00047 {
00048     return mbedtls_ecp_gen_keypair( grp, d, Q, f_rng, p_rng );
00049 }
00050 
00051 /*
00052  * Compute shared secret (SEC1 3.3.1)
00053  */
00054 int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z,
00055                          const mbedtls_ecp_point *Q, const mbedtls_mpi *d,
00056                          int (*f_rng)(void *, unsigned char *, size_t),
00057                          void *p_rng )
00058 {
00059     int ret;
00060     mbedtls_ecp_point P;
00061 
00062     mbedtls_ecp_point_init( &P );
00063 
00064     /*
00065      * Make sure Q is a valid pubkey before using it
00066      */
00067     MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, Q ) );
00068 
00069     MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, &P, d, Q, f_rng, p_rng ) );
00070 
00071     if( mbedtls_ecp_is_zero( &P ) )
00072     {
00073         ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
00074         goto cleanup;
00075     }
00076 
00077     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( z, &P.X  ) );
00078 
00079 cleanup:
00080     mbedtls_ecp_point_free( &P );
00081 
00082     return( ret );
00083 }
00084 
00085 /*
00086  * Initialize context
00087  */
00088 void mbedtls_ecdh_init( mbedtls_ecdh_context *ctx )
00089 {
00090     memset( ctx, 0, sizeof( mbedtls_ecdh_context ) );
00091 }
00092 
00093 /*
00094  * Free context
00095  */
00096 void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx )
00097 {
00098     if( ctx == NULL )
00099         return;
00100 
00101     mbedtls_ecp_group_free( &ctx->grp  );
00102     mbedtls_ecp_point_free( &ctx->Q    );
00103     mbedtls_ecp_point_free( &ctx->Qp   );
00104     mbedtls_ecp_point_free( &ctx->Vi   );
00105     mbedtls_ecp_point_free( &ctx->Vf   );
00106     mbedtls_mpi_free( &ctx->d   );
00107     mbedtls_mpi_free( &ctx->z   );
00108     mbedtls_mpi_free( &ctx->_d  );
00109 }
00110 
00111 /*
00112  * Setup and write the ServerKeyExhange parameters (RFC 4492)
00113  *      struct {
00114  *          ECParameters    curve_params;
00115  *          ECPoint         public;
00116  *      } ServerECDHParams;
00117  */
00118 int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen,
00119                       unsigned char *buf, size_t blen,
00120                       int (*f_rng)(void *, unsigned char *, size_t),
00121                       void *p_rng )
00122 {
00123     int ret;
00124     size_t grp_len, pt_len;
00125 
00126     if( ctx == NULL || ctx->grp .pbits  == 0 )
00127         return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
00128 
00129     if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp , &ctx->d , &ctx->Q , f_rng, p_rng ) )
00130                 != 0 )
00131         return( ret );
00132 
00133     if( ( ret = mbedtls_ecp_tls_write_group( &ctx->grp , &grp_len, buf, blen ) )
00134                 != 0 )
00135         return( ret );
00136 
00137     buf += grp_len;
00138     blen -= grp_len;
00139 
00140     if( ( ret = mbedtls_ecp_tls_write_point( &ctx->grp , &ctx->Q , ctx->point_format ,
00141                                      &pt_len, buf, blen ) ) != 0 )
00142         return( ret );
00143 
00144     *olen = grp_len + pt_len;
00145     return( 0 );
00146 }
00147 
00148 /*
00149  * Read the ServerKeyExhange parameters (RFC 4492)
00150  *      struct {
00151  *          ECParameters    curve_params;
00152  *          ECPoint         public;
00153  *      } ServerECDHParams;
00154  */
00155 int mbedtls_ecdh_read_params( mbedtls_ecdh_context *ctx,
00156                       const unsigned char **buf, const unsigned char *end )
00157 {
00158     int ret;
00159 
00160     if( ( ret = mbedtls_ecp_tls_read_group( &ctx->grp , buf, end - *buf ) ) != 0 )
00161         return( ret );
00162 
00163     if( ( ret = mbedtls_ecp_tls_read_point( &ctx->grp , &ctx->Qp , buf, end - *buf ) )
00164                 != 0 )
00165         return( ret );
00166 
00167     return( 0 );
00168 }
00169 
00170 /*
00171  * Get parameters from a keypair
00172  */
00173 int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx, const mbedtls_ecp_keypair *key,
00174                      mbedtls_ecdh_side side )
00175 {
00176     int ret;
00177 
00178     if( ( ret = mbedtls_ecp_group_copy( &ctx->grp , &key->grp  ) ) != 0 )
00179         return( ret );
00180 
00181     /* If it's not our key, just import the public part as Qp */
00182     if( side == MBEDTLS_ECDH_THEIRS )
00183         return( mbedtls_ecp_copy( &ctx->Qp , &key->Q  ) );
00184 
00185     /* Our key: import public (as Q) and private parts */
00186     if( side != MBEDTLS_ECDH_OURS )
00187         return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
00188 
00189     if( ( ret = mbedtls_ecp_copy( &ctx->Q , &key->Q  ) ) != 0 ||
00190         ( ret = mbedtls_mpi_copy( &ctx->d , &key->d  ) ) != 0 )
00191         return( ret );
00192 
00193     return( 0 );
00194 }
00195 
00196 /*
00197  * Setup and export the client public value
00198  */
00199 int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen,
00200                       unsigned char *buf, size_t blen,
00201                       int (*f_rng)(void *, unsigned char *, size_t),
00202                       void *p_rng )
00203 {
00204     int ret;
00205 
00206     if( ctx == NULL || ctx->grp .pbits  == 0 )
00207         return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
00208 
00209     if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp , &ctx->d , &ctx->Q , f_rng, p_rng ) )
00210                 != 0 )
00211         return( ret );
00212 
00213     return mbedtls_ecp_tls_write_point( &ctx->grp , &ctx->Q , ctx->point_format ,
00214                                 olen, buf, blen );
00215 }
00216 
00217 /*
00218  * Parse and import the client's public value
00219  */
00220 int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx,
00221                       const unsigned char *buf, size_t blen )
00222 {
00223     int ret;
00224     const unsigned char *p = buf;
00225 
00226     if( ctx == NULL )
00227         return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
00228 
00229     if( ( ret = mbedtls_ecp_tls_read_point( &ctx->grp , &ctx->Qp , &p, blen ) ) != 0 )
00230         return( ret );
00231 
00232     if( (size_t)( p - buf ) != blen )
00233         return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
00234 
00235     return( 0 );
00236 }
00237 
00238 /*
00239  * Derive and export the shared secret
00240  */
00241 int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen,
00242                       unsigned char *buf, size_t blen,
00243                       int (*f_rng)(void *, unsigned char *, size_t),
00244                       void *p_rng )
00245 {
00246     int ret;
00247 
00248     if( ctx == NULL )
00249         return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
00250 
00251     if( ( ret = mbedtls_ecdh_compute_shared( &ctx->grp , &ctx->z , &ctx->Qp , &ctx->d ,
00252                                      f_rng, p_rng ) ) != 0 )
00253     {
00254         return( ret );
00255     }
00256 
00257     if( mbedtls_mpi_size( &ctx->z  ) > blen )
00258         return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
00259 
00260     *olen = ctx->grp .pbits  / 8 + ( ( ctx->grp .pbits  % 8 ) != 0 );
00261     return mbedtls_mpi_write_binary( &ctx->z , buf, *olen );
00262 }
00263 
00264 #endif /* MBEDTLS_ECDH_C */