blob: 0532a295e6d04a6cf330230ae0ff898fa9354543 [file] [log] [blame]
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001/*
2 * Elliptic curve J-PAKE
3 *
Bence Szépkútia2947ac2020-08-19 16:37:36 +02004 * Copyright The Mbed TLS Contributors
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 * **********
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +020045 */
46
47/*
Manuel Pégourié-Gonnard6b798b92015-08-14 11:18:30 +020048 * References in the code are to the Thread v1.0 Specification,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +020049 * available to members of the Thread Group http://threadgroup.org/
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +020050 */
51
52#if !defined(MBEDTLS_CONFIG_FILE)
53#include "mbedtls/config.h"
54#else
55#include MBEDTLS_CONFIG_FILE
56#endif
57
58#if defined(MBEDTLS_ECJPAKE_C)
59
60#include "mbedtls/ecjpake.h"
Hanno Becker71c8e1b2018-12-14 17:09:39 +000061#include "mbedtls/platform_util.h"
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +020062
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +020063#include <string.h>
64
Hanno Becker616d1ca2018-01-24 10:25:05 +000065#if !defined(MBEDTLS_ECJPAKE_ALT)
66
Hanno Becker71c8e1b2018-12-14 17:09:39 +000067/* Parameter validation macros based on platform_util.h */
68#define ECJPAKE_VALIDATE_RET( cond ) \
69 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA )
70#define ECJPAKE_VALIDATE( cond ) \
71 MBEDTLS_INTERNAL_VALIDATE( cond )
72
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +020073/*
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +020074 * Convert a mbedtls_ecjpake_role to identifier string
75 */
76static const char * const ecjpake_id[] = {
77 "client",
78 "server"
79};
80
81#define ID_MINE ( ecjpake_id[ ctx->role ] )
82#define ID_PEER ( ecjpake_id[ 1 - ctx->role ] )
83
84/*
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020085 * Initialize context
86 */
87void mbedtls_ecjpake_init( mbedtls_ecjpake_context *ctx )
88{
Hanno Becker71c8e1b2018-12-14 17:09:39 +000089 ECJPAKE_VALIDATE( ctx != NULL );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020090
91 ctx->md_info = NULL;
92 mbedtls_ecp_group_init( &ctx->grp );
Manuel Pégourié-Gonnardb7da1942015-10-19 13:35:22 +020093 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020094
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +020095 mbedtls_ecp_point_init( &ctx->Xm1 );
96 mbedtls_ecp_point_init( &ctx->Xm2 );
97 mbedtls_ecp_point_init( &ctx->Xp1 );
98 mbedtls_ecp_point_init( &ctx->Xp2 );
99 mbedtls_ecp_point_init( &ctx->Xp );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200100
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200101 mbedtls_mpi_init( &ctx->xm1 );
102 mbedtls_mpi_init( &ctx->xm2 );
103 mbedtls_mpi_init( &ctx->s );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200104}
105
106/*
107 * Free context
108 */
109void mbedtls_ecjpake_free( mbedtls_ecjpake_context *ctx )
110{
111 if( ctx == NULL )
112 return;
113
114 ctx->md_info = NULL;
115 mbedtls_ecp_group_free( &ctx->grp );
116
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200117 mbedtls_ecp_point_free( &ctx->Xm1 );
118 mbedtls_ecp_point_free( &ctx->Xm2 );
119 mbedtls_ecp_point_free( &ctx->Xp1 );
120 mbedtls_ecp_point_free( &ctx->Xp2 );
121 mbedtls_ecp_point_free( &ctx->Xp );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200122
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200123 mbedtls_mpi_free( &ctx->xm1 );
124 mbedtls_mpi_free( &ctx->xm2 );
125 mbedtls_mpi_free( &ctx->s );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200126}
127
128/*
129 * Setup context
130 */
131int mbedtls_ecjpake_setup( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +0200132 mbedtls_ecjpake_role role,
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200133 mbedtls_md_type_t hash,
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200134 mbedtls_ecp_group_id curve,
135 const unsigned char *secret,
136 size_t len )
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200137{
138 int ret;
Hanno Becker185e5162018-12-19 09:48:50 +0000139
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000140 ECJPAKE_VALIDATE_RET( ctx != NULL );
141 ECJPAKE_VALIDATE_RET( role == MBEDTLS_ECJPAKE_CLIENT ||
142 role == MBEDTLS_ECJPAKE_SERVER );
143 ECJPAKE_VALIDATE_RET( secret != NULL || len == 0 );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200144
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +0200145 ctx->role = role;
146
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200147 if( ( ctx->md_info = mbedtls_md_info_from_type( hash ) ) == NULL )
148 return( MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE );
149
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200150 MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ctx->grp, curve ) );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200151
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200152 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->s, secret, len ) );
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200153
154cleanup:
155 if( ret != 0 )
156 mbedtls_ecjpake_free( ctx );
157
158 return( ret );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200159}
160
161/*
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200162 * Check if context is ready for use
163 */
164int mbedtls_ecjpake_check( const mbedtls_ecjpake_context *ctx )
165{
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000166 ECJPAKE_VALIDATE_RET( ctx != NULL );
167
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200168 if( ctx->md_info == NULL ||
169 ctx->grp.id == MBEDTLS_ECP_DP_NONE ||
170 ctx->s.p == NULL )
171 {
172 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
173 }
174
175 return( 0 );
176}
177
178/*
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200179 * Write a point plus its length to a buffer
180 */
181static int ecjpake_write_len_point( unsigned char **p,
182 const unsigned char *end,
183 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100184 const int pf,
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200185 const mbedtls_ecp_point *P )
186{
187 int ret;
188 size_t len;
189
190 /* Need at least 4 for length plus 1 for point */
191 if( end < *p || end - *p < 5 )
192 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
193
Robert Cragie7cdad772015-10-02 13:31:41 +0100194 ret = mbedtls_ecp_point_write_binary( grp, P, pf,
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200195 &len, *p + 4, end - ( *p + 4 ) );
196 if( ret != 0 )
197 return( ret );
198
199 (*p)[0] = (unsigned char)( ( len >> 24 ) & 0xFF );
200 (*p)[1] = (unsigned char)( ( len >> 16 ) & 0xFF );
201 (*p)[2] = (unsigned char)( ( len >> 8 ) & 0xFF );
202 (*p)[3] = (unsigned char)( ( len ) & 0xFF );
203
204 *p += 4 + len;
205
206 return( 0 );
207}
208
209/*
210 * Size of the temporary buffer for ecjpake_hash:
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200211 * 3 EC points plus their length, plus ID and its length (4 + 6 bytes)
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200212 */
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200213#define ECJPAKE_HASH_BUF_LEN ( 3 * ( 4 + MBEDTLS_ECP_MAX_PT_LEN ) + 4 + 6 )
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200214
215/*
216 * Compute hash for ZKP (7.4.2.2.2.1)
217 */
218static int ecjpake_hash( const mbedtls_md_info_t *md_info,
219 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100220 const int pf,
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200221 const mbedtls_ecp_point *G,
222 const mbedtls_ecp_point *V,
223 const mbedtls_ecp_point *X,
224 const char *id,
225 mbedtls_mpi *h )
226{
227 int ret;
228 unsigned char buf[ECJPAKE_HASH_BUF_LEN];
229 unsigned char *p = buf;
230 const unsigned char *end = buf + sizeof( buf );
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200231 const size_t id_len = strlen( id );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200232 unsigned char hash[MBEDTLS_MD_MAX_SIZE];
233
234 /* Write things to temporary buffer */
Robert Cragie7cdad772015-10-02 13:31:41 +0100235 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, G ) );
236 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, V ) );
237 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, X ) );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200238
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200239 if( end - p < 4 )
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200240 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
241
242 *p++ = (unsigned char)( ( id_len >> 24 ) & 0xFF );
243 *p++ = (unsigned char)( ( id_len >> 16 ) & 0xFF );
244 *p++ = (unsigned char)( ( id_len >> 8 ) & 0xFF );
245 *p++ = (unsigned char)( ( id_len ) & 0xFF );
246
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200247 if( end < p || (size_t)( end - p ) < id_len )
248 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
249
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200250 memcpy( p, id, id_len );
251 p += id_len;
252
253 /* Compute hash */
k-stachowiak4a6a55c2019-06-28 14:14:02 +0200254 MBEDTLS_MPI_CHK( mbedtls_md( md_info, buf, p - buf, hash ) );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200255
256 /* Turn it into an integer mod n */
257 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( h, hash,
258 mbedtls_md_get_size( md_info ) ) );
259 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( h, h, &grp->N ) );
260
261cleanup:
262 return( ret );
263}
264
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200265/*
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200266 * Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3)
267 */
268static int ecjpake_zkp_read( const mbedtls_md_info_t *md_info,
269 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100270 const int pf,
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200271 const mbedtls_ecp_point *G,
272 const mbedtls_ecp_point *X,
273 const char *id,
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200274 const unsigned char **p,
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200275 const unsigned char *end )
276{
277 int ret;
278 mbedtls_ecp_point V, VV;
279 mbedtls_mpi r, h;
280 size_t r_len;
281
282 mbedtls_ecp_point_init( &V );
283 mbedtls_ecp_point_init( &VV );
284 mbedtls_mpi_init( &r );
285 mbedtls_mpi_init( &h );
286
287 /*
288 * struct {
289 * ECPoint V;
290 * opaque r<1..2^8-1>;
291 * } ECSchnorrZKP;
292 */
293 if( end < *p )
294 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
295
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200296 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, &V, p, end - *p ) );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200297
298 if( end < *p || (size_t)( end - *p ) < 1 )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200299 {
300 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
301 goto cleanup;
302 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200303
304 r_len = *(*p)++;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200305
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200306 if( end < *p || (size_t)( end - *p ) < r_len )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200307 {
308 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
309 goto cleanup;
310 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200311
312 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &r, *p, r_len ) );
313 *p += r_len;
314
315 /*
316 * Verification
317 */
Robert Cragie7cdad772015-10-02 13:31:41 +0100318 MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200319 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( (mbedtls_ecp_group *) grp,
320 &VV, &h, X, &r, G ) );
321
322 if( mbedtls_ecp_point_cmp( &VV, &V ) != 0 )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200323 {
324 ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
325 goto cleanup;
326 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200327
328cleanup:
329 mbedtls_ecp_point_free( &V );
330 mbedtls_ecp_point_free( &VV );
331 mbedtls_mpi_free( &r );
332 mbedtls_mpi_free( &h );
333
334 return( ret );
335}
336
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200337/*
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200338 * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2)
339 */
340static int ecjpake_zkp_write( const mbedtls_md_info_t *md_info,
341 const mbedtls_ecp_group *grp,
Darryl Green11999bb2018-03-13 15:22:58 +0000342 const int pf,
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200343 const mbedtls_ecp_point *G,
344 const mbedtls_mpi *x,
345 const mbedtls_ecp_point *X,
346 const char *id,
347 unsigned char **p,
348 const unsigned char *end,
349 int (*f_rng)(void *, unsigned char *, size_t),
350 void *p_rng )
351{
352 int ret;
353 mbedtls_ecp_point V;
354 mbedtls_mpi v;
355 mbedtls_mpi h; /* later recycled to hold r */
356 size_t len;
357
358 if( end < *p )
359 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
360
361 mbedtls_ecp_point_init( &V );
362 mbedtls_mpi_init( &v );
363 mbedtls_mpi_init( &h );
364
365 /* Compute signature */
366 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp,
367 G, &v, &V, f_rng, p_rng ) );
Robert Cragie7cdad772015-10-02 13:31:41 +0100368 MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) );
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200369 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &h, &h, x ) ); /* x*h */
370 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &h, &v, &h ) ); /* v - x*h */
371 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &h, &h, &grp->N ) ); /* r */
372
373 /* Write it out */
374 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, &V,
Robert Cragie7cdad772015-10-02 13:31:41 +0100375 pf, &len, *p, end - *p ) );
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200376 *p += len;
377
378 len = mbedtls_mpi_size( &h ); /* actually r */
379 if( end < *p || (size_t)( end - *p ) < 1 + len || len > 255 )
380 {
381 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
382 goto cleanup;
383 }
384
385 *(*p)++ = (unsigned char)( len & 0xFF );
386 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, *p, len ) ); /* r */
387 *p += len;
388
389cleanup:
390 mbedtls_ecp_point_free( &V );
391 mbedtls_mpi_free( &v );
392 mbedtls_mpi_free( &h );
393
394 return( ret );
395}
396
397/*
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200398 * Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof
399 * Output: verified public key X
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200400 */
401static int ecjpake_kkp_read( const mbedtls_md_info_t *md_info,
402 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100403 const int pf,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200404 const mbedtls_ecp_point *G,
405 mbedtls_ecp_point *X,
406 const char *id,
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200407 const unsigned char **p,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200408 const unsigned char *end )
409{
410 int ret;
411
412 if( end < *p )
413 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
414
415 /*
416 * struct {
417 * ECPoint X;
418 * ECSchnorrZKP zkp;
419 * } ECJPAKEKeyKP;
420 */
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200421 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, X, p, end - *p ) );
Manuel Pégourié-Gonnard30590952015-08-17 10:37:40 +0200422 if( mbedtls_ecp_is_zero( X ) )
423 {
424 ret = MBEDTLS_ERR_ECP_INVALID_KEY;
425 goto cleanup;
426 }
427
Robert Cragie7cdad772015-10-02 13:31:41 +0100428 MBEDTLS_MPI_CHK( ecjpake_zkp_read( md_info, grp, pf, G, X, id, p, end ) );
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200429
430cleanup:
431 return( ret );
432}
433
434/*
435 * Generate an ECJPAKEKeyKP
436 * Output: the serialized structure, plus private/public key pair
437 */
438static int ecjpake_kkp_write( const mbedtls_md_info_t *md_info,
439 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100440 const int pf,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200441 const mbedtls_ecp_point *G,
442 mbedtls_mpi *x,
443 mbedtls_ecp_point *X,
444 const char *id,
445 unsigned char **p,
446 const unsigned char *end,
447 int (*f_rng)(void *, unsigned char *, size_t),
448 void *p_rng )
449{
450 int ret;
451 size_t len;
452
453 if( end < *p )
454 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
455
456 /* Generate key (7.4.2.3.1) and write it out */
457 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp, G, x, X,
458 f_rng, p_rng ) );
459 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, X,
Robert Cragie7cdad772015-10-02 13:31:41 +0100460 pf, &len, *p, end - *p ) );
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200461 *p += len;
462
463 /* Generate and write proof */
Robert Cragie7cdad772015-10-02 13:31:41 +0100464 MBEDTLS_MPI_CHK( ecjpake_zkp_write( md_info, grp, pf, G, x, X, id,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200465 p, end, f_rng, p_rng ) );
466
467cleanup:
468 return( ret );
469}
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200470
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200471/*
472 * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs
473 * Ouputs: verified peer public keys Xa, Xb
474 */
475static int ecjpake_kkpp_read( const mbedtls_md_info_t *md_info,
476 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100477 const int pf,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200478 const mbedtls_ecp_point *G,
479 mbedtls_ecp_point *Xa,
480 mbedtls_ecp_point *Xb,
481 const char *id,
482 const unsigned char *buf,
483 size_t len )
484{
485 int ret;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200486 const unsigned char *p = buf;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200487 const unsigned char *end = buf + len;
488
489 /*
490 * struct {
491 * ECJPAKEKeyKP ecjpake_key_kp_pair_list[2];
492 * } ECJPAKEKeyKPPairList;
493 */
Robert Cragie7cdad772015-10-02 13:31:41 +0100494 MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xa, id, &p, end ) );
495 MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xb, id, &p, end ) );
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200496
497 if( p != end )
498 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
499
500cleanup:
501 return( ret );
502}
503
504/*
505 * Generate a ECJPAKEKeyKPPairList
506 * Outputs: the serialized structure, plus two private/public key pairs
507 */
508static int ecjpake_kkpp_write( const mbedtls_md_info_t *md_info,
509 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100510 const int pf,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200511 const mbedtls_ecp_point *G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200512 mbedtls_mpi *xm1,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200513 mbedtls_ecp_point *Xa,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200514 mbedtls_mpi *xm2,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200515 mbedtls_ecp_point *Xb,
516 const char *id,
517 unsigned char *buf,
518 size_t len,
519 size_t *olen,
520 int (*f_rng)(void *, unsigned char *, size_t),
521 void *p_rng )
522{
523 int ret;
524 unsigned char *p = buf;
525 const unsigned char *end = buf + len;
526
Robert Cragie7cdad772015-10-02 13:31:41 +0100527 MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm1, Xa, id,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200528 &p, end, f_rng, p_rng ) );
Robert Cragie7cdad772015-10-02 13:31:41 +0100529 MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm2, Xb, id,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200530 &p, end, f_rng, p_rng ) );
531
532 *olen = p - buf;
533
534cleanup:
535 return( ret );
536}
537
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200538/*
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200539 * Read and process the first round message
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200540 */
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200541int mbedtls_ecjpake_read_round_one( mbedtls_ecjpake_context *ctx,
542 const unsigned char *buf,
543 size_t len )
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200544{
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000545 ECJPAKE_VALIDATE_RET( ctx != NULL );
546 ECJPAKE_VALIDATE_RET( buf != NULL );
547
Robert Cragie7cdad772015-10-02 13:31:41 +0100548 return( ecjpake_kkpp_read( ctx->md_info, &ctx->grp, ctx->point_format,
549 &ctx->grp.G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200550 &ctx->Xp1, &ctx->Xp2, ID_PEER,
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200551 buf, len ) );
552}
553
554/*
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200555 * Generate and write the first round message
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200556 */
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200557int mbedtls_ecjpake_write_round_one( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200558 unsigned char *buf, size_t len, size_t *olen,
559 int (*f_rng)(void *, unsigned char *, size_t),
560 void *p_rng )
561{
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000562 ECJPAKE_VALIDATE_RET( ctx != NULL );
563 ECJPAKE_VALIDATE_RET( buf != NULL );
564 ECJPAKE_VALIDATE_RET( olen != NULL );
565 ECJPAKE_VALIDATE_RET( f_rng != NULL );
566
Robert Cragie7cdad772015-10-02 13:31:41 +0100567 return( ecjpake_kkpp_write( ctx->md_info, &ctx->grp, ctx->point_format,
568 &ctx->grp.G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200569 &ctx->xm1, &ctx->Xm1, &ctx->xm2, &ctx->Xm2,
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200570 ID_MINE, buf, len, olen, f_rng, p_rng ) );
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200571}
572
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200573/*
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200574 * Compute the sum of three points R = A + B + C
575 */
576static int ecjpake_ecp_add3( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
577 const mbedtls_ecp_point *A,
578 const mbedtls_ecp_point *B,
579 const mbedtls_ecp_point *C )
580{
581 int ret;
582 mbedtls_mpi one;
583
584 mbedtls_mpi_init( &one );
585
586 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
587 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, A, &one, B ) );
588 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, R, &one, C ) );
589
590cleanup:
591 mbedtls_mpi_free( &one );
592
593 return( ret );
594}
595
596/*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200597 * 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 +0200598 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200599int mbedtls_ecjpake_read_round_two( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200600 const unsigned char *buf,
601 size_t len )
602{
603 int ret;
604 const unsigned char *p = buf;
605 const unsigned char *end = buf + len;
606 mbedtls_ecp_group grp;
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200607 mbedtls_ecp_point G; /* C: GB, S: GA */
Hanno Becker185e5162018-12-19 09:48:50 +0000608
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000609 ECJPAKE_VALIDATE_RET( ctx != NULL );
610 ECJPAKE_VALIDATE_RET( buf != NULL );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200611
612 mbedtls_ecp_group_init( &grp );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200613 mbedtls_ecp_point_init( &G );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200614
615 /*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200616 * Server: GA = X3 + X4 + X1 (7.4.2.6.1)
617 * Client: GB = X1 + X2 + X3 (7.4.2.5.1)
618 * Unified: G = Xm1 + Xm2 + Xp1
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200619 * We need that before parsing in order to check Xp as we read it
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200620 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200621 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200622 &ctx->Xm1, &ctx->Xm2, &ctx->Xp1 ) );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200623
624 /*
625 * struct {
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200626 * ECParameters curve_params; // only client reading server msg
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200627 * ECJPAKEKeyKP ecjpake_key_kp;
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200628 * } Client/ServerECJPAKEParams;
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200629 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200630 if( ctx->role == MBEDTLS_ECJPAKE_CLIENT )
Manuel Pégourié-Gonnardd9802af2015-08-17 12:47:38 +0200631 {
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200632 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_group( &grp, &p, len ) );
Manuel Pégourié-Gonnardd9802af2015-08-17 12:47:38 +0200633 if( grp.id != ctx->grp.id )
634 {
635 ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
636 goto cleanup;
637 }
638 }
639
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200640 MBEDTLS_MPI_CHK( ecjpake_kkp_read( ctx->md_info, &ctx->grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100641 ctx->point_format,
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200642 &G, &ctx->Xp, ID_PEER, &p, end ) );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200643
644 if( p != end )
645 {
646 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
647 goto cleanup;
648 }
649
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200650cleanup:
651 mbedtls_ecp_group_free( &grp );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200652 mbedtls_ecp_point_free( &G );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200653
654 return( ret );
655}
656
657/*
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200658 * Compute R = +/- X * S mod N, taking care not to leak S
659 */
660static int ecjpake_mul_secret( mbedtls_mpi *R, int sign,
661 const mbedtls_mpi *X,
662 const mbedtls_mpi *S,
663 const mbedtls_mpi *N,
664 int (*f_rng)(void *, unsigned char *, size_t),
665 void *p_rng )
666{
667 int ret;
668 mbedtls_mpi b; /* Blinding value, then s + N * blinding */
669
670 mbedtls_mpi_init( &b );
671
672 /* b = s + rnd-128-bit * N */
673 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &b, 16, f_rng, p_rng ) );
674 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &b, &b, N ) );
675 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &b, &b, S ) );
676
677 /* R = sign * X * b mod N */
678 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( R, X, &b ) );
679 R->s *= sign;
680 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( R, R, N ) );
681
682cleanup:
683 mbedtls_mpi_free( &b );
684
685 return( ret );
686}
687
688/*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200689 * 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 +0200690 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200691int mbedtls_ecjpake_write_round_two( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200692 unsigned char *buf, size_t len, size_t *olen,
693 int (*f_rng)(void *, unsigned char *, size_t),
694 void *p_rng )
695{
696 int ret;
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200697 mbedtls_ecp_point G; /* C: GA, S: GB */
698 mbedtls_ecp_point Xm; /* C: Xc, S: Xs */
699 mbedtls_mpi xm; /* C: xc, S: xs */
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200700 unsigned char *p = buf;
701 const unsigned char *end = buf + len;
702 size_t ec_len;
Hanno Becker185e5162018-12-19 09:48:50 +0000703
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000704 ECJPAKE_VALIDATE_RET( ctx != NULL );
705 ECJPAKE_VALIDATE_RET( buf != NULL );
706 ECJPAKE_VALIDATE_RET( olen != NULL );
707 ECJPAKE_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200708
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200709 mbedtls_ecp_point_init( &G );
710 mbedtls_ecp_point_init( &Xm );
711 mbedtls_mpi_init( &xm );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200712
713 /*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200714 * 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 +0200715 *
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200716 * Client: GA = X1 + X3 + X4 | xs = x2 * s | Xc = xc * GA
717 * Server: GB = X3 + X1 + X2 | xs = x4 * s | Xs = xs * GB
718 * Unified: G = Xm1 + Xp1 + Xp2 | xm = xm2 * s | Xm = xm * G
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200719 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200720 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200721 &ctx->Xp1, &ctx->Xp2, &ctx->Xm1 ) );
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200722 MBEDTLS_MPI_CHK( ecjpake_mul_secret( &xm, 1, &ctx->xm2, &ctx->s,
723 &ctx->grp.N, f_rng, p_rng ) );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200724 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &Xm, &xm, &G, f_rng, p_rng ) );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200725
726 /*
727 * Now write things out
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200728 *
729 * struct {
730 * ECParameters curve_params; // only server writing its message
731 * ECJPAKEKeyKP ecjpake_key_kp;
732 * } Client/ServerECJPAKEParams;
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200733 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200734 if( ctx->role == MBEDTLS_ECJPAKE_SERVER )
735 {
736 if( end < p )
737 {
738 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
739 goto cleanup;
740 }
741 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_group( &ctx->grp, &ec_len,
742 p, end - p ) );
743 p += ec_len;
744 }
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200745
746 if( end < p )
747 {
748 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
749 goto cleanup;
750 }
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200751 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( &ctx->grp, &Xm,
Robert Cragie7cdad772015-10-02 13:31:41 +0100752 ctx->point_format, &ec_len, p, end - p ) );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200753 p += ec_len;
754
755 MBEDTLS_MPI_CHK( ecjpake_zkp_write( ctx->md_info, &ctx->grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100756 ctx->point_format,
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200757 &G, &xm, &Xm, ID_MINE,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200758 &p, end, f_rng, p_rng ) );
759
760 *olen = p - buf;
761
762cleanup:
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200763 mbedtls_ecp_point_free( &G );
764 mbedtls_ecp_point_free( &Xm );
765 mbedtls_mpi_free( &xm );
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +0200766
767 return( ret );
768}
769
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200770/*
771 * Derive PMS (7.4.2.7 / 7.4.2.8)
772 */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +0200773int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200774 unsigned char *buf, size_t len, size_t *olen,
775 int (*f_rng)(void *, unsigned char *, size_t),
776 void *p_rng )
777{
778 int ret;
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200779 mbedtls_ecp_point K;
780 mbedtls_mpi m_xm2_s, one;
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200781 unsigned char kx[MBEDTLS_ECP_MAX_BYTES];
782 size_t x_bytes;
Hanno Becker185e5162018-12-19 09:48:50 +0000783
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000784 ECJPAKE_VALIDATE_RET( ctx != NULL );
785 ECJPAKE_VALIDATE_RET( buf != NULL );
786 ECJPAKE_VALIDATE_RET( olen != NULL );
787 ECJPAKE_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200788
789 *olen = mbedtls_md_get_size( ctx->md_info );
790 if( len < *olen )
791 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
792
793 mbedtls_ecp_point_init( &K );
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200794 mbedtls_mpi_init( &m_xm2_s );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200795 mbedtls_mpi_init( &one );
796
797 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200798
799 /*
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200800 * Client: K = ( Xs - X4 * x2 * s ) * x2
801 * Server: K = ( Xc - X2 * x4 * s ) * x4
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200802 * Unified: K = ( Xp - Xp2 * xm2 * s ) * xm2
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200803 */
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200804 MBEDTLS_MPI_CHK( ecjpake_mul_secret( &m_xm2_s, -1, &ctx->xm2, &ctx->s,
805 &ctx->grp.N, f_rng, p_rng ) );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200806 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( &ctx->grp, &K,
807 &one, &ctx->Xp,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200808 &m_xm2_s, &ctx->Xp2 ) );
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200809 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &K, &ctx->xm2, &K,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200810 f_rng, p_rng ) );
811
812 /* PMS = SHA-256( K.X ) */
813 x_bytes = ( ctx->grp.pbits + 7 ) / 8;
814 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &K.X, kx, x_bytes ) );
815 MBEDTLS_MPI_CHK( mbedtls_md( ctx->md_info, kx, x_bytes, buf ) );
816
817cleanup:
818 mbedtls_ecp_point_free( &K );
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200819 mbedtls_mpi_free( &m_xm2_s );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200820 mbedtls_mpi_free( &one );
821
822 return( ret );
823}
824
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200825#undef ID_MINE
826#undef ID_PEER
827
Hanno Becker616d1ca2018-01-24 10:25:05 +0000828#endif /* ! MBEDTLS_ECJPAKE_ALT */
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200829
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200830#if defined(MBEDTLS_SELF_TEST)
831
832#if defined(MBEDTLS_PLATFORM_C)
833#include "mbedtls/platform.h"
834#else
835#include <stdio.h>
836#define mbedtls_printf printf
837#endif
838
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200839#if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
840 !defined(MBEDTLS_SHA256_C)
841int mbedtls_ecjpake_self_test( int verbose )
842{
843 (void) verbose;
844 return( 0 );
845}
846#else
847
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200848static const unsigned char ecjpake_test_password[] = {
849 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x6a, 0x70, 0x61, 0x6b, 0x65, 0x74,
850 0x65, 0x73, 0x74
851};
852
Steven Cooreman0b7cb312021-01-11 17:20:10 +0100853#if !defined(MBEDTLS_ECJPAKE_ALT)
854
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200855static 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
Steven Cooreman0b7cb312021-01-11 17:20:10 +0100999#endif /* ! MBEDTLS_ECJPAKE_ALT */
1000
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001001/* For tests we don't need a secure RNG;
1002 * use the LGC from Numerical Recipes for simplicity */
1003static int ecjpake_lgc( void *p, unsigned char *out, size_t len )
1004{
1005 static uint32_t x = 42;
1006 (void) p;
1007
1008 while( len > 0 )
1009 {
1010 size_t use_len = len > 4 ? 4 : len;
1011 x = 1664525 * x + 1013904223;
1012 memcpy( out, &x, use_len );
1013 out += use_len;
1014 len -= use_len;
1015 }
1016
1017 return( 0 );
1018}
1019
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +02001020#define TEST_ASSERT( x ) \
1021 do { \
1022 if( x ) \
1023 ret = 0; \
1024 else \
1025 { \
1026 ret = 1; \
1027 goto cleanup; \
1028 } \
1029 } while( 0 )
1030
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001031/*
1032 * Checkup routine
1033 */
1034int mbedtls_ecjpake_self_test( int verbose )
1035{
1036 int ret;
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001037 mbedtls_ecjpake_context cli;
1038 mbedtls_ecjpake_context srv;
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001039 unsigned char buf[512], pms[32];
1040 size_t len, pmslen;
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001041
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001042 mbedtls_ecjpake_init( &cli );
1043 mbedtls_ecjpake_init( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001044
1045 if( verbose != 0 )
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001046 mbedtls_printf( " ECJPAKE test #0 (setup): " );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +02001047
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +02001048 TEST_ASSERT( mbedtls_ecjpake_setup( &cli, MBEDTLS_ECJPAKE_CLIENT,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001049 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1050 ecjpake_test_password,
1051 sizeof( ecjpake_test_password ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001052
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +02001053 TEST_ASSERT( mbedtls_ecjpake_setup( &srv, MBEDTLS_ECJPAKE_SERVER,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001054 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1055 ecjpake_test_password,
1056 sizeof( ecjpake_test_password ) ) == 0 );
1057
1058 if( verbose != 0 )
1059 mbedtls_printf( "passed\n" );
1060
1061 if( verbose != 0 )
1062 mbedtls_printf( " ECJPAKE test #1 (random handshake): " );
1063
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001064 TEST_ASSERT( mbedtls_ecjpake_write_round_one( &cli,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001065 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1066
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001067 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv, buf, len ) == 0 );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001068
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001069 TEST_ASSERT( mbedtls_ecjpake_write_round_one( &srv,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001070 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1071
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001072 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli, buf, len ) == 0 );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001073
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001074 TEST_ASSERT( mbedtls_ecjpake_write_round_two( &srv,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +02001075 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1076
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001077 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli, buf, len ) == 0 );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +02001078
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001079 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001080 pms, sizeof( pms ), &pmslen, ecjpake_lgc, NULL ) == 0 );
1081
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001082 TEST_ASSERT( mbedtls_ecjpake_write_round_two( &cli,
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +02001083 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1084
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001085 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv, buf, len ) == 0 );
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +02001086
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001087 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001088 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1089
1090 TEST_ASSERT( len == pmslen );
1091 TEST_ASSERT( memcmp( buf, pms, len ) == 0 );
1092
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001093 if( verbose != 0 )
1094 mbedtls_printf( "passed\n" );
1095
Steven Cooreman0b7cb312021-01-11 17:20:10 +01001096#if !defined(MBEDTLS_ECJPAKE_ALT)
1097 /* 'reference handshake' tests can only be run against implementations
1098 * for which we have 100% control over how the random ephemeral keys
1099 * are generated. This is only the case for the internal mbed TLS
1100 * implementation, so these tests are skipped in case the internal
1101 * implementation is swapped out for an alternative one. */
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001102 if( verbose != 0 )
1103 mbedtls_printf( " ECJPAKE test #2 (reference handshake): " );
1104
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001105 /* Simulate generation of round one */
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001106 MBEDTLS_MPI_CHK( ecjpake_test_load( &cli,
1107 ecjpake_test_x1, sizeof( ecjpake_test_x1 ),
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001108 ecjpake_test_x2, sizeof( ecjpake_test_x2 ) ) );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001109
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001110 MBEDTLS_MPI_CHK( ecjpake_test_load( &srv,
1111 ecjpake_test_x3, sizeof( ecjpake_test_x3 ),
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001112 ecjpake_test_x4, sizeof( ecjpake_test_x4 ) ) );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001113
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001114 /* Read round one */
1115 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv,
1116 ecjpake_test_cli_one,
1117 sizeof( ecjpake_test_cli_one ) ) == 0 );
1118
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001119 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001120 ecjpake_test_srv_one,
1121 sizeof( ecjpake_test_srv_one ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001122
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001123 /* Skip generation of round two, read round two */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001124 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001125 ecjpake_test_srv_two,
1126 sizeof( ecjpake_test_srv_two ) ) == 0 );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +02001127
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001128 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001129 ecjpake_test_cli_two,
1130 sizeof( ecjpake_test_cli_two ) ) == 0 );
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +02001131
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001132 /* Server derives PMS */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001133 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001134 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1135
1136 TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
1137 TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
1138
1139 memset( buf, 0, len ); /* Avoid interferences with next step */
1140
1141 /* Client derives PMS */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001142 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001143 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1144
1145 TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
1146 TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
1147
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001148 if( verbose != 0 )
1149 mbedtls_printf( "passed\n" );
Steven Cooreman0b7cb312021-01-11 17:20:10 +01001150#endif /* ! MBEDTLS_ECJPAKE_ALT */
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001151
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001152cleanup:
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001153 mbedtls_ecjpake_free( &cli );
1154 mbedtls_ecjpake_free( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001155
1156 if( ret != 0 )
1157 {
1158 if( verbose != 0 )
1159 mbedtls_printf( "failed\n" );
1160
1161 ret = 1;
1162 }
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001163
1164 if( verbose != 0 )
1165 mbedtls_printf( "\n" );
1166
1167 return( ret );
1168}
1169
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +02001170#undef TEST_ASSERT
1171
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001172#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_SHA256_C */
1173
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001174#endif /* MBEDTLS_SELF_TEST */
1175
1176#endif /* MBEDTLS_ECJPAKE_C */