blob: fe0b9d93e950c3bb4b92a4d8a0f333fc349eb70e [file] [log] [blame]
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001/*
2 * Elliptic curve J-PAKE
3 *
Bence Szépkúti1e148272020-08-07 13:07:28 +02004 * Copyright The Mbed TLS Contributors
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02005 * 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.
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +020018 */
19
20/*
Manuel Pégourié-Gonnard6b798b92015-08-14 11:18:30 +020021 * References in the code are to the Thread v1.0 Specification,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +020022 * available to members of the Thread Group http://threadgroup.org/
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +020023 */
24
Gilles Peskinedb09ef62020-06-03 01:43:33 +020025#include "common.h"
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +020026
27#if defined(MBEDTLS_ECJPAKE_C)
28
29#include "mbedtls/ecjpake.h"
Hanno Becker71c8e1b2018-12-14 17:09:39 +000030#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000031#include "mbedtls/error.h"
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +020032
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +020033#include <string.h>
34
Hanno Becker616d1ca2018-01-24 10:25:05 +000035#if !defined(MBEDTLS_ECJPAKE_ALT)
36
Hanno Becker71c8e1b2018-12-14 17:09:39 +000037/* Parameter validation macros based on platform_util.h */
38#define ECJPAKE_VALIDATE_RET( cond ) \
39 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA )
40#define ECJPAKE_VALIDATE( cond ) \
41 MBEDTLS_INTERNAL_VALIDATE( cond )
42
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +020043/*
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +020044 * Convert a mbedtls_ecjpake_role to identifier string
45 */
46static const char * const ecjpake_id[] = {
47 "client",
48 "server"
49};
50
51#define ID_MINE ( ecjpake_id[ ctx->role ] )
52#define ID_PEER ( ecjpake_id[ 1 - ctx->role ] )
53
54/*
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020055 * Initialize context
56 */
57void mbedtls_ecjpake_init( mbedtls_ecjpake_context *ctx )
58{
Hanno Becker71c8e1b2018-12-14 17:09:39 +000059 ECJPAKE_VALIDATE( ctx != NULL );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020060
61 ctx->md_info = NULL;
62 mbedtls_ecp_group_init( &ctx->grp );
Manuel Pégourié-Gonnardb7da1942015-10-19 13:35:22 +020063 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020064
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +020065 mbedtls_ecp_point_init( &ctx->Xm1 );
66 mbedtls_ecp_point_init( &ctx->Xm2 );
67 mbedtls_ecp_point_init( &ctx->Xp1 );
68 mbedtls_ecp_point_init( &ctx->Xp2 );
69 mbedtls_ecp_point_init( &ctx->Xp );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020070
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +020071 mbedtls_mpi_init( &ctx->xm1 );
72 mbedtls_mpi_init( &ctx->xm2 );
73 mbedtls_mpi_init( &ctx->s );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020074}
75
76/*
77 * Free context
78 */
79void mbedtls_ecjpake_free( mbedtls_ecjpake_context *ctx )
80{
81 if( ctx == NULL )
82 return;
83
84 ctx->md_info = NULL;
85 mbedtls_ecp_group_free( &ctx->grp );
86
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +020087 mbedtls_ecp_point_free( &ctx->Xm1 );
88 mbedtls_ecp_point_free( &ctx->Xm2 );
89 mbedtls_ecp_point_free( &ctx->Xp1 );
90 mbedtls_ecp_point_free( &ctx->Xp2 );
91 mbedtls_ecp_point_free( &ctx->Xp );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020092
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +020093 mbedtls_mpi_free( &ctx->xm1 );
94 mbedtls_mpi_free( &ctx->xm2 );
95 mbedtls_mpi_free( &ctx->s );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020096}
97
98/*
99 * Setup context
100 */
101int mbedtls_ecjpake_setup( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +0200102 mbedtls_ecjpake_role role,
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200103 mbedtls_md_type_t hash,
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200104 mbedtls_ecp_group_id curve,
105 const unsigned char *secret,
106 size_t len )
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200107{
Janos Follath24eed8d2019-11-22 13:21:35 +0000108 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker185e5162018-12-19 09:48:50 +0000109
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000110 ECJPAKE_VALIDATE_RET( ctx != NULL );
111 ECJPAKE_VALIDATE_RET( role == MBEDTLS_ECJPAKE_CLIENT ||
112 role == MBEDTLS_ECJPAKE_SERVER );
113 ECJPAKE_VALIDATE_RET( secret != NULL || len == 0 );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200114
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +0200115 ctx->role = role;
116
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200117 if( ( ctx->md_info = mbedtls_md_info_from_type( hash ) ) == NULL )
118 return( MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE );
119
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200120 MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ctx->grp, curve ) );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200121
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200122 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->s, secret, len ) );
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200123
124cleanup:
125 if( ret != 0 )
126 mbedtls_ecjpake_free( ctx );
127
128 return( ret );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200129}
130
131/*
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200132 * Check if context is ready for use
133 */
134int mbedtls_ecjpake_check( const mbedtls_ecjpake_context *ctx )
135{
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000136 ECJPAKE_VALIDATE_RET( ctx != NULL );
137
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200138 if( ctx->md_info == NULL ||
139 ctx->grp.id == MBEDTLS_ECP_DP_NONE ||
140 ctx->s.p == NULL )
141 {
142 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
143 }
144
145 return( 0 );
146}
147
148/*
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200149 * Write a point plus its length to a buffer
150 */
151static int ecjpake_write_len_point( unsigned char **p,
152 const unsigned char *end,
153 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100154 const int pf,
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200155 const mbedtls_ecp_point *P )
156{
Janos Follath24eed8d2019-11-22 13:21:35 +0000157 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200158 size_t len;
159
160 /* Need at least 4 for length plus 1 for point */
161 if( end < *p || end - *p < 5 )
162 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
163
Robert Cragie7cdad772015-10-02 13:31:41 +0100164 ret = mbedtls_ecp_point_write_binary( grp, P, pf,
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200165 &len, *p + 4, end - ( *p + 4 ) );
166 if( ret != 0 )
167 return( ret );
168
Joe Subbiania651e6f2021-08-23 11:35:25 +0100169 MBEDTLS_PUT_UINT32_BE( len, *p, 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200170
171 *p += 4 + len;
172
173 return( 0 );
174}
175
176/*
177 * Size of the temporary buffer for ecjpake_hash:
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200178 * 3 EC points plus their length, plus ID and its length (4 + 6 bytes)
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200179 */
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200180#define ECJPAKE_HASH_BUF_LEN ( 3 * ( 4 + MBEDTLS_ECP_MAX_PT_LEN ) + 4 + 6 )
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200181
182/*
183 * Compute hash for ZKP (7.4.2.2.2.1)
184 */
185static int ecjpake_hash( const mbedtls_md_info_t *md_info,
186 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100187 const int pf,
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200188 const mbedtls_ecp_point *G,
189 const mbedtls_ecp_point *V,
190 const mbedtls_ecp_point *X,
191 const char *id,
192 mbedtls_mpi *h )
193{
Janos Follath24eed8d2019-11-22 13:21:35 +0000194 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200195 unsigned char buf[ECJPAKE_HASH_BUF_LEN];
196 unsigned char *p = buf;
197 const unsigned char *end = buf + sizeof( buf );
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200198 const size_t id_len = strlen( id );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200199 unsigned char hash[MBEDTLS_MD_MAX_SIZE];
200
201 /* Write things to temporary buffer */
Robert Cragie7cdad772015-10-02 13:31:41 +0100202 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, G ) );
203 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, V ) );
204 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, X ) );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200205
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200206 if( end - p < 4 )
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200207 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
208
Joe Subbiania651e6f2021-08-23 11:35:25 +0100209 MBEDTLS_PUT_UINT32_BE( id_len, p, 0 );
210 p += 4;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200211
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200212 if( end < p || (size_t)( end - p ) < id_len )
213 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
214
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200215 memcpy( p, id, id_len );
216 p += id_len;
217
218 /* Compute hash */
k-stachowiak41503352019-06-28 14:14:02 +0200219 MBEDTLS_MPI_CHK( mbedtls_md( md_info, buf, p - buf, hash ) );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200220
221 /* Turn it into an integer mod n */
222 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( h, hash,
223 mbedtls_md_get_size( md_info ) ) );
224 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( h, h, &grp->N ) );
225
226cleanup:
227 return( ret );
228}
229
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200230/*
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200231 * Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3)
232 */
233static int ecjpake_zkp_read( const mbedtls_md_info_t *md_info,
234 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100235 const int pf,
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200236 const mbedtls_ecp_point *G,
237 const mbedtls_ecp_point *X,
238 const char *id,
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200239 const unsigned char **p,
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200240 const unsigned char *end )
241{
Janos Follath24eed8d2019-11-22 13:21:35 +0000242 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200243 mbedtls_ecp_point V, VV;
244 mbedtls_mpi r, h;
245 size_t r_len;
246
247 mbedtls_ecp_point_init( &V );
248 mbedtls_ecp_point_init( &VV );
249 mbedtls_mpi_init( &r );
250 mbedtls_mpi_init( &h );
251
252 /*
253 * struct {
254 * ECPoint V;
255 * opaque r<1..2^8-1>;
256 * } ECSchnorrZKP;
257 */
258 if( end < *p )
259 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
260
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200261 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, &V, p, end - *p ) );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200262
263 if( end < *p || (size_t)( end - *p ) < 1 )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200264 {
265 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
266 goto cleanup;
267 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200268
269 r_len = *(*p)++;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200270
TRodziewicz782a7ea2021-03-17 11:35:16 +0100271 if( end < *p || (size_t)( end - *p ) < r_len || r_len == 0 )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200272 {
273 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
274 goto cleanup;
275 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200276
277 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &r, *p, r_len ) );
278 *p += r_len;
279
280 /*
281 * Verification
282 */
Robert Cragie7cdad772015-10-02 13:31:41 +0100283 MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200284 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( (mbedtls_ecp_group *) grp,
285 &VV, &h, X, &r, G ) );
286
287 if( mbedtls_ecp_point_cmp( &VV, &V ) != 0 )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200288 {
289 ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
290 goto cleanup;
291 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200292
293cleanup:
294 mbedtls_ecp_point_free( &V );
295 mbedtls_ecp_point_free( &VV );
296 mbedtls_mpi_free( &r );
297 mbedtls_mpi_free( &h );
298
299 return( ret );
300}
301
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200302/*
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200303 * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2)
304 */
305static int ecjpake_zkp_write( const mbedtls_md_info_t *md_info,
306 const mbedtls_ecp_group *grp,
Darryl Green11999bb2018-03-13 15:22:58 +0000307 const int pf,
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200308 const mbedtls_ecp_point *G,
309 const mbedtls_mpi *x,
310 const mbedtls_ecp_point *X,
311 const char *id,
312 unsigned char **p,
313 const unsigned char *end,
314 int (*f_rng)(void *, unsigned char *, size_t),
315 void *p_rng )
316{
Janos Follath24eed8d2019-11-22 13:21:35 +0000317 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200318 mbedtls_ecp_point V;
319 mbedtls_mpi v;
320 mbedtls_mpi h; /* later recycled to hold r */
321 size_t len;
322
323 if( end < *p )
324 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
325
326 mbedtls_ecp_point_init( &V );
327 mbedtls_mpi_init( &v );
328 mbedtls_mpi_init( &h );
329
330 /* Compute signature */
331 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp,
332 G, &v, &V, f_rng, p_rng ) );
Robert Cragie7cdad772015-10-02 13:31:41 +0100333 MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) );
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200334 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &h, &h, x ) ); /* x*h */
335 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &h, &v, &h ) ); /* v - x*h */
336 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &h, &h, &grp->N ) ); /* r */
337
338 /* Write it out */
339 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, &V,
Robert Cragie7cdad772015-10-02 13:31:41 +0100340 pf, &len, *p, end - *p ) );
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200341 *p += len;
342
343 len = mbedtls_mpi_size( &h ); /* actually r */
344 if( end < *p || (size_t)( end - *p ) < 1 + len || len > 255 )
345 {
346 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
347 goto cleanup;
348 }
349
Joe Subbianic045dc12021-07-14 12:31:31 +0100350 *(*p)++ = MBEDTLS_BYTE_0( len );
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200351 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, *p, len ) ); /* r */
352 *p += len;
353
354cleanup:
355 mbedtls_ecp_point_free( &V );
356 mbedtls_mpi_free( &v );
357 mbedtls_mpi_free( &h );
358
359 return( ret );
360}
361
362/*
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200363 * Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof
364 * Output: verified public key X
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200365 */
366static int ecjpake_kkp_read( const mbedtls_md_info_t *md_info,
367 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100368 const int pf,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200369 const mbedtls_ecp_point *G,
370 mbedtls_ecp_point *X,
371 const char *id,
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200372 const unsigned char **p,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200373 const unsigned char *end )
374{
Janos Follath24eed8d2019-11-22 13:21:35 +0000375 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200376
377 if( end < *p )
378 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
379
380 /*
381 * struct {
382 * ECPoint X;
383 * ECSchnorrZKP zkp;
384 * } ECJPAKEKeyKP;
385 */
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200386 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, X, p, end - *p ) );
Manuel Pégourié-Gonnard30590952015-08-17 10:37:40 +0200387 if( mbedtls_ecp_is_zero( X ) )
388 {
389 ret = MBEDTLS_ERR_ECP_INVALID_KEY;
390 goto cleanup;
391 }
392
Robert Cragie7cdad772015-10-02 13:31:41 +0100393 MBEDTLS_MPI_CHK( ecjpake_zkp_read( md_info, grp, pf, G, X, id, p, end ) );
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200394
395cleanup:
396 return( ret );
397}
398
399/*
400 * Generate an ECJPAKEKeyKP
401 * Output: the serialized structure, plus private/public key pair
402 */
403static int ecjpake_kkp_write( const mbedtls_md_info_t *md_info,
404 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100405 const int pf,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200406 const mbedtls_ecp_point *G,
407 mbedtls_mpi *x,
408 mbedtls_ecp_point *X,
409 const char *id,
410 unsigned char **p,
411 const unsigned char *end,
412 int (*f_rng)(void *, unsigned char *, size_t),
413 void *p_rng )
414{
Janos Follath24eed8d2019-11-22 13:21:35 +0000415 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200416 size_t len;
417
418 if( end < *p )
419 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
420
421 /* Generate key (7.4.2.3.1) and write it out */
422 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp, G, x, X,
423 f_rng, p_rng ) );
424 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, X,
Robert Cragie7cdad772015-10-02 13:31:41 +0100425 pf, &len, *p, end - *p ) );
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200426 *p += len;
427
428 /* Generate and write proof */
Robert Cragie7cdad772015-10-02 13:31:41 +0100429 MBEDTLS_MPI_CHK( ecjpake_zkp_write( md_info, grp, pf, G, x, X, id,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200430 p, end, f_rng, p_rng ) );
431
432cleanup:
433 return( ret );
434}
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200435
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200436/*
437 * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs
Shaun Case0e7791f2021-12-20 21:14:10 -0800438 * Outputs: verified peer public keys Xa, Xb
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200439 */
440static int ecjpake_kkpp_read( const mbedtls_md_info_t *md_info,
441 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100442 const int pf,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200443 const mbedtls_ecp_point *G,
444 mbedtls_ecp_point *Xa,
445 mbedtls_ecp_point *Xb,
446 const char *id,
447 const unsigned char *buf,
448 size_t len )
449{
Janos Follath24eed8d2019-11-22 13:21:35 +0000450 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200451 const unsigned char *p = buf;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200452 const unsigned char *end = buf + len;
453
454 /*
455 * struct {
456 * ECJPAKEKeyKP ecjpake_key_kp_pair_list[2];
457 * } ECJPAKEKeyKPPairList;
458 */
Robert Cragie7cdad772015-10-02 13:31:41 +0100459 MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xa, id, &p, end ) );
460 MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xb, id, &p, end ) );
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200461
462 if( p != end )
463 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
464
465cleanup:
466 return( ret );
467}
468
469/*
470 * Generate a ECJPAKEKeyKPPairList
471 * Outputs: the serialized structure, plus two private/public key pairs
472 */
473static int ecjpake_kkpp_write( const mbedtls_md_info_t *md_info,
474 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100475 const int pf,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200476 const mbedtls_ecp_point *G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200477 mbedtls_mpi *xm1,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200478 mbedtls_ecp_point *Xa,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200479 mbedtls_mpi *xm2,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200480 mbedtls_ecp_point *Xb,
481 const char *id,
482 unsigned char *buf,
483 size_t len,
484 size_t *olen,
485 int (*f_rng)(void *, unsigned char *, size_t),
486 void *p_rng )
487{
Janos Follath24eed8d2019-11-22 13:21:35 +0000488 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200489 unsigned char *p = buf;
490 const unsigned char *end = buf + len;
491
Robert Cragie7cdad772015-10-02 13:31:41 +0100492 MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm1, Xa, id,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200493 &p, end, f_rng, p_rng ) );
Robert Cragie7cdad772015-10-02 13:31:41 +0100494 MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm2, Xb, id,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200495 &p, end, f_rng, p_rng ) );
496
497 *olen = p - buf;
498
499cleanup:
500 return( ret );
501}
502
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200503/*
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200504 * Read and process the first round message
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200505 */
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200506int mbedtls_ecjpake_read_round_one( mbedtls_ecjpake_context *ctx,
507 const unsigned char *buf,
508 size_t len )
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200509{
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000510 ECJPAKE_VALIDATE_RET( ctx != NULL );
511 ECJPAKE_VALIDATE_RET( buf != NULL );
512
Robert Cragie7cdad772015-10-02 13:31:41 +0100513 return( ecjpake_kkpp_read( ctx->md_info, &ctx->grp, ctx->point_format,
514 &ctx->grp.G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200515 &ctx->Xp1, &ctx->Xp2, ID_PEER,
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200516 buf, len ) );
517}
518
519/*
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200520 * Generate and write the first round message
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200521 */
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200522int mbedtls_ecjpake_write_round_one( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200523 unsigned char *buf, size_t len, size_t *olen,
524 int (*f_rng)(void *, unsigned char *, size_t),
525 void *p_rng )
526{
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000527 ECJPAKE_VALIDATE_RET( ctx != NULL );
528 ECJPAKE_VALIDATE_RET( buf != NULL );
529 ECJPAKE_VALIDATE_RET( olen != NULL );
530 ECJPAKE_VALIDATE_RET( f_rng != NULL );
531
Robert Cragie7cdad772015-10-02 13:31:41 +0100532 return( ecjpake_kkpp_write( ctx->md_info, &ctx->grp, ctx->point_format,
533 &ctx->grp.G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200534 &ctx->xm1, &ctx->Xm1, &ctx->xm2, &ctx->Xm2,
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200535 ID_MINE, buf, len, olen, f_rng, p_rng ) );
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200536}
537
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200538/*
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200539 * Compute the sum of three points R = A + B + C
540 */
541static int ecjpake_ecp_add3( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
542 const mbedtls_ecp_point *A,
543 const mbedtls_ecp_point *B,
544 const mbedtls_ecp_point *C )
545{
Janos Follath24eed8d2019-11-22 13:21:35 +0000546 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200547 mbedtls_mpi one;
548
549 mbedtls_mpi_init( &one );
550
551 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
552 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, A, &one, B ) );
553 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, R, &one, C ) );
554
555cleanup:
556 mbedtls_mpi_free( &one );
557
558 return( ret );
559}
560
561/*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200562 * 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 +0200563 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200564int mbedtls_ecjpake_read_round_two( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200565 const unsigned char *buf,
566 size_t len )
567{
Janos Follath24eed8d2019-11-22 13:21:35 +0000568 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200569 const unsigned char *p = buf;
570 const unsigned char *end = buf + len;
571 mbedtls_ecp_group grp;
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200572 mbedtls_ecp_point G; /* C: GB, S: GA */
Hanno Becker185e5162018-12-19 09:48:50 +0000573
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000574 ECJPAKE_VALIDATE_RET( ctx != NULL );
575 ECJPAKE_VALIDATE_RET( buf != NULL );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200576
577 mbedtls_ecp_group_init( &grp );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200578 mbedtls_ecp_point_init( &G );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200579
580 /*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200581 * Server: GA = X3 + X4 + X1 (7.4.2.6.1)
582 * Client: GB = X1 + X2 + X3 (7.4.2.5.1)
583 * Unified: G = Xm1 + Xm2 + Xp1
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200584 * We need that before parsing in order to check Xp as we read it
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200585 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200586 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200587 &ctx->Xm1, &ctx->Xm2, &ctx->Xp1 ) );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200588
589 /*
590 * struct {
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200591 * ECParameters curve_params; // only client reading server msg
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200592 * ECJPAKEKeyKP ecjpake_key_kp;
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200593 * } Client/ServerECJPAKEParams;
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200594 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200595 if( ctx->role == MBEDTLS_ECJPAKE_CLIENT )
Manuel Pégourié-Gonnardd9802af2015-08-17 12:47:38 +0200596 {
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200597 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_group( &grp, &p, len ) );
Manuel Pégourié-Gonnardd9802af2015-08-17 12:47:38 +0200598 if( grp.id != ctx->grp.id )
599 {
600 ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
601 goto cleanup;
602 }
603 }
604
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200605 MBEDTLS_MPI_CHK( ecjpake_kkp_read( ctx->md_info, &ctx->grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100606 ctx->point_format,
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200607 &G, &ctx->Xp, ID_PEER, &p, end ) );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200608
609 if( p != end )
610 {
611 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
612 goto cleanup;
613 }
614
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200615cleanup:
616 mbedtls_ecp_group_free( &grp );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200617 mbedtls_ecp_point_free( &G );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200618
619 return( ret );
620}
621
622/*
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200623 * Compute R = +/- X * S mod N, taking care not to leak S
624 */
625static int ecjpake_mul_secret( mbedtls_mpi *R, int sign,
626 const mbedtls_mpi *X,
627 const mbedtls_mpi *S,
628 const mbedtls_mpi *N,
629 int (*f_rng)(void *, unsigned char *, size_t),
630 void *p_rng )
631{
Janos Follath24eed8d2019-11-22 13:21:35 +0000632 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200633 mbedtls_mpi b; /* Blinding value, then s + N * blinding */
634
635 mbedtls_mpi_init( &b );
636
637 /* b = s + rnd-128-bit * N */
638 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &b, 16, f_rng, p_rng ) );
639 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &b, &b, N ) );
640 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &b, &b, S ) );
641
642 /* R = sign * X * b mod N */
643 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( R, X, &b ) );
644 R->s *= sign;
645 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( R, R, N ) );
646
647cleanup:
648 mbedtls_mpi_free( &b );
649
650 return( ret );
651}
652
653/*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200654 * 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 +0200655 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200656int mbedtls_ecjpake_write_round_two( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200657 unsigned char *buf, size_t len, size_t *olen,
658 int (*f_rng)(void *, unsigned char *, size_t),
659 void *p_rng )
660{
Janos Follath24eed8d2019-11-22 13:21:35 +0000661 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200662 mbedtls_ecp_point G; /* C: GA, S: GB */
663 mbedtls_ecp_point Xm; /* C: Xc, S: Xs */
664 mbedtls_mpi xm; /* C: xc, S: xs */
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200665 unsigned char *p = buf;
666 const unsigned char *end = buf + len;
667 size_t ec_len;
Hanno Becker185e5162018-12-19 09:48:50 +0000668
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000669 ECJPAKE_VALIDATE_RET( ctx != NULL );
670 ECJPAKE_VALIDATE_RET( buf != NULL );
671 ECJPAKE_VALIDATE_RET( olen != NULL );
672 ECJPAKE_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200673
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200674 mbedtls_ecp_point_init( &G );
675 mbedtls_ecp_point_init( &Xm );
676 mbedtls_mpi_init( &xm );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200677
678 /*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200679 * 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 +0200680 *
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200681 * Client: GA = X1 + X3 + X4 | xs = x2 * s | Xc = xc * GA
682 * Server: GB = X3 + X1 + X2 | xs = x4 * s | Xs = xs * GB
683 * Unified: G = Xm1 + Xp1 + Xp2 | xm = xm2 * s | Xm = xm * G
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200684 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200685 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200686 &ctx->Xp1, &ctx->Xp2, &ctx->Xm1 ) );
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200687 MBEDTLS_MPI_CHK( ecjpake_mul_secret( &xm, 1, &ctx->xm2, &ctx->s,
688 &ctx->grp.N, f_rng, p_rng ) );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200689 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &Xm, &xm, &G, f_rng, p_rng ) );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200690
691 /*
692 * Now write things out
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200693 *
694 * struct {
695 * ECParameters curve_params; // only server writing its message
696 * ECJPAKEKeyKP ecjpake_key_kp;
697 * } Client/ServerECJPAKEParams;
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200698 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200699 if( ctx->role == MBEDTLS_ECJPAKE_SERVER )
700 {
701 if( end < p )
702 {
703 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
704 goto cleanup;
705 }
706 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_group( &ctx->grp, &ec_len,
707 p, end - p ) );
708 p += ec_len;
709 }
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200710
711 if( end < p )
712 {
713 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
714 goto cleanup;
715 }
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200716 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( &ctx->grp, &Xm,
Robert Cragie7cdad772015-10-02 13:31:41 +0100717 ctx->point_format, &ec_len, p, end - p ) );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200718 p += ec_len;
719
720 MBEDTLS_MPI_CHK( ecjpake_zkp_write( ctx->md_info, &ctx->grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100721 ctx->point_format,
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200722 &G, &xm, &Xm, ID_MINE,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200723 &p, end, f_rng, p_rng ) );
724
725 *olen = p - buf;
726
727cleanup:
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200728 mbedtls_ecp_point_free( &G );
729 mbedtls_ecp_point_free( &Xm );
730 mbedtls_mpi_free( &xm );
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +0200731
732 return( ret );
733}
734
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200735/*
736 * Derive PMS (7.4.2.7 / 7.4.2.8)
737 */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +0200738int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200739 unsigned char *buf, size_t len, size_t *olen,
740 int (*f_rng)(void *, unsigned char *, size_t),
741 void *p_rng )
742{
Janos Follath24eed8d2019-11-22 13:21:35 +0000743 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200744 mbedtls_ecp_point K;
745 mbedtls_mpi m_xm2_s, one;
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200746 unsigned char kx[MBEDTLS_ECP_MAX_BYTES];
747 size_t x_bytes;
Hanno Becker185e5162018-12-19 09:48:50 +0000748
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000749 ECJPAKE_VALIDATE_RET( ctx != NULL );
750 ECJPAKE_VALIDATE_RET( buf != NULL );
751 ECJPAKE_VALIDATE_RET( olen != NULL );
752 ECJPAKE_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200753
754 *olen = mbedtls_md_get_size( ctx->md_info );
755 if( len < *olen )
756 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
757
758 mbedtls_ecp_point_init( &K );
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200759 mbedtls_mpi_init( &m_xm2_s );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200760 mbedtls_mpi_init( &one );
761
762 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200763
764 /*
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200765 * Client: K = ( Xs - X4 * x2 * s ) * x2
766 * Server: K = ( Xc - X2 * x4 * s ) * x4
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200767 * Unified: K = ( Xp - Xp2 * xm2 * s ) * xm2
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200768 */
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200769 MBEDTLS_MPI_CHK( ecjpake_mul_secret( &m_xm2_s, -1, &ctx->xm2, &ctx->s,
770 &ctx->grp.N, f_rng, p_rng ) );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200771 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( &ctx->grp, &K,
772 &one, &ctx->Xp,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200773 &m_xm2_s, &ctx->Xp2 ) );
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200774 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &K, &ctx->xm2, &K,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200775 f_rng, p_rng ) );
776
777 /* PMS = SHA-256( K.X ) */
778 x_bytes = ( ctx->grp.pbits + 7 ) / 8;
779 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &K.X, kx, x_bytes ) );
780 MBEDTLS_MPI_CHK( mbedtls_md( ctx->md_info, kx, x_bytes, buf ) );
781
782cleanup:
783 mbedtls_ecp_point_free( &K );
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200784 mbedtls_mpi_free( &m_xm2_s );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200785 mbedtls_mpi_free( &one );
786
787 return( ret );
788}
789
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200790#undef ID_MINE
791#undef ID_PEER
792
Hanno Becker616d1ca2018-01-24 10:25:05 +0000793#endif /* ! MBEDTLS_ECJPAKE_ALT */
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200794
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200795#if defined(MBEDTLS_SELF_TEST)
796
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200797#include "mbedtls/platform.h"
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200798
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200799#if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
800 !defined(MBEDTLS_SHA256_C)
801int mbedtls_ecjpake_self_test( int verbose )
802{
803 (void) verbose;
804 return( 0 );
805}
806#else
807
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200808static const unsigned char ecjpake_test_password[] = {
809 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x6a, 0x70, 0x61, 0x6b, 0x65, 0x74,
810 0x65, 0x73, 0x74
811};
812
Steven Cooreman64f27732021-01-11 17:20:10 +0100813#if !defined(MBEDTLS_ECJPAKE_ALT)
814
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200815static const unsigned char ecjpake_test_x1[] = {
816 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
817 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
818 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21
819};
820
821static const unsigned char ecjpake_test_x2[] = {
822 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
823 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
824 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
825};
826
827static const unsigned char ecjpake_test_x3[] = {
828 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
829 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
830 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
831};
832
833static const unsigned char ecjpake_test_x4[] = {
834 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc,
835 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
836 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1
837};
838
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200839static const unsigned char ecjpake_test_cli_one[] = {
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200840 0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19,
841 0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44,
842 0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad,
843 0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62,
844 0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9,
845 0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d,
846 0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e,
847 0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e,
848 0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73,
849 0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22,
850 0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce,
851 0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00,
852 0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200853 0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e,
854 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62,
855 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5,
856 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb,
857 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35,
858 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0,
859 0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb,
860 0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47,
861 0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39,
862 0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97,
863 0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40,
864 0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d,
865 0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa,
866 0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d,
867 0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200868};
869
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200870static const unsigned char ecjpake_test_srv_one[] = {
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200871 0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb,
872 0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18,
873 0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47,
874 0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f,
875 0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7,
876 0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d,
877 0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64,
878 0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36,
879 0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2,
880 0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec,
881 0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16,
882 0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96,
883 0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3,
884 0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19,
885 0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f,
886 0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8,
887 0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7,
888 0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea,
889 0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5,
890 0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6,
891 0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31,
892 0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d,
893 0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8,
894 0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee,
895 0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84,
896 0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f,
897 0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80,
898 0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12
899};
900
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200901static const unsigned char ecjpake_test_srv_two[] = {
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200902 0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23,
903 0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c,
904 0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f,
905 0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca,
906 0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26,
907 0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55,
908 0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38,
909 0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6,
910 0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9,
911 0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4,
912 0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2,
913 0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8,
914 0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd,
915 0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c
916};
917
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200918static const unsigned char ecjpake_test_cli_two[] = {
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +0200919 0x41, 0x04, 0x69, 0xd5, 0x4e, 0xe8, 0x5e, 0x90, 0xce, 0x3f, 0x12, 0x46,
920 0x74, 0x2d, 0xe5, 0x07, 0xe9, 0x39, 0xe8, 0x1d, 0x1d, 0xc1, 0xc5, 0xcb,
921 0x98, 0x8b, 0x58, 0xc3, 0x10, 0xc9, 0xfd, 0xd9, 0x52, 0x4d, 0x93, 0x72,
922 0x0b, 0x45, 0x54, 0x1c, 0x83, 0xee, 0x88, 0x41, 0x19, 0x1d, 0xa7, 0xce,
923 0xd8, 0x6e, 0x33, 0x12, 0xd4, 0x36, 0x23, 0xc1, 0xd6, 0x3e, 0x74, 0x98,
924 0x9a, 0xba, 0x4a, 0xff, 0xd1, 0xee, 0x41, 0x04, 0x07, 0x7e, 0x8c, 0x31,
925 0xe2, 0x0e, 0x6b, 0xed, 0xb7, 0x60, 0xc1, 0x35, 0x93, 0xe6, 0x9f, 0x15,
926 0xbe, 0x85, 0xc2, 0x7d, 0x68, 0xcd, 0x09, 0xcc, 0xb8, 0xc4, 0x18, 0x36,
927 0x08, 0x91, 0x7c, 0x5c, 0x3d, 0x40, 0x9f, 0xac, 0x39, 0xfe, 0xfe, 0xe8,
928 0x2f, 0x72, 0x92, 0xd3, 0x6f, 0x0d, 0x23, 0xe0, 0x55, 0x91, 0x3f, 0x45,
929 0xa5, 0x2b, 0x85, 0xdd, 0x8a, 0x20, 0x52, 0xe9, 0xe1, 0x29, 0xbb, 0x4d,
930 0x20, 0x0f, 0x01, 0x1f, 0x19, 0x48, 0x35, 0x35, 0xa6, 0xe8, 0x9a, 0x58,
931 0x0c, 0x9b, 0x00, 0x03, 0xba, 0xf2, 0x14, 0x62, 0xec, 0xe9, 0x1a, 0x82,
932 0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c
933};
934
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200935static const unsigned char ecjpake_test_pms[] = {
936 0xf3, 0xd4, 0x7f, 0x59, 0x98, 0x44, 0xdb, 0x92, 0xa5, 0x69, 0xbb, 0xe7,
937 0x98, 0x1e, 0x39, 0xd9, 0x31, 0xfd, 0x74, 0x3b, 0xf2, 0x2e, 0x98, 0xf9,
938 0xb4, 0x38, 0xf7, 0x19, 0xd3, 0xc4, 0xf3, 0x51
939};
940
Antonin Décimo36e89b52019-01-23 15:24:37 +0100941/* Load my private keys and generate the corresponding public keys */
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +0200942static int ecjpake_test_load( mbedtls_ecjpake_context *ctx,
943 const unsigned char *xm1, size_t len1,
944 const unsigned char *xm2, size_t len2 )
945{
Janos Follath24eed8d2019-11-22 13:21:35 +0000946 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +0200947
948 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm1, xm1, len1 ) );
949 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm2, xm2, len2 ) );
950 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm1, &ctx->xm1,
951 &ctx->grp.G, NULL, NULL ) );
952 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm2, &ctx->xm2,
953 &ctx->grp.G, NULL, NULL ) );
954
955cleanup:
956 return( ret );
957}
958
Steven Cooreman64f27732021-01-11 17:20:10 +0100959#endif /* ! MBEDTLS_ECJPAKE_ALT */
960
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200961/* For tests we don't need a secure RNG;
962 * use the LGC from Numerical Recipes for simplicity */
963static int ecjpake_lgc( void *p, unsigned char *out, size_t len )
964{
965 static uint32_t x = 42;
966 (void) p;
967
968 while( len > 0 )
969 {
970 size_t use_len = len > 4 ? 4 : len;
971 x = 1664525 * x + 1013904223;
972 memcpy( out, &x, use_len );
973 out += use_len;
974 len -= use_len;
975 }
976
977 return( 0 );
978}
979
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200980#define TEST_ASSERT( x ) \
981 do { \
982 if( x ) \
983 ret = 0; \
984 else \
985 { \
986 ret = 1; \
987 goto cleanup; \
988 } \
989 } while( 0 )
990
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200991/*
992 * Checkup routine
993 */
994int mbedtls_ecjpake_self_test( int verbose )
995{
Janos Follath24eed8d2019-11-22 13:21:35 +0000996 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200997 mbedtls_ecjpake_context cli;
998 mbedtls_ecjpake_context srv;
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200999 unsigned char buf[512], pms[32];
1000 size_t len, pmslen;
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001001
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001002 mbedtls_ecjpake_init( &cli );
1003 mbedtls_ecjpake_init( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001004
1005 if( verbose != 0 )
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001006 mbedtls_printf( " ECJPAKE test #0 (setup): " );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +02001007
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +02001008 TEST_ASSERT( mbedtls_ecjpake_setup( &cli, MBEDTLS_ECJPAKE_CLIENT,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001009 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1010 ecjpake_test_password,
1011 sizeof( ecjpake_test_password ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001012
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +02001013 TEST_ASSERT( mbedtls_ecjpake_setup( &srv, MBEDTLS_ECJPAKE_SERVER,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001014 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1015 ecjpake_test_password,
1016 sizeof( ecjpake_test_password ) ) == 0 );
1017
1018 if( verbose != 0 )
1019 mbedtls_printf( "passed\n" );
1020
1021 if( verbose != 0 )
1022 mbedtls_printf( " ECJPAKE test #1 (random handshake): " );
1023
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001024 TEST_ASSERT( mbedtls_ecjpake_write_round_one( &cli,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001025 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1026
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001027 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv, buf, len ) == 0 );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001028
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001029 TEST_ASSERT( mbedtls_ecjpake_write_round_one( &srv,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001030 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1031
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001032 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli, buf, len ) == 0 );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001033
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001034 TEST_ASSERT( mbedtls_ecjpake_write_round_two( &srv,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +02001035 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1036
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001037 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli, buf, len ) == 0 );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +02001038
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001039 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001040 pms, sizeof( pms ), &pmslen, ecjpake_lgc, NULL ) == 0 );
1041
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001042 TEST_ASSERT( mbedtls_ecjpake_write_round_two( &cli,
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +02001043 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1044
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001045 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv, buf, len ) == 0 );
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +02001046
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001047 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001048 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1049
1050 TEST_ASSERT( len == pmslen );
1051 TEST_ASSERT( memcmp( buf, pms, len ) == 0 );
1052
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001053 if( verbose != 0 )
1054 mbedtls_printf( "passed\n" );
1055
Steven Cooreman64f27732021-01-11 17:20:10 +01001056#if !defined(MBEDTLS_ECJPAKE_ALT)
1057 /* 'reference handshake' tests can only be run against implementations
1058 * for which we have 100% control over how the random ephemeral keys
1059 * are generated. This is only the case for the internal mbed TLS
1060 * implementation, so these tests are skipped in case the internal
1061 * implementation is swapped out for an alternative one. */
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001062 if( verbose != 0 )
1063 mbedtls_printf( " ECJPAKE test #2 (reference handshake): " );
1064
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001065 /* Simulate generation of round one */
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001066 MBEDTLS_MPI_CHK( ecjpake_test_load( &cli,
1067 ecjpake_test_x1, sizeof( ecjpake_test_x1 ),
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001068 ecjpake_test_x2, sizeof( ecjpake_test_x2 ) ) );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001069
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001070 MBEDTLS_MPI_CHK( ecjpake_test_load( &srv,
1071 ecjpake_test_x3, sizeof( ecjpake_test_x3 ),
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001072 ecjpake_test_x4, sizeof( ecjpake_test_x4 ) ) );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001073
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001074 /* Read round one */
1075 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv,
1076 ecjpake_test_cli_one,
1077 sizeof( ecjpake_test_cli_one ) ) == 0 );
1078
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001079 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001080 ecjpake_test_srv_one,
1081 sizeof( ecjpake_test_srv_one ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001082
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001083 /* Skip generation of round two, read round two */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001084 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001085 ecjpake_test_srv_two,
1086 sizeof( ecjpake_test_srv_two ) ) == 0 );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +02001087
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001088 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001089 ecjpake_test_cli_two,
1090 sizeof( ecjpake_test_cli_two ) ) == 0 );
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +02001091
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001092 /* Server derives PMS */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001093 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001094 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1095
1096 TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
1097 TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
1098
1099 memset( buf, 0, len ); /* Avoid interferences with next step */
1100
1101 /* Client derives PMS */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001102 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001103 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1104
1105 TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
1106 TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
1107
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001108 if( verbose != 0 )
1109 mbedtls_printf( "passed\n" );
Steven Cooreman64f27732021-01-11 17:20:10 +01001110#endif /* ! MBEDTLS_ECJPAKE_ALT */
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001111
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001112cleanup:
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001113 mbedtls_ecjpake_free( &cli );
1114 mbedtls_ecjpake_free( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001115
1116 if( ret != 0 )
1117 {
1118 if( verbose != 0 )
1119 mbedtls_printf( "failed\n" );
1120
1121 ret = 1;
1122 }
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001123
1124 if( verbose != 0 )
1125 mbedtls_printf( "\n" );
1126
1127 return( ret );
1128}
1129
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +02001130#undef TEST_ASSERT
1131
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001132#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_SHA256_C */
1133
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001134#endif /* MBEDTLS_SELF_TEST */
1135
1136#endif /* MBEDTLS_ECJPAKE_C */