blob: f6e24580c72e719ccc704a5847329d34e9604273 [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
853static const unsigned char ecjpake_test_x1[] = {
854 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
855 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
856 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21
857};
858
859static const unsigned char ecjpake_test_x2[] = {
860 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
861 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
862 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
863};
864
865static const unsigned char ecjpake_test_x3[] = {
866 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
867 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
868 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
869};
870
871static const unsigned char ecjpake_test_x4[] = {
872 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc,
873 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
874 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1
875};
876
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200877static const unsigned char ecjpake_test_cli_one[] = {
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200878 0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19,
879 0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44,
880 0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad,
881 0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62,
882 0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9,
883 0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d,
884 0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e,
885 0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e,
886 0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73,
887 0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22,
888 0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce,
889 0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00,
890 0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200891 0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e,
892 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62,
893 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5,
894 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb,
895 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35,
896 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0,
897 0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb,
898 0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47,
899 0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39,
900 0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97,
901 0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40,
902 0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d,
903 0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa,
904 0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d,
905 0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200906};
907
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200908static const unsigned char ecjpake_test_srv_one[] = {
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200909 0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb,
910 0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18,
911 0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47,
912 0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f,
913 0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7,
914 0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d,
915 0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64,
916 0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36,
917 0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2,
918 0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec,
919 0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16,
920 0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96,
921 0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3,
922 0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19,
923 0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f,
924 0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8,
925 0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7,
926 0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea,
927 0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5,
928 0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6,
929 0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31,
930 0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d,
931 0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8,
932 0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee,
933 0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84,
934 0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f,
935 0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80,
936 0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12
937};
938
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200939static const unsigned char ecjpake_test_srv_two[] = {
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200940 0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23,
941 0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c,
942 0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f,
943 0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca,
944 0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26,
945 0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55,
946 0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38,
947 0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6,
948 0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9,
949 0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4,
950 0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2,
951 0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8,
952 0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd,
953 0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c
954};
955
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200956static const unsigned char ecjpake_test_cli_two[] = {
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +0200957 0x41, 0x04, 0x69, 0xd5, 0x4e, 0xe8, 0x5e, 0x90, 0xce, 0x3f, 0x12, 0x46,
958 0x74, 0x2d, 0xe5, 0x07, 0xe9, 0x39, 0xe8, 0x1d, 0x1d, 0xc1, 0xc5, 0xcb,
959 0x98, 0x8b, 0x58, 0xc3, 0x10, 0xc9, 0xfd, 0xd9, 0x52, 0x4d, 0x93, 0x72,
960 0x0b, 0x45, 0x54, 0x1c, 0x83, 0xee, 0x88, 0x41, 0x19, 0x1d, 0xa7, 0xce,
961 0xd8, 0x6e, 0x33, 0x12, 0xd4, 0x36, 0x23, 0xc1, 0xd6, 0x3e, 0x74, 0x98,
962 0x9a, 0xba, 0x4a, 0xff, 0xd1, 0xee, 0x41, 0x04, 0x07, 0x7e, 0x8c, 0x31,
963 0xe2, 0x0e, 0x6b, 0xed, 0xb7, 0x60, 0xc1, 0x35, 0x93, 0xe6, 0x9f, 0x15,
964 0xbe, 0x85, 0xc2, 0x7d, 0x68, 0xcd, 0x09, 0xcc, 0xb8, 0xc4, 0x18, 0x36,
965 0x08, 0x91, 0x7c, 0x5c, 0x3d, 0x40, 0x9f, 0xac, 0x39, 0xfe, 0xfe, 0xe8,
966 0x2f, 0x72, 0x92, 0xd3, 0x6f, 0x0d, 0x23, 0xe0, 0x55, 0x91, 0x3f, 0x45,
967 0xa5, 0x2b, 0x85, 0xdd, 0x8a, 0x20, 0x52, 0xe9, 0xe1, 0x29, 0xbb, 0x4d,
968 0x20, 0x0f, 0x01, 0x1f, 0x19, 0x48, 0x35, 0x35, 0xa6, 0xe8, 0x9a, 0x58,
969 0x0c, 0x9b, 0x00, 0x03, 0xba, 0xf2, 0x14, 0x62, 0xec, 0xe9, 0x1a, 0x82,
970 0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c
971};
972
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200973static const unsigned char ecjpake_test_pms[] = {
974 0xf3, 0xd4, 0x7f, 0x59, 0x98, 0x44, 0xdb, 0x92, 0xa5, 0x69, 0xbb, 0xe7,
975 0x98, 0x1e, 0x39, 0xd9, 0x31, 0xfd, 0x74, 0x3b, 0xf2, 0x2e, 0x98, 0xf9,
976 0xb4, 0x38, 0xf7, 0x19, 0xd3, 0xc4, 0xf3, 0x51
977};
978
Antonin Décimod5f47592019-01-23 15:24:37 +0100979/* Load my private keys and generate the corresponding public keys */
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +0200980static int ecjpake_test_load( mbedtls_ecjpake_context *ctx,
981 const unsigned char *xm1, size_t len1,
982 const unsigned char *xm2, size_t len2 )
983{
984 int ret;
985
986 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm1, xm1, len1 ) );
987 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm2, xm2, len2 ) );
988 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm1, &ctx->xm1,
989 &ctx->grp.G, NULL, NULL ) );
990 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm2, &ctx->xm2,
991 &ctx->grp.G, NULL, NULL ) );
992
993cleanup:
994 return( ret );
995}
996
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200997/* For tests we don't need a secure RNG;
998 * use the LGC from Numerical Recipes for simplicity */
999static int ecjpake_lgc( void *p, unsigned char *out, size_t len )
1000{
1001 static uint32_t x = 42;
1002 (void) p;
1003
1004 while( len > 0 )
1005 {
1006 size_t use_len = len > 4 ? 4 : len;
1007 x = 1664525 * x + 1013904223;
1008 memcpy( out, &x, use_len );
1009 out += use_len;
1010 len -= use_len;
1011 }
1012
1013 return( 0 );
1014}
1015
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +02001016#define TEST_ASSERT( x ) \
1017 do { \
1018 if( x ) \
1019 ret = 0; \
1020 else \
1021 { \
1022 ret = 1; \
1023 goto cleanup; \
1024 } \
1025 } while( 0 )
1026
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001027/*
1028 * Checkup routine
1029 */
1030int mbedtls_ecjpake_self_test( int verbose )
1031{
1032 int ret;
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001033 mbedtls_ecjpake_context cli;
1034 mbedtls_ecjpake_context srv;
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001035 unsigned char buf[512], pms[32];
1036 size_t len, pmslen;
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001037
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001038 mbedtls_ecjpake_init( &cli );
1039 mbedtls_ecjpake_init( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001040
1041 if( verbose != 0 )
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001042 mbedtls_printf( " ECJPAKE test #0 (setup): " );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +02001043
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +02001044 TEST_ASSERT( mbedtls_ecjpake_setup( &cli, MBEDTLS_ECJPAKE_CLIENT,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001045 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1046 ecjpake_test_password,
1047 sizeof( ecjpake_test_password ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001048
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +02001049 TEST_ASSERT( mbedtls_ecjpake_setup( &srv, MBEDTLS_ECJPAKE_SERVER,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001050 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1051 ecjpake_test_password,
1052 sizeof( ecjpake_test_password ) ) == 0 );
1053
1054 if( verbose != 0 )
1055 mbedtls_printf( "passed\n" );
1056
1057 if( verbose != 0 )
1058 mbedtls_printf( " ECJPAKE test #1 (random handshake): " );
1059
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001060 TEST_ASSERT( mbedtls_ecjpake_write_round_one( &cli,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001061 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1062
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001063 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv, buf, len ) == 0 );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001064
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001065 TEST_ASSERT( mbedtls_ecjpake_write_round_one( &srv,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001066 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1067
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001068 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli, buf, len ) == 0 );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001069
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001070 TEST_ASSERT( mbedtls_ecjpake_write_round_two( &srv,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +02001071 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1072
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001073 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli, buf, len ) == 0 );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +02001074
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001075 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001076 pms, sizeof( pms ), &pmslen, ecjpake_lgc, NULL ) == 0 );
1077
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001078 TEST_ASSERT( mbedtls_ecjpake_write_round_two( &cli,
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +02001079 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1080
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001081 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv, buf, len ) == 0 );
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +02001082
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001083 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001084 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1085
1086 TEST_ASSERT( len == pmslen );
1087 TEST_ASSERT( memcmp( buf, pms, len ) == 0 );
1088
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001089 if( verbose != 0 )
1090 mbedtls_printf( "passed\n" );
1091
1092 if( verbose != 0 )
1093 mbedtls_printf( " ECJPAKE test #2 (reference handshake): " );
1094
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001095 /* Simulate generation of round one */
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001096 MBEDTLS_MPI_CHK( ecjpake_test_load( &cli,
1097 ecjpake_test_x1, sizeof( ecjpake_test_x1 ),
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001098 ecjpake_test_x2, sizeof( ecjpake_test_x2 ) ) );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001099
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001100 MBEDTLS_MPI_CHK( ecjpake_test_load( &srv,
1101 ecjpake_test_x3, sizeof( ecjpake_test_x3 ),
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001102 ecjpake_test_x4, sizeof( ecjpake_test_x4 ) ) );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001103
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001104 /* Read round one */
1105 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv,
1106 ecjpake_test_cli_one,
1107 sizeof( ecjpake_test_cli_one ) ) == 0 );
1108
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001109 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001110 ecjpake_test_srv_one,
1111 sizeof( ecjpake_test_srv_one ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001112
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001113 /* Skip generation of round two, read round two */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001114 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001115 ecjpake_test_srv_two,
1116 sizeof( ecjpake_test_srv_two ) ) == 0 );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +02001117
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001118 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001119 ecjpake_test_cli_two,
1120 sizeof( ecjpake_test_cli_two ) ) == 0 );
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +02001121
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001122 /* Server derives PMS */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001123 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001124 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1125
1126 TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
1127 TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
1128
1129 memset( buf, 0, len ); /* Avoid interferences with next step */
1130
1131 /* Client derives PMS */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001132 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001133 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1134
1135 TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
1136 TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
1137
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001138 if( verbose != 0 )
1139 mbedtls_printf( "passed\n" );
1140
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001141cleanup:
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001142 mbedtls_ecjpake_free( &cli );
1143 mbedtls_ecjpake_free( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001144
1145 if( ret != 0 )
1146 {
1147 if( verbose != 0 )
1148 mbedtls_printf( "failed\n" );
1149
1150 ret = 1;
1151 }
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001152
1153 if( verbose != 0 )
1154 mbedtls_printf( "\n" );
1155
1156 return( ret );
1157}
1158
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +02001159#undef TEST_ASSERT
1160
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001161#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_SHA256_C */
1162
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001163#endif /* MBEDTLS_SELF_TEST */
1164
1165#endif /* MBEDTLS_ECJPAKE_C */