blob: c5ab4cbba5849cf6c78d6a75741aeb910544fac7 [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 Becker71c8e1b2018-12-14 17:09:39 +0000114 ECJPAKE_VALIDATE_RET( ctx != NULL );
115 ECJPAKE_VALIDATE_RET( role == MBEDTLS_ECJPAKE_CLIENT ||
116 role == MBEDTLS_ECJPAKE_SERVER );
117 ECJPAKE_VALIDATE_RET( secret != NULL || len == 0 );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200118
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +0200119 ctx->role = role;
120
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200121 if( ( ctx->md_info = mbedtls_md_info_from_type( hash ) ) == NULL )
122 return( MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE );
123
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200124 MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ctx->grp, curve ) );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200125
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200126 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->s, secret, len ) );
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200127
128cleanup:
129 if( ret != 0 )
130 mbedtls_ecjpake_free( ctx );
131
132 return( ret );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200133}
134
135/*
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200136 * Check if context is ready for use
137 */
138int mbedtls_ecjpake_check( const mbedtls_ecjpake_context *ctx )
139{
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000140 ECJPAKE_VALIDATE_RET( ctx != NULL );
141
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200142 if( ctx->md_info == NULL ||
143 ctx->grp.id == MBEDTLS_ECP_DP_NONE ||
144 ctx->s.p == NULL )
145 {
146 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
147 }
148
149 return( 0 );
150}
151
152/*
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200153 * Write a point plus its length to a buffer
154 */
155static int ecjpake_write_len_point( unsigned char **p,
156 const unsigned char *end,
157 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100158 const int pf,
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200159 const mbedtls_ecp_point *P )
160{
161 int ret;
162 size_t len;
163
164 /* Need at least 4 for length plus 1 for point */
165 if( end < *p || end - *p < 5 )
166 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
167
Robert Cragie7cdad772015-10-02 13:31:41 +0100168 ret = mbedtls_ecp_point_write_binary( grp, P, pf,
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200169 &len, *p + 4, end - ( *p + 4 ) );
170 if( ret != 0 )
171 return( ret );
172
173 (*p)[0] = (unsigned char)( ( len >> 24 ) & 0xFF );
174 (*p)[1] = (unsigned char)( ( len >> 16 ) & 0xFF );
175 (*p)[2] = (unsigned char)( ( len >> 8 ) & 0xFF );
176 (*p)[3] = (unsigned char)( ( len ) & 0xFF );
177
178 *p += 4 + len;
179
180 return( 0 );
181}
182
183/*
184 * Size of the temporary buffer for ecjpake_hash:
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200185 * 3 EC points plus their length, plus ID and its length (4 + 6 bytes)
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200186 */
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200187#define ECJPAKE_HASH_BUF_LEN ( 3 * ( 4 + MBEDTLS_ECP_MAX_PT_LEN ) + 4 + 6 )
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200188
189/*
190 * Compute hash for ZKP (7.4.2.2.2.1)
191 */
192static int ecjpake_hash( const mbedtls_md_info_t *md_info,
193 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100194 const int pf,
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200195 const mbedtls_ecp_point *G,
196 const mbedtls_ecp_point *V,
197 const mbedtls_ecp_point *X,
198 const char *id,
199 mbedtls_mpi *h )
200{
201 int ret;
202 unsigned char buf[ECJPAKE_HASH_BUF_LEN];
203 unsigned char *p = buf;
204 const unsigned char *end = buf + sizeof( buf );
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200205 const size_t id_len = strlen( id );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200206 unsigned char hash[MBEDTLS_MD_MAX_SIZE];
207
208 /* Write things to temporary buffer */
Robert Cragie7cdad772015-10-02 13:31:41 +0100209 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, G ) );
210 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, V ) );
211 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, X ) );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200212
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200213 if( end - p < 4 )
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200214 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
215
216 *p++ = (unsigned char)( ( id_len >> 24 ) & 0xFF );
217 *p++ = (unsigned char)( ( id_len >> 16 ) & 0xFF );
218 *p++ = (unsigned char)( ( id_len >> 8 ) & 0xFF );
219 *p++ = (unsigned char)( ( id_len ) & 0xFF );
220
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200221 if( end < p || (size_t)( end - p ) < id_len )
222 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
223
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200224 memcpy( p, id, id_len );
225 p += id_len;
226
227 /* Compute hash */
228 mbedtls_md( md_info, buf, p - buf, hash );
229
230 /* Turn it into an integer mod n */
231 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( h, hash,
232 mbedtls_md_get_size( md_info ) ) );
233 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( h, h, &grp->N ) );
234
235cleanup:
236 return( ret );
237}
238
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200239/*
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200240 * Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3)
241 */
242static int ecjpake_zkp_read( const mbedtls_md_info_t *md_info,
243 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100244 const int pf,
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200245 const mbedtls_ecp_point *G,
246 const mbedtls_ecp_point *X,
247 const char *id,
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200248 const unsigned char **p,
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200249 const unsigned char *end )
250{
251 int ret;
252 mbedtls_ecp_point V, VV;
253 mbedtls_mpi r, h;
254 size_t r_len;
255
256 mbedtls_ecp_point_init( &V );
257 mbedtls_ecp_point_init( &VV );
258 mbedtls_mpi_init( &r );
259 mbedtls_mpi_init( &h );
260
261 /*
262 * struct {
263 * ECPoint V;
264 * opaque r<1..2^8-1>;
265 * } ECSchnorrZKP;
266 */
267 if( end < *p )
268 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
269
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200270 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, &V, p, end - *p ) );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200271
272 if( end < *p || (size_t)( end - *p ) < 1 )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200273 {
274 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
275 goto cleanup;
276 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200277
278 r_len = *(*p)++;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200279
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200280 if( end < *p || (size_t)( end - *p ) < r_len )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200281 {
282 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
283 goto cleanup;
284 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200285
286 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &r, *p, r_len ) );
287 *p += r_len;
288
289 /*
290 * Verification
291 */
Robert Cragie7cdad772015-10-02 13:31:41 +0100292 MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200293 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( (mbedtls_ecp_group *) grp,
294 &VV, &h, X, &r, G ) );
295
296 if( mbedtls_ecp_point_cmp( &VV, &V ) != 0 )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200297 {
298 ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
299 goto cleanup;
300 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200301
302cleanup:
303 mbedtls_ecp_point_free( &V );
304 mbedtls_ecp_point_free( &VV );
305 mbedtls_mpi_free( &r );
306 mbedtls_mpi_free( &h );
307
308 return( ret );
309}
310
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200311/*
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200312 * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2)
313 */
314static int ecjpake_zkp_write( const mbedtls_md_info_t *md_info,
315 const mbedtls_ecp_group *grp,
Darryl Green11999bb2018-03-13 15:22:58 +0000316 const int pf,
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200317 const mbedtls_ecp_point *G,
318 const mbedtls_mpi *x,
319 const mbedtls_ecp_point *X,
320 const char *id,
321 unsigned char **p,
322 const unsigned char *end,
323 int (*f_rng)(void *, unsigned char *, size_t),
324 void *p_rng )
325{
326 int ret;
327 mbedtls_ecp_point V;
328 mbedtls_mpi v;
329 mbedtls_mpi h; /* later recycled to hold r */
330 size_t len;
331
332 if( end < *p )
333 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
334
335 mbedtls_ecp_point_init( &V );
336 mbedtls_mpi_init( &v );
337 mbedtls_mpi_init( &h );
338
339 /* Compute signature */
340 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp,
341 G, &v, &V, f_rng, p_rng ) );
Robert Cragie7cdad772015-10-02 13:31:41 +0100342 MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) );
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200343 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &h, &h, x ) ); /* x*h */
344 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &h, &v, &h ) ); /* v - x*h */
345 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &h, &h, &grp->N ) ); /* r */
346
347 /* Write it out */
348 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, &V,
Robert Cragie7cdad772015-10-02 13:31:41 +0100349 pf, &len, *p, end - *p ) );
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200350 *p += len;
351
352 len = mbedtls_mpi_size( &h ); /* actually r */
353 if( end < *p || (size_t)( end - *p ) < 1 + len || len > 255 )
354 {
355 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
356 goto cleanup;
357 }
358
359 *(*p)++ = (unsigned char)( len & 0xFF );
360 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, *p, len ) ); /* r */
361 *p += len;
362
363cleanup:
364 mbedtls_ecp_point_free( &V );
365 mbedtls_mpi_free( &v );
366 mbedtls_mpi_free( &h );
367
368 return( ret );
369}
370
371/*
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200372 * Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof
373 * Output: verified public key X
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200374 */
375static int ecjpake_kkp_read( const mbedtls_md_info_t *md_info,
376 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100377 const int pf,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200378 const mbedtls_ecp_point *G,
379 mbedtls_ecp_point *X,
380 const char *id,
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200381 const unsigned char **p,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200382 const unsigned char *end )
383{
384 int ret;
385
386 if( end < *p )
387 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
388
389 /*
390 * struct {
391 * ECPoint X;
392 * ECSchnorrZKP zkp;
393 * } ECJPAKEKeyKP;
394 */
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200395 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, X, p, end - *p ) );
Manuel Pégourié-Gonnard30590952015-08-17 10:37:40 +0200396 if( mbedtls_ecp_is_zero( X ) )
397 {
398 ret = MBEDTLS_ERR_ECP_INVALID_KEY;
399 goto cleanup;
400 }
401
Robert Cragie7cdad772015-10-02 13:31:41 +0100402 MBEDTLS_MPI_CHK( ecjpake_zkp_read( md_info, grp, pf, G, X, id, p, end ) );
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200403
404cleanup:
405 return( ret );
406}
407
408/*
409 * Generate an ECJPAKEKeyKP
410 * Output: the serialized structure, plus private/public key pair
411 */
412static int ecjpake_kkp_write( const mbedtls_md_info_t *md_info,
413 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100414 const int pf,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200415 const mbedtls_ecp_point *G,
416 mbedtls_mpi *x,
417 mbedtls_ecp_point *X,
418 const char *id,
419 unsigned char **p,
420 const unsigned char *end,
421 int (*f_rng)(void *, unsigned char *, size_t),
422 void *p_rng )
423{
424 int ret;
425 size_t len;
426
427 if( end < *p )
428 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
429
430 /* Generate key (7.4.2.3.1) and write it out */
431 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp, G, x, X,
432 f_rng, p_rng ) );
433 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, X,
Robert Cragie7cdad772015-10-02 13:31:41 +0100434 pf, &len, *p, end - *p ) );
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200435 *p += len;
436
437 /* Generate and write proof */
Robert Cragie7cdad772015-10-02 13:31:41 +0100438 MBEDTLS_MPI_CHK( ecjpake_zkp_write( md_info, grp, pf, G, x, X, id,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200439 p, end, f_rng, p_rng ) );
440
441cleanup:
442 return( ret );
443}
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200444
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200445/*
446 * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs
447 * Ouputs: verified peer public keys Xa, Xb
448 */
449static int ecjpake_kkpp_read( const mbedtls_md_info_t *md_info,
450 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100451 const int pf,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200452 const mbedtls_ecp_point *G,
453 mbedtls_ecp_point *Xa,
454 mbedtls_ecp_point *Xb,
455 const char *id,
456 const unsigned char *buf,
457 size_t len )
458{
459 int ret;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200460 const unsigned char *p = buf;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200461 const unsigned char *end = buf + len;
462
463 /*
464 * struct {
465 * ECJPAKEKeyKP ecjpake_key_kp_pair_list[2];
466 * } ECJPAKEKeyKPPairList;
467 */
Robert Cragie7cdad772015-10-02 13:31:41 +0100468 MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xa, id, &p, end ) );
469 MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xb, id, &p, end ) );
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200470
471 if( p != end )
472 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
473
474cleanup:
475 return( ret );
476}
477
478/*
479 * Generate a ECJPAKEKeyKPPairList
480 * Outputs: the serialized structure, plus two private/public key pairs
481 */
482static int ecjpake_kkpp_write( const mbedtls_md_info_t *md_info,
483 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100484 const int pf,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200485 const mbedtls_ecp_point *G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200486 mbedtls_mpi *xm1,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200487 mbedtls_ecp_point *Xa,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200488 mbedtls_mpi *xm2,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200489 mbedtls_ecp_point *Xb,
490 const char *id,
491 unsigned char *buf,
492 size_t len,
493 size_t *olen,
494 int (*f_rng)(void *, unsigned char *, size_t),
495 void *p_rng )
496{
497 int ret;
498 unsigned char *p = buf;
499 const unsigned char *end = buf + len;
500
Robert Cragie7cdad772015-10-02 13:31:41 +0100501 MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm1, Xa, id,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200502 &p, end, f_rng, p_rng ) );
Robert Cragie7cdad772015-10-02 13:31:41 +0100503 MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm2, Xb, id,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200504 &p, end, f_rng, p_rng ) );
505
506 *olen = p - buf;
507
508cleanup:
509 return( ret );
510}
511
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200512/*
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200513 * Read and process the first round message
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200514 */
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200515int mbedtls_ecjpake_read_round_one( mbedtls_ecjpake_context *ctx,
516 const unsigned char *buf,
517 size_t len )
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200518{
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000519 ECJPAKE_VALIDATE_RET( ctx != NULL );
520 ECJPAKE_VALIDATE_RET( buf != NULL );
521
Robert Cragie7cdad772015-10-02 13:31:41 +0100522 return( ecjpake_kkpp_read( ctx->md_info, &ctx->grp, ctx->point_format,
523 &ctx->grp.G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200524 &ctx->Xp1, &ctx->Xp2, ID_PEER,
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200525 buf, len ) );
526}
527
528/*
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200529 * Generate and write the first round message
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200530 */
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200531int mbedtls_ecjpake_write_round_one( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200532 unsigned char *buf, size_t len, size_t *olen,
533 int (*f_rng)(void *, unsigned char *, size_t),
534 void *p_rng )
535{
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000536 ECJPAKE_VALIDATE_RET( ctx != NULL );
537 ECJPAKE_VALIDATE_RET( buf != NULL );
538 ECJPAKE_VALIDATE_RET( olen != NULL );
539 ECJPAKE_VALIDATE_RET( f_rng != NULL );
540
Robert Cragie7cdad772015-10-02 13:31:41 +0100541 return( ecjpake_kkpp_write( ctx->md_info, &ctx->grp, ctx->point_format,
542 &ctx->grp.G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200543 &ctx->xm1, &ctx->Xm1, &ctx->xm2, &ctx->Xm2,
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200544 ID_MINE, buf, len, olen, f_rng, p_rng ) );
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200545}
546
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200547/*
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200548 * Compute the sum of three points R = A + B + C
549 */
550static int ecjpake_ecp_add3( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
551 const mbedtls_ecp_point *A,
552 const mbedtls_ecp_point *B,
553 const mbedtls_ecp_point *C )
554{
555 int ret;
556 mbedtls_mpi one;
557
558 mbedtls_mpi_init( &one );
559
560 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
561 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, A, &one, B ) );
562 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, R, &one, C ) );
563
564cleanup:
565 mbedtls_mpi_free( &one );
566
567 return( ret );
568}
569
570/*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200571 * 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 +0200572 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200573int mbedtls_ecjpake_read_round_two( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200574 const unsigned char *buf,
575 size_t len )
576{
577 int ret;
578 const unsigned char *p = buf;
579 const unsigned char *end = buf + len;
580 mbedtls_ecp_group grp;
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200581 mbedtls_ecp_point G; /* C: GB, S: GA */
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000582 ECJPAKE_VALIDATE_RET( ctx != NULL );
583 ECJPAKE_VALIDATE_RET( buf != NULL );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200584
585 mbedtls_ecp_group_init( &grp );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200586 mbedtls_ecp_point_init( &G );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200587
588 /*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200589 * Server: GA = X3 + X4 + X1 (7.4.2.6.1)
590 * Client: GB = X1 + X2 + X3 (7.4.2.5.1)
591 * Unified: G = Xm1 + Xm2 + Xp1
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200592 * We need that before parsing in order to check Xp as we read it
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200593 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200594 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200595 &ctx->Xm1, &ctx->Xm2, &ctx->Xp1 ) );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200596
597 /*
598 * struct {
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200599 * ECParameters curve_params; // only client reading server msg
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200600 * ECJPAKEKeyKP ecjpake_key_kp;
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200601 * } Client/ServerECJPAKEParams;
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200602 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200603 if( ctx->role == MBEDTLS_ECJPAKE_CLIENT )
Manuel Pégourié-Gonnardd9802af2015-08-17 12:47:38 +0200604 {
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200605 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_group( &grp, &p, len ) );
Manuel Pégourié-Gonnardd9802af2015-08-17 12:47:38 +0200606 if( grp.id != ctx->grp.id )
607 {
608 ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
609 goto cleanup;
610 }
611 }
612
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200613 MBEDTLS_MPI_CHK( ecjpake_kkp_read( ctx->md_info, &ctx->grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100614 ctx->point_format,
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200615 &G, &ctx->Xp, ID_PEER, &p, end ) );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200616
617 if( p != end )
618 {
619 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
620 goto cleanup;
621 }
622
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200623cleanup:
624 mbedtls_ecp_group_free( &grp );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200625 mbedtls_ecp_point_free( &G );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200626
627 return( ret );
628}
629
630/*
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200631 * Compute R = +/- X * S mod N, taking care not to leak S
632 */
633static int ecjpake_mul_secret( mbedtls_mpi *R, int sign,
634 const mbedtls_mpi *X,
635 const mbedtls_mpi *S,
636 const mbedtls_mpi *N,
637 int (*f_rng)(void *, unsigned char *, size_t),
638 void *p_rng )
639{
640 int ret;
641 mbedtls_mpi b; /* Blinding value, then s + N * blinding */
642
643 mbedtls_mpi_init( &b );
644
645 /* b = s + rnd-128-bit * N */
646 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &b, 16, f_rng, p_rng ) );
647 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &b, &b, N ) );
648 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &b, &b, S ) );
649
650 /* R = sign * X * b mod N */
651 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( R, X, &b ) );
652 R->s *= sign;
653 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( R, R, N ) );
654
655cleanup:
656 mbedtls_mpi_free( &b );
657
658 return( ret );
659}
660
661/*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200662 * 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 +0200663 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200664int mbedtls_ecjpake_write_round_two( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200665 unsigned char *buf, size_t len, size_t *olen,
666 int (*f_rng)(void *, unsigned char *, size_t),
667 void *p_rng )
668{
669 int ret;
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200670 mbedtls_ecp_point G; /* C: GA, S: GB */
671 mbedtls_ecp_point Xm; /* C: Xc, S: Xs */
672 mbedtls_mpi xm; /* C: xc, S: xs */
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200673 unsigned char *p = buf;
674 const unsigned char *end = buf + len;
675 size_t ec_len;
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000676 ECJPAKE_VALIDATE_RET( ctx != NULL );
677 ECJPAKE_VALIDATE_RET( buf != NULL );
678 ECJPAKE_VALIDATE_RET( olen != NULL );
679 ECJPAKE_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200680
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200681 mbedtls_ecp_point_init( &G );
682 mbedtls_ecp_point_init( &Xm );
683 mbedtls_mpi_init( &xm );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200684
685 /*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200686 * 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 +0200687 *
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200688 * Client: GA = X1 + X3 + X4 | xs = x2 * s | Xc = xc * GA
689 * Server: GB = X3 + X1 + X2 | xs = x4 * s | Xs = xs * GB
690 * Unified: G = Xm1 + Xp1 + Xp2 | xm = xm2 * s | Xm = xm * G
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200691 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200692 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200693 &ctx->Xp1, &ctx->Xp2, &ctx->Xm1 ) );
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200694 MBEDTLS_MPI_CHK( ecjpake_mul_secret( &xm, 1, &ctx->xm2, &ctx->s,
695 &ctx->grp.N, f_rng, p_rng ) );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200696 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &Xm, &xm, &G, f_rng, p_rng ) );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200697
698 /*
699 * Now write things out
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200700 *
701 * struct {
702 * ECParameters curve_params; // only server writing its message
703 * ECJPAKEKeyKP ecjpake_key_kp;
704 * } Client/ServerECJPAKEParams;
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200705 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200706 if( ctx->role == MBEDTLS_ECJPAKE_SERVER )
707 {
708 if( end < p )
709 {
710 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
711 goto cleanup;
712 }
713 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_group( &ctx->grp, &ec_len,
714 p, end - p ) );
715 p += ec_len;
716 }
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200717
718 if( end < p )
719 {
720 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
721 goto cleanup;
722 }
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200723 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( &ctx->grp, &Xm,
Robert Cragie7cdad772015-10-02 13:31:41 +0100724 ctx->point_format, &ec_len, p, end - p ) );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200725 p += ec_len;
726
727 MBEDTLS_MPI_CHK( ecjpake_zkp_write( ctx->md_info, &ctx->grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100728 ctx->point_format,
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200729 &G, &xm, &Xm, ID_MINE,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200730 &p, end, f_rng, p_rng ) );
731
732 *olen = p - buf;
733
734cleanup:
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200735 mbedtls_ecp_point_free( &G );
736 mbedtls_ecp_point_free( &Xm );
737 mbedtls_mpi_free( &xm );
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +0200738
739 return( ret );
740}
741
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200742/*
743 * Derive PMS (7.4.2.7 / 7.4.2.8)
744 */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +0200745int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200746 unsigned char *buf, size_t len, size_t *olen,
747 int (*f_rng)(void *, unsigned char *, size_t),
748 void *p_rng )
749{
750 int ret;
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200751 mbedtls_ecp_point K;
752 mbedtls_mpi m_xm2_s, one;
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200753 unsigned char kx[MBEDTLS_ECP_MAX_BYTES];
754 size_t x_bytes;
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000755 ECJPAKE_VALIDATE_RET( ctx != NULL );
756 ECJPAKE_VALIDATE_RET( buf != NULL );
757 ECJPAKE_VALIDATE_RET( olen != NULL );
758 ECJPAKE_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200759
760 *olen = mbedtls_md_get_size( ctx->md_info );
761 if( len < *olen )
762 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
763
764 mbedtls_ecp_point_init( &K );
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200765 mbedtls_mpi_init( &m_xm2_s );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200766 mbedtls_mpi_init( &one );
767
768 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200769
770 /*
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200771 * Client: K = ( Xs - X4 * x2 * s ) * x2
772 * Server: K = ( Xc - X2 * x4 * s ) * x4
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200773 * Unified: K = ( Xp - Xp2 * xm2 * s ) * xm2
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200774 */
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200775 MBEDTLS_MPI_CHK( ecjpake_mul_secret( &m_xm2_s, -1, &ctx->xm2, &ctx->s,
776 &ctx->grp.N, f_rng, p_rng ) );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200777 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( &ctx->grp, &K,
778 &one, &ctx->Xp,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200779 &m_xm2_s, &ctx->Xp2 ) );
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200780 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &K, &ctx->xm2, &K,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200781 f_rng, p_rng ) );
782
783 /* PMS = SHA-256( K.X ) */
784 x_bytes = ( ctx->grp.pbits + 7 ) / 8;
785 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &K.X, kx, x_bytes ) );
786 MBEDTLS_MPI_CHK( mbedtls_md( ctx->md_info, kx, x_bytes, buf ) );
787
788cleanup:
789 mbedtls_ecp_point_free( &K );
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200790 mbedtls_mpi_free( &m_xm2_s );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200791 mbedtls_mpi_free( &one );
792
793 return( ret );
794}
795
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200796#undef ID_MINE
797#undef ID_PEER
798
Hanno Becker616d1ca2018-01-24 10:25:05 +0000799#endif /* ! MBEDTLS_ECJPAKE_ALT */
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200800
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200801#if defined(MBEDTLS_SELF_TEST)
802
803#if defined(MBEDTLS_PLATFORM_C)
804#include "mbedtls/platform.h"
805#else
806#include <stdio.h>
807#define mbedtls_printf printf
808#endif
809
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200810#if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
811 !defined(MBEDTLS_SHA256_C)
812int mbedtls_ecjpake_self_test( int verbose )
813{
814 (void) verbose;
815 return( 0 );
816}
817#else
818
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200819static const unsigned char ecjpake_test_password[] = {
820 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x6a, 0x70, 0x61, 0x6b, 0x65, 0x74,
821 0x65, 0x73, 0x74
822};
823
824static const unsigned char ecjpake_test_x1[] = {
825 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
826 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
827 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21
828};
829
830static const unsigned char ecjpake_test_x2[] = {
831 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
832 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
833 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
834};
835
836static const unsigned char ecjpake_test_x3[] = {
837 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
838 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
839 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
840};
841
842static const unsigned char ecjpake_test_x4[] = {
843 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc,
844 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
845 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1
846};
847
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200848static const unsigned char ecjpake_test_cli_one[] = {
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200849 0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19,
850 0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44,
851 0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad,
852 0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62,
853 0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9,
854 0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d,
855 0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e,
856 0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e,
857 0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73,
858 0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22,
859 0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce,
860 0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00,
861 0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200862 0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e,
863 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62,
864 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5,
865 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb,
866 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35,
867 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0,
868 0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb,
869 0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47,
870 0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39,
871 0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97,
872 0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40,
873 0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d,
874 0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa,
875 0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d,
876 0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200877};
878
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200879static const unsigned char ecjpake_test_srv_one[] = {
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200880 0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb,
881 0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18,
882 0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47,
883 0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f,
884 0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7,
885 0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d,
886 0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64,
887 0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36,
888 0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2,
889 0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec,
890 0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16,
891 0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96,
892 0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3,
893 0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19,
894 0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f,
895 0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8,
896 0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7,
897 0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea,
898 0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5,
899 0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6,
900 0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31,
901 0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d,
902 0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8,
903 0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee,
904 0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84,
905 0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f,
906 0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80,
907 0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12
908};
909
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200910static const unsigned char ecjpake_test_srv_two[] = {
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200911 0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23,
912 0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c,
913 0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f,
914 0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca,
915 0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26,
916 0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55,
917 0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38,
918 0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6,
919 0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9,
920 0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4,
921 0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2,
922 0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8,
923 0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd,
924 0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c
925};
926
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200927static const unsigned char ecjpake_test_cli_two[] = {
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +0200928 0x41, 0x04, 0x69, 0xd5, 0x4e, 0xe8, 0x5e, 0x90, 0xce, 0x3f, 0x12, 0x46,
929 0x74, 0x2d, 0xe5, 0x07, 0xe9, 0x39, 0xe8, 0x1d, 0x1d, 0xc1, 0xc5, 0xcb,
930 0x98, 0x8b, 0x58, 0xc3, 0x10, 0xc9, 0xfd, 0xd9, 0x52, 0x4d, 0x93, 0x72,
931 0x0b, 0x45, 0x54, 0x1c, 0x83, 0xee, 0x88, 0x41, 0x19, 0x1d, 0xa7, 0xce,
932 0xd8, 0x6e, 0x33, 0x12, 0xd4, 0x36, 0x23, 0xc1, 0xd6, 0x3e, 0x74, 0x98,
933 0x9a, 0xba, 0x4a, 0xff, 0xd1, 0xee, 0x41, 0x04, 0x07, 0x7e, 0x8c, 0x31,
934 0xe2, 0x0e, 0x6b, 0xed, 0xb7, 0x60, 0xc1, 0x35, 0x93, 0xe6, 0x9f, 0x15,
935 0xbe, 0x85, 0xc2, 0x7d, 0x68, 0xcd, 0x09, 0xcc, 0xb8, 0xc4, 0x18, 0x36,
936 0x08, 0x91, 0x7c, 0x5c, 0x3d, 0x40, 0x9f, 0xac, 0x39, 0xfe, 0xfe, 0xe8,
937 0x2f, 0x72, 0x92, 0xd3, 0x6f, 0x0d, 0x23, 0xe0, 0x55, 0x91, 0x3f, 0x45,
938 0xa5, 0x2b, 0x85, 0xdd, 0x8a, 0x20, 0x52, 0xe9, 0xe1, 0x29, 0xbb, 0x4d,
939 0x20, 0x0f, 0x01, 0x1f, 0x19, 0x48, 0x35, 0x35, 0xa6, 0xe8, 0x9a, 0x58,
940 0x0c, 0x9b, 0x00, 0x03, 0xba, 0xf2, 0x14, 0x62, 0xec, 0xe9, 0x1a, 0x82,
941 0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c
942};
943
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200944static const unsigned char ecjpake_test_pms[] = {
945 0xf3, 0xd4, 0x7f, 0x59, 0x98, 0x44, 0xdb, 0x92, 0xa5, 0x69, 0xbb, 0xe7,
946 0x98, 0x1e, 0x39, 0xd9, 0x31, 0xfd, 0x74, 0x3b, 0xf2, 0x2e, 0x98, 0xf9,
947 0xb4, 0x38, 0xf7, 0x19, 0xd3, 0xc4, 0xf3, 0x51
948};
949
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +0200950/* Load my private keys and generate the correponding public keys */
951static int ecjpake_test_load( mbedtls_ecjpake_context *ctx,
952 const unsigned char *xm1, size_t len1,
953 const unsigned char *xm2, size_t len2 )
954{
955 int ret;
956
957 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm1, xm1, len1 ) );
958 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm2, xm2, len2 ) );
959 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm1, &ctx->xm1,
960 &ctx->grp.G, NULL, NULL ) );
961 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm2, &ctx->xm2,
962 &ctx->grp.G, NULL, NULL ) );
963
964cleanup:
965 return( ret );
966}
967
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200968/* For tests we don't need a secure RNG;
969 * use the LGC from Numerical Recipes for simplicity */
970static int ecjpake_lgc( void *p, unsigned char *out, size_t len )
971{
972 static uint32_t x = 42;
973 (void) p;
974
975 while( len > 0 )
976 {
977 size_t use_len = len > 4 ? 4 : len;
978 x = 1664525 * x + 1013904223;
979 memcpy( out, &x, use_len );
980 out += use_len;
981 len -= use_len;
982 }
983
984 return( 0 );
985}
986
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200987#define TEST_ASSERT( x ) \
988 do { \
989 if( x ) \
990 ret = 0; \
991 else \
992 { \
993 ret = 1; \
994 goto cleanup; \
995 } \
996 } while( 0 )
997
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200998/*
999 * Checkup routine
1000 */
1001int mbedtls_ecjpake_self_test( int verbose )
1002{
1003 int ret;
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001004 mbedtls_ecjpake_context cli;
1005 mbedtls_ecjpake_context srv;
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001006 unsigned char buf[512], pms[32];
1007 size_t len, pmslen;
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001008
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001009 mbedtls_ecjpake_init( &cli );
1010 mbedtls_ecjpake_init( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001011
1012 if( verbose != 0 )
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001013 mbedtls_printf( " ECJPAKE test #0 (setup): " );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +02001014
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +02001015 TEST_ASSERT( mbedtls_ecjpake_setup( &cli, MBEDTLS_ECJPAKE_CLIENT,
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 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001019
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +02001020 TEST_ASSERT( mbedtls_ecjpake_setup( &srv, MBEDTLS_ECJPAKE_SERVER,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001021 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1022 ecjpake_test_password,
1023 sizeof( ecjpake_test_password ) ) == 0 );
1024
1025 if( verbose != 0 )
1026 mbedtls_printf( "passed\n" );
1027
1028 if( verbose != 0 )
1029 mbedtls_printf( " ECJPAKE test #1 (random handshake): " );
1030
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001031 TEST_ASSERT( mbedtls_ecjpake_write_round_one( &cli,
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( &srv, buf, len ) == 0 );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001035
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001036 TEST_ASSERT( mbedtls_ecjpake_write_round_one( &srv,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001037 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1038
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001039 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli, buf, len ) == 0 );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001040
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001041 TEST_ASSERT( mbedtls_ecjpake_write_round_two( &srv,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +02001042 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1043
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001044 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli, buf, len ) == 0 );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +02001045
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001046 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001047 pms, sizeof( pms ), &pmslen, ecjpake_lgc, NULL ) == 0 );
1048
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001049 TEST_ASSERT( mbedtls_ecjpake_write_round_two( &cli,
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +02001050 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1051
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001052 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv, buf, len ) == 0 );
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +02001053
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001054 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001055 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1056
1057 TEST_ASSERT( len == pmslen );
1058 TEST_ASSERT( memcmp( buf, pms, len ) == 0 );
1059
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001060 if( verbose != 0 )
1061 mbedtls_printf( "passed\n" );
1062
1063 if( verbose != 0 )
1064 mbedtls_printf( " ECJPAKE test #2 (reference handshake): " );
1065
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001066 /* Simulate generation of round one */
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001067 MBEDTLS_MPI_CHK( ecjpake_test_load( &cli,
1068 ecjpake_test_x1, sizeof( ecjpake_test_x1 ),
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001069 ecjpake_test_x2, sizeof( ecjpake_test_x2 ) ) );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001070
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001071 MBEDTLS_MPI_CHK( ecjpake_test_load( &srv,
1072 ecjpake_test_x3, sizeof( ecjpake_test_x3 ),
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001073 ecjpake_test_x4, sizeof( ecjpake_test_x4 ) ) );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001074
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001075 /* Read round one */
1076 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv,
1077 ecjpake_test_cli_one,
1078 sizeof( ecjpake_test_cli_one ) ) == 0 );
1079
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001080 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001081 ecjpake_test_srv_one,
1082 sizeof( ecjpake_test_srv_one ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001083
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001084 /* Skip generation of round two, read round two */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001085 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001086 ecjpake_test_srv_two,
1087 sizeof( ecjpake_test_srv_two ) ) == 0 );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +02001088
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001089 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001090 ecjpake_test_cli_two,
1091 sizeof( ecjpake_test_cli_two ) ) == 0 );
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +02001092
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001093 /* Server derives PMS */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001094 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001095 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1096
1097 TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
1098 TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
1099
1100 memset( buf, 0, len ); /* Avoid interferences with next step */
1101
1102 /* Client derives PMS */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001103 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001104 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1105
1106 TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
1107 TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
1108
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001109 if( verbose != 0 )
1110 mbedtls_printf( "passed\n" );
1111
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001112cleanup:
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001113 mbedtls_ecjpake_free( &cli );
1114 mbedtls_ecjpake_free( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001115
1116 if( ret != 0 )
1117 {
1118 if( verbose != 0 )
1119 mbedtls_printf( "failed\n" );
1120
1121 ret = 1;
1122 }
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001123
1124 if( verbose != 0 )
1125 mbedtls_printf( "\n" );
1126
1127 return( ret );
1128}
1129
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +02001130#undef TEST_ASSERT
1131
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001132#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_SHA256_C */
1133
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001134#endif /* MBEDTLS_SELF_TEST */
1135
1136#endif /* MBEDTLS_ECJPAKE_C */