blob: 0b9bffb93e68c03245af04bdf54576ab8faa35d8 [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
797#if defined(MBEDTLS_PLATFORM_C)
798#include "mbedtls/platform.h"
799#else
800#include <stdio.h>
801#define mbedtls_printf printf
802#endif
803
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200804#if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
805 !defined(MBEDTLS_SHA256_C)
806int mbedtls_ecjpake_self_test( int verbose )
807{
808 (void) verbose;
809 return( 0 );
810}
811#else
812
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200813static const unsigned char ecjpake_test_password[] = {
814 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x6a, 0x70, 0x61, 0x6b, 0x65, 0x74,
815 0x65, 0x73, 0x74
816};
817
Steven Cooreman64f27732021-01-11 17:20:10 +0100818#if !defined(MBEDTLS_ECJPAKE_ALT)
819
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200820static const unsigned char ecjpake_test_x1[] = {
821 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
822 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
823 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21
824};
825
826static const unsigned char ecjpake_test_x2[] = {
827 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
828 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
829 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
830};
831
832static const unsigned char ecjpake_test_x3[] = {
833 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
834 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
835 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
836};
837
838static const unsigned char ecjpake_test_x4[] = {
839 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc,
840 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
841 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1
842};
843
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200844static const unsigned char ecjpake_test_cli_one[] = {
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200845 0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19,
846 0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44,
847 0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad,
848 0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62,
849 0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9,
850 0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d,
851 0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e,
852 0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e,
853 0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73,
854 0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22,
855 0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce,
856 0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00,
857 0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200858 0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e,
859 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62,
860 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5,
861 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb,
862 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35,
863 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0,
864 0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb,
865 0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47,
866 0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39,
867 0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97,
868 0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40,
869 0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d,
870 0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa,
871 0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d,
872 0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200873};
874
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200875static const unsigned char ecjpake_test_srv_one[] = {
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200876 0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb,
877 0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18,
878 0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47,
879 0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f,
880 0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7,
881 0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d,
882 0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64,
883 0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36,
884 0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2,
885 0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec,
886 0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16,
887 0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96,
888 0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3,
889 0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19,
890 0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f,
891 0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8,
892 0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7,
893 0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea,
894 0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5,
895 0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6,
896 0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31,
897 0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d,
898 0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8,
899 0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee,
900 0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84,
901 0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f,
902 0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80,
903 0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12
904};
905
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200906static const unsigned char ecjpake_test_srv_two[] = {
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200907 0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23,
908 0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c,
909 0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f,
910 0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca,
911 0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26,
912 0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55,
913 0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38,
914 0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6,
915 0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9,
916 0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4,
917 0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2,
918 0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8,
919 0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd,
920 0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c
921};
922
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200923static const unsigned char ecjpake_test_cli_two[] = {
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +0200924 0x41, 0x04, 0x69, 0xd5, 0x4e, 0xe8, 0x5e, 0x90, 0xce, 0x3f, 0x12, 0x46,
925 0x74, 0x2d, 0xe5, 0x07, 0xe9, 0x39, 0xe8, 0x1d, 0x1d, 0xc1, 0xc5, 0xcb,
926 0x98, 0x8b, 0x58, 0xc3, 0x10, 0xc9, 0xfd, 0xd9, 0x52, 0x4d, 0x93, 0x72,
927 0x0b, 0x45, 0x54, 0x1c, 0x83, 0xee, 0x88, 0x41, 0x19, 0x1d, 0xa7, 0xce,
928 0xd8, 0x6e, 0x33, 0x12, 0xd4, 0x36, 0x23, 0xc1, 0xd6, 0x3e, 0x74, 0x98,
929 0x9a, 0xba, 0x4a, 0xff, 0xd1, 0xee, 0x41, 0x04, 0x07, 0x7e, 0x8c, 0x31,
930 0xe2, 0x0e, 0x6b, 0xed, 0xb7, 0x60, 0xc1, 0x35, 0x93, 0xe6, 0x9f, 0x15,
931 0xbe, 0x85, 0xc2, 0x7d, 0x68, 0xcd, 0x09, 0xcc, 0xb8, 0xc4, 0x18, 0x36,
932 0x08, 0x91, 0x7c, 0x5c, 0x3d, 0x40, 0x9f, 0xac, 0x39, 0xfe, 0xfe, 0xe8,
933 0x2f, 0x72, 0x92, 0xd3, 0x6f, 0x0d, 0x23, 0xe0, 0x55, 0x91, 0x3f, 0x45,
934 0xa5, 0x2b, 0x85, 0xdd, 0x8a, 0x20, 0x52, 0xe9, 0xe1, 0x29, 0xbb, 0x4d,
935 0x20, 0x0f, 0x01, 0x1f, 0x19, 0x48, 0x35, 0x35, 0xa6, 0xe8, 0x9a, 0x58,
936 0x0c, 0x9b, 0x00, 0x03, 0xba, 0xf2, 0x14, 0x62, 0xec, 0xe9, 0x1a, 0x82,
937 0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c
938};
939
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200940static const unsigned char ecjpake_test_pms[] = {
941 0xf3, 0xd4, 0x7f, 0x59, 0x98, 0x44, 0xdb, 0x92, 0xa5, 0x69, 0xbb, 0xe7,
942 0x98, 0x1e, 0x39, 0xd9, 0x31, 0xfd, 0x74, 0x3b, 0xf2, 0x2e, 0x98, 0xf9,
943 0xb4, 0x38, 0xf7, 0x19, 0xd3, 0xc4, 0xf3, 0x51
944};
945
Antonin Décimo36e89b52019-01-23 15:24:37 +0100946/* Load my private keys and generate the corresponding public keys */
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +0200947static int ecjpake_test_load( mbedtls_ecjpake_context *ctx,
948 const unsigned char *xm1, size_t len1,
949 const unsigned char *xm2, size_t len2 )
950{
Janos Follath24eed8d2019-11-22 13:21:35 +0000951 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +0200952
953 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm1, xm1, len1 ) );
954 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm2, xm2, len2 ) );
955 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm1, &ctx->xm1,
956 &ctx->grp.G, NULL, NULL ) );
957 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm2, &ctx->xm2,
958 &ctx->grp.G, NULL, NULL ) );
959
960cleanup:
961 return( ret );
962}
963
Steven Cooreman64f27732021-01-11 17:20:10 +0100964#endif /* ! MBEDTLS_ECJPAKE_ALT */
965
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200966/* For tests we don't need a secure RNG;
967 * use the LGC from Numerical Recipes for simplicity */
968static int ecjpake_lgc( void *p, unsigned char *out, size_t len )
969{
970 static uint32_t x = 42;
971 (void) p;
972
973 while( len > 0 )
974 {
975 size_t use_len = len > 4 ? 4 : len;
976 x = 1664525 * x + 1013904223;
977 memcpy( out, &x, use_len );
978 out += use_len;
979 len -= use_len;
980 }
981
982 return( 0 );
983}
984
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200985#define TEST_ASSERT( x ) \
986 do { \
987 if( x ) \
988 ret = 0; \
989 else \
990 { \
991 ret = 1; \
992 goto cleanup; \
993 } \
994 } while( 0 )
995
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200996/*
997 * Checkup routine
998 */
999int mbedtls_ecjpake_self_test( int verbose )
1000{
Janos Follath24eed8d2019-11-22 13:21:35 +00001001 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001002 mbedtls_ecjpake_context cli;
1003 mbedtls_ecjpake_context srv;
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001004 unsigned char buf[512], pms[32];
1005 size_t len, pmslen;
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001006
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001007 mbedtls_ecjpake_init( &cli );
1008 mbedtls_ecjpake_init( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001009
1010 if( verbose != 0 )
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001011 mbedtls_printf( " ECJPAKE test #0 (setup): " );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +02001012
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +02001013 TEST_ASSERT( mbedtls_ecjpake_setup( &cli, MBEDTLS_ECJPAKE_CLIENT,
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 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001017
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +02001018 TEST_ASSERT( mbedtls_ecjpake_setup( &srv, MBEDTLS_ECJPAKE_SERVER,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001019 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1020 ecjpake_test_password,
1021 sizeof( ecjpake_test_password ) ) == 0 );
1022
1023 if( verbose != 0 )
1024 mbedtls_printf( "passed\n" );
1025
1026 if( verbose != 0 )
1027 mbedtls_printf( " ECJPAKE test #1 (random handshake): " );
1028
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001029 TEST_ASSERT( mbedtls_ecjpake_write_round_one( &cli,
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( &srv, buf, len ) == 0 );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001033
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001034 TEST_ASSERT( mbedtls_ecjpake_write_round_one( &srv,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001035 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1036
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001037 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli, buf, len ) == 0 );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001038
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001039 TEST_ASSERT( mbedtls_ecjpake_write_round_two( &srv,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +02001040 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1041
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001042 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli, buf, len ) == 0 );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +02001043
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001044 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001045 pms, sizeof( pms ), &pmslen, ecjpake_lgc, NULL ) == 0 );
1046
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001047 TEST_ASSERT( mbedtls_ecjpake_write_round_two( &cli,
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +02001048 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1049
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001050 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv, buf, len ) == 0 );
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +02001051
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001052 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001053 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1054
1055 TEST_ASSERT( len == pmslen );
1056 TEST_ASSERT( memcmp( buf, pms, len ) == 0 );
1057
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001058 if( verbose != 0 )
1059 mbedtls_printf( "passed\n" );
1060
Steven Cooreman64f27732021-01-11 17:20:10 +01001061#if !defined(MBEDTLS_ECJPAKE_ALT)
1062 /* 'reference handshake' tests can only be run against implementations
1063 * for which we have 100% control over how the random ephemeral keys
1064 * are generated. This is only the case for the internal mbed TLS
1065 * implementation, so these tests are skipped in case the internal
1066 * implementation is swapped out for an alternative one. */
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001067 if( verbose != 0 )
1068 mbedtls_printf( " ECJPAKE test #2 (reference handshake): " );
1069
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001070 /* Simulate generation of round one */
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001071 MBEDTLS_MPI_CHK( ecjpake_test_load( &cli,
1072 ecjpake_test_x1, sizeof( ecjpake_test_x1 ),
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001073 ecjpake_test_x2, sizeof( ecjpake_test_x2 ) ) );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001074
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001075 MBEDTLS_MPI_CHK( ecjpake_test_load( &srv,
1076 ecjpake_test_x3, sizeof( ecjpake_test_x3 ),
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001077 ecjpake_test_x4, sizeof( ecjpake_test_x4 ) ) );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001078
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001079 /* Read round one */
1080 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv,
1081 ecjpake_test_cli_one,
1082 sizeof( ecjpake_test_cli_one ) ) == 0 );
1083
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001084 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001085 ecjpake_test_srv_one,
1086 sizeof( ecjpake_test_srv_one ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001087
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001088 /* Skip generation of round two, read round two */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001089 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001090 ecjpake_test_srv_two,
1091 sizeof( ecjpake_test_srv_two ) ) == 0 );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +02001092
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001093 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001094 ecjpake_test_cli_two,
1095 sizeof( ecjpake_test_cli_two ) ) == 0 );
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +02001096
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001097 /* Server derives PMS */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001098 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001099 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1100
1101 TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
1102 TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
1103
1104 memset( buf, 0, len ); /* Avoid interferences with next step */
1105
1106 /* Client derives PMS */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001107 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001108 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1109
1110 TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
1111 TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
1112
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001113 if( verbose != 0 )
1114 mbedtls_printf( "passed\n" );
Steven Cooreman64f27732021-01-11 17:20:10 +01001115#endif /* ! MBEDTLS_ECJPAKE_ALT */
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001116
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001117cleanup:
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001118 mbedtls_ecjpake_free( &cli );
1119 mbedtls_ecjpake_free( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001120
1121 if( ret != 0 )
1122 {
1123 if( verbose != 0 )
1124 mbedtls_printf( "failed\n" );
1125
1126 ret = 1;
1127 }
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001128
1129 if( verbose != 0 )
1130 mbedtls_printf( "\n" );
1131
1132 return( ret );
1133}
1134
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +02001135#undef TEST_ASSERT
1136
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001137#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_SHA256_C */
1138
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001139#endif /* MBEDTLS_SELF_TEST */
1140
1141#endif /* MBEDTLS_ECJPAKE_C */