blob: a12bac05c0ca6fe477745d4122fb4d13455b796d [file] [log] [blame]
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001/*
2 * Elliptic curve J-PAKE
3 *
4 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 * This file is part of mbed TLS (https://tls.mbed.org)
20 */
21
22/*
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +020023 * We implement EC-JPAKE as defined in Chapter 7.4 of the Thread v1.0
24 * Specification. References below are to this document.
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +020025 */
26
27#if !defined(MBEDTLS_CONFIG_FILE)
28#include "mbedtls/config.h"
29#else
30#include MBEDTLS_CONFIG_FILE
31#endif
32
33#if defined(MBEDTLS_ECJPAKE_C)
34
35#include "mbedtls/ecjpake.h"
36
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +020037#include <string.h>
38
39/*
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020040 * Initialize context
41 */
42void mbedtls_ecjpake_init( mbedtls_ecjpake_context *ctx )
43{
44 if( ctx == NULL )
45 return;
46
47 ctx->md_info = NULL;
48 mbedtls_ecp_group_init( &ctx->grp );
49
50 mbedtls_ecp_point_init( &ctx->X1 );
51 mbedtls_ecp_point_init( &ctx->X2 );
52 mbedtls_ecp_point_init( &ctx->X3 );
53 mbedtls_ecp_point_init( &ctx->X4 );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +020054 mbedtls_ecp_point_init( &ctx->Xp );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020055
56 mbedtls_mpi_init( &ctx->xa );
57 mbedtls_mpi_init( &ctx->xb );
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +020058 mbedtls_mpi_init( &ctx->s );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020059}
60
61/*
62 * Free context
63 */
64void mbedtls_ecjpake_free( mbedtls_ecjpake_context *ctx )
65{
66 if( ctx == NULL )
67 return;
68
69 ctx->md_info = NULL;
70 mbedtls_ecp_group_free( &ctx->grp );
71
72 mbedtls_ecp_point_free( &ctx->X1 );
73 mbedtls_ecp_point_free( &ctx->X2 );
74 mbedtls_ecp_point_free( &ctx->X3 );
75 mbedtls_ecp_point_free( &ctx->X4 );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +020076 mbedtls_ecp_point_free( &ctx->Xp );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020077
78 mbedtls_mpi_free( &ctx->xa );
79 mbedtls_mpi_free( &ctx->xb );
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +020080 mbedtls_mpi_free( &ctx->s );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020081}
82
83/*
84 * Setup context
85 */
86int mbedtls_ecjpake_setup( mbedtls_ecjpake_context *ctx,
87 mbedtls_md_type_t hash,
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +020088 mbedtls_ecp_group_id curve,
89 const unsigned char *secret,
90 size_t len )
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020091{
92 int ret;
93
94 if( ( ctx->md_info = mbedtls_md_info_from_type( hash ) ) == NULL )
95 return( MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE );
96
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +020097 MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ctx->grp, curve ) );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020098
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +020099 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->s, secret, len ) );
100 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->s, &ctx->s, &ctx->grp.N ) );
101
102cleanup:
103 if( ret != 0 )
104 mbedtls_ecjpake_free( ctx );
105
106 return( ret );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200107}
108
109/*
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200110 * Write a point plus its length to a buffer
111 */
112static int ecjpake_write_len_point( unsigned char **p,
113 const unsigned char *end,
114 const mbedtls_ecp_group *grp,
115 const mbedtls_ecp_point *P )
116{
117 int ret;
118 size_t len;
119
120 /* Need at least 4 for length plus 1 for point */
121 if( end < *p || end - *p < 5 )
122 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
123
124 ret = mbedtls_ecp_point_write_binary( grp, P, MBEDTLS_ECP_PF_UNCOMPRESSED,
125 &len, *p + 4, end - ( *p + 4 ) );
126 if( ret != 0 )
127 return( ret );
128
129 (*p)[0] = (unsigned char)( ( len >> 24 ) & 0xFF );
130 (*p)[1] = (unsigned char)( ( len >> 16 ) & 0xFF );
131 (*p)[2] = (unsigned char)( ( len >> 8 ) & 0xFF );
132 (*p)[3] = (unsigned char)( ( len ) & 0xFF );
133
134 *p += 4 + len;
135
136 return( 0 );
137}
138
139/*
140 * Size of the temporary buffer for ecjpake_hash:
141 * 3 EC points plus their length, plus ID (6 bytes)
142 */
143#define ECJPAKE_HASH_BUF_LEN ( 3 * ( 4 + MBEDTLS_ECP_MAX_PT_LEN ) + 6 )
144
145/*
146 * Compute hash for ZKP (7.4.2.2.2.1)
147 */
148static int ecjpake_hash( const mbedtls_md_info_t *md_info,
149 const mbedtls_ecp_group *grp,
150 const mbedtls_ecp_point *G,
151 const mbedtls_ecp_point *V,
152 const mbedtls_ecp_point *X,
153 const char *id,
154 mbedtls_mpi *h )
155{
156 int ret;
157 unsigned char buf[ECJPAKE_HASH_BUF_LEN];
158 unsigned char *p = buf;
159 const unsigned char *end = buf + sizeof( buf );
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200160 const size_t id_len = strlen( id );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200161 unsigned char hash[MBEDTLS_MD_MAX_SIZE];
162
163 /* Write things to temporary buffer */
164 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, G ) );
165 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, V ) );
166 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, X ) );
167
168 if( end < p || (size_t)( end - p ) < id_len )
169 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
170
171 *p++ = (unsigned char)( ( id_len >> 24 ) & 0xFF );
172 *p++ = (unsigned char)( ( id_len >> 16 ) & 0xFF );
173 *p++ = (unsigned char)( ( id_len >> 8 ) & 0xFF );
174 *p++ = (unsigned char)( ( id_len ) & 0xFF );
175
176 memcpy( p, id, id_len );
177 p += id_len;
178
179 /* Compute hash */
180 mbedtls_md( md_info, buf, p - buf, hash );
181
182 /* Turn it into an integer mod n */
183 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( h, hash,
184 mbedtls_md_get_size( md_info ) ) );
185 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( h, h, &grp->N ) );
186
187cleanup:
188 return( ret );
189}
190
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200191/*
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200192 * Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3)
193 */
194static int ecjpake_zkp_read( const mbedtls_md_info_t *md_info,
195 const mbedtls_ecp_group *grp,
196 const mbedtls_ecp_point *G,
197 const mbedtls_ecp_point *X,
198 const char *id,
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200199 const unsigned char **p,
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200200 const unsigned char *end )
201{
202 int ret;
203 mbedtls_ecp_point V, VV;
204 mbedtls_mpi r, h;
205 size_t r_len;
206
207 mbedtls_ecp_point_init( &V );
208 mbedtls_ecp_point_init( &VV );
209 mbedtls_mpi_init( &r );
210 mbedtls_mpi_init( &h );
211
212 /*
213 * struct {
214 * ECPoint V;
215 * opaque r<1..2^8-1>;
216 * } ECSchnorrZKP;
217 */
218 if( end < *p )
219 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
220
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200221 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, &V, p, end - *p ) );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200222
223 if( end < *p || (size_t)( end - *p ) < 1 )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200224 {
225 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
226 goto cleanup;
227 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200228
229 r_len = *(*p)++;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200230
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200231 if( end < *p || (size_t)( end - *p ) < r_len )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200232 {
233 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
234 goto cleanup;
235 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200236
237 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &r, *p, r_len ) );
238 *p += r_len;
239
240 /*
241 * Verification
242 */
243 MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, G, &V, X, id, &h ) );
244 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( (mbedtls_ecp_group *) grp,
245 &VV, &h, X, &r, G ) );
246
247 if( mbedtls_ecp_point_cmp( &VV, &V ) != 0 )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200248 {
249 ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
250 goto cleanup;
251 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200252
253cleanup:
254 mbedtls_ecp_point_free( &V );
255 mbedtls_ecp_point_free( &VV );
256 mbedtls_mpi_free( &r );
257 mbedtls_mpi_free( &h );
258
259 return( ret );
260}
261
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200262/*
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200263 * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2)
264 */
265static int ecjpake_zkp_write( const mbedtls_md_info_t *md_info,
266 const mbedtls_ecp_group *grp,
267 const mbedtls_ecp_point *G,
268 const mbedtls_mpi *x,
269 const mbedtls_ecp_point *X,
270 const char *id,
271 unsigned char **p,
272 const unsigned char *end,
273 int (*f_rng)(void *, unsigned char *, size_t),
274 void *p_rng )
275{
276 int ret;
277 mbedtls_ecp_point V;
278 mbedtls_mpi v;
279 mbedtls_mpi h; /* later recycled to hold r */
280 size_t len;
281
282 if( end < *p )
283 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
284
285 mbedtls_ecp_point_init( &V );
286 mbedtls_mpi_init( &v );
287 mbedtls_mpi_init( &h );
288
289 /* Compute signature */
290 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp,
291 G, &v, &V, f_rng, p_rng ) );
292 MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, G, &V, X, id, &h ) );
293 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &h, &h, x ) ); /* x*h */
294 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &h, &v, &h ) ); /* v - x*h */
295 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &h, &h, &grp->N ) ); /* r */
296
297 /* Write it out */
298 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, &V,
299 MBEDTLS_ECP_PF_UNCOMPRESSED, &len, *p, end - *p ) );
300 *p += len;
301
302 len = mbedtls_mpi_size( &h ); /* actually r */
303 if( end < *p || (size_t)( end - *p ) < 1 + len || len > 255 )
304 {
305 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
306 goto cleanup;
307 }
308
309 *(*p)++ = (unsigned char)( len & 0xFF );
310 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, *p, len ) ); /* r */
311 *p += len;
312
313cleanup:
314 mbedtls_ecp_point_free( &V );
315 mbedtls_mpi_free( &v );
316 mbedtls_mpi_free( &h );
317
318 return( ret );
319}
320
321/*
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200322 * Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof
323 * Output: verified public key X
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200324 */
325static int ecjpake_kkp_read( const mbedtls_md_info_t *md_info,
326 const mbedtls_ecp_group *grp,
327 const mbedtls_ecp_point *G,
328 mbedtls_ecp_point *X,
329 const char *id,
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200330 const unsigned char **p,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200331 const unsigned char *end )
332{
333 int ret;
334
335 if( end < *p )
336 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
337
338 /*
339 * struct {
340 * ECPoint X;
341 * ECSchnorrZKP zkp;
342 * } ECJPAKEKeyKP;
343 */
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200344 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, X, p, end - *p ) );
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200345 MBEDTLS_MPI_CHK( ecjpake_zkp_read( md_info, grp, G, X, id, p, end ) );
346
347cleanup:
348 return( ret );
349}
350
351/*
352 * Generate an ECJPAKEKeyKP
353 * Output: the serialized structure, plus private/public key pair
354 */
355static int ecjpake_kkp_write( const mbedtls_md_info_t *md_info,
356 const mbedtls_ecp_group *grp,
357 const mbedtls_ecp_point *G,
358 mbedtls_mpi *x,
359 mbedtls_ecp_point *X,
360 const char *id,
361 unsigned char **p,
362 const unsigned char *end,
363 int (*f_rng)(void *, unsigned char *, size_t),
364 void *p_rng )
365{
366 int ret;
367 size_t len;
368
369 if( end < *p )
370 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
371
372 /* Generate key (7.4.2.3.1) and write it out */
373 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp, G, x, X,
374 f_rng, p_rng ) );
375 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, X,
376 MBEDTLS_ECP_PF_UNCOMPRESSED, &len, *p, end - *p ) );
377 *p += len;
378
379 /* Generate and write proof */
380 MBEDTLS_MPI_CHK( ecjpake_zkp_write( md_info, grp, G, x, X, id,
381 p, end, f_rng, p_rng ) );
382
383cleanup:
384 return( ret );
385}
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200386
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200387/*
388 * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs
389 * Ouputs: verified peer public keys Xa, Xb
390 */
391static int ecjpake_kkpp_read( const mbedtls_md_info_t *md_info,
392 const mbedtls_ecp_group *grp,
393 const mbedtls_ecp_point *G,
394 mbedtls_ecp_point *Xa,
395 mbedtls_ecp_point *Xb,
396 const char *id,
397 const unsigned char *buf,
398 size_t len )
399{
400 int ret;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200401 const unsigned char *p = buf;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200402 const unsigned char *end = buf + len;
403
404 /*
405 * struct {
406 * ECJPAKEKeyKP ecjpake_key_kp_pair_list[2];
407 * } ECJPAKEKeyKPPairList;
408 */
409 MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, G, Xa, id, &p, end ) );
410 MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, G, Xb, id, &p, end ) );
411
412 if( p != end )
413 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
414
415cleanup:
416 return( ret );
417}
418
419/*
420 * Generate a ECJPAKEKeyKPPairList
421 * Outputs: the serialized structure, plus two private/public key pairs
422 */
423static int ecjpake_kkpp_write( const mbedtls_md_info_t *md_info,
424 const mbedtls_ecp_group *grp,
425 const mbedtls_ecp_point *G,
426 mbedtls_mpi *xa,
427 mbedtls_ecp_point *Xa,
428 mbedtls_mpi *xb,
429 mbedtls_ecp_point *Xb,
430 const char *id,
431 unsigned char *buf,
432 size_t len,
433 size_t *olen,
434 int (*f_rng)(void *, unsigned char *, size_t),
435 void *p_rng )
436{
437 int ret;
438 unsigned char *p = buf;
439 const unsigned char *end = buf + len;
440
441 MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, G, xa, Xa, id,
442 &p, end, f_rng, p_rng ) );
443 MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, G, xb, Xb, id,
444 &p, end, f_rng, p_rng ) );
445
446 *olen = p - buf;
447
448cleanup:
449 return( ret );
450}
451
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200452/*
453 * Read the contents of the ClientHello extension
454 */
455int mbedtls_ecjpake_tls_read_client_ext( mbedtls_ecjpake_context *ctx,
456 const unsigned char *buf,
457 size_t len )
458{
459 return( ecjpake_kkpp_read( ctx->md_info, &ctx->grp, &ctx->grp.G,
460 &ctx->X1, &ctx->X2, "client",
461 buf, len ) );
462}
463
464/*
465 * Read the contents of the ServerHello extension
466 */
467int mbedtls_ecjpake_tls_read_server_ext( mbedtls_ecjpake_context *ctx,
468 const unsigned char *buf,
469 size_t len )
470{
471 return( ecjpake_kkpp_read( ctx->md_info, &ctx->grp, &ctx->grp.G,
472 &ctx->X3, &ctx->X4, "server",
473 buf, len ) );
474}
475
476/*
477 * Generate the contents of the ClientHello extension
478 */
479int mbedtls_ecjpake_tls_write_client_ext( mbedtls_ecjpake_context *ctx,
480 unsigned char *buf, size_t len, size_t *olen,
481 int (*f_rng)(void *, unsigned char *, size_t),
482 void *p_rng )
483{
484 return( ecjpake_kkpp_write( ctx->md_info, &ctx->grp, &ctx->grp.G,
485 &ctx->xa, &ctx->X1, &ctx->xb, &ctx->X2,
486 "client", buf, len, olen, f_rng, p_rng ) );
487}
488
489/*
490 * Generate the contents of the ServerHello extension
491 */
492int mbedtls_ecjpake_tls_write_server_ext( mbedtls_ecjpake_context *ctx,
493 unsigned char *buf, size_t len, size_t *olen,
494 int (*f_rng)(void *, unsigned char *, size_t),
495 void *p_rng )
496{
497 return( ecjpake_kkpp_write( ctx->md_info, &ctx->grp, &ctx->grp.G,
498 &ctx->xa, &ctx->X3, &ctx->xb, &ctx->X4,
499 "server", buf, len, olen, f_rng, p_rng ) );
500}
501
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200502/*
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200503 * Compute the sum of three points R = A + B + C
504 */
505static int ecjpake_ecp_add3( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
506 const mbedtls_ecp_point *A,
507 const mbedtls_ecp_point *B,
508 const mbedtls_ecp_point *C )
509{
510 int ret;
511 mbedtls_mpi one;
512
513 mbedtls_mpi_init( &one );
514
515 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
516 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, A, &one, B ) );
517 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, R, &one, C ) );
518
519cleanup:
520 mbedtls_mpi_free( &one );
521
522 return( ret );
523}
524
525/*
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200526 * Read and process ServerECJPAKEParams (7.4.2.5)
527 */
528int mbedtls_ecjpake_tls_read_server_params( mbedtls_ecjpake_context *ctx,
529 const unsigned char *buf,
530 size_t len )
531{
532 int ret;
533 const unsigned char *p = buf;
534 const unsigned char *end = buf + len;
535 mbedtls_ecp_group grp;
536 mbedtls_ecp_point GB;
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200537
538 mbedtls_ecp_group_init( &grp );
539 mbedtls_ecp_point_init( &GB );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200540
541 /*
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200542 * GB = X1 + X2 + X3 (7.4.2.5.1)
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200543 * We need that before parsing in order to check Xs as we read it
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200544 */
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200545 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &GB,
546 &ctx->X1, &ctx->X2, &ctx->X3 ) );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200547
548 /*
549 * struct {
550 * ECParameters curve_params;
551 * ECJPAKEKeyKP ecjpake_key_kp;
552 * } ServerECJPAKEParams;
553 */
554 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_group( &grp, &p, len ) );
555 MBEDTLS_MPI_CHK( ecjpake_kkp_read( ctx->md_info, &ctx->grp,
556 &GB, &ctx->Xp, "server", &p, end ) );
557
558 if( p != end )
559 {
560 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
561 goto cleanup;
562 }
563
564 /*
565 * Xs already checked, only thing left to check is the group
566 */
567 if( grp.id != ctx->grp.id )
568 {
569 ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
570 goto cleanup;
571 }
572
573cleanup:
574 mbedtls_ecp_group_free( &grp );
575 mbedtls_ecp_point_free( &GB );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200576
577 return( ret );
578}
579
580/*
581 * Generate and write ServerECJPAKEParams (7.4.2.5)
582 */
583int mbedtls_ecjpake_tls_write_server_params( mbedtls_ecjpake_context *ctx,
584 unsigned char *buf, size_t len, size_t *olen,
585 int (*f_rng)(void *, unsigned char *, size_t),
586 void *p_rng )
587{
588 int ret;
589 mbedtls_ecp_point GB, Xs;
590 mbedtls_mpi xs;
591 unsigned char *p = buf;
592 const unsigned char *end = buf + len;
593 size_t ec_len;
594
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +0200595 if( end < p )
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200596 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
597
598 mbedtls_ecp_point_init( &GB );
599 mbedtls_ecp_point_init( &Xs );
600 mbedtls_mpi_init( &xs );
601
602 /*
603 * First generate private/public key pair (7.4.2.5.1)
604 *
605 * GB = X1 + X2 + X3
606 * xs = x4 * s mod n
607 * Xs = xs * GB
608 */
609 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &GB,
610 &ctx->X1, &ctx->X2, &ctx->X3 ) );
611 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &xs, &ctx->xb, &ctx->s ) );
612 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &xs, &xs, &ctx->grp.N ) );
613 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &Xs, &xs, &GB, f_rng, p_rng ) );
614
615 /*
616 * Now write things out
617 */
618 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_group( &ctx->grp, &ec_len,
619 p, end - p ) );
620 p += ec_len;
621
622 if( end < p )
623 {
624 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
625 goto cleanup;
626 }
627 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( &ctx->grp, &Xs,
628 MBEDTLS_ECP_PF_UNCOMPRESSED, &ec_len, p, end - p ) );
629 p += ec_len;
630
631 MBEDTLS_MPI_CHK( ecjpake_zkp_write( ctx->md_info, &ctx->grp,
632 &GB, &xs, &Xs, "server",
633 &p, end, f_rng, p_rng ) );
634
635 *olen = p - buf;
636
637cleanup:
638 mbedtls_ecp_point_free( &GB );
639 mbedtls_ecp_point_free( &Xs );
640 mbedtls_mpi_free( &xs );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200641
642 return( ret );
643}
644
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +0200645/*
646 * Read and process ClientECJPAKEParams (7.4.2.6)
647 */
648int mbedtls_ecjpake_tls_read_client_params( mbedtls_ecjpake_context *ctx,
649 const unsigned char *buf,
650 size_t len )
651{
652 int ret;
653 const unsigned char *p = buf;
654 const unsigned char *end = buf + len;
655 mbedtls_ecp_group grp;
656 mbedtls_ecp_point GA;
657
658 mbedtls_ecp_group_init( &grp );
659 mbedtls_ecp_point_init( &GA );
660
661 /*
662 * GA = X1 + X3 + X4 (7.4.2.6.1)
663 * We need that before parsing in order to check Xc as we read it
664 */
665 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &GA,
666 &ctx->X1, &ctx->X3, &ctx->X4 ) );
667
668 /*
669 * struct {
670 * ECJPAKEKeyKP ecjpake_key_kp;
671 * } CLientECJPAKEParams;
672 */
673 MBEDTLS_MPI_CHK( ecjpake_kkp_read( ctx->md_info, &ctx->grp,
674 &GA, &ctx->Xp, "client", &p, end ) );
675
676 if( p != end )
677 {
678 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
679 goto cleanup;
680 }
681
682cleanup:
683 mbedtls_ecp_group_free( &grp );
684 mbedtls_ecp_point_free( &GA );
685
686 return( ret );
687}
688
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200689#if defined(MBEDTLS_SELF_TEST)
690
691#if defined(MBEDTLS_PLATFORM_C)
692#include "mbedtls/platform.h"
693#else
694#include <stdio.h>
695#define mbedtls_printf printf
696#endif
697
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200698#if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
699 !defined(MBEDTLS_SHA256_C)
700int mbedtls_ecjpake_self_test( int verbose )
701{
702 (void) verbose;
703 return( 0 );
704}
705#else
706
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200707static const unsigned char ecjpake_test_password[] = {
708 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x6a, 0x70, 0x61, 0x6b, 0x65, 0x74,
709 0x65, 0x73, 0x74
710};
711
712static const unsigned char ecjpake_test_x1[] = {
713 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
714 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
715 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21
716};
717
718static const unsigned char ecjpake_test_x2[] = {
719 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
720 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
721 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
722};
723
724static const unsigned char ecjpake_test_x3[] = {
725 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
726 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
727 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
728};
729
730static const unsigned char ecjpake_test_x4[] = {
731 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc,
732 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
733 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1
734};
735
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200736static const unsigned char ecjpake_test_cli_ext[] = {
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200737 0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19,
738 0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44,
739 0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad,
740 0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62,
741 0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9,
742 0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d,
743 0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e,
744 0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e,
745 0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73,
746 0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22,
747 0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce,
748 0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00,
749 0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200750 0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e,
751 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62,
752 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5,
753 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb,
754 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35,
755 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0,
756 0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb,
757 0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47,
758 0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39,
759 0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97,
760 0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40,
761 0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d,
762 0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa,
763 0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d,
764 0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200765};
766
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200767static const unsigned char ecjpake_test_srv_ext[] = {
768 0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb,
769 0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18,
770 0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47,
771 0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f,
772 0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7,
773 0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d,
774 0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64,
775 0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36,
776 0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2,
777 0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec,
778 0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16,
779 0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96,
780 0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3,
781 0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19,
782 0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f,
783 0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8,
784 0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7,
785 0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea,
786 0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5,
787 0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6,
788 0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31,
789 0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d,
790 0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8,
791 0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee,
792 0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84,
793 0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f,
794 0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80,
795 0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12
796};
797
798static const unsigned char ecjpake_test_srv_kx[] = {
799 0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23,
800 0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c,
801 0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f,
802 0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca,
803 0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26,
804 0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55,
805 0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38,
806 0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6,
807 0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9,
808 0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4,
809 0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2,
810 0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8,
811 0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd,
812 0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c
813};
814
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +0200815static const unsigned char ecjpake_test_cli_kx[] = {
816 0x41, 0x04, 0x69, 0xd5, 0x4e, 0xe8, 0x5e, 0x90, 0xce, 0x3f, 0x12, 0x46,
817 0x74, 0x2d, 0xe5, 0x07, 0xe9, 0x39, 0xe8, 0x1d, 0x1d, 0xc1, 0xc5, 0xcb,
818 0x98, 0x8b, 0x58, 0xc3, 0x10, 0xc9, 0xfd, 0xd9, 0x52, 0x4d, 0x93, 0x72,
819 0x0b, 0x45, 0x54, 0x1c, 0x83, 0xee, 0x88, 0x41, 0x19, 0x1d, 0xa7, 0xce,
820 0xd8, 0x6e, 0x33, 0x12, 0xd4, 0x36, 0x23, 0xc1, 0xd6, 0x3e, 0x74, 0x98,
821 0x9a, 0xba, 0x4a, 0xff, 0xd1, 0xee, 0x41, 0x04, 0x07, 0x7e, 0x8c, 0x31,
822 0xe2, 0x0e, 0x6b, 0xed, 0xb7, 0x60, 0xc1, 0x35, 0x93, 0xe6, 0x9f, 0x15,
823 0xbe, 0x85, 0xc2, 0x7d, 0x68, 0xcd, 0x09, 0xcc, 0xb8, 0xc4, 0x18, 0x36,
824 0x08, 0x91, 0x7c, 0x5c, 0x3d, 0x40, 0x9f, 0xac, 0x39, 0xfe, 0xfe, 0xe8,
825 0x2f, 0x72, 0x92, 0xd3, 0x6f, 0x0d, 0x23, 0xe0, 0x55, 0x91, 0x3f, 0x45,
826 0xa5, 0x2b, 0x85, 0xdd, 0x8a, 0x20, 0x52, 0xe9, 0xe1, 0x29, 0xbb, 0x4d,
827 0x20, 0x0f, 0x01, 0x1f, 0x19, 0x48, 0x35, 0x35, 0xa6, 0xe8, 0x9a, 0x58,
828 0x0c, 0x9b, 0x00, 0x03, 0xba, 0xf2, 0x14, 0x62, 0xec, 0xe9, 0x1a, 0x82,
829 0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c
830};
831
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200832/* For tests we don't need a secure RNG;
833 * use the LGC from Numerical Recipes for simplicity */
834static int ecjpake_lgc( void *p, unsigned char *out, size_t len )
835{
836 static uint32_t x = 42;
837 (void) p;
838
839 while( len > 0 )
840 {
841 size_t use_len = len > 4 ? 4 : len;
842 x = 1664525 * x + 1013904223;
843 memcpy( out, &x, use_len );
844 out += use_len;
845 len -= use_len;
846 }
847
848 return( 0 );
849}
850
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200851#define TEST_ASSERT( x ) \
852 do { \
853 if( x ) \
854 ret = 0; \
855 else \
856 { \
857 ret = 1; \
858 goto cleanup; \
859 } \
860 } while( 0 )
861
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200862/*
863 * Checkup routine
864 */
865int mbedtls_ecjpake_self_test( int verbose )
866{
867 int ret;
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200868 mbedtls_ecjpake_context cli;
869 mbedtls_ecjpake_context srv;
870 unsigned char buf[512];
871 size_t len;
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200872
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200873 mbedtls_ecjpake_init( &cli );
874 mbedtls_ecjpake_init( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200875
876 if( verbose != 0 )
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200877 mbedtls_printf( " ECJPAKE test #0 (setup): " );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200878
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200879 TEST_ASSERT( mbedtls_ecjpake_setup( &cli,
880 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
881 ecjpake_test_password,
882 sizeof( ecjpake_test_password ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200883
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200884 TEST_ASSERT( mbedtls_ecjpake_setup( &srv,
885 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
886 ecjpake_test_password,
887 sizeof( ecjpake_test_password ) ) == 0 );
888
889 if( verbose != 0 )
890 mbedtls_printf( "passed\n" );
891
892 if( verbose != 0 )
893 mbedtls_printf( " ECJPAKE test #1 (random handshake): " );
894
895 TEST_ASSERT( mbedtls_ecjpake_tls_write_client_ext( &cli,
896 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
897
898 TEST_ASSERT( mbedtls_ecjpake_tls_read_client_ext( &srv, buf, len ) == 0 );
899
900 TEST_ASSERT( mbedtls_ecjpake_tls_write_server_ext( &srv,
901 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
902
903 TEST_ASSERT( mbedtls_ecjpake_tls_read_server_ext( &cli, buf, len ) == 0 );
904
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200905 TEST_ASSERT( mbedtls_ecjpake_tls_write_server_params( &srv,
906 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
907
908 TEST_ASSERT( mbedtls_ecjpake_tls_read_server_params( &cli, buf, len ) == 0 );
909
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200910 if( verbose != 0 )
911 mbedtls_printf( "passed\n" );
912
913 if( verbose != 0 )
914 mbedtls_printf( " ECJPAKE test #2 (reference handshake): " );
915
916 /* Simulate key generation on client, skip writing client_ext */
917 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &cli.xa,
918 ecjpake_test_x1, sizeof( ecjpake_test_x1 ) ) );
919 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &cli.xb,
920 ecjpake_test_x2, sizeof( ecjpake_test_x2 ) ) );
921 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &cli.grp, &cli.X1, &cli.xa,
922 &cli.grp.G, NULL, NULL ) );
923 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &cli.grp, &cli.X2, &cli.xb,
924 &cli.grp.G, NULL, NULL ) );
925
926 /* Server reads client ext */
927 TEST_ASSERT( mbedtls_ecjpake_tls_read_client_ext( &srv,
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200928 ecjpake_test_cli_ext,
929 sizeof( ecjpake_test_cli_ext ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200930
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200931 /* Simulate key generation on server, skip writing server_ext */
932 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &srv.xa,
933 ecjpake_test_x3, sizeof( ecjpake_test_x3 ) ) );
934 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &srv.xb,
935 ecjpake_test_x4, sizeof( ecjpake_test_x4 ) ) );
936 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &srv.grp, &srv.X3, &srv.xa,
937 &srv.grp.G, NULL, NULL ) );
938 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &srv.grp, &srv.X4, &srv.xb,
939 &srv.grp.G, NULL, NULL ) );
940
941 /* Client reads server ext and key exchange */
942 TEST_ASSERT( mbedtls_ecjpake_tls_read_server_ext( &cli,
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200943 ecjpake_test_srv_ext,
944 sizeof( ecjpake_test_srv_ext ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200945
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200946 TEST_ASSERT( mbedtls_ecjpake_tls_read_server_params( &cli,
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200947 ecjpake_test_srv_kx,
948 sizeof( ecjpake_test_srv_kx ) ) == 0 );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200949
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +0200950 /* Server reads client key exchange */
951 TEST_ASSERT( mbedtls_ecjpake_tls_read_client_params( &srv,
952 ecjpake_test_cli_kx,
953 sizeof( ecjpake_test_cli_kx ) ) == 0 );
954
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200955 if( verbose != 0 )
956 mbedtls_printf( "passed\n" );
957
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200958cleanup:
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200959 mbedtls_ecjpake_free( &cli );
960 mbedtls_ecjpake_free( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200961
962 if( ret != 0 )
963 {
964 if( verbose != 0 )
965 mbedtls_printf( "failed\n" );
966
967 ret = 1;
968 }
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200969
970 if( verbose != 0 )
971 mbedtls_printf( "\n" );
972
973 return( ret );
974}
975
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200976#undef TEST_ASSERT
977
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200978#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_SHA256_C */
979
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200980#endif /* MBEDTLS_SELF_TEST */
981
982#endif /* MBEDTLS_ECJPAKE_C */