mbed TLS library

Dependents:   HTTPClient-SSL WS_SERVER

Committer:
ansond
Date:
Thu Jun 11 03:27:03 2015 +0000
Revision:
0:137634ff4186
initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ansond 0:137634ff4186 1 /*
ansond 0:137634ff4186 2 * Elliptic curve Diffie-Hellman
ansond 0:137634ff4186 3 *
ansond 0:137634ff4186 4 * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
ansond 0:137634ff4186 5 *
ansond 0:137634ff4186 6 * This file is part of mbed TLS (https://tls.mbed.org)
ansond 0:137634ff4186 7 *
ansond 0:137634ff4186 8 * This program is free software; you can redistribute it and/or modify
ansond 0:137634ff4186 9 * it under the terms of the GNU General Public License as published by
ansond 0:137634ff4186 10 * the Free Software Foundation; either version 2 of the License, or
ansond 0:137634ff4186 11 * (at your option) any later version.
ansond 0:137634ff4186 12 *
ansond 0:137634ff4186 13 * This program is distributed in the hope that it will be useful,
ansond 0:137634ff4186 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
ansond 0:137634ff4186 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
ansond 0:137634ff4186 16 * GNU General Public License for more details.
ansond 0:137634ff4186 17 *
ansond 0:137634ff4186 18 * You should have received a copy of the GNU General Public License along
ansond 0:137634ff4186 19 * with this program; if not, write to the Free Software Foundation, Inc.,
ansond 0:137634ff4186 20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
ansond 0:137634ff4186 21 */
ansond 0:137634ff4186 22
ansond 0:137634ff4186 23 /*
ansond 0:137634ff4186 24 * References:
ansond 0:137634ff4186 25 *
ansond 0:137634ff4186 26 * SEC1 http://www.secg.org/index.php?action=secg,docs_secg
ansond 0:137634ff4186 27 * RFC 4492
ansond 0:137634ff4186 28 */
ansond 0:137634ff4186 29
ansond 0:137634ff4186 30 #if !defined(POLARSSL_CONFIG_FILE)
ansond 0:137634ff4186 31 #include "polarssl/config.h"
ansond 0:137634ff4186 32 #else
ansond 0:137634ff4186 33 #include POLARSSL_CONFIG_FILE
ansond 0:137634ff4186 34 #endif
ansond 0:137634ff4186 35
ansond 0:137634ff4186 36 #if defined(POLARSSL_ECDH_C)
ansond 0:137634ff4186 37
ansond 0:137634ff4186 38 #include "polarssl/ecdh.h"
ansond 0:137634ff4186 39
ansond 0:137634ff4186 40 #include <string.h>
ansond 0:137634ff4186 41
ansond 0:137634ff4186 42 /*
ansond 0:137634ff4186 43 * Generate public key: simple wrapper around ecp_gen_keypair
ansond 0:137634ff4186 44 */
ansond 0:137634ff4186 45 int ecdh_gen_public( ecp_group *grp, mpi *d, ecp_point *Q,
ansond 0:137634ff4186 46 int (*f_rng)(void *, unsigned char *, size_t),
ansond 0:137634ff4186 47 void *p_rng )
ansond 0:137634ff4186 48 {
ansond 0:137634ff4186 49 return ecp_gen_keypair( grp, d, Q, f_rng, p_rng );
ansond 0:137634ff4186 50 }
ansond 0:137634ff4186 51
ansond 0:137634ff4186 52 /*
ansond 0:137634ff4186 53 * Compute shared secret (SEC1 3.3.1)
ansond 0:137634ff4186 54 */
ansond 0:137634ff4186 55 int ecdh_compute_shared( ecp_group *grp, mpi *z,
ansond 0:137634ff4186 56 const ecp_point *Q, const mpi *d,
ansond 0:137634ff4186 57 int (*f_rng)(void *, unsigned char *, size_t),
ansond 0:137634ff4186 58 void *p_rng )
ansond 0:137634ff4186 59 {
ansond 0:137634ff4186 60 int ret;
ansond 0:137634ff4186 61 ecp_point P;
ansond 0:137634ff4186 62
ansond 0:137634ff4186 63 ecp_point_init( &P );
ansond 0:137634ff4186 64
ansond 0:137634ff4186 65 /*
ansond 0:137634ff4186 66 * Make sure Q is a valid pubkey before using it
ansond 0:137634ff4186 67 */
ansond 0:137634ff4186 68 MPI_CHK( ecp_check_pubkey( grp, Q ) );
ansond 0:137634ff4186 69
ansond 0:137634ff4186 70 MPI_CHK( ecp_mul( grp, &P, d, Q, f_rng, p_rng ) );
ansond 0:137634ff4186 71
ansond 0:137634ff4186 72 if( ecp_is_zero( &P ) )
ansond 0:137634ff4186 73 {
ansond 0:137634ff4186 74 ret = POLARSSL_ERR_ECP_BAD_INPUT_DATA;
ansond 0:137634ff4186 75 goto cleanup;
ansond 0:137634ff4186 76 }
ansond 0:137634ff4186 77
ansond 0:137634ff4186 78 MPI_CHK( mpi_copy( z, &P.X ) );
ansond 0:137634ff4186 79
ansond 0:137634ff4186 80 cleanup:
ansond 0:137634ff4186 81 ecp_point_free( &P );
ansond 0:137634ff4186 82
ansond 0:137634ff4186 83 return( ret );
ansond 0:137634ff4186 84 }
ansond 0:137634ff4186 85
ansond 0:137634ff4186 86 /*
ansond 0:137634ff4186 87 * Initialize context
ansond 0:137634ff4186 88 */
ansond 0:137634ff4186 89 void ecdh_init( ecdh_context *ctx )
ansond 0:137634ff4186 90 {
ansond 0:137634ff4186 91 memset( ctx, 0, sizeof( ecdh_context ) );
ansond 0:137634ff4186 92 }
ansond 0:137634ff4186 93
ansond 0:137634ff4186 94 /*
ansond 0:137634ff4186 95 * Free context
ansond 0:137634ff4186 96 */
ansond 0:137634ff4186 97 void ecdh_free( ecdh_context *ctx )
ansond 0:137634ff4186 98 {
ansond 0:137634ff4186 99 if( ctx == NULL )
ansond 0:137634ff4186 100 return;
ansond 0:137634ff4186 101
ansond 0:137634ff4186 102 ecp_group_free( &ctx->grp );
ansond 0:137634ff4186 103 ecp_point_free( &ctx->Q );
ansond 0:137634ff4186 104 ecp_point_free( &ctx->Qp );
ansond 0:137634ff4186 105 ecp_point_free( &ctx->Vi );
ansond 0:137634ff4186 106 ecp_point_free( &ctx->Vf );
ansond 0:137634ff4186 107 mpi_free( &ctx->d );
ansond 0:137634ff4186 108 mpi_free( &ctx->z );
ansond 0:137634ff4186 109 mpi_free( &ctx->_d );
ansond 0:137634ff4186 110 }
ansond 0:137634ff4186 111
ansond 0:137634ff4186 112 /*
ansond 0:137634ff4186 113 * Setup and write the ServerKeyExhange parameters (RFC 4492)
ansond 0:137634ff4186 114 * struct {
ansond 0:137634ff4186 115 * ECParameters curve_params;
ansond 0:137634ff4186 116 * ECPoint public;
ansond 0:137634ff4186 117 * } ServerECDHParams;
ansond 0:137634ff4186 118 */
ansond 0:137634ff4186 119 int ecdh_make_params( ecdh_context *ctx, size_t *olen,
ansond 0:137634ff4186 120 unsigned char *buf, size_t blen,
ansond 0:137634ff4186 121 int (*f_rng)(void *, unsigned char *, size_t),
ansond 0:137634ff4186 122 void *p_rng )
ansond 0:137634ff4186 123 {
ansond 0:137634ff4186 124 int ret;
ansond 0:137634ff4186 125 size_t grp_len, pt_len;
ansond 0:137634ff4186 126
ansond 0:137634ff4186 127 if( ctx == NULL || ctx->grp.pbits == 0 )
ansond 0:137634ff4186 128 return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
ansond 0:137634ff4186 129
ansond 0:137634ff4186 130 if( ( ret = ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) )
ansond 0:137634ff4186 131 != 0 )
ansond 0:137634ff4186 132 return( ret );
ansond 0:137634ff4186 133
ansond 0:137634ff4186 134 if( ( ret = ecp_tls_write_group( &ctx->grp, &grp_len, buf, blen ) )
ansond 0:137634ff4186 135 != 0 )
ansond 0:137634ff4186 136 return( ret );
ansond 0:137634ff4186 137
ansond 0:137634ff4186 138 buf += grp_len;
ansond 0:137634ff4186 139 blen -= grp_len;
ansond 0:137634ff4186 140
ansond 0:137634ff4186 141 if( ( ret = ecp_tls_write_point( &ctx->grp, &ctx->Q, ctx->point_format,
ansond 0:137634ff4186 142 &pt_len, buf, blen ) ) != 0 )
ansond 0:137634ff4186 143 return( ret );
ansond 0:137634ff4186 144
ansond 0:137634ff4186 145 *olen = grp_len + pt_len;
ansond 0:137634ff4186 146 return( 0 );
ansond 0:137634ff4186 147 }
ansond 0:137634ff4186 148
ansond 0:137634ff4186 149 /*
ansond 0:137634ff4186 150 * Read the ServerKeyExhange parameters (RFC 4492)
ansond 0:137634ff4186 151 * struct {
ansond 0:137634ff4186 152 * ECParameters curve_params;
ansond 0:137634ff4186 153 * ECPoint public;
ansond 0:137634ff4186 154 * } ServerECDHParams;
ansond 0:137634ff4186 155 */
ansond 0:137634ff4186 156 int ecdh_read_params( ecdh_context *ctx,
ansond 0:137634ff4186 157 const unsigned char **buf, const unsigned char *end )
ansond 0:137634ff4186 158 {
ansond 0:137634ff4186 159 int ret;
ansond 0:137634ff4186 160
ansond 0:137634ff4186 161 if( ( ret = ecp_tls_read_group( &ctx->grp, buf, end - *buf ) ) != 0 )
ansond 0:137634ff4186 162 return( ret );
ansond 0:137634ff4186 163
ansond 0:137634ff4186 164 if( ( ret = ecp_tls_read_point( &ctx->grp, &ctx->Qp, buf, end - *buf ) )
ansond 0:137634ff4186 165 != 0 )
ansond 0:137634ff4186 166 return( ret );
ansond 0:137634ff4186 167
ansond 0:137634ff4186 168 return( 0 );
ansond 0:137634ff4186 169 }
ansond 0:137634ff4186 170
ansond 0:137634ff4186 171 /*
ansond 0:137634ff4186 172 * Get parameters from a keypair
ansond 0:137634ff4186 173 */
ansond 0:137634ff4186 174 int ecdh_get_params( ecdh_context *ctx, const ecp_keypair *key,
ansond 0:137634ff4186 175 ecdh_side side )
ansond 0:137634ff4186 176 {
ansond 0:137634ff4186 177 int ret;
ansond 0:137634ff4186 178
ansond 0:137634ff4186 179 if( ( ret = ecp_group_copy( &ctx->grp, &key->grp ) ) != 0 )
ansond 0:137634ff4186 180 return( ret );
ansond 0:137634ff4186 181
ansond 0:137634ff4186 182 /* If it's not our key, just import the public part as Qp */
ansond 0:137634ff4186 183 if( side == POLARSSL_ECDH_THEIRS )
ansond 0:137634ff4186 184 return( ecp_copy( &ctx->Qp, &key->Q ) );
ansond 0:137634ff4186 185
ansond 0:137634ff4186 186 /* Our key: import public (as Q) and private parts */
ansond 0:137634ff4186 187 if( side != POLARSSL_ECDH_OURS )
ansond 0:137634ff4186 188 return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
ansond 0:137634ff4186 189
ansond 0:137634ff4186 190 if( ( ret = ecp_copy( &ctx->Q, &key->Q ) ) != 0 ||
ansond 0:137634ff4186 191 ( ret = mpi_copy( &ctx->d, &key->d ) ) != 0 )
ansond 0:137634ff4186 192 return( ret );
ansond 0:137634ff4186 193
ansond 0:137634ff4186 194 return( 0 );
ansond 0:137634ff4186 195 }
ansond 0:137634ff4186 196
ansond 0:137634ff4186 197 /*
ansond 0:137634ff4186 198 * Setup and export the client public value
ansond 0:137634ff4186 199 */
ansond 0:137634ff4186 200 int ecdh_make_public( ecdh_context *ctx, size_t *olen,
ansond 0:137634ff4186 201 unsigned char *buf, size_t blen,
ansond 0:137634ff4186 202 int (*f_rng)(void *, unsigned char *, size_t),
ansond 0:137634ff4186 203 void *p_rng )
ansond 0:137634ff4186 204 {
ansond 0:137634ff4186 205 int ret;
ansond 0:137634ff4186 206
ansond 0:137634ff4186 207 if( ctx == NULL || ctx->grp.pbits == 0 )
ansond 0:137634ff4186 208 return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
ansond 0:137634ff4186 209
ansond 0:137634ff4186 210 if( ( ret = ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) )
ansond 0:137634ff4186 211 != 0 )
ansond 0:137634ff4186 212 return( ret );
ansond 0:137634ff4186 213
ansond 0:137634ff4186 214 return ecp_tls_write_point( &ctx->grp, &ctx->Q, ctx->point_format,
ansond 0:137634ff4186 215 olen, buf, blen );
ansond 0:137634ff4186 216 }
ansond 0:137634ff4186 217
ansond 0:137634ff4186 218 /*
ansond 0:137634ff4186 219 * Parse and import the client's public value
ansond 0:137634ff4186 220 */
ansond 0:137634ff4186 221 int ecdh_read_public( ecdh_context *ctx,
ansond 0:137634ff4186 222 const unsigned char *buf, size_t blen )
ansond 0:137634ff4186 223 {
ansond 0:137634ff4186 224 int ret;
ansond 0:137634ff4186 225 const unsigned char *p = buf;
ansond 0:137634ff4186 226
ansond 0:137634ff4186 227 if( ctx == NULL )
ansond 0:137634ff4186 228 return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
ansond 0:137634ff4186 229
ansond 0:137634ff4186 230 if( ( ret = ecp_tls_read_point( &ctx->grp, &ctx->Qp, &p, blen ) ) != 0 )
ansond 0:137634ff4186 231 return( ret );
ansond 0:137634ff4186 232
ansond 0:137634ff4186 233 if( (size_t)( p - buf ) != blen )
ansond 0:137634ff4186 234 return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
ansond 0:137634ff4186 235
ansond 0:137634ff4186 236 return( 0 );
ansond 0:137634ff4186 237 }
ansond 0:137634ff4186 238
ansond 0:137634ff4186 239 /*
ansond 0:137634ff4186 240 * Derive and export the shared secret
ansond 0:137634ff4186 241 */
ansond 0:137634ff4186 242 int ecdh_calc_secret( ecdh_context *ctx, size_t *olen,
ansond 0:137634ff4186 243 unsigned char *buf, size_t blen,
ansond 0:137634ff4186 244 int (*f_rng)(void *, unsigned char *, size_t),
ansond 0:137634ff4186 245 void *p_rng )
ansond 0:137634ff4186 246 {
ansond 0:137634ff4186 247 int ret;
ansond 0:137634ff4186 248
ansond 0:137634ff4186 249 if( ctx == NULL )
ansond 0:137634ff4186 250 return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
ansond 0:137634ff4186 251
ansond 0:137634ff4186 252 if( ( ret = ecdh_compute_shared( &ctx->grp, &ctx->z, &ctx->Qp, &ctx->d,
ansond 0:137634ff4186 253 f_rng, p_rng ) ) != 0 )
ansond 0:137634ff4186 254 {
ansond 0:137634ff4186 255 return( ret );
ansond 0:137634ff4186 256 }
ansond 0:137634ff4186 257
ansond 0:137634ff4186 258 if( mpi_size( &ctx->z ) > blen )
ansond 0:137634ff4186 259 return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
ansond 0:137634ff4186 260
ansond 0:137634ff4186 261 *olen = ctx->grp.pbits / 8 + ( ( ctx->grp.pbits % 8 ) != 0 );
ansond 0:137634ff4186 262 return mpi_write_binary( &ctx->z, buf, *olen );
ansond 0:137634ff4186 263 }
ansond 0:137634ff4186 264
ansond 0:137634ff4186 265
ansond 0:137634ff4186 266 #if defined(POLARSSL_SELF_TEST)
ansond 0:137634ff4186 267
ansond 0:137634ff4186 268 /*
ansond 0:137634ff4186 269 * Checkup routine
ansond 0:137634ff4186 270 */
ansond 0:137634ff4186 271 int ecdh_self_test( int verbose )
ansond 0:137634ff4186 272 {
ansond 0:137634ff4186 273 ((void) verbose );
ansond 0:137634ff4186 274 return( 0 );
ansond 0:137634ff4186 275 }
ansond 0:137634ff4186 276
ansond 0:137634ff4186 277 #endif /* POLARSSL_SELF_TEST */
ansond 0:137634ff4186 278
ansond 0:137634ff4186 279 #endif /* POLARSSL_ECDH_C */
ansond 0:137634ff4186 280