blob: a6f508386511101b9fa194c94bf728b0b361f719 [file] [log] [blame]
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001/*
2 * Elliptic curve J-PAKE
3 *
Bence Szépkúti44bfbe32020-08-19 16:54:51 +02004 * Copyright The Mbed TLS Contributors
Bence Szépkúti4e9f7122020-06-05 13:02:18 +02005 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6 *
7 * This file is provided under the Apache License 2.0, or the
8 * GNU General Public License v2.0 or later.
9 *
10 * **********
11 * Apache License 2.0:
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +020012 *
13 * Licensed under the Apache License, Version 2.0 (the "License"); you may
14 * not use this file except in compliance with the License.
15 * You may obtain a copy of the License at
16 *
17 * http://www.apache.org/licenses/LICENSE-2.0
18 *
19 * Unless required by applicable law or agreed to in writing, software
20 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
21 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 * See the License for the specific language governing permissions and
23 * limitations under the License.
24 *
Bence Szépkúti4e9f7122020-06-05 13:02:18 +020025 * **********
26 *
27 * **********
28 * GNU General Public License v2.0 or later:
29 *
30 * This program is free software; you can redistribute it and/or modify
31 * it under the terms of the GNU General Public License as published by
32 * the Free Software Foundation; either version 2 of the License, or
33 * (at your option) any later version.
34 *
35 * This program is distributed in the hope that it will be useful,
36 * but WITHOUT ANY WARRANTY; without even the implied warranty of
37 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38 * GNU General Public License for more details.
39 *
40 * You should have received a copy of the GNU General Public License along
41 * with this program; if not, write to the Free Software Foundation, Inc.,
42 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
43 *
44 * **********
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +020045 */
46
47/*
Manuel Pégourié-Gonnard6b798b92015-08-14 11:18:30 +020048 * References in the code are to the Thread v1.0 Specification,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +020049 * available to members of the Thread Group http://threadgroup.org/
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +020050 */
51
52#if !defined(MBEDTLS_CONFIG_FILE)
53#include "mbedtls/config.h"
54#else
55#include MBEDTLS_CONFIG_FILE
56#endif
57
58#if defined(MBEDTLS_ECJPAKE_C)
59
60#include "mbedtls/ecjpake.h"
61
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +020062#include <string.h>
63
Hanno Becker616d1ca2018-01-24 10:25:05 +000064#if !defined(MBEDTLS_ECJPAKE_ALT)
65
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +020066/*
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +020067 * Convert a mbedtls_ecjpake_role to identifier string
68 */
69static const char * const ecjpake_id[] = {
70 "client",
71 "server"
72};
73
74#define ID_MINE ( ecjpake_id[ ctx->role ] )
75#define ID_PEER ( ecjpake_id[ 1 - ctx->role ] )
76
77/*
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020078 * Initialize context
79 */
80void mbedtls_ecjpake_init( mbedtls_ecjpake_context *ctx )
81{
82 if( ctx == NULL )
83 return;
84
85 ctx->md_info = NULL;
86 mbedtls_ecp_group_init( &ctx->grp );
Manuel Pégourié-Gonnardb7da1942015-10-19 13:35:22 +020087 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020088
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +020089 mbedtls_ecp_point_init( &ctx->Xm1 );
90 mbedtls_ecp_point_init( &ctx->Xm2 );
91 mbedtls_ecp_point_init( &ctx->Xp1 );
92 mbedtls_ecp_point_init( &ctx->Xp2 );
93 mbedtls_ecp_point_init( &ctx->Xp );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020094
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +020095 mbedtls_mpi_init( &ctx->xm1 );
96 mbedtls_mpi_init( &ctx->xm2 );
97 mbedtls_mpi_init( &ctx->s );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020098}
99
100/*
101 * Free context
102 */
103void mbedtls_ecjpake_free( mbedtls_ecjpake_context *ctx )
104{
105 if( ctx == NULL )
106 return;
107
108 ctx->md_info = NULL;
109 mbedtls_ecp_group_free( &ctx->grp );
110
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200111 mbedtls_ecp_point_free( &ctx->Xm1 );
112 mbedtls_ecp_point_free( &ctx->Xm2 );
113 mbedtls_ecp_point_free( &ctx->Xp1 );
114 mbedtls_ecp_point_free( &ctx->Xp2 );
115 mbedtls_ecp_point_free( &ctx->Xp );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200116
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200117 mbedtls_mpi_free( &ctx->xm1 );
118 mbedtls_mpi_free( &ctx->xm2 );
119 mbedtls_mpi_free( &ctx->s );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200120}
121
122/*
123 * Setup context
124 */
125int mbedtls_ecjpake_setup( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +0200126 mbedtls_ecjpake_role role,
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200127 mbedtls_md_type_t hash,
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200128 mbedtls_ecp_group_id curve,
129 const unsigned char *secret,
130 size_t len )
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200131{
132 int ret;
133
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +0200134 ctx->role = role;
135
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200136 if( ( ctx->md_info = mbedtls_md_info_from_type( hash ) ) == NULL )
137 return( MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE );
138
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200139 MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ctx->grp, curve ) );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200140
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200141 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->s, secret, len ) );
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200142
143cleanup:
144 if( ret != 0 )
145 mbedtls_ecjpake_free( ctx );
146
147 return( ret );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200148}
149
150/*
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200151 * Check if context is ready for use
152 */
153int mbedtls_ecjpake_check( const mbedtls_ecjpake_context *ctx )
154{
155 if( ctx->md_info == NULL ||
156 ctx->grp.id == MBEDTLS_ECP_DP_NONE ||
157 ctx->s.p == NULL )
158 {
159 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
160 }
161
162 return( 0 );
163}
164
165/*
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200166 * Write a point plus its length to a buffer
167 */
168static int ecjpake_write_len_point( unsigned char **p,
169 const unsigned char *end,
170 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100171 const int pf,
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200172 const mbedtls_ecp_point *P )
173{
174 int ret;
175 size_t len;
176
177 /* Need at least 4 for length plus 1 for point */
178 if( end < *p || end - *p < 5 )
179 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
180
Robert Cragie7cdad772015-10-02 13:31:41 +0100181 ret = mbedtls_ecp_point_write_binary( grp, P, pf,
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200182 &len, *p + 4, end - ( *p + 4 ) );
183 if( ret != 0 )
184 return( ret );
185
186 (*p)[0] = (unsigned char)( ( len >> 24 ) & 0xFF );
187 (*p)[1] = (unsigned char)( ( len >> 16 ) & 0xFF );
188 (*p)[2] = (unsigned char)( ( len >> 8 ) & 0xFF );
189 (*p)[3] = (unsigned char)( ( len ) & 0xFF );
190
191 *p += 4 + len;
192
193 return( 0 );
194}
195
196/*
197 * Size of the temporary buffer for ecjpake_hash:
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200198 * 3 EC points plus their length, plus ID and its length (4 + 6 bytes)
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200199 */
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200200#define ECJPAKE_HASH_BUF_LEN ( 3 * ( 4 + MBEDTLS_ECP_MAX_PT_LEN ) + 4 + 6 )
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200201
202/*
203 * Compute hash for ZKP (7.4.2.2.2.1)
204 */
205static int ecjpake_hash( const mbedtls_md_info_t *md_info,
206 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100207 const int pf,
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200208 const mbedtls_ecp_point *G,
209 const mbedtls_ecp_point *V,
210 const mbedtls_ecp_point *X,
211 const char *id,
212 mbedtls_mpi *h )
213{
214 int ret;
215 unsigned char buf[ECJPAKE_HASH_BUF_LEN];
216 unsigned char *p = buf;
217 const unsigned char *end = buf + sizeof( buf );
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200218 const size_t id_len = strlen( id );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200219 unsigned char hash[MBEDTLS_MD_MAX_SIZE];
220
221 /* Write things to temporary buffer */
Robert Cragie7cdad772015-10-02 13:31:41 +0100222 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, G ) );
223 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, V ) );
224 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, X ) );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200225
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200226 if( end - p < 4 )
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200227 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
228
229 *p++ = (unsigned char)( ( id_len >> 24 ) & 0xFF );
230 *p++ = (unsigned char)( ( id_len >> 16 ) & 0xFF );
231 *p++ = (unsigned char)( ( id_len >> 8 ) & 0xFF );
232 *p++ = (unsigned char)( ( id_len ) & 0xFF );
233
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200234 if( end < p || (size_t)( end - p ) < id_len )
235 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
236
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200237 memcpy( p, id, id_len );
238 p += id_len;
239
240 /* Compute hash */
k-stachowiak202b1df2019-06-28 14:14:02 +0200241 MBEDTLS_MPI_CHK( mbedtls_md( md_info, buf, p - buf, hash ) );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200242
243 /* Turn it into an integer mod n */
244 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( h, hash,
245 mbedtls_md_get_size( md_info ) ) );
246 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( h, h, &grp->N ) );
247
248cleanup:
249 return( ret );
250}
251
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200252/*
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200253 * Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3)
254 */
255static int ecjpake_zkp_read( const mbedtls_md_info_t *md_info,
256 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100257 const int pf,
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200258 const mbedtls_ecp_point *G,
259 const mbedtls_ecp_point *X,
260 const char *id,
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200261 const unsigned char **p,
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200262 const unsigned char *end )
263{
264 int ret;
265 mbedtls_ecp_point V, VV;
266 mbedtls_mpi r, h;
267 size_t r_len;
268
269 mbedtls_ecp_point_init( &V );
270 mbedtls_ecp_point_init( &VV );
271 mbedtls_mpi_init( &r );
272 mbedtls_mpi_init( &h );
273
274 /*
275 * struct {
276 * ECPoint V;
277 * opaque r<1..2^8-1>;
278 * } ECSchnorrZKP;
279 */
280 if( end < *p )
281 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
282
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200283 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, &V, p, end - *p ) );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200284
285 if( end < *p || (size_t)( end - *p ) < 1 )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200286 {
287 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
288 goto cleanup;
289 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200290
291 r_len = *(*p)++;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200292
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200293 if( end < *p || (size_t)( end - *p ) < r_len )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200294 {
295 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
296 goto cleanup;
297 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200298
299 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &r, *p, r_len ) );
300 *p += r_len;
301
302 /*
303 * Verification
304 */
Robert Cragie7cdad772015-10-02 13:31:41 +0100305 MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200306 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( (mbedtls_ecp_group *) grp,
307 &VV, &h, X, &r, G ) );
308
309 if( mbedtls_ecp_point_cmp( &VV, &V ) != 0 )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200310 {
311 ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
312 goto cleanup;
313 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200314
315cleanup:
316 mbedtls_ecp_point_free( &V );
317 mbedtls_ecp_point_free( &VV );
318 mbedtls_mpi_free( &r );
319 mbedtls_mpi_free( &h );
320
321 return( ret );
322}
323
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200324/*
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200325 * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2)
326 */
327static int ecjpake_zkp_write( const mbedtls_md_info_t *md_info,
328 const mbedtls_ecp_group *grp,
Simon Butcherbb5e1c32018-06-08 11:14:43 +0100329 const int pf,
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200330 const mbedtls_ecp_point *G,
331 const mbedtls_mpi *x,
332 const mbedtls_ecp_point *X,
333 const char *id,
334 unsigned char **p,
335 const unsigned char *end,
336 int (*f_rng)(void *, unsigned char *, size_t),
337 void *p_rng )
338{
339 int ret;
340 mbedtls_ecp_point V;
341 mbedtls_mpi v;
342 mbedtls_mpi h; /* later recycled to hold r */
343 size_t len;
344
345 if( end < *p )
346 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
347
348 mbedtls_ecp_point_init( &V );
349 mbedtls_mpi_init( &v );
350 mbedtls_mpi_init( &h );
351
352 /* Compute signature */
353 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp,
354 G, &v, &V, f_rng, p_rng ) );
Robert Cragie7cdad772015-10-02 13:31:41 +0100355 MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) );
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200356 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &h, &h, x ) ); /* x*h */
357 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &h, &v, &h ) ); /* v - x*h */
358 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &h, &h, &grp->N ) ); /* r */
359
360 /* Write it out */
361 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, &V,
Robert Cragie7cdad772015-10-02 13:31:41 +0100362 pf, &len, *p, end - *p ) );
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200363 *p += len;
364
365 len = mbedtls_mpi_size( &h ); /* actually r */
366 if( end < *p || (size_t)( end - *p ) < 1 + len || len > 255 )
367 {
368 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
369 goto cleanup;
370 }
371
372 *(*p)++ = (unsigned char)( len & 0xFF );
373 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, *p, len ) ); /* r */
374 *p += len;
375
376cleanup:
377 mbedtls_ecp_point_free( &V );
378 mbedtls_mpi_free( &v );
379 mbedtls_mpi_free( &h );
380
381 return( ret );
382}
383
384/*
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200385 * Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof
386 * Output: verified public key X
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200387 */
388static int ecjpake_kkp_read( const mbedtls_md_info_t *md_info,
389 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100390 const int pf,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200391 const mbedtls_ecp_point *G,
392 mbedtls_ecp_point *X,
393 const char *id,
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200394 const unsigned char **p,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200395 const unsigned char *end )
396{
397 int ret;
398
399 if( end < *p )
400 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
401
402 /*
403 * struct {
404 * ECPoint X;
405 * ECSchnorrZKP zkp;
406 * } ECJPAKEKeyKP;
407 */
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200408 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, X, p, end - *p ) );
Manuel Pégourié-Gonnard30590952015-08-17 10:37:40 +0200409 if( mbedtls_ecp_is_zero( X ) )
410 {
411 ret = MBEDTLS_ERR_ECP_INVALID_KEY;
412 goto cleanup;
413 }
414
Robert Cragie7cdad772015-10-02 13:31:41 +0100415 MBEDTLS_MPI_CHK( ecjpake_zkp_read( md_info, grp, pf, G, X, id, p, end ) );
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200416
417cleanup:
418 return( ret );
419}
420
421/*
422 * Generate an ECJPAKEKeyKP
423 * Output: the serialized structure, plus private/public key pair
424 */
425static int ecjpake_kkp_write( const mbedtls_md_info_t *md_info,
426 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100427 const int pf,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200428 const mbedtls_ecp_point *G,
429 mbedtls_mpi *x,
430 mbedtls_ecp_point *X,
431 const char *id,
432 unsigned char **p,
433 const unsigned char *end,
434 int (*f_rng)(void *, unsigned char *, size_t),
435 void *p_rng )
436{
437 int ret;
438 size_t len;
439
440 if( end < *p )
441 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
442
443 /* Generate key (7.4.2.3.1) and write it out */
444 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp, G, x, X,
445 f_rng, p_rng ) );
446 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, X,
Robert Cragie7cdad772015-10-02 13:31:41 +0100447 pf, &len, *p, end - *p ) );
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200448 *p += len;
449
450 /* Generate and write proof */
Robert Cragie7cdad772015-10-02 13:31:41 +0100451 MBEDTLS_MPI_CHK( ecjpake_zkp_write( md_info, grp, pf, G, x, X, id,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200452 p, end, f_rng, p_rng ) );
453
454cleanup:
455 return( ret );
456}
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200457
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200458/*
459 * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs
460 * Ouputs: verified peer public keys Xa, Xb
461 */
462static int ecjpake_kkpp_read( const mbedtls_md_info_t *md_info,
463 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100464 const int pf,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200465 const mbedtls_ecp_point *G,
466 mbedtls_ecp_point *Xa,
467 mbedtls_ecp_point *Xb,
468 const char *id,
469 const unsigned char *buf,
470 size_t len )
471{
472 int ret;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200473 const unsigned char *p = buf;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200474 const unsigned char *end = buf + len;
475
476 /*
477 * struct {
478 * ECJPAKEKeyKP ecjpake_key_kp_pair_list[2];
479 * } ECJPAKEKeyKPPairList;
480 */
Robert Cragie7cdad772015-10-02 13:31:41 +0100481 MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xa, id, &p, end ) );
482 MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xb, id, &p, end ) );
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200483
484 if( p != end )
485 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
486
487cleanup:
488 return( ret );
489}
490
491/*
492 * Generate a ECJPAKEKeyKPPairList
493 * Outputs: the serialized structure, plus two private/public key pairs
494 */
495static int ecjpake_kkpp_write( const mbedtls_md_info_t *md_info,
496 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100497 const int pf,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200498 const mbedtls_ecp_point *G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200499 mbedtls_mpi *xm1,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200500 mbedtls_ecp_point *Xa,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200501 mbedtls_mpi *xm2,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200502 mbedtls_ecp_point *Xb,
503 const char *id,
504 unsigned char *buf,
505 size_t len,
506 size_t *olen,
507 int (*f_rng)(void *, unsigned char *, size_t),
508 void *p_rng )
509{
510 int ret;
511 unsigned char *p = buf;
512 const unsigned char *end = buf + len;
513
Robert Cragie7cdad772015-10-02 13:31:41 +0100514 MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm1, Xa, id,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200515 &p, end, f_rng, p_rng ) );
Robert Cragie7cdad772015-10-02 13:31:41 +0100516 MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm2, Xb, id,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200517 &p, end, f_rng, p_rng ) );
518
519 *olen = p - buf;
520
521cleanup:
522 return( ret );
523}
524
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200525/*
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200526 * Read and process the first round message
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200527 */
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200528int mbedtls_ecjpake_read_round_one( mbedtls_ecjpake_context *ctx,
529 const unsigned char *buf,
530 size_t len )
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200531{
Robert Cragie7cdad772015-10-02 13:31:41 +0100532 return( ecjpake_kkpp_read( ctx->md_info, &ctx->grp, ctx->point_format,
533 &ctx->grp.G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200534 &ctx->Xp1, &ctx->Xp2, ID_PEER,
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200535 buf, len ) );
536}
537
538/*
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200539 * Generate and write the first round message
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200540 */
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200541int mbedtls_ecjpake_write_round_one( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200542 unsigned char *buf, size_t len, size_t *olen,
543 int (*f_rng)(void *, unsigned char *, size_t),
544 void *p_rng )
545{
Robert Cragie7cdad772015-10-02 13:31:41 +0100546 return( ecjpake_kkpp_write( ctx->md_info, &ctx->grp, ctx->point_format,
547 &ctx->grp.G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200548 &ctx->xm1, &ctx->Xm1, &ctx->xm2, &ctx->Xm2,
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200549 ID_MINE, buf, len, olen, f_rng, p_rng ) );
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200550}
551
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200552/*
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200553 * Compute the sum of three points R = A + B + C
554 */
555static int ecjpake_ecp_add3( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
556 const mbedtls_ecp_point *A,
557 const mbedtls_ecp_point *B,
558 const mbedtls_ecp_point *C )
559{
560 int ret;
561 mbedtls_mpi one;
562
563 mbedtls_mpi_init( &one );
564
565 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
566 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, A, &one, B ) );
567 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, R, &one, C ) );
568
569cleanup:
570 mbedtls_mpi_free( &one );
571
572 return( ret );
573}
574
575/*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200576 * Read and process second round message (C: 7.4.2.5, S: 7.4.2.6)
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200577 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200578int mbedtls_ecjpake_read_round_two( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200579 const unsigned char *buf,
580 size_t len )
581{
582 int ret;
583 const unsigned char *p = buf;
584 const unsigned char *end = buf + len;
585 mbedtls_ecp_group grp;
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200586 mbedtls_ecp_point G; /* C: GB, S: GA */
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200587
588 mbedtls_ecp_group_init( &grp );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200589 mbedtls_ecp_point_init( &G );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200590
591 /*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200592 * Server: GA = X3 + X4 + X1 (7.4.2.6.1)
593 * Client: GB = X1 + X2 + X3 (7.4.2.5.1)
594 * Unified: G = Xm1 + Xm2 + Xp1
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200595 * We need that before parsing in order to check Xp as we read it
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200596 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200597 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200598 &ctx->Xm1, &ctx->Xm2, &ctx->Xp1 ) );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200599
600 /*
601 * struct {
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200602 * ECParameters curve_params; // only client reading server msg
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200603 * ECJPAKEKeyKP ecjpake_key_kp;
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200604 * } Client/ServerECJPAKEParams;
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200605 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200606 if( ctx->role == MBEDTLS_ECJPAKE_CLIENT )
Manuel Pégourié-Gonnardd9802af2015-08-17 12:47:38 +0200607 {
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200608 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_group( &grp, &p, len ) );
Manuel Pégourié-Gonnardd9802af2015-08-17 12:47:38 +0200609 if( grp.id != ctx->grp.id )
610 {
611 ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
612 goto cleanup;
613 }
614 }
615
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200616 MBEDTLS_MPI_CHK( ecjpake_kkp_read( ctx->md_info, &ctx->grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100617 ctx->point_format,
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200618 &G, &ctx->Xp, ID_PEER, &p, end ) );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200619
620 if( p != end )
621 {
622 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
623 goto cleanup;
624 }
625
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200626cleanup:
627 mbedtls_ecp_group_free( &grp );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200628 mbedtls_ecp_point_free( &G );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200629
630 return( ret );
631}
632
633/*
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200634 * Compute R = +/- X * S mod N, taking care not to leak S
635 */
636static int ecjpake_mul_secret( mbedtls_mpi *R, int sign,
637 const mbedtls_mpi *X,
638 const mbedtls_mpi *S,
639 const mbedtls_mpi *N,
640 int (*f_rng)(void *, unsigned char *, size_t),
641 void *p_rng )
642{
643 int ret;
644 mbedtls_mpi b; /* Blinding value, then s + N * blinding */
645
646 mbedtls_mpi_init( &b );
647
648 /* b = s + rnd-128-bit * N */
649 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &b, 16, f_rng, p_rng ) );
650 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &b, &b, N ) );
651 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &b, &b, S ) );
652
653 /* R = sign * X * b mod N */
654 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( R, X, &b ) );
655 R->s *= sign;
656 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( R, R, N ) );
657
658cleanup:
659 mbedtls_mpi_free( &b );
660
661 return( ret );
662}
663
664/*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200665 * Generate and write the second round message (S: 7.4.2.5, C: 7.4.2.6)
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200666 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200667int mbedtls_ecjpake_write_round_two( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200668 unsigned char *buf, size_t len, size_t *olen,
669 int (*f_rng)(void *, unsigned char *, size_t),
670 void *p_rng )
671{
672 int ret;
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200673 mbedtls_ecp_point G; /* C: GA, S: GB */
674 mbedtls_ecp_point Xm; /* C: Xc, S: Xs */
675 mbedtls_mpi xm; /* C: xc, S: xs */
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200676 unsigned char *p = buf;
677 const unsigned char *end = buf + len;
678 size_t ec_len;
679
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200680 mbedtls_ecp_point_init( &G );
681 mbedtls_ecp_point_init( &Xm );
682 mbedtls_mpi_init( &xm );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200683
684 /*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200685 * First generate private/public key pair (S: 7.4.2.5.1, C: 7.4.2.6.1)
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200686 *
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200687 * Client: GA = X1 + X3 + X4 | xs = x2 * s | Xc = xc * GA
688 * Server: GB = X3 + X1 + X2 | xs = x4 * s | Xs = xs * GB
689 * Unified: G = Xm1 + Xp1 + Xp2 | xm = xm2 * s | Xm = xm * G
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200690 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200691 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200692 &ctx->Xp1, &ctx->Xp2, &ctx->Xm1 ) );
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200693 MBEDTLS_MPI_CHK( ecjpake_mul_secret( &xm, 1, &ctx->xm2, &ctx->s,
694 &ctx->grp.N, f_rng, p_rng ) );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200695 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &Xm, &xm, &G, f_rng, p_rng ) );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200696
697 /*
698 * Now write things out
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200699 *
700 * struct {
701 * ECParameters curve_params; // only server writing its message
702 * ECJPAKEKeyKP ecjpake_key_kp;
703 * } Client/ServerECJPAKEParams;
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200704 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200705 if( ctx->role == MBEDTLS_ECJPAKE_SERVER )
706 {
707 if( end < p )
708 {
709 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
710 goto cleanup;
711 }
712 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_group( &ctx->grp, &ec_len,
713 p, end - p ) );
714 p += ec_len;
715 }
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200716
717 if( end < p )
718 {
719 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
720 goto cleanup;
721 }
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200722 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( &ctx->grp, &Xm,
Robert Cragie7cdad772015-10-02 13:31:41 +0100723 ctx->point_format, &ec_len, p, end - p ) );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200724 p += ec_len;
725
726 MBEDTLS_MPI_CHK( ecjpake_zkp_write( ctx->md_info, &ctx->grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100727 ctx->point_format,
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200728 &G, &xm, &Xm, ID_MINE,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200729 &p, end, f_rng, p_rng ) );
730
731 *olen = p - buf;
732
733cleanup:
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200734 mbedtls_ecp_point_free( &G );
735 mbedtls_ecp_point_free( &Xm );
736 mbedtls_mpi_free( &xm );
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +0200737
738 return( ret );
739}
740
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200741/*
742 * Derive PMS (7.4.2.7 / 7.4.2.8)
743 */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +0200744int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200745 unsigned char *buf, size_t len, size_t *olen,
746 int (*f_rng)(void *, unsigned char *, size_t),
747 void *p_rng )
748{
749 int ret;
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200750 mbedtls_ecp_point K;
751 mbedtls_mpi m_xm2_s, one;
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200752 unsigned char kx[MBEDTLS_ECP_MAX_BYTES];
753 size_t x_bytes;
754
755 *olen = mbedtls_md_get_size( ctx->md_info );
756 if( len < *olen )
757 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
758
759 mbedtls_ecp_point_init( &K );
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200760 mbedtls_mpi_init( &m_xm2_s );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200761 mbedtls_mpi_init( &one );
762
763 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200764
765 /*
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200766 * Client: K = ( Xs - X4 * x2 * s ) * x2
767 * Server: K = ( Xc - X2 * x4 * s ) * x4
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200768 * Unified: K = ( Xp - Xp2 * xm2 * s ) * xm2
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200769 */
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200770 MBEDTLS_MPI_CHK( ecjpake_mul_secret( &m_xm2_s, -1, &ctx->xm2, &ctx->s,
771 &ctx->grp.N, f_rng, p_rng ) );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200772 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( &ctx->grp, &K,
773 &one, &ctx->Xp,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200774 &m_xm2_s, &ctx->Xp2 ) );
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200775 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &K, &ctx->xm2, &K,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200776 f_rng, p_rng ) );
777
778 /* PMS = SHA-256( K.X ) */
779 x_bytes = ( ctx->grp.pbits + 7 ) / 8;
780 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &K.X, kx, x_bytes ) );
781 MBEDTLS_MPI_CHK( mbedtls_md( ctx->md_info, kx, x_bytes, buf ) );
782
783cleanup:
784 mbedtls_ecp_point_free( &K );
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200785 mbedtls_mpi_free( &m_xm2_s );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200786 mbedtls_mpi_free( &one );
787
788 return( ret );
789}
790
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200791#undef ID_MINE
792#undef ID_PEER
793
Hanno Becker616d1ca2018-01-24 10:25:05 +0000794#endif /* ! MBEDTLS_ECJPAKE_ALT */
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200795
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200796#if defined(MBEDTLS_SELF_TEST)
797
798#if defined(MBEDTLS_PLATFORM_C)
799#include "mbedtls/platform.h"
800#else
801#include <stdio.h>
802#define mbedtls_printf printf
803#endif
804
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200805#if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
806 !defined(MBEDTLS_SHA256_C)
807int mbedtls_ecjpake_self_test( int verbose )
808{
809 (void) verbose;
810 return( 0 );
811}
812#else
813
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200814static const unsigned char ecjpake_test_password[] = {
815 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x6a, 0x70, 0x61, 0x6b, 0x65, 0x74,
816 0x65, 0x73, 0x74
817};
818
819static const unsigned char ecjpake_test_x1[] = {
820 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
821 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
822 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21
823};
824
825static const unsigned char ecjpake_test_x2[] = {
826 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
827 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
828 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
829};
830
831static const unsigned char ecjpake_test_x3[] = {
832 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
833 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
834 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
835};
836
837static const unsigned char ecjpake_test_x4[] = {
838 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc,
839 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
840 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1
841};
842
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200843static const unsigned char ecjpake_test_cli_one[] = {
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200844 0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19,
845 0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44,
846 0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad,
847 0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62,
848 0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9,
849 0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d,
850 0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e,
851 0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e,
852 0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73,
853 0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22,
854 0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce,
855 0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00,
856 0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200857 0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e,
858 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62,
859 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5,
860 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb,
861 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35,
862 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0,
863 0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb,
864 0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47,
865 0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39,
866 0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97,
867 0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40,
868 0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d,
869 0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa,
870 0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d,
871 0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200872};
873
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200874static const unsigned char ecjpake_test_srv_one[] = {
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200875 0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb,
876 0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18,
877 0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47,
878 0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f,
879 0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7,
880 0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d,
881 0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64,
882 0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36,
883 0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2,
884 0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec,
885 0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16,
886 0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96,
887 0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3,
888 0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19,
889 0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f,
890 0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8,
891 0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7,
892 0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea,
893 0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5,
894 0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6,
895 0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31,
896 0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d,
897 0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8,
898 0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee,
899 0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84,
900 0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f,
901 0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80,
902 0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12
903};
904
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200905static const unsigned char ecjpake_test_srv_two[] = {
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200906 0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23,
907 0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c,
908 0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f,
909 0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca,
910 0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26,
911 0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55,
912 0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38,
913 0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6,
914 0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9,
915 0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4,
916 0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2,
917 0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8,
918 0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd,
919 0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c
920};
921
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200922static const unsigned char ecjpake_test_cli_two[] = {
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +0200923 0x41, 0x04, 0x69, 0xd5, 0x4e, 0xe8, 0x5e, 0x90, 0xce, 0x3f, 0x12, 0x46,
924 0x74, 0x2d, 0xe5, 0x07, 0xe9, 0x39, 0xe8, 0x1d, 0x1d, 0xc1, 0xc5, 0xcb,
925 0x98, 0x8b, 0x58, 0xc3, 0x10, 0xc9, 0xfd, 0xd9, 0x52, 0x4d, 0x93, 0x72,
926 0x0b, 0x45, 0x54, 0x1c, 0x83, 0xee, 0x88, 0x41, 0x19, 0x1d, 0xa7, 0xce,
927 0xd8, 0x6e, 0x33, 0x12, 0xd4, 0x36, 0x23, 0xc1, 0xd6, 0x3e, 0x74, 0x98,
928 0x9a, 0xba, 0x4a, 0xff, 0xd1, 0xee, 0x41, 0x04, 0x07, 0x7e, 0x8c, 0x31,
929 0xe2, 0x0e, 0x6b, 0xed, 0xb7, 0x60, 0xc1, 0x35, 0x93, 0xe6, 0x9f, 0x15,
930 0xbe, 0x85, 0xc2, 0x7d, 0x68, 0xcd, 0x09, 0xcc, 0xb8, 0xc4, 0x18, 0x36,
931 0x08, 0x91, 0x7c, 0x5c, 0x3d, 0x40, 0x9f, 0xac, 0x39, 0xfe, 0xfe, 0xe8,
932 0x2f, 0x72, 0x92, 0xd3, 0x6f, 0x0d, 0x23, 0xe0, 0x55, 0x91, 0x3f, 0x45,
933 0xa5, 0x2b, 0x85, 0xdd, 0x8a, 0x20, 0x52, 0xe9, 0xe1, 0x29, 0xbb, 0x4d,
934 0x20, 0x0f, 0x01, 0x1f, 0x19, 0x48, 0x35, 0x35, 0xa6, 0xe8, 0x9a, 0x58,
935 0x0c, 0x9b, 0x00, 0x03, 0xba, 0xf2, 0x14, 0x62, 0xec, 0xe9, 0x1a, 0x82,
936 0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c
937};
938
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200939static const unsigned char ecjpake_test_pms[] = {
940 0xf3, 0xd4, 0x7f, 0x59, 0x98, 0x44, 0xdb, 0x92, 0xa5, 0x69, 0xbb, 0xe7,
941 0x98, 0x1e, 0x39, 0xd9, 0x31, 0xfd, 0x74, 0x3b, 0xf2, 0x2e, 0x98, 0xf9,
942 0xb4, 0x38, 0xf7, 0x19, 0xd3, 0xc4, 0xf3, 0x51
943};
944
Antonin Décimo8fd91562019-01-23 15:24:37 +0100945/* Load my private keys and generate the corresponding public keys */
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +0200946static int ecjpake_test_load( mbedtls_ecjpake_context *ctx,
947 const unsigned char *xm1, size_t len1,
948 const unsigned char *xm2, size_t len2 )
949{
950 int ret;
951
952 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm1, xm1, len1 ) );
953 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm2, xm2, len2 ) );
954 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm1, &ctx->xm1,
955 &ctx->grp.G, NULL, NULL ) );
956 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm2, &ctx->xm2,
957 &ctx->grp.G, NULL, NULL ) );
958
959cleanup:
960 return( ret );
961}
962
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200963/* For tests we don't need a secure RNG;
964 * use the LGC from Numerical Recipes for simplicity */
965static int ecjpake_lgc( void *p, unsigned char *out, size_t len )
966{
967 static uint32_t x = 42;
968 (void) p;
969
970 while( len > 0 )
971 {
972 size_t use_len = len > 4 ? 4 : len;
973 x = 1664525 * x + 1013904223;
974 memcpy( out, &x, use_len );
975 out += use_len;
976 len -= use_len;
977 }
978
979 return( 0 );
980}
981
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200982#define TEST_ASSERT( x ) \
983 do { \
984 if( x ) \
985 ret = 0; \
986 else \
987 { \
988 ret = 1; \
989 goto cleanup; \
990 } \
991 } while( 0 )
992
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200993/*
994 * Checkup routine
995 */
996int mbedtls_ecjpake_self_test( int verbose )
997{
998 int ret;
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200999 mbedtls_ecjpake_context cli;
1000 mbedtls_ecjpake_context srv;
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001001 unsigned char buf[512], pms[32];
1002 size_t len, pmslen;
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001003
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001004 mbedtls_ecjpake_init( &cli );
1005 mbedtls_ecjpake_init( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001006
1007 if( verbose != 0 )
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001008 mbedtls_printf( " ECJPAKE test #0 (setup): " );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +02001009
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +02001010 TEST_ASSERT( mbedtls_ecjpake_setup( &cli, MBEDTLS_ECJPAKE_CLIENT,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001011 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1012 ecjpake_test_password,
1013 sizeof( ecjpake_test_password ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001014
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +02001015 TEST_ASSERT( mbedtls_ecjpake_setup( &srv, MBEDTLS_ECJPAKE_SERVER,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001016 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1017 ecjpake_test_password,
1018 sizeof( ecjpake_test_password ) ) == 0 );
1019
1020 if( verbose != 0 )
1021 mbedtls_printf( "passed\n" );
1022
1023 if( verbose != 0 )
1024 mbedtls_printf( " ECJPAKE test #1 (random handshake): " );
1025
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001026 TEST_ASSERT( mbedtls_ecjpake_write_round_one( &cli,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001027 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1028
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001029 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv, buf, len ) == 0 );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001030
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001031 TEST_ASSERT( mbedtls_ecjpake_write_round_one( &srv,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001032 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1033
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001034 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli, buf, len ) == 0 );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001035
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001036 TEST_ASSERT( mbedtls_ecjpake_write_round_two( &srv,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +02001037 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1038
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001039 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli, buf, len ) == 0 );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +02001040
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001041 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001042 pms, sizeof( pms ), &pmslen, ecjpake_lgc, NULL ) == 0 );
1043
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001044 TEST_ASSERT( mbedtls_ecjpake_write_round_two( &cli,
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +02001045 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1046
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001047 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv, buf, len ) == 0 );
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +02001048
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001049 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001050 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1051
1052 TEST_ASSERT( len == pmslen );
1053 TEST_ASSERT( memcmp( buf, pms, len ) == 0 );
1054
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001055 if( verbose != 0 )
1056 mbedtls_printf( "passed\n" );
1057
1058 if( verbose != 0 )
1059 mbedtls_printf( " ECJPAKE test #2 (reference handshake): " );
1060
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001061 /* Simulate generation of round one */
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001062 MBEDTLS_MPI_CHK( ecjpake_test_load( &cli,
1063 ecjpake_test_x1, sizeof( ecjpake_test_x1 ),
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001064 ecjpake_test_x2, sizeof( ecjpake_test_x2 ) ) );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001065
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001066 MBEDTLS_MPI_CHK( ecjpake_test_load( &srv,
1067 ecjpake_test_x3, sizeof( ecjpake_test_x3 ),
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001068 ecjpake_test_x4, sizeof( ecjpake_test_x4 ) ) );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001069
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001070 /* Read round one */
1071 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv,
1072 ecjpake_test_cli_one,
1073 sizeof( ecjpake_test_cli_one ) ) == 0 );
1074
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001075 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001076 ecjpake_test_srv_one,
1077 sizeof( ecjpake_test_srv_one ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001078
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001079 /* Skip generation of round two, read round two */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001080 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001081 ecjpake_test_srv_two,
1082 sizeof( ecjpake_test_srv_two ) ) == 0 );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +02001083
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001084 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001085 ecjpake_test_cli_two,
1086 sizeof( ecjpake_test_cli_two ) ) == 0 );
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +02001087
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001088 /* Server derives PMS */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001089 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001090 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1091
1092 TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
1093 TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
1094
1095 memset( buf, 0, len ); /* Avoid interferences with next step */
1096
1097 /* Client derives PMS */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001098 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001099 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1100
1101 TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
1102 TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
1103
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001104 if( verbose != 0 )
1105 mbedtls_printf( "passed\n" );
1106
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001107cleanup:
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001108 mbedtls_ecjpake_free( &cli );
1109 mbedtls_ecjpake_free( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001110
1111 if( ret != 0 )
1112 {
1113 if( verbose != 0 )
1114 mbedtls_printf( "failed\n" );
1115
1116 ret = 1;
1117 }
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001118
1119 if( verbose != 0 )
1120 mbedtls_printf( "\n" );
1121
1122 return( ret );
1123}
1124
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +02001125#undef TEST_ASSERT
1126
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001127#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_SHA256_C */
1128
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001129#endif /* MBEDTLS_SELF_TEST */
1130
1131#endif /* MBEDTLS_ECJPAKE_C */