mbed TLS library
Dependents: HTTPClient-SSL WS_SERVER
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
Generated on Tue Jul 12 2022 13:50:37 by 1.7.2