blob: be941b14b115db6373fa7d7abc1c4eb07bc068cf [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é-Gonnard6b798b92015-08-14 11:18:30 +020023 * References in the code are to the Thread v1.0 Specification,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +020024 * available to members of the Thread Group http://threadgroup.org/
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"
Hanno Becker71c8e1b2018-12-14 17:09:39 +000036#include "mbedtls/platform_util.h"
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +020037
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +020038#include <string.h>
39
Hanno Becker616d1ca2018-01-24 10:25:05 +000040#if !defined(MBEDTLS_ECJPAKE_ALT)
41
Hanno Becker71c8e1b2018-12-14 17:09:39 +000042/* Parameter validation macros based on platform_util.h */
43#define ECJPAKE_VALIDATE_RET( cond ) \
44 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA )
45#define ECJPAKE_VALIDATE( cond ) \
46 MBEDTLS_INTERNAL_VALIDATE( cond )
47
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +020048/*
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +020049 * Convert a mbedtls_ecjpake_role to identifier string
50 */
51static const char * const ecjpake_id[] = {
52 "client",
53 "server"
54};
55
56#define ID_MINE ( ecjpake_id[ ctx->role ] )
57#define ID_PEER ( ecjpake_id[ 1 - ctx->role ] )
58
59/*
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020060 * Initialize context
61 */
62void mbedtls_ecjpake_init( mbedtls_ecjpake_context *ctx )
63{
Hanno Becker71c8e1b2018-12-14 17:09:39 +000064 ECJPAKE_VALIDATE( ctx != NULL );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020065
66 ctx->md_info = NULL;
67 mbedtls_ecp_group_init( &ctx->grp );
Manuel Pégourié-Gonnardb7da1942015-10-19 13:35:22 +020068 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020069
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +020070 mbedtls_ecp_point_init( &ctx->Xm1 );
71 mbedtls_ecp_point_init( &ctx->Xm2 );
72 mbedtls_ecp_point_init( &ctx->Xp1 );
73 mbedtls_ecp_point_init( &ctx->Xp2 );
74 mbedtls_ecp_point_init( &ctx->Xp );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020075
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +020076 mbedtls_mpi_init( &ctx->xm1 );
77 mbedtls_mpi_init( &ctx->xm2 );
78 mbedtls_mpi_init( &ctx->s );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020079}
80
81/*
82 * Free context
83 */
84void mbedtls_ecjpake_free( mbedtls_ecjpake_context *ctx )
85{
86 if( ctx == NULL )
87 return;
88
89 ctx->md_info = NULL;
90 mbedtls_ecp_group_free( &ctx->grp );
91
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +020092 mbedtls_ecp_point_free( &ctx->Xm1 );
93 mbedtls_ecp_point_free( &ctx->Xm2 );
94 mbedtls_ecp_point_free( &ctx->Xp1 );
95 mbedtls_ecp_point_free( &ctx->Xp2 );
96 mbedtls_ecp_point_free( &ctx->Xp );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020097
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +020098 mbedtls_mpi_free( &ctx->xm1 );
99 mbedtls_mpi_free( &ctx->xm2 );
100 mbedtls_mpi_free( &ctx->s );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200101}
102
103/*
104 * Setup context
105 */
106int mbedtls_ecjpake_setup( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +0200107 mbedtls_ecjpake_role role,
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200108 mbedtls_md_type_t hash,
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200109 mbedtls_ecp_group_id curve,
110 const unsigned char *secret,
111 size_t len )
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200112{
113 int ret;
Hanno Becker185e5162018-12-19 09:48:50 +0000114
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000115 ECJPAKE_VALIDATE_RET( ctx != NULL );
116 ECJPAKE_VALIDATE_RET( role == MBEDTLS_ECJPAKE_CLIENT ||
117 role == MBEDTLS_ECJPAKE_SERVER );
118 ECJPAKE_VALIDATE_RET( secret != NULL || len == 0 );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200119
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +0200120 ctx->role = role;
121
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200122 if( ( ctx->md_info = mbedtls_md_info_from_type( hash ) ) == NULL )
123 return( MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE );
124
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200125 MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ctx->grp, curve ) );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200126
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200127 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->s, secret, len ) );
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200128
129cleanup:
130 if( ret != 0 )
131 mbedtls_ecjpake_free( ctx );
132
133 return( ret );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200134}
135
136/*
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200137 * Check if context is ready for use
138 */
139int mbedtls_ecjpake_check( const mbedtls_ecjpake_context *ctx )
140{
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000141 ECJPAKE_VALIDATE_RET( ctx != NULL );
142
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200143 if( ctx->md_info == NULL ||
144 ctx->grp.id == MBEDTLS_ECP_DP_NONE ||
145 ctx->s.p == NULL )
146 {
147 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
148 }
149
150 return( 0 );
151}
152
153/*
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200154 * Write a point plus its length to a buffer
155 */
156static int ecjpake_write_len_point( unsigned char **p,
157 const unsigned char *end,
158 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100159 const int pf,
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200160 const mbedtls_ecp_point *P )
161{
162 int ret;
163 size_t len;
164
165 /* Need at least 4 for length plus 1 for point */
166 if( end < *p || end - *p < 5 )
167 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
168
Robert Cragie7cdad772015-10-02 13:31:41 +0100169 ret = mbedtls_ecp_point_write_binary( grp, P, pf,
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200170 &len, *p + 4, end - ( *p + 4 ) );
171 if( ret != 0 )
172 return( ret );
173
174 (*p)[0] = (unsigned char)( ( len >> 24 ) & 0xFF );
175 (*p)[1] = (unsigned char)( ( len >> 16 ) & 0xFF );
176 (*p)[2] = (unsigned char)( ( len >> 8 ) & 0xFF );
177 (*p)[3] = (unsigned char)( ( len ) & 0xFF );
178
179 *p += 4 + len;
180
181 return( 0 );
182}
183
184/*
185 * Size of the temporary buffer for ecjpake_hash:
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200186 * 3 EC points plus their length, plus ID and its length (4 + 6 bytes)
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200187 */
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200188#define ECJPAKE_HASH_BUF_LEN ( 3 * ( 4 + MBEDTLS_ECP_MAX_PT_LEN ) + 4 + 6 )
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200189
190/*
191 * Compute hash for ZKP (7.4.2.2.2.1)
192 */
193static int ecjpake_hash( const mbedtls_md_info_t *md_info,
194 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100195 const int pf,
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200196 const mbedtls_ecp_point *G,
197 const mbedtls_ecp_point *V,
198 const mbedtls_ecp_point *X,
199 const char *id,
200 mbedtls_mpi *h )
201{
202 int ret;
203 unsigned char buf[ECJPAKE_HASH_BUF_LEN];
204 unsigned char *p = buf;
205 const unsigned char *end = buf + sizeof( buf );
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200206 const size_t id_len = strlen( id );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200207 unsigned char hash[MBEDTLS_MD_MAX_SIZE];
208
209 /* Write things to temporary buffer */
Robert Cragie7cdad772015-10-02 13:31:41 +0100210 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, G ) );
211 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, V ) );
212 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, X ) );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200213
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200214 if( end - p < 4 )
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200215 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
216
217 *p++ = (unsigned char)( ( id_len >> 24 ) & 0xFF );
218 *p++ = (unsigned char)( ( id_len >> 16 ) & 0xFF );
219 *p++ = (unsigned char)( ( id_len >> 8 ) & 0xFF );
220 *p++ = (unsigned char)( ( id_len ) & 0xFF );
221
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200222 if( end < p || (size_t)( end - p ) < id_len )
223 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
224
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200225 memcpy( p, id, id_len );
226 p += id_len;
227
228 /* Compute hash */
229 mbedtls_md( md_info, buf, p - buf, hash );
230
231 /* Turn it into an integer mod n */
232 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( h, hash,
233 mbedtls_md_get_size( md_info ) ) );
234 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( h, h, &grp->N ) );
235
236cleanup:
237 return( ret );
238}
239
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200240/*
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200241 * Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3)
242 */
243static int ecjpake_zkp_read( const mbedtls_md_info_t *md_info,
244 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100245 const int pf,
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200246 const mbedtls_ecp_point *G,
247 const mbedtls_ecp_point *X,
248 const char *id,
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200249 const unsigned char **p,
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200250 const unsigned char *end )
251{
252 int ret;
253 mbedtls_ecp_point V, VV;
254 mbedtls_mpi r, h;
255 size_t r_len;
256
257 mbedtls_ecp_point_init( &V );
258 mbedtls_ecp_point_init( &VV );
259 mbedtls_mpi_init( &r );
260 mbedtls_mpi_init( &h );
261
262 /*
263 * struct {
264 * ECPoint V;
265 * opaque r<1..2^8-1>;
266 * } ECSchnorrZKP;
267 */
268 if( end < *p )
269 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
270
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200271 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, &V, p, end - *p ) );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200272
273 if( end < *p || (size_t)( end - *p ) < 1 )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200274 {
275 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
276 goto cleanup;
277 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200278
279 r_len = *(*p)++;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200280
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200281 if( end < *p || (size_t)( end - *p ) < r_len )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200282 {
283 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
284 goto cleanup;
285 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200286
287 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &r, *p, r_len ) );
288 *p += r_len;
289
290 /*
291 * Verification
292 */
Robert Cragie7cdad772015-10-02 13:31:41 +0100293 MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200294 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( (mbedtls_ecp_group *) grp,
295 &VV, &h, X, &r, G ) );
296
297 if( mbedtls_ecp_point_cmp( &VV, &V ) != 0 )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200298 {
299 ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
300 goto cleanup;
301 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200302
303cleanup:
304 mbedtls_ecp_point_free( &V );
305 mbedtls_ecp_point_free( &VV );
306 mbedtls_mpi_free( &r );
307 mbedtls_mpi_free( &h );
308
309 return( ret );
310}
311
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200312/*
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200313 * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2)
314 */
315static int ecjpake_zkp_write( const mbedtls_md_info_t *md_info,
316 const mbedtls_ecp_group *grp,
Darryl Green11999bb2018-03-13 15:22:58 +0000317 const int pf,
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200318 const mbedtls_ecp_point *G,
319 const mbedtls_mpi *x,
320 const mbedtls_ecp_point *X,
321 const char *id,
322 unsigned char **p,
323 const unsigned char *end,
324 int (*f_rng)(void *, unsigned char *, size_t),
325 void *p_rng )
326{
327 int ret;
328 mbedtls_ecp_point V;
329 mbedtls_mpi v;
330 mbedtls_mpi h; /* later recycled to hold r */
331 size_t len;
332
333 if( end < *p )
334 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
335
336 mbedtls_ecp_point_init( &V );
337 mbedtls_mpi_init( &v );
338 mbedtls_mpi_init( &h );
339
340 /* Compute signature */
341 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp,
342 G, &v, &V, f_rng, p_rng ) );
Robert Cragie7cdad772015-10-02 13:31:41 +0100343 MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) );
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200344 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &h, &h, x ) ); /* x*h */
345 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &h, &v, &h ) ); /* v - x*h */
346 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &h, &h, &grp->N ) ); /* r */
347
348 /* Write it out */
349 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, &V,
Robert Cragie7cdad772015-10-02 13:31:41 +0100350 pf, &len, *p, end - *p ) );
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200351 *p += len;
352
353 len = mbedtls_mpi_size( &h ); /* actually r */
354 if( end < *p || (size_t)( end - *p ) < 1 + len || len > 255 )
355 {
356 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
357 goto cleanup;
358 }
359
360 *(*p)++ = (unsigned char)( len & 0xFF );
361 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, *p, len ) ); /* r */
362 *p += len;
363
364cleanup:
365 mbedtls_ecp_point_free( &V );
366 mbedtls_mpi_free( &v );
367 mbedtls_mpi_free( &h );
368
369 return( ret );
370}
371
372/*
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200373 * Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof
374 * Output: verified public key X
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200375 */
376static int ecjpake_kkp_read( const mbedtls_md_info_t *md_info,
377 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100378 const int pf,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200379 const mbedtls_ecp_point *G,
380 mbedtls_ecp_point *X,
381 const char *id,
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200382 const unsigned char **p,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200383 const unsigned char *end )
384{
385 int ret;
386
387 if( end < *p )
388 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
389
390 /*
391 * struct {
392 * ECPoint X;
393 * ECSchnorrZKP zkp;
394 * } ECJPAKEKeyKP;
395 */
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200396 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, X, p, end - *p ) );
Manuel Pégourié-Gonnard30590952015-08-17 10:37:40 +0200397 if( mbedtls_ecp_is_zero( X ) )
398 {
399 ret = MBEDTLS_ERR_ECP_INVALID_KEY;
400 goto cleanup;
401 }
402
Robert Cragie7cdad772015-10-02 13:31:41 +0100403 MBEDTLS_MPI_CHK( ecjpake_zkp_read( md_info, grp, pf, G, X, id, p, end ) );
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200404
405cleanup:
406 return( ret );
407}
408
409/*
410 * Generate an ECJPAKEKeyKP
411 * Output: the serialized structure, plus private/public key pair
412 */
413static int ecjpake_kkp_write( const mbedtls_md_info_t *md_info,
414 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100415 const int pf,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200416 const mbedtls_ecp_point *G,
417 mbedtls_mpi *x,
418 mbedtls_ecp_point *X,
419 const char *id,
420 unsigned char **p,
421 const unsigned char *end,
422 int (*f_rng)(void *, unsigned char *, size_t),
423 void *p_rng )
424{
425 int ret;
426 size_t len;
427
428 if( end < *p )
429 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
430
431 /* Generate key (7.4.2.3.1) and write it out */
432 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp, G, x, X,
433 f_rng, p_rng ) );
434 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, X,
Robert Cragie7cdad772015-10-02 13:31:41 +0100435 pf, &len, *p, end - *p ) );
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200436 *p += len;
437
438 /* Generate and write proof */
Robert Cragie7cdad772015-10-02 13:31:41 +0100439 MBEDTLS_MPI_CHK( ecjpake_zkp_write( md_info, grp, pf, G, x, X, id,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200440 p, end, f_rng, p_rng ) );
441
442cleanup:
443 return( ret );
444}
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200445
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200446/*
447 * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs
448 * Ouputs: verified peer public keys Xa, Xb
449 */
450static int ecjpake_kkpp_read( const mbedtls_md_info_t *md_info,
451 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100452 const int pf,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200453 const mbedtls_ecp_point *G,
454 mbedtls_ecp_point *Xa,
455 mbedtls_ecp_point *Xb,
456 const char *id,
457 const unsigned char *buf,
458 size_t len )
459{
460 int ret;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200461 const unsigned char *p = buf;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200462 const unsigned char *end = buf + len;
463
464 /*
465 * struct {
466 * ECJPAKEKeyKP ecjpake_key_kp_pair_list[2];
467 * } ECJPAKEKeyKPPairList;
468 */
Robert Cragie7cdad772015-10-02 13:31:41 +0100469 MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xa, id, &p, end ) );
470 MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xb, id, &p, end ) );
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200471
472 if( p != end )
473 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
474
475cleanup:
476 return( ret );
477}
478
479/*
480 * Generate a ECJPAKEKeyKPPairList
481 * Outputs: the serialized structure, plus two private/public key pairs
482 */
483static int ecjpake_kkpp_write( const mbedtls_md_info_t *md_info,
484 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100485 const int pf,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200486 const mbedtls_ecp_point *G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200487 mbedtls_mpi *xm1,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200488 mbedtls_ecp_point *Xa,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200489 mbedtls_mpi *xm2,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200490 mbedtls_ecp_point *Xb,
491 const char *id,
492 unsigned char *buf,
493 size_t len,
494 size_t *olen,
495 int (*f_rng)(void *, unsigned char *, size_t),
496 void *p_rng )
497{
498 int ret;
499 unsigned char *p = buf;
500 const unsigned char *end = buf + len;
501
Robert Cragie7cdad772015-10-02 13:31:41 +0100502 MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm1, Xa, id,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200503 &p, end, f_rng, p_rng ) );
Robert Cragie7cdad772015-10-02 13:31:41 +0100504 MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm2, Xb, id,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200505 &p, end, f_rng, p_rng ) );
506
507 *olen = p - buf;
508
509cleanup:
510 return( ret );
511}
512
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200513/*
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200514 * Read and process the first round message
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200515 */
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200516int mbedtls_ecjpake_read_round_one( mbedtls_ecjpake_context *ctx,
517 const unsigned char *buf,
518 size_t len )
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200519{
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000520 ECJPAKE_VALIDATE_RET( ctx != NULL );
521 ECJPAKE_VALIDATE_RET( buf != NULL );
522
Robert Cragie7cdad772015-10-02 13:31:41 +0100523 return( ecjpake_kkpp_read( ctx->md_info, &ctx->grp, ctx->point_format,
524 &ctx->grp.G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200525 &ctx->Xp1, &ctx->Xp2, ID_PEER,
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200526 buf, len ) );
527}
528
529/*
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200530 * Generate and write the first round message
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200531 */
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200532int mbedtls_ecjpake_write_round_one( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200533 unsigned char *buf, size_t len, size_t *olen,
534 int (*f_rng)(void *, unsigned char *, size_t),
535 void *p_rng )
536{
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000537 ECJPAKE_VALIDATE_RET( ctx != NULL );
538 ECJPAKE_VALIDATE_RET( buf != NULL );
539 ECJPAKE_VALIDATE_RET( olen != NULL );
540 ECJPAKE_VALIDATE_RET( f_rng != NULL );
541
Robert Cragie7cdad772015-10-02 13:31:41 +0100542 return( ecjpake_kkpp_write( ctx->md_info, &ctx->grp, ctx->point_format,
543 &ctx->grp.G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200544 &ctx->xm1, &ctx->Xm1, &ctx->xm2, &ctx->Xm2,
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200545 ID_MINE, buf, len, olen, f_rng, p_rng ) );
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200546}
547
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200548/*
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200549 * Compute the sum of three points R = A + B + C
550 */
551static int ecjpake_ecp_add3( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
552 const mbedtls_ecp_point *A,
553 const mbedtls_ecp_point *B,
554 const mbedtls_ecp_point *C )
555{
556 int ret;
557 mbedtls_mpi one;
558
559 mbedtls_mpi_init( &one );
560
561 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
562 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, A, &one, B ) );
563 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, R, &one, C ) );
564
565cleanup:
566 mbedtls_mpi_free( &one );
567
568 return( ret );
569}
570
571/*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200572 * 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 +0200573 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200574int mbedtls_ecjpake_read_round_two( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200575 const unsigned char *buf,
576 size_t len )
577{
578 int ret;
579 const unsigned char *p = buf;
580 const unsigned char *end = buf + len;
581 mbedtls_ecp_group grp;
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200582 mbedtls_ecp_point G; /* C: GB, S: GA */
Hanno Becker185e5162018-12-19 09:48:50 +0000583
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000584 ECJPAKE_VALIDATE_RET( ctx != NULL );
585 ECJPAKE_VALIDATE_RET( buf != NULL );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200586
587 mbedtls_ecp_group_init( &grp );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200588 mbedtls_ecp_point_init( &G );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200589
590 /*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200591 * Server: GA = X3 + X4 + X1 (7.4.2.6.1)
592 * Client: GB = X1 + X2 + X3 (7.4.2.5.1)
593 * Unified: G = Xm1 + Xm2 + Xp1
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200594 * We need that before parsing in order to check Xp as we read it
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200595 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200596 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200597 &ctx->Xm1, &ctx->Xm2, &ctx->Xp1 ) );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200598
599 /*
600 * struct {
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200601 * ECParameters curve_params; // only client reading server msg
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200602 * ECJPAKEKeyKP ecjpake_key_kp;
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200603 * } Client/ServerECJPAKEParams;
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200604 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200605 if( ctx->role == MBEDTLS_ECJPAKE_CLIENT )
Manuel Pégourié-Gonnardd9802af2015-08-17 12:47:38 +0200606 {
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200607 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_group( &grp, &p, len ) );
Manuel Pégourié-Gonnardd9802af2015-08-17 12:47:38 +0200608 if( grp.id != ctx->grp.id )
609 {
610 ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
611 goto cleanup;
612 }
613 }
614
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200615 MBEDTLS_MPI_CHK( ecjpake_kkp_read( ctx->md_info, &ctx->grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100616 ctx->point_format,
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200617 &G, &ctx->Xp, ID_PEER, &p, end ) );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200618
619 if( p != end )
620 {
621 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
622 goto cleanup;
623 }
624
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200625cleanup:
626 mbedtls_ecp_group_free( &grp );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200627 mbedtls_ecp_point_free( &G );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200628
629 return( ret );
630}
631
632/*
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200633 * Compute R = +/- X * S mod N, taking care not to leak S
634 */
635static int ecjpake_mul_secret( mbedtls_mpi *R, int sign,
636 const mbedtls_mpi *X,
637 const mbedtls_mpi *S,
638 const mbedtls_mpi *N,
639 int (*f_rng)(void *, unsigned char *, size_t),
640 void *p_rng )
641{
642 int ret;
643 mbedtls_mpi b; /* Blinding value, then s + N * blinding */
644
645 mbedtls_mpi_init( &b );
646
647 /* b = s + rnd-128-bit * N */
648 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &b, 16, f_rng, p_rng ) );
649 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &b, &b, N ) );
650 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &b, &b, S ) );
651
652 /* R = sign * X * b mod N */
653 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( R, X, &b ) );
654 R->s *= sign;
655 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( R, R, N ) );
656
657cleanup:
658 mbedtls_mpi_free( &b );
659
660 return( ret );
661}
662
663/*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200664 * 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 +0200665 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200666int mbedtls_ecjpake_write_round_two( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200667 unsigned char *buf, size_t len, size_t *olen,
668 int (*f_rng)(void *, unsigned char *, size_t),
669 void *p_rng )
670{
671 int ret;
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200672 mbedtls_ecp_point G; /* C: GA, S: GB */
673 mbedtls_ecp_point Xm; /* C: Xc, S: Xs */
674 mbedtls_mpi xm; /* C: xc, S: xs */
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200675 unsigned char *p = buf;
676 const unsigned char *end = buf + len;
677 size_t ec_len;
Hanno Becker185e5162018-12-19 09:48:50 +0000678
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000679 ECJPAKE_VALIDATE_RET( ctx != NULL );
680 ECJPAKE_VALIDATE_RET( buf != NULL );
681 ECJPAKE_VALIDATE_RET( olen != NULL );
682 ECJPAKE_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200683
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200684 mbedtls_ecp_point_init( &G );
685 mbedtls_ecp_point_init( &Xm );
686 mbedtls_mpi_init( &xm );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200687
688 /*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200689 * 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 +0200690 *
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200691 * Client: GA = X1 + X3 + X4 | xs = x2 * s | Xc = xc * GA
692 * Server: GB = X3 + X1 + X2 | xs = x4 * s | Xs = xs * GB
693 * Unified: G = Xm1 + Xp1 + Xp2 | xm = xm2 * s | Xm = xm * G
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200694 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200695 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200696 &ctx->Xp1, &ctx->Xp2, &ctx->Xm1 ) );
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200697 MBEDTLS_MPI_CHK( ecjpake_mul_secret( &xm, 1, &ctx->xm2, &ctx->s,
698 &ctx->grp.N, f_rng, p_rng ) );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200699 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &Xm, &xm, &G, f_rng, p_rng ) );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200700
701 /*
702 * Now write things out
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200703 *
704 * struct {
705 * ECParameters curve_params; // only server writing its message
706 * ECJPAKEKeyKP ecjpake_key_kp;
707 * } Client/ServerECJPAKEParams;
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200708 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200709 if( ctx->role == MBEDTLS_ECJPAKE_SERVER )
710 {
711 if( end < p )
712 {
713 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
714 goto cleanup;
715 }
716 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_group( &ctx->grp, &ec_len,
717 p, end - p ) );
718 p += ec_len;
719 }
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200720
721 if( end < p )
722 {
723 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
724 goto cleanup;
725 }
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200726 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( &ctx->grp, &Xm,
Robert Cragie7cdad772015-10-02 13:31:41 +0100727 ctx->point_format, &ec_len, p, end - p ) );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200728 p += ec_len;
729
730 MBEDTLS_MPI_CHK( ecjpake_zkp_write( ctx->md_info, &ctx->grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100731 ctx->point_format,
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200732 &G, &xm, &Xm, ID_MINE,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200733 &p, end, f_rng, p_rng ) );
734
735 *olen = p - buf;
736
737cleanup:
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200738 mbedtls_ecp_point_free( &G );
739 mbedtls_ecp_point_free( &Xm );
740 mbedtls_mpi_free( &xm );
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +0200741
742 return( ret );
743}
744
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200745/*
746 * Derive PMS (7.4.2.7 / 7.4.2.8)
747 */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +0200748int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200749 unsigned char *buf, size_t len, size_t *olen,
750 int (*f_rng)(void *, unsigned char *, size_t),
751 void *p_rng )
752{
753 int ret;
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200754 mbedtls_ecp_point K;
755 mbedtls_mpi m_xm2_s, one;
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200756 unsigned char kx[MBEDTLS_ECP_MAX_BYTES];
757 size_t x_bytes;
Hanno Becker185e5162018-12-19 09:48:50 +0000758
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000759 ECJPAKE_VALIDATE_RET( ctx != NULL );
760 ECJPAKE_VALIDATE_RET( buf != NULL );
761 ECJPAKE_VALIDATE_RET( olen != NULL );
762 ECJPAKE_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200763
764 *olen = mbedtls_md_get_size( ctx->md_info );
765 if( len < *olen )
766 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
767
768 mbedtls_ecp_point_init( &K );
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200769 mbedtls_mpi_init( &m_xm2_s );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200770 mbedtls_mpi_init( &one );
771
772 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200773
774 /*
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200775 * Client: K = ( Xs - X4 * x2 * s ) * x2
776 * Server: K = ( Xc - X2 * x4 * s ) * x4
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200777 * Unified: K = ( Xp - Xp2 * xm2 * s ) * xm2
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200778 */
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200779 MBEDTLS_MPI_CHK( ecjpake_mul_secret( &m_xm2_s, -1, &ctx->xm2, &ctx->s,
780 &ctx->grp.N, f_rng, p_rng ) );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200781 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( &ctx->grp, &K,
782 &one, &ctx->Xp,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200783 &m_xm2_s, &ctx->Xp2 ) );
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200784 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &K, &ctx->xm2, &K,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200785 f_rng, p_rng ) );
786
787 /* PMS = SHA-256( K.X ) */
788 x_bytes = ( ctx->grp.pbits + 7 ) / 8;
789 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &K.X, kx, x_bytes ) );
790 MBEDTLS_MPI_CHK( mbedtls_md( ctx->md_info, kx, x_bytes, buf ) );
791
792cleanup:
793 mbedtls_ecp_point_free( &K );
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200794 mbedtls_mpi_free( &m_xm2_s );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200795 mbedtls_mpi_free( &one );
796
797 return( ret );
798}
799
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200800#undef ID_MINE
801#undef ID_PEER
802
Hanno Becker616d1ca2018-01-24 10:25:05 +0000803#endif /* ! MBEDTLS_ECJPAKE_ALT */
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200804
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200805#if defined(MBEDTLS_SELF_TEST)
806
807#if defined(MBEDTLS_PLATFORM_C)
808#include "mbedtls/platform.h"
809#else
810#include <stdio.h>
811#define mbedtls_printf printf
812#endif
813
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200814#if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
815 !defined(MBEDTLS_SHA256_C)
816int mbedtls_ecjpake_self_test( int verbose )
817{
818 (void) verbose;
819 return( 0 );
820}
821#else
822
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200823static const unsigned char ecjpake_test_password[] = {
824 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x6a, 0x70, 0x61, 0x6b, 0x65, 0x74,
825 0x65, 0x73, 0x74
826};
827
828static const unsigned char ecjpake_test_x1[] = {
829 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
830 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
831 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21
832};
833
834static const unsigned char ecjpake_test_x2[] = {
835 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
836 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
837 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
838};
839
840static const unsigned char ecjpake_test_x3[] = {
841 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
842 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
843 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
844};
845
846static const unsigned char ecjpake_test_x4[] = {
847 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc,
848 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
849 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1
850};
851
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200852static const unsigned char ecjpake_test_cli_one[] = {
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200853 0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19,
854 0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44,
855 0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad,
856 0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62,
857 0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9,
858 0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d,
859 0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e,
860 0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e,
861 0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73,
862 0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22,
863 0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce,
864 0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00,
865 0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200866 0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e,
867 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62,
868 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5,
869 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb,
870 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35,
871 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0,
872 0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb,
873 0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47,
874 0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39,
875 0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97,
876 0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40,
877 0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d,
878 0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa,
879 0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d,
880 0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200881};
882
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200883static const unsigned char ecjpake_test_srv_one[] = {
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200884 0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb,
885 0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18,
886 0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47,
887 0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f,
888 0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7,
889 0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d,
890 0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64,
891 0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36,
892 0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2,
893 0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec,
894 0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16,
895 0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96,
896 0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3,
897 0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19,
898 0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f,
899 0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8,
900 0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7,
901 0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea,
902 0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5,
903 0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6,
904 0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31,
905 0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d,
906 0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8,
907 0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee,
908 0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84,
909 0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f,
910 0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80,
911 0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12
912};
913
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200914static const unsigned char ecjpake_test_srv_two[] = {
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200915 0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23,
916 0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c,
917 0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f,
918 0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca,
919 0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26,
920 0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55,
921 0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38,
922 0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6,
923 0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9,
924 0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4,
925 0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2,
926 0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8,
927 0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd,
928 0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c
929};
930
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200931static const unsigned char ecjpake_test_cli_two[] = {
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +0200932 0x41, 0x04, 0x69, 0xd5, 0x4e, 0xe8, 0x5e, 0x90, 0xce, 0x3f, 0x12, 0x46,
933 0x74, 0x2d, 0xe5, 0x07, 0xe9, 0x39, 0xe8, 0x1d, 0x1d, 0xc1, 0xc5, 0xcb,
934 0x98, 0x8b, 0x58, 0xc3, 0x10, 0xc9, 0xfd, 0xd9, 0x52, 0x4d, 0x93, 0x72,
935 0x0b, 0x45, 0x54, 0x1c, 0x83, 0xee, 0x88, 0x41, 0x19, 0x1d, 0xa7, 0xce,
936 0xd8, 0x6e, 0x33, 0x12, 0xd4, 0x36, 0x23, 0xc1, 0xd6, 0x3e, 0x74, 0x98,
937 0x9a, 0xba, 0x4a, 0xff, 0xd1, 0xee, 0x41, 0x04, 0x07, 0x7e, 0x8c, 0x31,
938 0xe2, 0x0e, 0x6b, 0xed, 0xb7, 0x60, 0xc1, 0x35, 0x93, 0xe6, 0x9f, 0x15,
939 0xbe, 0x85, 0xc2, 0x7d, 0x68, 0xcd, 0x09, 0xcc, 0xb8, 0xc4, 0x18, 0x36,
940 0x08, 0x91, 0x7c, 0x5c, 0x3d, 0x40, 0x9f, 0xac, 0x39, 0xfe, 0xfe, 0xe8,
941 0x2f, 0x72, 0x92, 0xd3, 0x6f, 0x0d, 0x23, 0xe0, 0x55, 0x91, 0x3f, 0x45,
942 0xa5, 0x2b, 0x85, 0xdd, 0x8a, 0x20, 0x52, 0xe9, 0xe1, 0x29, 0xbb, 0x4d,
943 0x20, 0x0f, 0x01, 0x1f, 0x19, 0x48, 0x35, 0x35, 0xa6, 0xe8, 0x9a, 0x58,
944 0x0c, 0x9b, 0x00, 0x03, 0xba, 0xf2, 0x14, 0x62, 0xec, 0xe9, 0x1a, 0x82,
945 0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c
946};
947
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200948static const unsigned char ecjpake_test_pms[] = {
949 0xf3, 0xd4, 0x7f, 0x59, 0x98, 0x44, 0xdb, 0x92, 0xa5, 0x69, 0xbb, 0xe7,
950 0x98, 0x1e, 0x39, 0xd9, 0x31, 0xfd, 0x74, 0x3b, 0xf2, 0x2e, 0x98, 0xf9,
951 0xb4, 0x38, 0xf7, 0x19, 0xd3, 0xc4, 0xf3, 0x51
952};
953
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +0200954/* Load my private keys and generate the correponding public keys */
955static int ecjpake_test_load( mbedtls_ecjpake_context *ctx,
956 const unsigned char *xm1, size_t len1,
957 const unsigned char *xm2, size_t len2 )
958{
959 int ret;
960
961 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm1, xm1, len1 ) );
962 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm2, xm2, len2 ) );
963 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm1, &ctx->xm1,
964 &ctx->grp.G, NULL, NULL ) );
965 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm2, &ctx->xm2,
966 &ctx->grp.G, NULL, NULL ) );
967
968cleanup:
969 return( ret );
970}
971
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200972/* For tests we don't need a secure RNG;
973 * use the LGC from Numerical Recipes for simplicity */
974static int ecjpake_lgc( void *p, unsigned char *out, size_t len )
975{
976 static uint32_t x = 42;
977 (void) p;
978
979 while( len > 0 )
980 {
981 size_t use_len = len > 4 ? 4 : len;
982 x = 1664525 * x + 1013904223;
983 memcpy( out, &x, use_len );
984 out += use_len;
985 len -= use_len;
986 }
987
988 return( 0 );
989}
990
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200991#define TEST_ASSERT( x ) \
992 do { \
993 if( x ) \
994 ret = 0; \
995 else \
996 { \
997 ret = 1; \
998 goto cleanup; \
999 } \
1000 } while( 0 )
1001
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001002/*
1003 * Checkup routine
1004 */
1005int mbedtls_ecjpake_self_test( int verbose )
1006{
1007 int ret;
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001008 mbedtls_ecjpake_context cli;
1009 mbedtls_ecjpake_context srv;
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001010 unsigned char buf[512], pms[32];
1011 size_t len, pmslen;
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001012
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001013 mbedtls_ecjpake_init( &cli );
1014 mbedtls_ecjpake_init( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001015
1016 if( verbose != 0 )
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001017 mbedtls_printf( " ECJPAKE test #0 (setup): " );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +02001018
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +02001019 TEST_ASSERT( mbedtls_ecjpake_setup( &cli, MBEDTLS_ECJPAKE_CLIENT,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001020 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1021 ecjpake_test_password,
1022 sizeof( ecjpake_test_password ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001023
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +02001024 TEST_ASSERT( mbedtls_ecjpake_setup( &srv, MBEDTLS_ECJPAKE_SERVER,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001025 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1026 ecjpake_test_password,
1027 sizeof( ecjpake_test_password ) ) == 0 );
1028
1029 if( verbose != 0 )
1030 mbedtls_printf( "passed\n" );
1031
1032 if( verbose != 0 )
1033 mbedtls_printf( " ECJPAKE test #1 (random handshake): " );
1034
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001035 TEST_ASSERT( mbedtls_ecjpake_write_round_one( &cli,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001036 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1037
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001038 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv, buf, len ) == 0 );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001039
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001040 TEST_ASSERT( mbedtls_ecjpake_write_round_one( &srv,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001041 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1042
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001043 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli, buf, len ) == 0 );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001044
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001045 TEST_ASSERT( mbedtls_ecjpake_write_round_two( &srv,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +02001046 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1047
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001048 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli, buf, len ) == 0 );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +02001049
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001050 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001051 pms, sizeof( pms ), &pmslen, ecjpake_lgc, NULL ) == 0 );
1052
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001053 TEST_ASSERT( mbedtls_ecjpake_write_round_two( &cli,
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +02001054 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1055
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001056 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv, buf, len ) == 0 );
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +02001057
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001058 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001059 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1060
1061 TEST_ASSERT( len == pmslen );
1062 TEST_ASSERT( memcmp( buf, pms, len ) == 0 );
1063
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001064 if( verbose != 0 )
1065 mbedtls_printf( "passed\n" );
1066
1067 if( verbose != 0 )
1068 mbedtls_printf( " ECJPAKE test #2 (reference handshake): " );
1069
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001070 /* Simulate generation of round one */
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001071 MBEDTLS_MPI_CHK( ecjpake_test_load( &cli,
1072 ecjpake_test_x1, sizeof( ecjpake_test_x1 ),
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001073 ecjpake_test_x2, sizeof( ecjpake_test_x2 ) ) );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001074
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001075 MBEDTLS_MPI_CHK( ecjpake_test_load( &srv,
1076 ecjpake_test_x3, sizeof( ecjpake_test_x3 ),
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001077 ecjpake_test_x4, sizeof( ecjpake_test_x4 ) ) );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001078
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001079 /* Read round one */
1080 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv,
1081 ecjpake_test_cli_one,
1082 sizeof( ecjpake_test_cli_one ) ) == 0 );
1083
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001084 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001085 ecjpake_test_srv_one,
1086 sizeof( ecjpake_test_srv_one ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001087
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001088 /* Skip generation of round two, read round two */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001089 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001090 ecjpake_test_srv_two,
1091 sizeof( ecjpake_test_srv_two ) ) == 0 );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +02001092
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001093 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001094 ecjpake_test_cli_two,
1095 sizeof( ecjpake_test_cli_two ) ) == 0 );
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +02001096
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001097 /* Server derives PMS */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001098 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv,
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
1104 memset( buf, 0, len ); /* Avoid interferences with next step */
1105
1106 /* Client derives PMS */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001107 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001108 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1109
1110 TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
1111 TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
1112
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001113 if( verbose != 0 )
1114 mbedtls_printf( "passed\n" );
1115
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001116cleanup:
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001117 mbedtls_ecjpake_free( &cli );
1118 mbedtls_ecjpake_free( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001119
1120 if( ret != 0 )
1121 {
1122 if( verbose != 0 )
1123 mbedtls_printf( "failed\n" );
1124
1125 ret = 1;
1126 }
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001127
1128 if( verbose != 0 )
1129 mbedtls_printf( "\n" );
1130
1131 return( ret );
1132}
1133
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +02001134#undef TEST_ASSERT
1135
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001136#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_SHA256_C */
1137
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001138#endif /* MBEDTLS_SELF_TEST */
1139
1140#endif /* MBEDTLS_ECJPAKE_C */