blob: 0fb5b5416be72792aa0feaaf87d7538e50cefbe4 [file] [log] [blame]
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001/*
2 * Elliptic curve J-PAKE
3 *
4 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 * This file is part of mbed TLS (https://tls.mbed.org)
20 */
21
22/*
Manuel Pégourié-Gonnard6b798b92015-08-14 11:18:30 +020023 * References in the code are to the Thread v1.0 Specification,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +020024 * available to members of the Thread Group http://threadgroup.org/
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +020025 */
26
27#if !defined(MBEDTLS_CONFIG_FILE)
28#include "mbedtls/config.h"
29#else
30#include MBEDTLS_CONFIG_FILE
31#endif
32
33#if defined(MBEDTLS_ECJPAKE_C)
34
35#include "mbedtls/ecjpake.h"
Hanno Becker71c8e1b2018-12-14 17:09:39 +000036#include "mbedtls/platform_util.h"
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +020037
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +020038#include <string.h>
39
Hanno Becker616d1ca2018-01-24 10:25:05 +000040#if !defined(MBEDTLS_ECJPAKE_ALT)
41
Hanno Becker71c8e1b2018-12-14 17:09:39 +000042/* Parameter validation macros based on platform_util.h */
43#define ECJPAKE_VALIDATE_RET( cond ) \
44 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA )
45#define ECJPAKE_VALIDATE( cond ) \
46 MBEDTLS_INTERNAL_VALIDATE( cond )
47
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +020048/*
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +020049 * Convert a mbedtls_ecjpake_role to identifier string
50 */
51static const char * const ecjpake_id[] = {
52 "client",
53 "server"
54};
55
56#define ID_MINE ( ecjpake_id[ ctx->role ] )
57#define ID_PEER ( ecjpake_id[ 1 - ctx->role ] )
58
59/*
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020060 * Initialize context
61 */
62void mbedtls_ecjpake_init( mbedtls_ecjpake_context *ctx )
63{
Hanno Becker71c8e1b2018-12-14 17:09:39 +000064 ECJPAKE_VALIDATE( ctx != NULL );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020065
Hanno Beckera5cedbc2019-07-17 11:21:02 +010066 ctx->md_info = MBEDTLS_MD_INVALID_HANDLE;
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020067 mbedtls_ecp_group_init( &ctx->grp );
Manuel Pégourié-Gonnardb7da1942015-10-19 13:35:22 +020068 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020069
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +020070 mbedtls_ecp_point_init( &ctx->Xm1 );
71 mbedtls_ecp_point_init( &ctx->Xm2 );
72 mbedtls_ecp_point_init( &ctx->Xp1 );
73 mbedtls_ecp_point_init( &ctx->Xp2 );
74 mbedtls_ecp_point_init( &ctx->Xp );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020075
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +020076 mbedtls_mpi_init( &ctx->xm1 );
77 mbedtls_mpi_init( &ctx->xm2 );
78 mbedtls_mpi_init( &ctx->s );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020079}
80
81/*
82 * Free context
83 */
84void mbedtls_ecjpake_free( mbedtls_ecjpake_context *ctx )
85{
86 if( ctx == NULL )
87 return;
88
Hanno Beckera5cedbc2019-07-17 11:21:02 +010089 ctx->md_info = MBEDTLS_MD_INVALID_HANDLE;
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020090 mbedtls_ecp_group_free( &ctx->grp );
91
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +020092 mbedtls_ecp_point_free( &ctx->Xm1 );
93 mbedtls_ecp_point_free( &ctx->Xm2 );
94 mbedtls_ecp_point_free( &ctx->Xp1 );
95 mbedtls_ecp_point_free( &ctx->Xp2 );
96 mbedtls_ecp_point_free( &ctx->Xp );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020097
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +020098 mbedtls_mpi_free( &ctx->xm1 );
99 mbedtls_mpi_free( &ctx->xm2 );
100 mbedtls_mpi_free( &ctx->s );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200101}
102
103/*
104 * Setup context
105 */
106int mbedtls_ecjpake_setup( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +0200107 mbedtls_ecjpake_role role,
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200108 mbedtls_md_type_t hash,
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200109 mbedtls_ecp_group_id curve,
110 const unsigned char *secret,
111 size_t len )
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200112{
113 int ret;
Hanno Becker185e5162018-12-19 09:48:50 +0000114
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000115 ECJPAKE_VALIDATE_RET( ctx != NULL );
116 ECJPAKE_VALIDATE_RET( role == MBEDTLS_ECJPAKE_CLIENT ||
117 role == MBEDTLS_ECJPAKE_SERVER );
118 ECJPAKE_VALIDATE_RET( secret != NULL || len == 0 );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200119
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +0200120 ctx->role = role;
121
Hanno Beckera5cedbc2019-07-17 11:21:02 +0100122 if( ( ctx->md_info = mbedtls_md_info_from_type( hash ) ) ==
123 MBEDTLS_MD_INVALID_HANDLE )
124 {
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200125 return( MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE );
Hanno Beckera5cedbc2019-07-17 11:21:02 +0100126 }
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200127
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200128 MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ctx->grp, curve ) );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200129
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200130 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->s, secret, len ) );
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200131
132cleanup:
133 if( ret != 0 )
134 mbedtls_ecjpake_free( ctx );
135
136 return( ret );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200137}
138
139/*
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200140 * Check if context is ready for use
141 */
142int mbedtls_ecjpake_check( const mbedtls_ecjpake_context *ctx )
143{
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000144 ECJPAKE_VALIDATE_RET( ctx != NULL );
145
Hanno Beckera5cedbc2019-07-17 11:21:02 +0100146 if( ctx->md_info == MBEDTLS_MD_INVALID_HANDLE ||
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200147 ctx->grp.id == MBEDTLS_ECP_DP_NONE ||
148 ctx->s.p == NULL )
149 {
150 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
151 }
152
153 return( 0 );
154}
155
156/*
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200157 * Write a point plus its length to a buffer
158 */
159static int ecjpake_write_len_point( unsigned char **p,
160 const unsigned char *end,
161 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100162 const int pf,
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200163 const mbedtls_ecp_point *P )
164{
165 int ret;
166 size_t len;
167
168 /* Need at least 4 for length plus 1 for point */
169 if( end < *p || end - *p < 5 )
170 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
171
Robert Cragie7cdad772015-10-02 13:31:41 +0100172 ret = mbedtls_ecp_point_write_binary( grp, P, pf,
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200173 &len, *p + 4, end - ( *p + 4 ) );
174 if( ret != 0 )
175 return( ret );
176
177 (*p)[0] = (unsigned char)( ( len >> 24 ) & 0xFF );
178 (*p)[1] = (unsigned char)( ( len >> 16 ) & 0xFF );
179 (*p)[2] = (unsigned char)( ( len >> 8 ) & 0xFF );
180 (*p)[3] = (unsigned char)( ( len ) & 0xFF );
181
182 *p += 4 + len;
183
184 return( 0 );
185}
186
187/*
188 * Size of the temporary buffer for ecjpake_hash:
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200189 * 3 EC points plus their length, plus ID and its length (4 + 6 bytes)
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200190 */
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200191#define ECJPAKE_HASH_BUF_LEN ( 3 * ( 4 + MBEDTLS_ECP_MAX_PT_LEN ) + 4 + 6 )
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200192
193/*
194 * Compute hash for ZKP (7.4.2.2.2.1)
195 */
Hanno Beckera5cedbc2019-07-17 11:21:02 +0100196static int ecjpake_hash( mbedtls_md_handle_t md_info,
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200197 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100198 const int pf,
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200199 const mbedtls_ecp_point *G,
200 const mbedtls_ecp_point *V,
201 const mbedtls_ecp_point *X,
202 const char *id,
203 mbedtls_mpi *h )
204{
205 int ret;
206 unsigned char buf[ECJPAKE_HASH_BUF_LEN];
207 unsigned char *p = buf;
208 const unsigned char *end = buf + sizeof( buf );
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200209 const size_t id_len = strlen( id );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200210 unsigned char hash[MBEDTLS_MD_MAX_SIZE];
211
212 /* Write things to temporary buffer */
Robert Cragie7cdad772015-10-02 13:31:41 +0100213 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, G ) );
214 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, V ) );
215 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, X ) );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200216
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200217 if( end - p < 4 )
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200218 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
219
220 *p++ = (unsigned char)( ( id_len >> 24 ) & 0xFF );
221 *p++ = (unsigned char)( ( id_len >> 16 ) & 0xFF );
222 *p++ = (unsigned char)( ( id_len >> 8 ) & 0xFF );
223 *p++ = (unsigned char)( ( id_len ) & 0xFF );
224
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200225 if( end < p || (size_t)( end - p ) < id_len )
226 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
227
Teppo Järvelin91d79382019-10-02 09:09:31 +0300228 mbedtls_platform_memcpy( p, id, id_len );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200229 p += id_len;
230
231 /* Compute hash */
k-stachowiak4a6a55c2019-06-28 14:14:02 +0200232 MBEDTLS_MPI_CHK( mbedtls_md( md_info, buf, p - buf, hash ) );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200233
234 /* Turn it into an integer mod n */
235 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( h, hash,
236 mbedtls_md_get_size( md_info ) ) );
237 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( h, h, &grp->N ) );
238
239cleanup:
240 return( ret );
241}
242
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200243/*
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200244 * Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3)
245 */
Hanno Beckera5cedbc2019-07-17 11:21:02 +0100246static int ecjpake_zkp_read( mbedtls_md_handle_t md_info,
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200247 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100248 const int pf,
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200249 const mbedtls_ecp_point *G,
250 const mbedtls_ecp_point *X,
251 const char *id,
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200252 const unsigned char **p,
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200253 const unsigned char *end )
254{
255 int ret;
256 mbedtls_ecp_point V, VV;
257 mbedtls_mpi r, h;
258 size_t r_len;
259
260 mbedtls_ecp_point_init( &V );
261 mbedtls_ecp_point_init( &VV );
262 mbedtls_mpi_init( &r );
263 mbedtls_mpi_init( &h );
264
265 /*
266 * struct {
267 * ECPoint V;
268 * opaque r<1..2^8-1>;
269 * } ECSchnorrZKP;
270 */
271 if( end < *p )
272 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
273
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200274 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, &V, p, end - *p ) );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200275
276 if( end < *p || (size_t)( end - *p ) < 1 )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200277 {
278 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
279 goto cleanup;
280 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200281
282 r_len = *(*p)++;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200283
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200284 if( end < *p || (size_t)( end - *p ) < r_len )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200285 {
286 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
287 goto cleanup;
288 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200289
290 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &r, *p, r_len ) );
291 *p += r_len;
292
293 /*
294 * Verification
295 */
Robert Cragie7cdad772015-10-02 13:31:41 +0100296 MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200297 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( (mbedtls_ecp_group *) grp,
298 &VV, &h, X, &r, G ) );
299
300 if( mbedtls_ecp_point_cmp( &VV, &V ) != 0 )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200301 {
302 ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
303 goto cleanup;
304 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200305
306cleanup:
307 mbedtls_ecp_point_free( &V );
308 mbedtls_ecp_point_free( &VV );
309 mbedtls_mpi_free( &r );
310 mbedtls_mpi_free( &h );
311
312 return( ret );
313}
314
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200315/*
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200316 * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2)
317 */
Hanno Beckera5cedbc2019-07-17 11:21:02 +0100318static int ecjpake_zkp_write( mbedtls_md_handle_t md_info,
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200319 const mbedtls_ecp_group *grp,
Darryl Green11999bb2018-03-13 15:22:58 +0000320 const int pf,
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200321 const mbedtls_ecp_point *G,
322 const mbedtls_mpi *x,
323 const mbedtls_ecp_point *X,
324 const char *id,
325 unsigned char **p,
326 const unsigned char *end,
327 int (*f_rng)(void *, unsigned char *, size_t),
328 void *p_rng )
329{
330 int ret;
331 mbedtls_ecp_point V;
332 mbedtls_mpi v;
333 mbedtls_mpi h; /* later recycled to hold r */
334 size_t len;
335
336 if( end < *p )
337 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
338
339 mbedtls_ecp_point_init( &V );
340 mbedtls_mpi_init( &v );
341 mbedtls_mpi_init( &h );
342
343 /* Compute signature */
344 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp,
345 G, &v, &V, f_rng, p_rng ) );
Robert Cragie7cdad772015-10-02 13:31:41 +0100346 MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) );
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200347 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &h, &h, x ) ); /* x*h */
348 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &h, &v, &h ) ); /* v - x*h */
349 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &h, &h, &grp->N ) ); /* r */
350
351 /* Write it out */
352 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, &V,
Robert Cragie7cdad772015-10-02 13:31:41 +0100353 pf, &len, *p, end - *p ) );
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200354 *p += len;
355
356 len = mbedtls_mpi_size( &h ); /* actually r */
357 if( end < *p || (size_t)( end - *p ) < 1 + len || len > 255 )
358 {
359 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
360 goto cleanup;
361 }
362
363 *(*p)++ = (unsigned char)( len & 0xFF );
364 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, *p, len ) ); /* r */
365 *p += len;
366
367cleanup:
368 mbedtls_ecp_point_free( &V );
369 mbedtls_mpi_free( &v );
370 mbedtls_mpi_free( &h );
371
372 return( ret );
373}
374
375/*
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200376 * Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof
377 * Output: verified public key X
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200378 */
Hanno Beckera5cedbc2019-07-17 11:21:02 +0100379static int ecjpake_kkp_read( mbedtls_md_handle_t md_info,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200380 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100381 const int pf,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200382 const mbedtls_ecp_point *G,
383 mbedtls_ecp_point *X,
384 const char *id,
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200385 const unsigned char **p,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200386 const unsigned char *end )
387{
388 int ret;
389
390 if( end < *p )
391 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
392
393 /*
394 * struct {
395 * ECPoint X;
396 * ECSchnorrZKP zkp;
397 * } ECJPAKEKeyKP;
398 */
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200399 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, X, p, end - *p ) );
Manuel Pégourié-Gonnard30590952015-08-17 10:37:40 +0200400 if( mbedtls_ecp_is_zero( X ) )
401 {
402 ret = MBEDTLS_ERR_ECP_INVALID_KEY;
403 goto cleanup;
404 }
405
Robert Cragie7cdad772015-10-02 13:31:41 +0100406 MBEDTLS_MPI_CHK( ecjpake_zkp_read( md_info, grp, pf, G, X, id, p, end ) );
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200407
408cleanup:
409 return( ret );
410}
411
412/*
413 * Generate an ECJPAKEKeyKP
414 * Output: the serialized structure, plus private/public key pair
415 */
Hanno Beckera5cedbc2019-07-17 11:21:02 +0100416static int ecjpake_kkp_write( mbedtls_md_handle_t md_info,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200417 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100418 const int pf,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200419 const mbedtls_ecp_point *G,
420 mbedtls_mpi *x,
421 mbedtls_ecp_point *X,
422 const char *id,
423 unsigned char **p,
424 const unsigned char *end,
425 int (*f_rng)(void *, unsigned char *, size_t),
426 void *p_rng )
427{
428 int ret;
429 size_t len;
430
431 if( end < *p )
432 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
433
434 /* Generate key (7.4.2.3.1) and write it out */
435 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp, G, x, X,
436 f_rng, p_rng ) );
437 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, X,
Robert Cragie7cdad772015-10-02 13:31:41 +0100438 pf, &len, *p, end - *p ) );
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200439 *p += len;
440
441 /* Generate and write proof */
Robert Cragie7cdad772015-10-02 13:31:41 +0100442 MBEDTLS_MPI_CHK( ecjpake_zkp_write( md_info, grp, pf, G, x, X, id,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200443 p, end, f_rng, p_rng ) );
444
445cleanup:
446 return( ret );
447}
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200448
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200449/*
450 * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs
451 * Ouputs: verified peer public keys Xa, Xb
452 */
Hanno Beckera5cedbc2019-07-17 11:21:02 +0100453static int ecjpake_kkpp_read( mbedtls_md_handle_t md_info,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200454 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100455 const int pf,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200456 const mbedtls_ecp_point *G,
457 mbedtls_ecp_point *Xa,
458 mbedtls_ecp_point *Xb,
459 const char *id,
460 const unsigned char *buf,
461 size_t len )
462{
463 int ret;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200464 const unsigned char *p = buf;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200465 const unsigned char *end = buf + len;
466
467 /*
468 * struct {
469 * ECJPAKEKeyKP ecjpake_key_kp_pair_list[2];
470 * } ECJPAKEKeyKPPairList;
471 */
Robert Cragie7cdad772015-10-02 13:31:41 +0100472 MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xa, id, &p, end ) );
473 MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xb, id, &p, end ) );
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200474
475 if( p != end )
476 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
477
478cleanup:
479 return( ret );
480}
481
482/*
483 * Generate a ECJPAKEKeyKPPairList
484 * Outputs: the serialized structure, plus two private/public key pairs
485 */
Hanno Beckera5cedbc2019-07-17 11:21:02 +0100486static int ecjpake_kkpp_write( mbedtls_md_handle_t md_info,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200487 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100488 const int pf,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200489 const mbedtls_ecp_point *G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200490 mbedtls_mpi *xm1,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200491 mbedtls_ecp_point *Xa,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200492 mbedtls_mpi *xm2,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200493 mbedtls_ecp_point *Xb,
494 const char *id,
495 unsigned char *buf,
496 size_t len,
497 size_t *olen,
498 int (*f_rng)(void *, unsigned char *, size_t),
499 void *p_rng )
500{
501 int ret;
502 unsigned char *p = buf;
503 const unsigned char *end = buf + len;
504
Robert Cragie7cdad772015-10-02 13:31:41 +0100505 MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm1, Xa, id,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200506 &p, end, f_rng, p_rng ) );
Robert Cragie7cdad772015-10-02 13:31:41 +0100507 MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm2, Xb, id,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200508 &p, end, f_rng, p_rng ) );
509
510 *olen = p - buf;
511
512cleanup:
513 return( ret );
514}
515
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200516/*
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200517 * Read and process the first round message
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200518 */
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200519int mbedtls_ecjpake_read_round_one( mbedtls_ecjpake_context *ctx,
520 const unsigned char *buf,
521 size_t len )
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200522{
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000523 ECJPAKE_VALIDATE_RET( ctx != NULL );
524 ECJPAKE_VALIDATE_RET( buf != NULL );
525
Robert Cragie7cdad772015-10-02 13:31:41 +0100526 return( ecjpake_kkpp_read( ctx->md_info, &ctx->grp, ctx->point_format,
527 &ctx->grp.G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200528 &ctx->Xp1, &ctx->Xp2, ID_PEER,
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200529 buf, len ) );
530}
531
532/*
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200533 * Generate and write the first round message
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200534 */
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200535int mbedtls_ecjpake_write_round_one( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200536 unsigned char *buf, size_t len, size_t *olen,
537 int (*f_rng)(void *, unsigned char *, size_t),
538 void *p_rng )
539{
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000540 ECJPAKE_VALIDATE_RET( ctx != NULL );
541 ECJPAKE_VALIDATE_RET( buf != NULL );
542 ECJPAKE_VALIDATE_RET( olen != NULL );
543 ECJPAKE_VALIDATE_RET( f_rng != NULL );
544
Robert Cragie7cdad772015-10-02 13:31:41 +0100545 return( ecjpake_kkpp_write( ctx->md_info, &ctx->grp, ctx->point_format,
546 &ctx->grp.G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200547 &ctx->xm1, &ctx->Xm1, &ctx->xm2, &ctx->Xm2,
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200548 ID_MINE, buf, len, olen, f_rng, p_rng ) );
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200549}
550
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200551/*
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200552 * Compute the sum of three points R = A + B + C
553 */
554static int ecjpake_ecp_add3( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
555 const mbedtls_ecp_point *A,
556 const mbedtls_ecp_point *B,
557 const mbedtls_ecp_point *C )
558{
559 int ret;
560 mbedtls_mpi one;
561
562 mbedtls_mpi_init( &one );
563
564 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
565 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, A, &one, B ) );
566 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, R, &one, C ) );
567
568cleanup:
569 mbedtls_mpi_free( &one );
570
571 return( ret );
572}
573
574/*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200575 * 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 +0200576 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200577int mbedtls_ecjpake_read_round_two( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200578 const unsigned char *buf,
579 size_t len )
580{
581 int ret;
582 const unsigned char *p = buf;
583 const unsigned char *end = buf + len;
584 mbedtls_ecp_group grp;
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200585 mbedtls_ecp_point G; /* C: GB, S: GA */
Hanno Becker185e5162018-12-19 09:48:50 +0000586
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000587 ECJPAKE_VALIDATE_RET( ctx != NULL );
588 ECJPAKE_VALIDATE_RET( buf != NULL );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200589
590 mbedtls_ecp_group_init( &grp );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200591 mbedtls_ecp_point_init( &G );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200592
593 /*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200594 * Server: GA = X3 + X4 + X1 (7.4.2.6.1)
595 * Client: GB = X1 + X2 + X3 (7.4.2.5.1)
596 * Unified: G = Xm1 + Xm2 + Xp1
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200597 * We need that before parsing in order to check Xp as we read it
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200598 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200599 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200600 &ctx->Xm1, &ctx->Xm2, &ctx->Xp1 ) );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200601
602 /*
603 * struct {
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200604 * ECParameters curve_params; // only client reading server msg
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200605 * ECJPAKEKeyKP ecjpake_key_kp;
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200606 * } Client/ServerECJPAKEParams;
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200607 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200608 if( ctx->role == MBEDTLS_ECJPAKE_CLIENT )
Manuel Pégourié-Gonnardd9802af2015-08-17 12:47:38 +0200609 {
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200610 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_group( &grp, &p, len ) );
Manuel Pégourié-Gonnardd9802af2015-08-17 12:47:38 +0200611 if( grp.id != ctx->grp.id )
612 {
613 ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
614 goto cleanup;
615 }
616 }
617
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200618 MBEDTLS_MPI_CHK( ecjpake_kkp_read( ctx->md_info, &ctx->grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100619 ctx->point_format,
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200620 &G, &ctx->Xp, ID_PEER, &p, end ) );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200621
622 if( p != end )
623 {
624 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
625 goto cleanup;
626 }
627
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200628cleanup:
629 mbedtls_ecp_group_free( &grp );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200630 mbedtls_ecp_point_free( &G );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200631
632 return( ret );
633}
634
635/*
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200636 * Compute R = +/- X * S mod N, taking care not to leak S
637 */
638static int ecjpake_mul_secret( mbedtls_mpi *R, int sign,
639 const mbedtls_mpi *X,
640 const mbedtls_mpi *S,
641 const mbedtls_mpi *N,
642 int (*f_rng)(void *, unsigned char *, size_t),
643 void *p_rng )
644{
645 int ret;
646 mbedtls_mpi b; /* Blinding value, then s + N * blinding */
647
648 mbedtls_mpi_init( &b );
649
650 /* b = s + rnd-128-bit * N */
651 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &b, 16, f_rng, p_rng ) );
652 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &b, &b, N ) );
653 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &b, &b, S ) );
654
655 /* R = sign * X * b mod N */
656 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( R, X, &b ) );
657 R->s *= sign;
658 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( R, R, N ) );
659
660cleanup:
661 mbedtls_mpi_free( &b );
662
663 return( ret );
664}
665
666/*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200667 * 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 +0200668 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200669int mbedtls_ecjpake_write_round_two( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200670 unsigned char *buf, size_t len, size_t *olen,
671 int (*f_rng)(void *, unsigned char *, size_t),
672 void *p_rng )
673{
674 int ret;
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200675 mbedtls_ecp_point G; /* C: GA, S: GB */
676 mbedtls_ecp_point Xm; /* C: Xc, S: Xs */
677 mbedtls_mpi xm; /* C: xc, S: xs */
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200678 unsigned char *p = buf;
679 const unsigned char *end = buf + len;
680 size_t ec_len;
Hanno Becker185e5162018-12-19 09:48:50 +0000681
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000682 ECJPAKE_VALIDATE_RET( ctx != NULL );
683 ECJPAKE_VALIDATE_RET( buf != NULL );
684 ECJPAKE_VALIDATE_RET( olen != NULL );
685 ECJPAKE_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200686
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200687 mbedtls_ecp_point_init( &G );
688 mbedtls_ecp_point_init( &Xm );
689 mbedtls_mpi_init( &xm );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200690
691 /*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200692 * 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 +0200693 *
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200694 * Client: GA = X1 + X3 + X4 | xs = x2 * s | Xc = xc * GA
695 * Server: GB = X3 + X1 + X2 | xs = x4 * s | Xs = xs * GB
696 * Unified: G = Xm1 + Xp1 + Xp2 | xm = xm2 * s | Xm = xm * G
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200697 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200698 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200699 &ctx->Xp1, &ctx->Xp2, &ctx->Xm1 ) );
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200700 MBEDTLS_MPI_CHK( ecjpake_mul_secret( &xm, 1, &ctx->xm2, &ctx->s,
701 &ctx->grp.N, f_rng, p_rng ) );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200702 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &Xm, &xm, &G, f_rng, p_rng ) );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200703
704 /*
705 * Now write things out
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200706 *
707 * struct {
708 * ECParameters curve_params; // only server writing its message
709 * ECJPAKEKeyKP ecjpake_key_kp;
710 * } Client/ServerECJPAKEParams;
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200711 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200712 if( ctx->role == MBEDTLS_ECJPAKE_SERVER )
713 {
714 if( end < p )
715 {
716 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
717 goto cleanup;
718 }
719 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_group( &ctx->grp, &ec_len,
720 p, end - p ) );
721 p += ec_len;
722 }
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200723
724 if( end < p )
725 {
726 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
727 goto cleanup;
728 }
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200729 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( &ctx->grp, &Xm,
Robert Cragie7cdad772015-10-02 13:31:41 +0100730 ctx->point_format, &ec_len, p, end - p ) );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200731 p += ec_len;
732
733 MBEDTLS_MPI_CHK( ecjpake_zkp_write( ctx->md_info, &ctx->grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100734 ctx->point_format,
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200735 &G, &xm, &Xm, ID_MINE,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200736 &p, end, f_rng, p_rng ) );
737
738 *olen = p - buf;
739
740cleanup:
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200741 mbedtls_ecp_point_free( &G );
742 mbedtls_ecp_point_free( &Xm );
743 mbedtls_mpi_free( &xm );
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +0200744
745 return( ret );
746}
747
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200748/*
749 * Derive PMS (7.4.2.7 / 7.4.2.8)
750 */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +0200751int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200752 unsigned char *buf, size_t len, size_t *olen,
753 int (*f_rng)(void *, unsigned char *, size_t),
754 void *p_rng )
755{
756 int ret;
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200757 mbedtls_ecp_point K;
758 mbedtls_mpi m_xm2_s, one;
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200759 unsigned char kx[MBEDTLS_ECP_MAX_BYTES];
760 size_t x_bytes;
Hanno Becker185e5162018-12-19 09:48:50 +0000761
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000762 ECJPAKE_VALIDATE_RET( ctx != NULL );
763 ECJPAKE_VALIDATE_RET( buf != NULL );
764 ECJPAKE_VALIDATE_RET( olen != NULL );
765 ECJPAKE_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200766
767 *olen = mbedtls_md_get_size( ctx->md_info );
768 if( len < *olen )
769 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
770
771 mbedtls_ecp_point_init( &K );
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200772 mbedtls_mpi_init( &m_xm2_s );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200773 mbedtls_mpi_init( &one );
774
775 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200776
777 /*
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200778 * Client: K = ( Xs - X4 * x2 * s ) * x2
779 * Server: K = ( Xc - X2 * x4 * s ) * x4
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200780 * Unified: K = ( Xp - Xp2 * xm2 * s ) * xm2
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200781 */
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200782 MBEDTLS_MPI_CHK( ecjpake_mul_secret( &m_xm2_s, -1, &ctx->xm2, &ctx->s,
783 &ctx->grp.N, f_rng, p_rng ) );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200784 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( &ctx->grp, &K,
785 &one, &ctx->Xp,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200786 &m_xm2_s, &ctx->Xp2 ) );
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200787 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &K, &ctx->xm2, &K,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200788 f_rng, p_rng ) );
789
790 /* PMS = SHA-256( K.X ) */
791 x_bytes = ( ctx->grp.pbits + 7 ) / 8;
792 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &K.X, kx, x_bytes ) );
793 MBEDTLS_MPI_CHK( mbedtls_md( ctx->md_info, kx, x_bytes, buf ) );
794
795cleanup:
796 mbedtls_ecp_point_free( &K );
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200797 mbedtls_mpi_free( &m_xm2_s );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200798 mbedtls_mpi_free( &one );
799
800 return( ret );
801}
802
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200803#undef ID_MINE
804#undef ID_PEER
805
Hanno Becker616d1ca2018-01-24 10:25:05 +0000806#endif /* ! MBEDTLS_ECJPAKE_ALT */
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200807
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200808#if defined(MBEDTLS_SELF_TEST)
809
810#if defined(MBEDTLS_PLATFORM_C)
811#include "mbedtls/platform.h"
812#else
813#include <stdio.h>
814#define mbedtls_printf printf
815#endif
816
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200817#if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
818 !defined(MBEDTLS_SHA256_C)
819int mbedtls_ecjpake_self_test( int verbose )
820{
821 (void) verbose;
822 return( 0 );
823}
824#else
825
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200826static const unsigned char ecjpake_test_password[] = {
827 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x6a, 0x70, 0x61, 0x6b, 0x65, 0x74,
828 0x65, 0x73, 0x74
829};
830
831static const unsigned char ecjpake_test_x1[] = {
832 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
833 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
834 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21
835};
836
837static const unsigned char ecjpake_test_x2[] = {
838 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
839 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
840 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
841};
842
843static const unsigned char ecjpake_test_x3[] = {
844 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
845 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
846 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
847};
848
849static const unsigned char ecjpake_test_x4[] = {
850 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc,
851 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
852 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1
853};
854
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200855static const unsigned char ecjpake_test_cli_one[] = {
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200856 0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19,
857 0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44,
858 0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad,
859 0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62,
860 0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9,
861 0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d,
862 0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e,
863 0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e,
864 0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73,
865 0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22,
866 0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce,
867 0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00,
868 0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200869 0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e,
870 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62,
871 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5,
872 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb,
873 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35,
874 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0,
875 0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb,
876 0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47,
877 0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39,
878 0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97,
879 0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40,
880 0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d,
881 0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa,
882 0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d,
883 0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200884};
885
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200886static const unsigned char ecjpake_test_srv_one[] = {
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200887 0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb,
888 0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18,
889 0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47,
890 0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f,
891 0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7,
892 0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d,
893 0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64,
894 0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36,
895 0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2,
896 0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec,
897 0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16,
898 0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96,
899 0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3,
900 0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19,
901 0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f,
902 0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8,
903 0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7,
904 0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea,
905 0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5,
906 0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6,
907 0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31,
908 0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d,
909 0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8,
910 0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee,
911 0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84,
912 0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f,
913 0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80,
914 0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12
915};
916
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200917static const unsigned char ecjpake_test_srv_two[] = {
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200918 0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23,
919 0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c,
920 0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f,
921 0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca,
922 0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26,
923 0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55,
924 0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38,
925 0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6,
926 0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9,
927 0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4,
928 0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2,
929 0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8,
930 0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd,
931 0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c
932};
933
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200934static const unsigned char ecjpake_test_cli_two[] = {
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +0200935 0x41, 0x04, 0x69, 0xd5, 0x4e, 0xe8, 0x5e, 0x90, 0xce, 0x3f, 0x12, 0x46,
936 0x74, 0x2d, 0xe5, 0x07, 0xe9, 0x39, 0xe8, 0x1d, 0x1d, 0xc1, 0xc5, 0xcb,
937 0x98, 0x8b, 0x58, 0xc3, 0x10, 0xc9, 0xfd, 0xd9, 0x52, 0x4d, 0x93, 0x72,
938 0x0b, 0x45, 0x54, 0x1c, 0x83, 0xee, 0x88, 0x41, 0x19, 0x1d, 0xa7, 0xce,
939 0xd8, 0x6e, 0x33, 0x12, 0xd4, 0x36, 0x23, 0xc1, 0xd6, 0x3e, 0x74, 0x98,
940 0x9a, 0xba, 0x4a, 0xff, 0xd1, 0xee, 0x41, 0x04, 0x07, 0x7e, 0x8c, 0x31,
941 0xe2, 0x0e, 0x6b, 0xed, 0xb7, 0x60, 0xc1, 0x35, 0x93, 0xe6, 0x9f, 0x15,
942 0xbe, 0x85, 0xc2, 0x7d, 0x68, 0xcd, 0x09, 0xcc, 0xb8, 0xc4, 0x18, 0x36,
943 0x08, 0x91, 0x7c, 0x5c, 0x3d, 0x40, 0x9f, 0xac, 0x39, 0xfe, 0xfe, 0xe8,
944 0x2f, 0x72, 0x92, 0xd3, 0x6f, 0x0d, 0x23, 0xe0, 0x55, 0x91, 0x3f, 0x45,
945 0xa5, 0x2b, 0x85, 0xdd, 0x8a, 0x20, 0x52, 0xe9, 0xe1, 0x29, 0xbb, 0x4d,
946 0x20, 0x0f, 0x01, 0x1f, 0x19, 0x48, 0x35, 0x35, 0xa6, 0xe8, 0x9a, 0x58,
947 0x0c, 0x9b, 0x00, 0x03, 0xba, 0xf2, 0x14, 0x62, 0xec, 0xe9, 0x1a, 0x82,
948 0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c
949};
950
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200951static const unsigned char ecjpake_test_pms[] = {
952 0xf3, 0xd4, 0x7f, 0x59, 0x98, 0x44, 0xdb, 0x92, 0xa5, 0x69, 0xbb, 0xe7,
953 0x98, 0x1e, 0x39, 0xd9, 0x31, 0xfd, 0x74, 0x3b, 0xf2, 0x2e, 0x98, 0xf9,
954 0xb4, 0x38, 0xf7, 0x19, 0xd3, 0xc4, 0xf3, 0x51
955};
956
Antonin Décimod5f47592019-01-23 15:24:37 +0100957/* Load my private keys and generate the corresponding public keys */
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +0200958static int ecjpake_test_load( mbedtls_ecjpake_context *ctx,
959 const unsigned char *xm1, size_t len1,
960 const unsigned char *xm2, size_t len2 )
961{
962 int ret;
963
964 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm1, xm1, len1 ) );
965 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm2, xm2, len2 ) );
966 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm1, &ctx->xm1,
967 &ctx->grp.G, NULL, NULL ) );
968 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm2, &ctx->xm2,
969 &ctx->grp.G, NULL, NULL ) );
970
971cleanup:
972 return( ret );
973}
974
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200975/* For tests we don't need a secure RNG;
976 * use the LGC from Numerical Recipes for simplicity */
977static int ecjpake_lgc( void *p, unsigned char *out, size_t len )
978{
979 static uint32_t x = 42;
980 (void) p;
981
982 while( len > 0 )
983 {
984 size_t use_len = len > 4 ? 4 : len;
985 x = 1664525 * x + 1013904223;
Teppo Järvelinb5c46712019-10-04 13:35:55 +0300986 memcpy( out, &x, use_len );
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200987 out += use_len;
988 len -= use_len;
989 }
990
991 return( 0 );
992}
993
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200994#define TEST_ASSERT( x ) \
995 do { \
996 if( x ) \
997 ret = 0; \
998 else \
999 { \
1000 ret = 1; \
1001 goto cleanup; \
1002 } \
1003 } while( 0 )
1004
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001005/*
1006 * Checkup routine
1007 */
1008int mbedtls_ecjpake_self_test( int verbose )
1009{
1010 int ret;
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001011 mbedtls_ecjpake_context cli;
1012 mbedtls_ecjpake_context srv;
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001013 unsigned char buf[512], pms[32];
1014 size_t len, pmslen;
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001015
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001016 mbedtls_ecjpake_init( &cli );
1017 mbedtls_ecjpake_init( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001018
1019 if( verbose != 0 )
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001020 mbedtls_printf( " ECJPAKE test #0 (setup): " );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +02001021
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +02001022 TEST_ASSERT( mbedtls_ecjpake_setup( &cli, MBEDTLS_ECJPAKE_CLIENT,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001023 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1024 ecjpake_test_password,
1025 sizeof( ecjpake_test_password ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001026
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +02001027 TEST_ASSERT( mbedtls_ecjpake_setup( &srv, MBEDTLS_ECJPAKE_SERVER,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001028 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1029 ecjpake_test_password,
1030 sizeof( ecjpake_test_password ) ) == 0 );
1031
1032 if( verbose != 0 )
1033 mbedtls_printf( "passed\n" );
1034
1035 if( verbose != 0 )
1036 mbedtls_printf( " ECJPAKE test #1 (random handshake): " );
1037
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001038 TEST_ASSERT( mbedtls_ecjpake_write_round_one( &cli,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001039 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1040
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001041 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv, buf, len ) == 0 );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001042
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001043 TEST_ASSERT( mbedtls_ecjpake_write_round_one( &srv,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001044 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1045
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001046 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli, buf, len ) == 0 );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001047
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001048 TEST_ASSERT( mbedtls_ecjpake_write_round_two( &srv,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +02001049 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1050
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001051 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli, buf, len ) == 0 );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +02001052
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001053 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001054 pms, sizeof( pms ), &pmslen, ecjpake_lgc, NULL ) == 0 );
1055
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001056 TEST_ASSERT( mbedtls_ecjpake_write_round_two( &cli,
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +02001057 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1058
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001059 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv, buf, len ) == 0 );
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +02001060
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001061 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001062 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1063
1064 TEST_ASSERT( len == pmslen );
1065 TEST_ASSERT( memcmp( buf, pms, len ) == 0 );
1066
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001067 if( verbose != 0 )
1068 mbedtls_printf( "passed\n" );
1069
1070 if( verbose != 0 )
1071 mbedtls_printf( " ECJPAKE test #2 (reference handshake): " );
1072
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001073 /* Simulate generation of round one */
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001074 MBEDTLS_MPI_CHK( ecjpake_test_load( &cli,
1075 ecjpake_test_x1, sizeof( ecjpake_test_x1 ),
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001076 ecjpake_test_x2, sizeof( ecjpake_test_x2 ) ) );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001077
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001078 MBEDTLS_MPI_CHK( ecjpake_test_load( &srv,
1079 ecjpake_test_x3, sizeof( ecjpake_test_x3 ),
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001080 ecjpake_test_x4, sizeof( ecjpake_test_x4 ) ) );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001081
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001082 /* Read round one */
1083 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv,
1084 ecjpake_test_cli_one,
1085 sizeof( ecjpake_test_cli_one ) ) == 0 );
1086
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001087 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001088 ecjpake_test_srv_one,
1089 sizeof( ecjpake_test_srv_one ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001090
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001091 /* Skip generation of round two, read round two */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001092 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001093 ecjpake_test_srv_two,
1094 sizeof( ecjpake_test_srv_two ) ) == 0 );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +02001095
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001096 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001097 ecjpake_test_cli_two,
1098 sizeof( ecjpake_test_cli_two ) ) == 0 );
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +02001099
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001100 /* Server derives PMS */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001101 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001102 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1103
1104 TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
1105 TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
1106
Teppo Järvelind49d2b62019-10-30 13:48:12 +02001107 memset( buf, 0, len ); /* Avoid interferences with next step */
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001108
1109 /* Client derives PMS */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001110 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001111 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1112
1113 TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
1114 TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
1115
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001116 if( verbose != 0 )
1117 mbedtls_printf( "passed\n" );
1118
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001119cleanup:
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001120 mbedtls_ecjpake_free( &cli );
1121 mbedtls_ecjpake_free( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001122
1123 if( ret != 0 )
1124 {
1125 if( verbose != 0 )
1126 mbedtls_printf( "failed\n" );
1127
1128 ret = 1;
1129 }
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001130
1131 if( verbose != 0 )
1132 mbedtls_printf( "\n" );
1133
1134 return( ret );
1135}
1136
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +02001137#undef TEST_ASSERT
1138
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001139#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_SHA256_C */
1140
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001141#endif /* MBEDTLS_SELF_TEST */
1142
1143#endif /* MBEDTLS_ECJPAKE_C */