blob: d6087a040783a6937728b1131b2b02da93fef418 [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
595 if( end < *p )
596 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é-Gonnard4d8685b2015-08-05 15:44:42 +0200645#if defined(MBEDTLS_SELF_TEST)
646
647#if defined(MBEDTLS_PLATFORM_C)
648#include "mbedtls/platform.h"
649#else
650#include <stdio.h>
651#define mbedtls_printf printf
652#endif
653
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200654#if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
655 !defined(MBEDTLS_SHA256_C)
656int mbedtls_ecjpake_self_test( int verbose )
657{
658 (void) verbose;
659 return( 0 );
660}
661#else
662
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200663static const unsigned char ecjpake_test_password[] = {
664 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x6a, 0x70, 0x61, 0x6b, 0x65, 0x74,
665 0x65, 0x73, 0x74
666};
667
668static const unsigned char ecjpake_test_x1[] = {
669 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
670 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
671 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21
672};
673
674static const unsigned char ecjpake_test_x2[] = {
675 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
676 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
677 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
678};
679
680static const unsigned char ecjpake_test_x3[] = {
681 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
682 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
683 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
684};
685
686static const unsigned char ecjpake_test_x4[] = {
687 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc,
688 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
689 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1
690};
691
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200692static const unsigned char ecjpake_test_cli_ext[] = {
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200693 0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19,
694 0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44,
695 0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad,
696 0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62,
697 0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9,
698 0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d,
699 0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e,
700 0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e,
701 0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73,
702 0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22,
703 0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce,
704 0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00,
705 0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200706 0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e,
707 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62,
708 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5,
709 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb,
710 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35,
711 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0,
712 0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb,
713 0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47,
714 0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39,
715 0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97,
716 0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40,
717 0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d,
718 0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa,
719 0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d,
720 0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200721};
722
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200723static const unsigned char ecjpake_test_srv_ext[] = {
724 0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb,
725 0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18,
726 0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47,
727 0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f,
728 0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7,
729 0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d,
730 0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64,
731 0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36,
732 0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2,
733 0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec,
734 0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16,
735 0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96,
736 0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3,
737 0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19,
738 0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f,
739 0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8,
740 0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7,
741 0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea,
742 0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5,
743 0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6,
744 0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31,
745 0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d,
746 0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8,
747 0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee,
748 0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84,
749 0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f,
750 0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80,
751 0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12
752};
753
754static const unsigned char ecjpake_test_srv_kx[] = {
755 0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23,
756 0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c,
757 0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f,
758 0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca,
759 0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26,
760 0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55,
761 0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38,
762 0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6,
763 0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9,
764 0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4,
765 0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2,
766 0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8,
767 0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd,
768 0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c
769};
770
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200771/* For tests we don't need a secure RNG;
772 * use the LGC from Numerical Recipes for simplicity */
773static int ecjpake_lgc( void *p, unsigned char *out, size_t len )
774{
775 static uint32_t x = 42;
776 (void) p;
777
778 while( len > 0 )
779 {
780 size_t use_len = len > 4 ? 4 : len;
781 x = 1664525 * x + 1013904223;
782 memcpy( out, &x, use_len );
783 out += use_len;
784 len -= use_len;
785 }
786
787 return( 0 );
788}
789
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200790#define TEST_ASSERT( x ) \
791 do { \
792 if( x ) \
793 ret = 0; \
794 else \
795 { \
796 ret = 1; \
797 goto cleanup; \
798 } \
799 } while( 0 )
800
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200801/*
802 * Checkup routine
803 */
804int mbedtls_ecjpake_self_test( int verbose )
805{
806 int ret;
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200807 mbedtls_ecjpake_context cli;
808 mbedtls_ecjpake_context srv;
809 unsigned char buf[512];
810 size_t len;
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200811
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200812 mbedtls_ecjpake_init( &cli );
813 mbedtls_ecjpake_init( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200814
815 if( verbose != 0 )
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200816 mbedtls_printf( " ECJPAKE test #0 (setup): " );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200817
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200818 TEST_ASSERT( mbedtls_ecjpake_setup( &cli,
819 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
820 ecjpake_test_password,
821 sizeof( ecjpake_test_password ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200822
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200823 TEST_ASSERT( mbedtls_ecjpake_setup( &srv,
824 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
825 ecjpake_test_password,
826 sizeof( ecjpake_test_password ) ) == 0 );
827
828 if( verbose != 0 )
829 mbedtls_printf( "passed\n" );
830
831 if( verbose != 0 )
832 mbedtls_printf( " ECJPAKE test #1 (random handshake): " );
833
834 TEST_ASSERT( mbedtls_ecjpake_tls_write_client_ext( &cli,
835 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
836
837 TEST_ASSERT( mbedtls_ecjpake_tls_read_client_ext( &srv, buf, len ) == 0 );
838
839 TEST_ASSERT( mbedtls_ecjpake_tls_write_server_ext( &srv,
840 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
841
842 TEST_ASSERT( mbedtls_ecjpake_tls_read_server_ext( &cli, buf, len ) == 0 );
843
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200844 TEST_ASSERT( mbedtls_ecjpake_tls_write_server_params( &srv,
845 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
846
847 TEST_ASSERT( mbedtls_ecjpake_tls_read_server_params( &cli, buf, len ) == 0 );
848
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200849 if( verbose != 0 )
850 mbedtls_printf( "passed\n" );
851
852 if( verbose != 0 )
853 mbedtls_printf( " ECJPAKE test #2 (reference handshake): " );
854
855 /* Simulate key generation on client, skip writing client_ext */
856 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &cli.xa,
857 ecjpake_test_x1, sizeof( ecjpake_test_x1 ) ) );
858 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &cli.xb,
859 ecjpake_test_x2, sizeof( ecjpake_test_x2 ) ) );
860 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &cli.grp, &cli.X1, &cli.xa,
861 &cli.grp.G, NULL, NULL ) );
862 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &cli.grp, &cli.X2, &cli.xb,
863 &cli.grp.G, NULL, NULL ) );
864
865 /* Server reads client ext */
866 TEST_ASSERT( mbedtls_ecjpake_tls_read_client_ext( &srv,
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200867 ecjpake_test_cli_ext,
868 sizeof( ecjpake_test_cli_ext ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200869
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200870 /* Simulate key generation on server, skip writing server_ext */
871 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &srv.xa,
872 ecjpake_test_x3, sizeof( ecjpake_test_x3 ) ) );
873 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &srv.xb,
874 ecjpake_test_x4, sizeof( ecjpake_test_x4 ) ) );
875 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &srv.grp, &srv.X3, &srv.xa,
876 &srv.grp.G, NULL, NULL ) );
877 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &srv.grp, &srv.X4, &srv.xb,
878 &srv.grp.G, NULL, NULL ) );
879
880 /* Client reads server ext and key exchange */
881 TEST_ASSERT( mbedtls_ecjpake_tls_read_server_ext( &cli,
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200882 ecjpake_test_srv_ext,
883 sizeof( ecjpake_test_srv_ext ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200884
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200885 TEST_ASSERT( mbedtls_ecjpake_tls_read_server_params( &cli,
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200886 ecjpake_test_srv_kx,
887 sizeof( ecjpake_test_srv_kx ) ) == 0 );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200888
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200889 if( verbose != 0 )
890 mbedtls_printf( "passed\n" );
891
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200892cleanup:
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200893 mbedtls_ecjpake_free( &cli );
894 mbedtls_ecjpake_free( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200895
896 if( ret != 0 )
897 {
898 if( verbose != 0 )
899 mbedtls_printf( "failed\n" );
900
901 ret = 1;
902 }
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200903
904 if( verbose != 0 )
905 mbedtls_printf( "\n" );
906
907 return( ret );
908}
909
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200910#undef TEST_ASSERT
911
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200912#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_SHA256_C */
913
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200914#endif /* MBEDTLS_SELF_TEST */
915
916#endif /* MBEDTLS_ECJPAKE_C */