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