Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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
Generated on Tue Jul 12 2022 19:40:15 by
1.7.2