blob: c89163c68a410d84a9995072e2acf0b16a6d4b47 [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
Bence Szépkútif744bd72020-06-05 13:02:18 +02005 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6 *
7 * This file is provided under the Apache License 2.0, or the
8 * GNU General Public License v2.0 or later.
9 *
10 * **********
11 * Apache License 2.0:
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +020012 *
13 * Licensed under the Apache License, Version 2.0 (the "License"); you may
14 * not use this file except in compliance with the License.
15 * You may obtain a copy of the License at
16 *
17 * http://www.apache.org/licenses/LICENSE-2.0
18 *
19 * Unless required by applicable law or agreed to in writing, software
20 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
21 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 * See the License for the specific language governing permissions and
23 * limitations under the License.
24 *
Bence Szépkútif744bd72020-06-05 13:02:18 +020025 * **********
26 *
27 * **********
28 * GNU General Public License v2.0 or later:
29 *
30 * This program is free software; you can redistribute it and/or modify
31 * it under the terms of the GNU General Public License as published by
32 * the Free Software Foundation; either version 2 of the License, or
33 * (at your option) any later version.
34 *
35 * This program is distributed in the hope that it will be useful,
36 * but WITHOUT ANY WARRANTY; without even the implied warranty of
37 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38 * GNU General Public License for more details.
39 *
40 * You should have received a copy of the GNU General Public License along
41 * with this program; if not, write to the Free Software Foundation, Inc.,
42 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
43 *
44 * **********
45 *
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +020046 * This file is part of mbed TLS (https://tls.mbed.org)
47 */
48
49/*
Manuel Pégourié-Gonnard6b798b92015-08-14 11:18:30 +020050 * References in the code are to the Thread v1.0 Specification,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +020051 * available to members of the Thread Group http://threadgroup.org/
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +020052 */
53
54#if !defined(MBEDTLS_CONFIG_FILE)
55#include "mbedtls/config.h"
56#else
57#include MBEDTLS_CONFIG_FILE
58#endif
59
60#if defined(MBEDTLS_ECJPAKE_C)
61
62#include "mbedtls/ecjpake.h"
Hanno Becker71c8e1b2018-12-14 17:09:39 +000063#include "mbedtls/platform_util.h"
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +020064
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +020065#include <string.h>
66
Hanno Becker616d1ca2018-01-24 10:25:05 +000067#if !defined(MBEDTLS_ECJPAKE_ALT)
68
Hanno Becker71c8e1b2018-12-14 17:09:39 +000069/* Parameter validation macros based on platform_util.h */
70#define ECJPAKE_VALIDATE_RET( cond ) \
71 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA )
72#define ECJPAKE_VALIDATE( cond ) \
73 MBEDTLS_INTERNAL_VALIDATE( cond )
74
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +020075/*
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +020076 * Convert a mbedtls_ecjpake_role to identifier string
77 */
78static const char * const ecjpake_id[] = {
79 "client",
80 "server"
81};
82
83#define ID_MINE ( ecjpake_id[ ctx->role ] )
84#define ID_PEER ( ecjpake_id[ 1 - ctx->role ] )
85
86/*
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020087 * Initialize context
88 */
89void mbedtls_ecjpake_init( mbedtls_ecjpake_context *ctx )
90{
Hanno Becker71c8e1b2018-12-14 17:09:39 +000091 ECJPAKE_VALIDATE( ctx != NULL );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020092
93 ctx->md_info = NULL;
94 mbedtls_ecp_group_init( &ctx->grp );
Manuel Pégourié-Gonnardb7da1942015-10-19 13:35:22 +020095 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020096
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +020097 mbedtls_ecp_point_init( &ctx->Xm1 );
98 mbedtls_ecp_point_init( &ctx->Xm2 );
99 mbedtls_ecp_point_init( &ctx->Xp1 );
100 mbedtls_ecp_point_init( &ctx->Xp2 );
101 mbedtls_ecp_point_init( &ctx->Xp );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200102
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200103 mbedtls_mpi_init( &ctx->xm1 );
104 mbedtls_mpi_init( &ctx->xm2 );
105 mbedtls_mpi_init( &ctx->s );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200106}
107
108/*
109 * Free context
110 */
111void mbedtls_ecjpake_free( mbedtls_ecjpake_context *ctx )
112{
113 if( ctx == NULL )
114 return;
115
116 ctx->md_info = NULL;
117 mbedtls_ecp_group_free( &ctx->grp );
118
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200119 mbedtls_ecp_point_free( &ctx->Xm1 );
120 mbedtls_ecp_point_free( &ctx->Xm2 );
121 mbedtls_ecp_point_free( &ctx->Xp1 );
122 mbedtls_ecp_point_free( &ctx->Xp2 );
123 mbedtls_ecp_point_free( &ctx->Xp );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200124
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200125 mbedtls_mpi_free( &ctx->xm1 );
126 mbedtls_mpi_free( &ctx->xm2 );
127 mbedtls_mpi_free( &ctx->s );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200128}
129
130/*
131 * Setup context
132 */
133int mbedtls_ecjpake_setup( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +0200134 mbedtls_ecjpake_role role,
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200135 mbedtls_md_type_t hash,
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200136 mbedtls_ecp_group_id curve,
137 const unsigned char *secret,
138 size_t len )
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200139{
140 int ret;
Hanno Becker185e5162018-12-19 09:48:50 +0000141
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000142 ECJPAKE_VALIDATE_RET( ctx != NULL );
143 ECJPAKE_VALIDATE_RET( role == MBEDTLS_ECJPAKE_CLIENT ||
144 role == MBEDTLS_ECJPAKE_SERVER );
145 ECJPAKE_VALIDATE_RET( secret != NULL || len == 0 );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200146
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +0200147 ctx->role = role;
148
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200149 if( ( ctx->md_info = mbedtls_md_info_from_type( hash ) ) == NULL )
150 return( MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE );
151
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200152 MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ctx->grp, curve ) );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200153
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200154 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->s, secret, len ) );
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200155
156cleanup:
157 if( ret != 0 )
158 mbedtls_ecjpake_free( ctx );
159
160 return( ret );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200161}
162
163/*
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200164 * Check if context is ready for use
165 */
166int mbedtls_ecjpake_check( const mbedtls_ecjpake_context *ctx )
167{
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000168 ECJPAKE_VALIDATE_RET( ctx != NULL );
169
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200170 if( ctx->md_info == NULL ||
171 ctx->grp.id == MBEDTLS_ECP_DP_NONE ||
172 ctx->s.p == NULL )
173 {
174 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
175 }
176
177 return( 0 );
178}
179
180/*
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200181 * Write a point plus its length to a buffer
182 */
183static int ecjpake_write_len_point( unsigned char **p,
184 const unsigned char *end,
185 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100186 const int pf,
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200187 const mbedtls_ecp_point *P )
188{
189 int ret;
190 size_t len;
191
192 /* Need at least 4 for length plus 1 for point */
193 if( end < *p || end - *p < 5 )
194 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
195
Robert Cragie7cdad772015-10-02 13:31:41 +0100196 ret = mbedtls_ecp_point_write_binary( grp, P, pf,
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200197 &len, *p + 4, end - ( *p + 4 ) );
198 if( ret != 0 )
199 return( ret );
200
201 (*p)[0] = (unsigned char)( ( len >> 24 ) & 0xFF );
202 (*p)[1] = (unsigned char)( ( len >> 16 ) & 0xFF );
203 (*p)[2] = (unsigned char)( ( len >> 8 ) & 0xFF );
204 (*p)[3] = (unsigned char)( ( len ) & 0xFF );
205
206 *p += 4 + len;
207
208 return( 0 );
209}
210
211/*
212 * Size of the temporary buffer for ecjpake_hash:
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200213 * 3 EC points plus their length, plus ID and its length (4 + 6 bytes)
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200214 */
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200215#define ECJPAKE_HASH_BUF_LEN ( 3 * ( 4 + MBEDTLS_ECP_MAX_PT_LEN ) + 4 + 6 )
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200216
217/*
218 * Compute hash for ZKP (7.4.2.2.2.1)
219 */
220static int ecjpake_hash( const mbedtls_md_info_t *md_info,
221 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100222 const int pf,
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200223 const mbedtls_ecp_point *G,
224 const mbedtls_ecp_point *V,
225 const mbedtls_ecp_point *X,
226 const char *id,
227 mbedtls_mpi *h )
228{
229 int ret;
230 unsigned char buf[ECJPAKE_HASH_BUF_LEN];
231 unsigned char *p = buf;
232 const unsigned char *end = buf + sizeof( buf );
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200233 const size_t id_len = strlen( id );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200234 unsigned char hash[MBEDTLS_MD_MAX_SIZE];
235
236 /* Write things to temporary buffer */
Robert Cragie7cdad772015-10-02 13:31:41 +0100237 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, G ) );
238 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, V ) );
239 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, X ) );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200240
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200241 if( end - p < 4 )
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200242 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
243
244 *p++ = (unsigned char)( ( id_len >> 24 ) & 0xFF );
245 *p++ = (unsigned char)( ( id_len >> 16 ) & 0xFF );
246 *p++ = (unsigned char)( ( id_len >> 8 ) & 0xFF );
247 *p++ = (unsigned char)( ( id_len ) & 0xFF );
248
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200249 if( end < p || (size_t)( end - p ) < id_len )
250 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
251
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200252 memcpy( p, id, id_len );
253 p += id_len;
254
255 /* Compute hash */
k-stachowiak4a6a55c2019-06-28 14:14:02 +0200256 MBEDTLS_MPI_CHK( mbedtls_md( md_info, buf, p - buf, hash ) );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200257
258 /* Turn it into an integer mod n */
259 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( h, hash,
260 mbedtls_md_get_size( md_info ) ) );
261 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( h, h, &grp->N ) );
262
263cleanup:
264 return( ret );
265}
266
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200267/*
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200268 * Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3)
269 */
270static int ecjpake_zkp_read( const mbedtls_md_info_t *md_info,
271 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100272 const int pf,
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200273 const mbedtls_ecp_point *G,
274 const mbedtls_ecp_point *X,
275 const char *id,
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200276 const unsigned char **p,
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200277 const unsigned char *end )
278{
279 int ret;
280 mbedtls_ecp_point V, VV;
281 mbedtls_mpi r, h;
282 size_t r_len;
283
284 mbedtls_ecp_point_init( &V );
285 mbedtls_ecp_point_init( &VV );
286 mbedtls_mpi_init( &r );
287 mbedtls_mpi_init( &h );
288
289 /*
290 * struct {
291 * ECPoint V;
292 * opaque r<1..2^8-1>;
293 * } ECSchnorrZKP;
294 */
295 if( end < *p )
296 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
297
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200298 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, &V, p, end - *p ) );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200299
300 if( end < *p || (size_t)( end - *p ) < 1 )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200301 {
302 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
303 goto cleanup;
304 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200305
306 r_len = *(*p)++;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200307
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200308 if( end < *p || (size_t)( end - *p ) < r_len )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200309 {
310 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
311 goto cleanup;
312 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200313
314 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &r, *p, r_len ) );
315 *p += r_len;
316
317 /*
318 * Verification
319 */
Robert Cragie7cdad772015-10-02 13:31:41 +0100320 MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200321 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( (mbedtls_ecp_group *) grp,
322 &VV, &h, X, &r, G ) );
323
324 if( mbedtls_ecp_point_cmp( &VV, &V ) != 0 )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200325 {
326 ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
327 goto cleanup;
328 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200329
330cleanup:
331 mbedtls_ecp_point_free( &V );
332 mbedtls_ecp_point_free( &VV );
333 mbedtls_mpi_free( &r );
334 mbedtls_mpi_free( &h );
335
336 return( ret );
337}
338
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200339/*
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200340 * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2)
341 */
342static int ecjpake_zkp_write( const mbedtls_md_info_t *md_info,
343 const mbedtls_ecp_group *grp,
Darryl Green11999bb2018-03-13 15:22:58 +0000344 const int pf,
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200345 const mbedtls_ecp_point *G,
346 const mbedtls_mpi *x,
347 const mbedtls_ecp_point *X,
348 const char *id,
349 unsigned char **p,
350 const unsigned char *end,
351 int (*f_rng)(void *, unsigned char *, size_t),
352 void *p_rng )
353{
354 int ret;
355 mbedtls_ecp_point V;
356 mbedtls_mpi v;
357 mbedtls_mpi h; /* later recycled to hold r */
358 size_t len;
359
360 if( end < *p )
361 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
362
363 mbedtls_ecp_point_init( &V );
364 mbedtls_mpi_init( &v );
365 mbedtls_mpi_init( &h );
366
367 /* Compute signature */
368 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp,
369 G, &v, &V, f_rng, p_rng ) );
Robert Cragie7cdad772015-10-02 13:31:41 +0100370 MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) );
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200371 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &h, &h, x ) ); /* x*h */
372 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &h, &v, &h ) ); /* v - x*h */
373 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &h, &h, &grp->N ) ); /* r */
374
375 /* Write it out */
376 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, &V,
Robert Cragie7cdad772015-10-02 13:31:41 +0100377 pf, &len, *p, end - *p ) );
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200378 *p += len;
379
380 len = mbedtls_mpi_size( &h ); /* actually r */
381 if( end < *p || (size_t)( end - *p ) < 1 + len || len > 255 )
382 {
383 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
384 goto cleanup;
385 }
386
387 *(*p)++ = (unsigned char)( len & 0xFF );
388 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, *p, len ) ); /* r */
389 *p += len;
390
391cleanup:
392 mbedtls_ecp_point_free( &V );
393 mbedtls_mpi_free( &v );
394 mbedtls_mpi_free( &h );
395
396 return( ret );
397}
398
399/*
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200400 * Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof
401 * Output: verified public key X
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200402 */
403static int ecjpake_kkp_read( const mbedtls_md_info_t *md_info,
404 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100405 const int pf,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200406 const mbedtls_ecp_point *G,
407 mbedtls_ecp_point *X,
408 const char *id,
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200409 const unsigned char **p,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200410 const unsigned char *end )
411{
412 int ret;
413
414 if( end < *p )
415 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
416
417 /*
418 * struct {
419 * ECPoint X;
420 * ECSchnorrZKP zkp;
421 * } ECJPAKEKeyKP;
422 */
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200423 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, X, p, end - *p ) );
Manuel Pégourié-Gonnard30590952015-08-17 10:37:40 +0200424 if( mbedtls_ecp_is_zero( X ) )
425 {
426 ret = MBEDTLS_ERR_ECP_INVALID_KEY;
427 goto cleanup;
428 }
429
Robert Cragie7cdad772015-10-02 13:31:41 +0100430 MBEDTLS_MPI_CHK( ecjpake_zkp_read( md_info, grp, pf, G, X, id, p, end ) );
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200431
432cleanup:
433 return( ret );
434}
435
436/*
437 * Generate an ECJPAKEKeyKP
438 * Output: the serialized structure, plus private/public key pair
439 */
440static int ecjpake_kkp_write( const mbedtls_md_info_t *md_info,
441 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100442 const int pf,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200443 const mbedtls_ecp_point *G,
444 mbedtls_mpi *x,
445 mbedtls_ecp_point *X,
446 const char *id,
447 unsigned char **p,
448 const unsigned char *end,
449 int (*f_rng)(void *, unsigned char *, size_t),
450 void *p_rng )
451{
452 int ret;
453 size_t len;
454
455 if( end < *p )
456 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
457
458 /* Generate key (7.4.2.3.1) and write it out */
459 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp, G, x, X,
460 f_rng, p_rng ) );
461 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, X,
Robert Cragie7cdad772015-10-02 13:31:41 +0100462 pf, &len, *p, end - *p ) );
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200463 *p += len;
464
465 /* Generate and write proof */
Robert Cragie7cdad772015-10-02 13:31:41 +0100466 MBEDTLS_MPI_CHK( ecjpake_zkp_write( md_info, grp, pf, G, x, X, id,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200467 p, end, f_rng, p_rng ) );
468
469cleanup:
470 return( ret );
471}
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200472
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200473/*
474 * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs
475 * Ouputs: verified peer public keys Xa, Xb
476 */
477static int ecjpake_kkpp_read( const mbedtls_md_info_t *md_info,
478 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100479 const int pf,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200480 const mbedtls_ecp_point *G,
481 mbedtls_ecp_point *Xa,
482 mbedtls_ecp_point *Xb,
483 const char *id,
484 const unsigned char *buf,
485 size_t len )
486{
487 int ret;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200488 const unsigned char *p = buf;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200489 const unsigned char *end = buf + len;
490
491 /*
492 * struct {
493 * ECJPAKEKeyKP ecjpake_key_kp_pair_list[2];
494 * } ECJPAKEKeyKPPairList;
495 */
Robert Cragie7cdad772015-10-02 13:31:41 +0100496 MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xa, id, &p, end ) );
497 MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xb, id, &p, end ) );
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200498
499 if( p != end )
500 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
501
502cleanup:
503 return( ret );
504}
505
506/*
507 * Generate a ECJPAKEKeyKPPairList
508 * Outputs: the serialized structure, plus two private/public key pairs
509 */
510static int ecjpake_kkpp_write( const mbedtls_md_info_t *md_info,
511 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100512 const int pf,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200513 const mbedtls_ecp_point *G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200514 mbedtls_mpi *xm1,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200515 mbedtls_ecp_point *Xa,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200516 mbedtls_mpi *xm2,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200517 mbedtls_ecp_point *Xb,
518 const char *id,
519 unsigned char *buf,
520 size_t len,
521 size_t *olen,
522 int (*f_rng)(void *, unsigned char *, size_t),
523 void *p_rng )
524{
525 int ret;
526 unsigned char *p = buf;
527 const unsigned char *end = buf + len;
528
Robert Cragie7cdad772015-10-02 13:31:41 +0100529 MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm1, Xa, id,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200530 &p, end, f_rng, p_rng ) );
Robert Cragie7cdad772015-10-02 13:31:41 +0100531 MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm2, Xb, id,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200532 &p, end, f_rng, p_rng ) );
533
534 *olen = p - buf;
535
536cleanup:
537 return( ret );
538}
539
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200540/*
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200541 * Read and process the first round message
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200542 */
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200543int mbedtls_ecjpake_read_round_one( mbedtls_ecjpake_context *ctx,
544 const unsigned char *buf,
545 size_t len )
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200546{
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000547 ECJPAKE_VALIDATE_RET( ctx != NULL );
548 ECJPAKE_VALIDATE_RET( buf != NULL );
549
Robert Cragie7cdad772015-10-02 13:31:41 +0100550 return( ecjpake_kkpp_read( ctx->md_info, &ctx->grp, ctx->point_format,
551 &ctx->grp.G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200552 &ctx->Xp1, &ctx->Xp2, ID_PEER,
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200553 buf, len ) );
554}
555
556/*
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200557 * Generate and write the first round message
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200558 */
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200559int mbedtls_ecjpake_write_round_one( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200560 unsigned char *buf, size_t len, size_t *olen,
561 int (*f_rng)(void *, unsigned char *, size_t),
562 void *p_rng )
563{
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000564 ECJPAKE_VALIDATE_RET( ctx != NULL );
565 ECJPAKE_VALIDATE_RET( buf != NULL );
566 ECJPAKE_VALIDATE_RET( olen != NULL );
567 ECJPAKE_VALIDATE_RET( f_rng != NULL );
568
Robert Cragie7cdad772015-10-02 13:31:41 +0100569 return( ecjpake_kkpp_write( ctx->md_info, &ctx->grp, ctx->point_format,
570 &ctx->grp.G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200571 &ctx->xm1, &ctx->Xm1, &ctx->xm2, &ctx->Xm2,
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200572 ID_MINE, buf, len, olen, f_rng, p_rng ) );
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200573}
574
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200575/*
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200576 * Compute the sum of three points R = A + B + C
577 */
578static int ecjpake_ecp_add3( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
579 const mbedtls_ecp_point *A,
580 const mbedtls_ecp_point *B,
581 const mbedtls_ecp_point *C )
582{
583 int ret;
584 mbedtls_mpi one;
585
586 mbedtls_mpi_init( &one );
587
588 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
589 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, A, &one, B ) );
590 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, R, &one, C ) );
591
592cleanup:
593 mbedtls_mpi_free( &one );
594
595 return( ret );
596}
597
598/*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200599 * 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 +0200600 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200601int mbedtls_ecjpake_read_round_two( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200602 const unsigned char *buf,
603 size_t len )
604{
605 int ret;
606 const unsigned char *p = buf;
607 const unsigned char *end = buf + len;
608 mbedtls_ecp_group grp;
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200609 mbedtls_ecp_point G; /* C: GB, S: GA */
Hanno Becker185e5162018-12-19 09:48:50 +0000610
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000611 ECJPAKE_VALIDATE_RET( ctx != NULL );
612 ECJPAKE_VALIDATE_RET( buf != NULL );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200613
614 mbedtls_ecp_group_init( &grp );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200615 mbedtls_ecp_point_init( &G );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200616
617 /*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200618 * Server: GA = X3 + X4 + X1 (7.4.2.6.1)
619 * Client: GB = X1 + X2 + X3 (7.4.2.5.1)
620 * Unified: G = Xm1 + Xm2 + Xp1
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200621 * We need that before parsing in order to check Xp as we read it
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200622 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200623 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200624 &ctx->Xm1, &ctx->Xm2, &ctx->Xp1 ) );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200625
626 /*
627 * struct {
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200628 * ECParameters curve_params; // only client reading server msg
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200629 * ECJPAKEKeyKP ecjpake_key_kp;
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200630 * } Client/ServerECJPAKEParams;
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200631 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200632 if( ctx->role == MBEDTLS_ECJPAKE_CLIENT )
Manuel Pégourié-Gonnardd9802af2015-08-17 12:47:38 +0200633 {
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200634 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_group( &grp, &p, len ) );
Manuel Pégourié-Gonnardd9802af2015-08-17 12:47:38 +0200635 if( grp.id != ctx->grp.id )
636 {
637 ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
638 goto cleanup;
639 }
640 }
641
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200642 MBEDTLS_MPI_CHK( ecjpake_kkp_read( ctx->md_info, &ctx->grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100643 ctx->point_format,
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200644 &G, &ctx->Xp, ID_PEER, &p, end ) );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200645
646 if( p != end )
647 {
648 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
649 goto cleanup;
650 }
651
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200652cleanup:
653 mbedtls_ecp_group_free( &grp );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200654 mbedtls_ecp_point_free( &G );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200655
656 return( ret );
657}
658
659/*
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200660 * Compute R = +/- X * S mod N, taking care not to leak S
661 */
662static int ecjpake_mul_secret( mbedtls_mpi *R, int sign,
663 const mbedtls_mpi *X,
664 const mbedtls_mpi *S,
665 const mbedtls_mpi *N,
666 int (*f_rng)(void *, unsigned char *, size_t),
667 void *p_rng )
668{
669 int ret;
670 mbedtls_mpi b; /* Blinding value, then s + N * blinding */
671
672 mbedtls_mpi_init( &b );
673
674 /* b = s + rnd-128-bit * N */
675 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &b, 16, f_rng, p_rng ) );
676 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &b, &b, N ) );
677 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &b, &b, S ) );
678
679 /* R = sign * X * b mod N */
680 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( R, X, &b ) );
681 R->s *= sign;
682 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( R, R, N ) );
683
684cleanup:
685 mbedtls_mpi_free( &b );
686
687 return( ret );
688}
689
690/*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200691 * 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 +0200692 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200693int mbedtls_ecjpake_write_round_two( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200694 unsigned char *buf, size_t len, size_t *olen,
695 int (*f_rng)(void *, unsigned char *, size_t),
696 void *p_rng )
697{
698 int ret;
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200699 mbedtls_ecp_point G; /* C: GA, S: GB */
700 mbedtls_ecp_point Xm; /* C: Xc, S: Xs */
701 mbedtls_mpi xm; /* C: xc, S: xs */
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200702 unsigned char *p = buf;
703 const unsigned char *end = buf + len;
704 size_t ec_len;
Hanno Becker185e5162018-12-19 09:48:50 +0000705
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000706 ECJPAKE_VALIDATE_RET( ctx != NULL );
707 ECJPAKE_VALIDATE_RET( buf != NULL );
708 ECJPAKE_VALIDATE_RET( olen != NULL );
709 ECJPAKE_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200710
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200711 mbedtls_ecp_point_init( &G );
712 mbedtls_ecp_point_init( &Xm );
713 mbedtls_mpi_init( &xm );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200714
715 /*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200716 * 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 +0200717 *
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200718 * Client: GA = X1 + X3 + X4 | xs = x2 * s | Xc = xc * GA
719 * Server: GB = X3 + X1 + X2 | xs = x4 * s | Xs = xs * GB
720 * Unified: G = Xm1 + Xp1 + Xp2 | xm = xm2 * s | Xm = xm * G
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200721 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200722 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200723 &ctx->Xp1, &ctx->Xp2, &ctx->Xm1 ) );
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200724 MBEDTLS_MPI_CHK( ecjpake_mul_secret( &xm, 1, &ctx->xm2, &ctx->s,
725 &ctx->grp.N, f_rng, p_rng ) );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200726 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &Xm, &xm, &G, f_rng, p_rng ) );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200727
728 /*
729 * Now write things out
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200730 *
731 * struct {
732 * ECParameters curve_params; // only server writing its message
733 * ECJPAKEKeyKP ecjpake_key_kp;
734 * } Client/ServerECJPAKEParams;
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200735 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200736 if( ctx->role == MBEDTLS_ECJPAKE_SERVER )
737 {
738 if( end < p )
739 {
740 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
741 goto cleanup;
742 }
743 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_group( &ctx->grp, &ec_len,
744 p, end - p ) );
745 p += ec_len;
746 }
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200747
748 if( end < p )
749 {
750 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
751 goto cleanup;
752 }
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200753 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( &ctx->grp, &Xm,
Robert Cragie7cdad772015-10-02 13:31:41 +0100754 ctx->point_format, &ec_len, p, end - p ) );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200755 p += ec_len;
756
757 MBEDTLS_MPI_CHK( ecjpake_zkp_write( ctx->md_info, &ctx->grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100758 ctx->point_format,
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200759 &G, &xm, &Xm, ID_MINE,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200760 &p, end, f_rng, p_rng ) );
761
762 *olen = p - buf;
763
764cleanup:
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200765 mbedtls_ecp_point_free( &G );
766 mbedtls_ecp_point_free( &Xm );
767 mbedtls_mpi_free( &xm );
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +0200768
769 return( ret );
770}
771
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200772/*
773 * Derive PMS (7.4.2.7 / 7.4.2.8)
774 */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +0200775int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200776 unsigned char *buf, size_t len, size_t *olen,
777 int (*f_rng)(void *, unsigned char *, size_t),
778 void *p_rng )
779{
780 int ret;
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200781 mbedtls_ecp_point K;
782 mbedtls_mpi m_xm2_s, one;
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200783 unsigned char kx[MBEDTLS_ECP_MAX_BYTES];
784 size_t x_bytes;
Hanno Becker185e5162018-12-19 09:48:50 +0000785
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000786 ECJPAKE_VALIDATE_RET( ctx != NULL );
787 ECJPAKE_VALIDATE_RET( buf != NULL );
788 ECJPAKE_VALIDATE_RET( olen != NULL );
789 ECJPAKE_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200790
791 *olen = mbedtls_md_get_size( ctx->md_info );
792 if( len < *olen )
793 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
794
795 mbedtls_ecp_point_init( &K );
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200796 mbedtls_mpi_init( &m_xm2_s );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200797 mbedtls_mpi_init( &one );
798
799 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200800
801 /*
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200802 * Client: K = ( Xs - X4 * x2 * s ) * x2
803 * Server: K = ( Xc - X2 * x4 * s ) * x4
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200804 * Unified: K = ( Xp - Xp2 * xm2 * s ) * xm2
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200805 */
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200806 MBEDTLS_MPI_CHK( ecjpake_mul_secret( &m_xm2_s, -1, &ctx->xm2, &ctx->s,
807 &ctx->grp.N, f_rng, p_rng ) );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200808 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( &ctx->grp, &K,
809 &one, &ctx->Xp,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200810 &m_xm2_s, &ctx->Xp2 ) );
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200811 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &K, &ctx->xm2, &K,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200812 f_rng, p_rng ) );
813
814 /* PMS = SHA-256( K.X ) */
815 x_bytes = ( ctx->grp.pbits + 7 ) / 8;
816 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &K.X, kx, x_bytes ) );
817 MBEDTLS_MPI_CHK( mbedtls_md( ctx->md_info, kx, x_bytes, buf ) );
818
819cleanup:
820 mbedtls_ecp_point_free( &K );
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200821 mbedtls_mpi_free( &m_xm2_s );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200822 mbedtls_mpi_free( &one );
823
824 return( ret );
825}
826
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200827#undef ID_MINE
828#undef ID_PEER
829
Hanno Becker616d1ca2018-01-24 10:25:05 +0000830#endif /* ! MBEDTLS_ECJPAKE_ALT */
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200831
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200832#if defined(MBEDTLS_SELF_TEST)
833
834#if defined(MBEDTLS_PLATFORM_C)
835#include "mbedtls/platform.h"
836#else
837#include <stdio.h>
838#define mbedtls_printf printf
839#endif
840
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200841#if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
842 !defined(MBEDTLS_SHA256_C)
843int mbedtls_ecjpake_self_test( int verbose )
844{
845 (void) verbose;
846 return( 0 );
847}
848#else
849
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200850static const unsigned char ecjpake_test_password[] = {
851 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x6a, 0x70, 0x61, 0x6b, 0x65, 0x74,
852 0x65, 0x73, 0x74
853};
854
855static const unsigned char ecjpake_test_x1[] = {
856 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
857 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
858 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21
859};
860
861static const unsigned char ecjpake_test_x2[] = {
862 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
863 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
864 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
865};
866
867static const unsigned char ecjpake_test_x3[] = {
868 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
869 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
870 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
871};
872
873static const unsigned char ecjpake_test_x4[] = {
874 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc,
875 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
876 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1
877};
878
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200879static const unsigned char ecjpake_test_cli_one[] = {
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200880 0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19,
881 0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44,
882 0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad,
883 0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62,
884 0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9,
885 0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d,
886 0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e,
887 0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e,
888 0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73,
889 0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22,
890 0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce,
891 0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00,
892 0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200893 0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e,
894 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62,
895 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5,
896 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb,
897 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35,
898 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0,
899 0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb,
900 0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47,
901 0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39,
902 0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97,
903 0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40,
904 0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d,
905 0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa,
906 0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d,
907 0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200908};
909
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200910static const unsigned char ecjpake_test_srv_one[] = {
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200911 0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb,
912 0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18,
913 0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47,
914 0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f,
915 0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7,
916 0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d,
917 0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64,
918 0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36,
919 0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2,
920 0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec,
921 0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16,
922 0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96,
923 0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3,
924 0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19,
925 0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f,
926 0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8,
927 0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7,
928 0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea,
929 0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5,
930 0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6,
931 0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31,
932 0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d,
933 0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8,
934 0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee,
935 0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84,
936 0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f,
937 0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80,
938 0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12
939};
940
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200941static const unsigned char ecjpake_test_srv_two[] = {
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200942 0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23,
943 0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c,
944 0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f,
945 0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca,
946 0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26,
947 0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55,
948 0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38,
949 0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6,
950 0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9,
951 0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4,
952 0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2,
953 0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8,
954 0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd,
955 0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c
956};
957
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200958static const unsigned char ecjpake_test_cli_two[] = {
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +0200959 0x41, 0x04, 0x69, 0xd5, 0x4e, 0xe8, 0x5e, 0x90, 0xce, 0x3f, 0x12, 0x46,
960 0x74, 0x2d, 0xe5, 0x07, 0xe9, 0x39, 0xe8, 0x1d, 0x1d, 0xc1, 0xc5, 0xcb,
961 0x98, 0x8b, 0x58, 0xc3, 0x10, 0xc9, 0xfd, 0xd9, 0x52, 0x4d, 0x93, 0x72,
962 0x0b, 0x45, 0x54, 0x1c, 0x83, 0xee, 0x88, 0x41, 0x19, 0x1d, 0xa7, 0xce,
963 0xd8, 0x6e, 0x33, 0x12, 0xd4, 0x36, 0x23, 0xc1, 0xd6, 0x3e, 0x74, 0x98,
964 0x9a, 0xba, 0x4a, 0xff, 0xd1, 0xee, 0x41, 0x04, 0x07, 0x7e, 0x8c, 0x31,
965 0xe2, 0x0e, 0x6b, 0xed, 0xb7, 0x60, 0xc1, 0x35, 0x93, 0xe6, 0x9f, 0x15,
966 0xbe, 0x85, 0xc2, 0x7d, 0x68, 0xcd, 0x09, 0xcc, 0xb8, 0xc4, 0x18, 0x36,
967 0x08, 0x91, 0x7c, 0x5c, 0x3d, 0x40, 0x9f, 0xac, 0x39, 0xfe, 0xfe, 0xe8,
968 0x2f, 0x72, 0x92, 0xd3, 0x6f, 0x0d, 0x23, 0xe0, 0x55, 0x91, 0x3f, 0x45,
969 0xa5, 0x2b, 0x85, 0xdd, 0x8a, 0x20, 0x52, 0xe9, 0xe1, 0x29, 0xbb, 0x4d,
970 0x20, 0x0f, 0x01, 0x1f, 0x19, 0x48, 0x35, 0x35, 0xa6, 0xe8, 0x9a, 0x58,
971 0x0c, 0x9b, 0x00, 0x03, 0xba, 0xf2, 0x14, 0x62, 0xec, 0xe9, 0x1a, 0x82,
972 0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c
973};
974
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200975static const unsigned char ecjpake_test_pms[] = {
976 0xf3, 0xd4, 0x7f, 0x59, 0x98, 0x44, 0xdb, 0x92, 0xa5, 0x69, 0xbb, 0xe7,
977 0x98, 0x1e, 0x39, 0xd9, 0x31, 0xfd, 0x74, 0x3b, 0xf2, 0x2e, 0x98, 0xf9,
978 0xb4, 0x38, 0xf7, 0x19, 0xd3, 0xc4, 0xf3, 0x51
979};
980
Antonin Décimod5f47592019-01-23 15:24:37 +0100981/* Load my private keys and generate the corresponding public keys */
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +0200982static int ecjpake_test_load( mbedtls_ecjpake_context *ctx,
983 const unsigned char *xm1, size_t len1,
984 const unsigned char *xm2, size_t len2 )
985{
986 int ret;
987
988 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm1, xm1, len1 ) );
989 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm2, xm2, len2 ) );
990 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm1, &ctx->xm1,
991 &ctx->grp.G, NULL, NULL ) );
992 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm2, &ctx->xm2,
993 &ctx->grp.G, NULL, NULL ) );
994
995cleanup:
996 return( ret );
997}
998
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200999/* For tests we don't need a secure RNG;
1000 * use the LGC from Numerical Recipes for simplicity */
1001static int ecjpake_lgc( void *p, unsigned char *out, size_t len )
1002{
1003 static uint32_t x = 42;
1004 (void) p;
1005
1006 while( len > 0 )
1007 {
1008 size_t use_len = len > 4 ? 4 : len;
1009 x = 1664525 * x + 1013904223;
1010 memcpy( out, &x, use_len );
1011 out += use_len;
1012 len -= use_len;
1013 }
1014
1015 return( 0 );
1016}
1017
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +02001018#define TEST_ASSERT( x ) \
1019 do { \
1020 if( x ) \
1021 ret = 0; \
1022 else \
1023 { \
1024 ret = 1; \
1025 goto cleanup; \
1026 } \
1027 } while( 0 )
1028
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001029/*
1030 * Checkup routine
1031 */
1032int mbedtls_ecjpake_self_test( int verbose )
1033{
1034 int ret;
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001035 mbedtls_ecjpake_context cli;
1036 mbedtls_ecjpake_context srv;
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001037 unsigned char buf[512], pms[32];
1038 size_t len, pmslen;
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001039
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001040 mbedtls_ecjpake_init( &cli );
1041 mbedtls_ecjpake_init( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001042
1043 if( verbose != 0 )
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001044 mbedtls_printf( " ECJPAKE test #0 (setup): " );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +02001045
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +02001046 TEST_ASSERT( mbedtls_ecjpake_setup( &cli, MBEDTLS_ECJPAKE_CLIENT,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001047 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1048 ecjpake_test_password,
1049 sizeof( ecjpake_test_password ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001050
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +02001051 TEST_ASSERT( mbedtls_ecjpake_setup( &srv, MBEDTLS_ECJPAKE_SERVER,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001052 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1053 ecjpake_test_password,
1054 sizeof( ecjpake_test_password ) ) == 0 );
1055
1056 if( verbose != 0 )
1057 mbedtls_printf( "passed\n" );
1058
1059 if( verbose != 0 )
1060 mbedtls_printf( " ECJPAKE test #1 (random handshake): " );
1061
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001062 TEST_ASSERT( mbedtls_ecjpake_write_round_one( &cli,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001063 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1064
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001065 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv, buf, len ) == 0 );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001066
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001067 TEST_ASSERT( mbedtls_ecjpake_write_round_one( &srv,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001068 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1069
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001070 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli, buf, len ) == 0 );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001071
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001072 TEST_ASSERT( mbedtls_ecjpake_write_round_two( &srv,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +02001073 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1074
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001075 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli, buf, len ) == 0 );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +02001076
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001077 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001078 pms, sizeof( pms ), &pmslen, ecjpake_lgc, NULL ) == 0 );
1079
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001080 TEST_ASSERT( mbedtls_ecjpake_write_round_two( &cli,
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +02001081 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1082
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001083 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv, buf, len ) == 0 );
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +02001084
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001085 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001086 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1087
1088 TEST_ASSERT( len == pmslen );
1089 TEST_ASSERT( memcmp( buf, pms, len ) == 0 );
1090
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001091 if( verbose != 0 )
1092 mbedtls_printf( "passed\n" );
1093
1094 if( verbose != 0 )
1095 mbedtls_printf( " ECJPAKE test #2 (reference handshake): " );
1096
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001097 /* Simulate generation of round one */
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001098 MBEDTLS_MPI_CHK( ecjpake_test_load( &cli,
1099 ecjpake_test_x1, sizeof( ecjpake_test_x1 ),
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001100 ecjpake_test_x2, sizeof( ecjpake_test_x2 ) ) );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001101
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001102 MBEDTLS_MPI_CHK( ecjpake_test_load( &srv,
1103 ecjpake_test_x3, sizeof( ecjpake_test_x3 ),
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001104 ecjpake_test_x4, sizeof( ecjpake_test_x4 ) ) );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001105
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001106 /* Read round one */
1107 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv,
1108 ecjpake_test_cli_one,
1109 sizeof( ecjpake_test_cli_one ) ) == 0 );
1110
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001111 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001112 ecjpake_test_srv_one,
1113 sizeof( ecjpake_test_srv_one ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001114
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001115 /* Skip generation of round two, read round two */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001116 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001117 ecjpake_test_srv_two,
1118 sizeof( ecjpake_test_srv_two ) ) == 0 );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +02001119
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001120 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001121 ecjpake_test_cli_two,
1122 sizeof( ecjpake_test_cli_two ) ) == 0 );
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +02001123
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001124 /* Server derives PMS */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001125 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001126 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1127
1128 TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
1129 TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
1130
1131 memset( buf, 0, len ); /* Avoid interferences with next step */
1132
1133 /* Client derives PMS */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001134 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001135 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1136
1137 TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
1138 TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
1139
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001140 if( verbose != 0 )
1141 mbedtls_printf( "passed\n" );
1142
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001143cleanup:
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001144 mbedtls_ecjpake_free( &cli );
1145 mbedtls_ecjpake_free( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001146
1147 if( ret != 0 )
1148 {
1149 if( verbose != 0 )
1150 mbedtls_printf( "failed\n" );
1151
1152 ret = 1;
1153 }
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001154
1155 if( verbose != 0 )
1156 mbedtls_printf( "\n" );
1157
1158 return( ret );
1159}
1160
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +02001161#undef TEST_ASSERT
1162
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001163#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_SHA256_C */
1164
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001165#endif /* MBEDTLS_SELF_TEST */
1166
1167#endif /* MBEDTLS_ECJPAKE_C */