blob: c591924b775b523df31aa41acbe5f31babbd477b [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
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +020037/*
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +020038 * Convert a mbedtls_ecjpake_role to identifier string
39 */
40static const char * const ecjpake_id[] = {
41 "client",
42 "server"
43};
44
45#define ID_MINE ( ecjpake_id[ ctx->role ] )
46#define ID_PEER ( ecjpake_id[ 1 - ctx->role ] )
47
48/*
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020049 * Initialize context
50 */
51void mbedtls_ecjpake_init( mbedtls_ecjpake_context *ctx )
52{
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020053 ctx->md_info = NULL;
54 mbedtls_ecp_group_init( &ctx->grp );
Manuel Pégourié-Gonnardb7da1942015-10-19 13:35:22 +020055 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020056
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +020057 mbedtls_ecp_point_init( &ctx->Xm1 );
58 mbedtls_ecp_point_init( &ctx->Xm2 );
59 mbedtls_ecp_point_init( &ctx->Xp1 );
60 mbedtls_ecp_point_init( &ctx->Xp2 );
61 mbedtls_ecp_point_init( &ctx->Xp );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020062
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +020063 mbedtls_mpi_init( &ctx->xm1 );
64 mbedtls_mpi_init( &ctx->xm2 );
65 mbedtls_mpi_init( &ctx->s );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020066}
67
68/*
69 * Free context
70 */
71void mbedtls_ecjpake_free( mbedtls_ecjpake_context *ctx )
72{
73 if( ctx == NULL )
74 return;
75
76 ctx->md_info = NULL;
77 mbedtls_ecp_group_free( &ctx->grp );
78
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +020079 mbedtls_ecp_point_free( &ctx->Xm1 );
80 mbedtls_ecp_point_free( &ctx->Xm2 );
81 mbedtls_ecp_point_free( &ctx->Xp1 );
82 mbedtls_ecp_point_free( &ctx->Xp2 );
83 mbedtls_ecp_point_free( &ctx->Xp );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020084
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +020085 mbedtls_mpi_free( &ctx->xm1 );
86 mbedtls_mpi_free( &ctx->xm2 );
87 mbedtls_mpi_free( &ctx->s );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020088}
89
90/*
91 * Setup context
92 */
93int mbedtls_ecjpake_setup( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +020094 mbedtls_ecjpake_role role,
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020095 mbedtls_md_type_t hash,
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +020096 mbedtls_ecp_group_id curve,
97 const unsigned char *secret,
98 size_t len )
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020099{
Janos Follath24eed8d2019-11-22 13:21:35 +0000100 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker185e5162018-12-19 09:48:50 +0000101
Tuvshinzaya Erdenekhuua891f832022-07-27 15:13:04 +0100102 if( role != MBEDTLS_ECJPAKE_CLIENT && role != MBEDTLS_ECJPAKE_SERVER )
103 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200104
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +0200105 ctx->role = role;
106
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200107 if( ( ctx->md_info = mbedtls_md_info_from_type( hash ) ) == NULL )
108 return( MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE );
109
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200110 MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ctx->grp, curve ) );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200111
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200112 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->s, secret, len ) );
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200113
114cleanup:
115 if( ret != 0 )
116 mbedtls_ecjpake_free( ctx );
117
118 return( ret );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200119}
120
Gilles Peskinecd07e222021-05-27 23:17:34 +0200121int mbedtls_ecjpake_set_point_format( mbedtls_ecjpake_context *ctx,
122 int point_format )
123{
124 switch( point_format )
125 {
126 case MBEDTLS_ECP_PF_UNCOMPRESSED:
127 case MBEDTLS_ECP_PF_COMPRESSED:
128 ctx->point_format = point_format;
129 return( 0 );
130 default:
131 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
132 }
133}
134
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200135/*
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200136 * Check if context is ready for use
137 */
138int mbedtls_ecjpake_check( const mbedtls_ecjpake_context *ctx )
139{
140 if( ctx->md_info == NULL ||
141 ctx->grp.id == MBEDTLS_ECP_DP_NONE ||
142 ctx->s.p == NULL )
143 {
144 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
145 }
146
147 return( 0 );
148}
149
150/*
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200151 * Write a point plus its length to a buffer
152 */
153static int ecjpake_write_len_point( unsigned char **p,
154 const unsigned char *end,
155 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100156 const int pf,
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200157 const mbedtls_ecp_point *P )
158{
Janos Follath24eed8d2019-11-22 13:21:35 +0000159 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200160 size_t len;
161
162 /* Need at least 4 for length plus 1 for point */
163 if( end < *p || end - *p < 5 )
164 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
165
Robert Cragie7cdad772015-10-02 13:31:41 +0100166 ret = mbedtls_ecp_point_write_binary( grp, P, pf,
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200167 &len, *p + 4, end - ( *p + 4 ) );
168 if( ret != 0 )
169 return( ret );
170
Joe Subbiania5cb0d22021-08-23 11:35:25 +0100171 MBEDTLS_PUT_UINT32_BE( len, *p, 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200172
173 *p += 4 + len;
174
175 return( 0 );
176}
177
178/*
179 * Size of the temporary buffer for ecjpake_hash:
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200180 * 3 EC points plus their length, plus ID and its length (4 + 6 bytes)
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200181 */
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200182#define ECJPAKE_HASH_BUF_LEN ( 3 * ( 4 + MBEDTLS_ECP_MAX_PT_LEN ) + 4 + 6 )
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200183
184/*
185 * Compute hash for ZKP (7.4.2.2.2.1)
186 */
187static int ecjpake_hash( const mbedtls_md_info_t *md_info,
188 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100189 const int pf,
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200190 const mbedtls_ecp_point *G,
191 const mbedtls_ecp_point *V,
192 const mbedtls_ecp_point *X,
193 const char *id,
194 mbedtls_mpi *h )
195{
Janos Follath24eed8d2019-11-22 13:21:35 +0000196 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200197 unsigned char buf[ECJPAKE_HASH_BUF_LEN];
198 unsigned char *p = buf;
199 const unsigned char *end = buf + sizeof( buf );
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200200 const size_t id_len = strlen( id );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200201 unsigned char hash[MBEDTLS_MD_MAX_SIZE];
202
203 /* Write things to temporary buffer */
Robert Cragie7cdad772015-10-02 13:31:41 +0100204 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, G ) );
205 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, V ) );
206 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, X ) );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200207
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200208 if( end - p < 4 )
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200209 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
210
Joe Subbiania5cb0d22021-08-23 11:35:25 +0100211 MBEDTLS_PUT_UINT32_BE( id_len, p, 0 );
212 p += 4;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200213
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200214 if( end < p || (size_t)( end - p ) < id_len )
215 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
216
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200217 memcpy( p, id, id_len );
218 p += id_len;
219
220 /* Compute hash */
k-stachowiak41503352019-06-28 14:14:02 +0200221 MBEDTLS_MPI_CHK( mbedtls_md( md_info, buf, p - buf, hash ) );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200222
223 /* Turn it into an integer mod n */
224 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( h, hash,
225 mbedtls_md_get_size( md_info ) ) );
226 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( h, h, &grp->N ) );
227
228cleanup:
229 return( ret );
230}
231
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200232/*
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200233 * Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3)
234 */
235static int ecjpake_zkp_read( const mbedtls_md_info_t *md_info,
236 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100237 const int pf,
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200238 const mbedtls_ecp_point *G,
239 const mbedtls_ecp_point *X,
240 const char *id,
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200241 const unsigned char **p,
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200242 const unsigned char *end )
243{
Janos Follath24eed8d2019-11-22 13:21:35 +0000244 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200245 mbedtls_ecp_point V, VV;
246 mbedtls_mpi r, h;
247 size_t r_len;
248
249 mbedtls_ecp_point_init( &V );
250 mbedtls_ecp_point_init( &VV );
251 mbedtls_mpi_init( &r );
252 mbedtls_mpi_init( &h );
253
254 /*
255 * struct {
256 * ECPoint V;
257 * opaque r<1..2^8-1>;
258 * } ECSchnorrZKP;
259 */
260 if( end < *p )
261 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
262
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200263 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, &V, p, end - *p ) );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200264
265 if( end < *p || (size_t)( end - *p ) < 1 )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200266 {
267 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
268 goto cleanup;
269 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200270
271 r_len = *(*p)++;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200272
TRodziewicz782a7ea2021-03-17 11:35:16 +0100273 if( end < *p || (size_t)( end - *p ) < r_len || r_len == 0 )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200274 {
275 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
276 goto cleanup;
277 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200278
279 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &r, *p, r_len ) );
280 *p += r_len;
281
282 /*
283 * Verification
284 */
Robert Cragie7cdad772015-10-02 13:31:41 +0100285 MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200286 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( (mbedtls_ecp_group *) grp,
287 &VV, &h, X, &r, G ) );
288
289 if( mbedtls_ecp_point_cmp( &VV, &V ) != 0 )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200290 {
291 ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
292 goto cleanup;
293 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200294
295cleanup:
296 mbedtls_ecp_point_free( &V );
297 mbedtls_ecp_point_free( &VV );
298 mbedtls_mpi_free( &r );
299 mbedtls_mpi_free( &h );
300
301 return( ret );
302}
303
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200304/*
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200305 * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2)
306 */
307static int ecjpake_zkp_write( const mbedtls_md_info_t *md_info,
308 const mbedtls_ecp_group *grp,
Darryl Green11999bb2018-03-13 15:22:58 +0000309 const int pf,
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200310 const mbedtls_ecp_point *G,
311 const mbedtls_mpi *x,
312 const mbedtls_ecp_point *X,
313 const char *id,
314 unsigned char **p,
315 const unsigned char *end,
316 int (*f_rng)(void *, unsigned char *, size_t),
317 void *p_rng )
318{
Janos Follath24eed8d2019-11-22 13:21:35 +0000319 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200320 mbedtls_ecp_point V;
321 mbedtls_mpi v;
322 mbedtls_mpi h; /* later recycled to hold r */
323 size_t len;
324
325 if( end < *p )
326 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
327
328 mbedtls_ecp_point_init( &V );
329 mbedtls_mpi_init( &v );
330 mbedtls_mpi_init( &h );
331
332 /* Compute signature */
333 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp,
334 G, &v, &V, f_rng, p_rng ) );
Robert Cragie7cdad772015-10-02 13:31:41 +0100335 MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) );
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200336 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &h, &h, x ) ); /* x*h */
337 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &h, &v, &h ) ); /* v - x*h */
338 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &h, &h, &grp->N ) ); /* r */
339
340 /* Write it out */
341 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, &V,
Robert Cragie7cdad772015-10-02 13:31:41 +0100342 pf, &len, *p, end - *p ) );
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200343 *p += len;
344
345 len = mbedtls_mpi_size( &h ); /* actually r */
346 if( end < *p || (size_t)( end - *p ) < 1 + len || len > 255 )
347 {
348 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
349 goto cleanup;
350 }
351
Joe Subbiani2194dc42021-07-14 12:31:31 +0100352 *(*p)++ = MBEDTLS_BYTE_0( len );
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200353 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, *p, len ) ); /* r */
354 *p += len;
355
356cleanup:
357 mbedtls_ecp_point_free( &V );
358 mbedtls_mpi_free( &v );
359 mbedtls_mpi_free( &h );
360
361 return( ret );
362}
363
364/*
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200365 * Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof
366 * Output: verified public key X
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200367 */
368static int ecjpake_kkp_read( const mbedtls_md_info_t *md_info,
369 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100370 const int pf,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200371 const mbedtls_ecp_point *G,
372 mbedtls_ecp_point *X,
373 const char *id,
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200374 const unsigned char **p,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200375 const unsigned char *end )
376{
Janos Follath24eed8d2019-11-22 13:21:35 +0000377 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200378
379 if( end < *p )
380 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
381
382 /*
383 * struct {
384 * ECPoint X;
385 * ECSchnorrZKP zkp;
386 * } ECJPAKEKeyKP;
387 */
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200388 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, X, p, end - *p ) );
Manuel Pégourié-Gonnard30590952015-08-17 10:37:40 +0200389 if( mbedtls_ecp_is_zero( X ) )
390 {
391 ret = MBEDTLS_ERR_ECP_INVALID_KEY;
392 goto cleanup;
393 }
394
Robert Cragie7cdad772015-10-02 13:31:41 +0100395 MBEDTLS_MPI_CHK( ecjpake_zkp_read( md_info, grp, pf, G, X, id, p, end ) );
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200396
397cleanup:
398 return( ret );
399}
400
401/*
402 * Generate an ECJPAKEKeyKP
403 * Output: the serialized structure, plus private/public key pair
404 */
405static int ecjpake_kkp_write( const mbedtls_md_info_t *md_info,
406 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100407 const int pf,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200408 const mbedtls_ecp_point *G,
409 mbedtls_mpi *x,
410 mbedtls_ecp_point *X,
411 const char *id,
412 unsigned char **p,
413 const unsigned char *end,
414 int (*f_rng)(void *, unsigned char *, size_t),
415 void *p_rng )
416{
Janos Follath24eed8d2019-11-22 13:21:35 +0000417 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200418 size_t len;
419
420 if( end < *p )
421 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
422
423 /* Generate key (7.4.2.3.1) and write it out */
424 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp, G, x, X,
425 f_rng, p_rng ) );
426 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, X,
Robert Cragie7cdad772015-10-02 13:31:41 +0100427 pf, &len, *p, end - *p ) );
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200428 *p += len;
429
430 /* Generate and write proof */
Robert Cragie7cdad772015-10-02 13:31:41 +0100431 MBEDTLS_MPI_CHK( ecjpake_zkp_write( md_info, grp, pf, G, x, X, id,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200432 p, end, f_rng, p_rng ) );
433
434cleanup:
435 return( ret );
436}
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200437
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200438/*
439 * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs
Shaun Case8b0ecbc2021-12-20 21:14:10 -0800440 * Outputs: verified peer public keys Xa, Xb
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200441 */
442static int ecjpake_kkpp_read( const mbedtls_md_info_t *md_info,
443 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100444 const int pf,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200445 const mbedtls_ecp_point *G,
446 mbedtls_ecp_point *Xa,
447 mbedtls_ecp_point *Xb,
448 const char *id,
449 const unsigned char *buf,
450 size_t len )
451{
Janos Follath24eed8d2019-11-22 13:21:35 +0000452 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200453 const unsigned char *p = buf;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200454 const unsigned char *end = buf + len;
455
456 /*
457 * struct {
458 * ECJPAKEKeyKP ecjpake_key_kp_pair_list[2];
459 * } ECJPAKEKeyKPPairList;
460 */
Robert Cragie7cdad772015-10-02 13:31:41 +0100461 MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xa, id, &p, end ) );
462 MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xb, id, &p, end ) );
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200463
464 if( p != end )
465 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
466
467cleanup:
468 return( ret );
469}
470
471/*
472 * Generate a ECJPAKEKeyKPPairList
473 * Outputs: the serialized structure, plus two private/public key pairs
474 */
475static int ecjpake_kkpp_write( const mbedtls_md_info_t *md_info,
476 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100477 const int pf,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200478 const mbedtls_ecp_point *G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200479 mbedtls_mpi *xm1,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200480 mbedtls_ecp_point *Xa,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200481 mbedtls_mpi *xm2,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200482 mbedtls_ecp_point *Xb,
483 const char *id,
484 unsigned char *buf,
485 size_t len,
486 size_t *olen,
487 int (*f_rng)(void *, unsigned char *, size_t),
488 void *p_rng )
489{
Janos Follath24eed8d2019-11-22 13:21:35 +0000490 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200491 unsigned char *p = buf;
492 const unsigned char *end = buf + len;
493
Robert Cragie7cdad772015-10-02 13:31:41 +0100494 MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm1, Xa, id,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200495 &p, end, f_rng, p_rng ) );
Robert Cragie7cdad772015-10-02 13:31:41 +0100496 MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm2, Xb, id,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200497 &p, end, f_rng, p_rng ) );
498
499 *olen = p - buf;
500
501cleanup:
502 return( ret );
503}
504
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200505/*
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200506 * Read and process the first round message
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200507 */
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200508int mbedtls_ecjpake_read_round_one( mbedtls_ecjpake_context *ctx,
509 const unsigned char *buf,
510 size_t len )
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200511{
Robert Cragie7cdad772015-10-02 13:31:41 +0100512 return( ecjpake_kkpp_read( ctx->md_info, &ctx->grp, ctx->point_format,
513 &ctx->grp.G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200514 &ctx->Xp1, &ctx->Xp2, ID_PEER,
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200515 buf, len ) );
516}
517
518/*
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200519 * Generate and write the first round message
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200520 */
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200521int mbedtls_ecjpake_write_round_one( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200522 unsigned char *buf, size_t len, size_t *olen,
523 int (*f_rng)(void *, unsigned char *, size_t),
524 void *p_rng )
525{
Robert Cragie7cdad772015-10-02 13:31:41 +0100526 return( ecjpake_kkpp_write( ctx->md_info, &ctx->grp, ctx->point_format,
527 &ctx->grp.G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200528 &ctx->xm1, &ctx->Xm1, &ctx->xm2, &ctx->Xm2,
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200529 ID_MINE, buf, len, olen, f_rng, p_rng ) );
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200530}
531
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200532/*
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200533 * Compute the sum of three points R = A + B + C
534 */
535static int ecjpake_ecp_add3( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
536 const mbedtls_ecp_point *A,
537 const mbedtls_ecp_point *B,
538 const mbedtls_ecp_point *C )
539{
Janos Follath24eed8d2019-11-22 13:21:35 +0000540 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200541 mbedtls_mpi one;
542
543 mbedtls_mpi_init( &one );
544
545 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
546 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, A, &one, B ) );
547 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, R, &one, C ) );
548
549cleanup:
550 mbedtls_mpi_free( &one );
551
552 return( ret );
553}
554
555/*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200556 * 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 +0200557 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200558int mbedtls_ecjpake_read_round_two( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200559 const unsigned char *buf,
560 size_t len )
561{
Janos Follath24eed8d2019-11-22 13:21:35 +0000562 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200563 const unsigned char *p = buf;
564 const unsigned char *end = buf + len;
565 mbedtls_ecp_group grp;
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200566 mbedtls_ecp_point G; /* C: GB, S: GA */
Hanno Becker185e5162018-12-19 09:48:50 +0000567
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200568 mbedtls_ecp_group_init( &grp );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200569 mbedtls_ecp_point_init( &G );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200570
571 /*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200572 * Server: GA = X3 + X4 + X1 (7.4.2.6.1)
573 * Client: GB = X1 + X2 + X3 (7.4.2.5.1)
574 * Unified: G = Xm1 + Xm2 + Xp1
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200575 * We need that before parsing in order to check Xp as we read it
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200576 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200577 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200578 &ctx->Xm1, &ctx->Xm2, &ctx->Xp1 ) );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200579
580 /*
581 * struct {
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200582 * ECParameters curve_params; // only client reading server msg
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200583 * ECJPAKEKeyKP ecjpake_key_kp;
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200584 * } Client/ServerECJPAKEParams;
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200585 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200586 if( ctx->role == MBEDTLS_ECJPAKE_CLIENT )
Manuel Pégourié-Gonnardd9802af2015-08-17 12:47:38 +0200587 {
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200588 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_group( &grp, &p, len ) );
Manuel Pégourié-Gonnardd9802af2015-08-17 12:47:38 +0200589 if( grp.id != ctx->grp.id )
590 {
591 ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
592 goto cleanup;
593 }
594 }
595
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200596 MBEDTLS_MPI_CHK( ecjpake_kkp_read( ctx->md_info, &ctx->grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100597 ctx->point_format,
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200598 &G, &ctx->Xp, ID_PEER, &p, end ) );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200599
600 if( p != end )
601 {
602 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
603 goto cleanup;
604 }
605
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200606cleanup:
607 mbedtls_ecp_group_free( &grp );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200608 mbedtls_ecp_point_free( &G );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200609
610 return( ret );
611}
612
613/*
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200614 * Compute R = +/- X * S mod N, taking care not to leak S
615 */
616static int ecjpake_mul_secret( mbedtls_mpi *R, int sign,
617 const mbedtls_mpi *X,
618 const mbedtls_mpi *S,
619 const mbedtls_mpi *N,
620 int (*f_rng)(void *, unsigned char *, size_t),
621 void *p_rng )
622{
Janos Follath24eed8d2019-11-22 13:21:35 +0000623 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200624 mbedtls_mpi b; /* Blinding value, then s + N * blinding */
625
626 mbedtls_mpi_init( &b );
627
628 /* b = s + rnd-128-bit * N */
629 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &b, 16, f_rng, p_rng ) );
630 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &b, &b, N ) );
631 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &b, &b, S ) );
632
633 /* R = sign * X * b mod N */
634 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( R, X, &b ) );
635 R->s *= sign;
636 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( R, R, N ) );
637
638cleanup:
639 mbedtls_mpi_free( &b );
640
641 return( ret );
642}
643
644/*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200645 * 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 +0200646 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200647int mbedtls_ecjpake_write_round_two( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200648 unsigned char *buf, size_t len, size_t *olen,
649 int (*f_rng)(void *, unsigned char *, size_t),
650 void *p_rng )
651{
Janos Follath24eed8d2019-11-22 13:21:35 +0000652 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200653 mbedtls_ecp_point G; /* C: GA, S: GB */
654 mbedtls_ecp_point Xm; /* C: Xc, S: Xs */
655 mbedtls_mpi xm; /* C: xc, S: xs */
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200656 unsigned char *p = buf;
657 const unsigned char *end = buf + len;
658 size_t ec_len;
Hanno Becker185e5162018-12-19 09:48:50 +0000659
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200660 mbedtls_ecp_point_init( &G );
661 mbedtls_ecp_point_init( &Xm );
662 mbedtls_mpi_init( &xm );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200663
664 /*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200665 * 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 +0200666 *
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200667 * Client: GA = X1 + X3 + X4 | xs = x2 * s | Xc = xc * GA
668 * Server: GB = X3 + X1 + X2 | xs = x4 * s | Xs = xs * GB
669 * Unified: G = Xm1 + Xp1 + Xp2 | xm = xm2 * s | Xm = xm * G
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200670 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200671 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200672 &ctx->Xp1, &ctx->Xp2, &ctx->Xm1 ) );
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200673 MBEDTLS_MPI_CHK( ecjpake_mul_secret( &xm, 1, &ctx->xm2, &ctx->s,
674 &ctx->grp.N, f_rng, p_rng ) );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200675 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &Xm, &xm, &G, f_rng, p_rng ) );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200676
677 /*
678 * Now write things out
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200679 *
680 * struct {
681 * ECParameters curve_params; // only server writing its message
682 * ECJPAKEKeyKP ecjpake_key_kp;
683 * } Client/ServerECJPAKEParams;
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200684 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200685 if( ctx->role == MBEDTLS_ECJPAKE_SERVER )
686 {
687 if( end < p )
688 {
689 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
690 goto cleanup;
691 }
692 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_group( &ctx->grp, &ec_len,
693 p, end - p ) );
694 p += ec_len;
695 }
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200696
697 if( end < p )
698 {
699 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
700 goto cleanup;
701 }
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200702 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( &ctx->grp, &Xm,
Robert Cragie7cdad772015-10-02 13:31:41 +0100703 ctx->point_format, &ec_len, p, end - p ) );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200704 p += ec_len;
705
706 MBEDTLS_MPI_CHK( ecjpake_zkp_write( ctx->md_info, &ctx->grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100707 ctx->point_format,
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200708 &G, &xm, &Xm, ID_MINE,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200709 &p, end, f_rng, p_rng ) );
710
711 *olen = p - buf;
712
713cleanup:
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200714 mbedtls_ecp_point_free( &G );
715 mbedtls_ecp_point_free( &Xm );
716 mbedtls_mpi_free( &xm );
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +0200717
718 return( ret );
719}
720
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200721/*
722 * Derive PMS (7.4.2.7 / 7.4.2.8)
723 */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +0200724int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200725 unsigned char *buf, size_t len, size_t *olen,
726 int (*f_rng)(void *, unsigned char *, size_t),
727 void *p_rng )
728{
Janos Follath24eed8d2019-11-22 13:21:35 +0000729 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200730 mbedtls_ecp_point K;
731 mbedtls_mpi m_xm2_s, one;
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200732 unsigned char kx[MBEDTLS_ECP_MAX_BYTES];
733 size_t x_bytes;
Hanno Becker185e5162018-12-19 09:48:50 +0000734
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200735 *olen = mbedtls_md_get_size( ctx->md_info );
736 if( len < *olen )
737 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
738
739 mbedtls_ecp_point_init( &K );
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200740 mbedtls_mpi_init( &m_xm2_s );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200741 mbedtls_mpi_init( &one );
742
743 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200744
745 /*
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200746 * Client: K = ( Xs - X4 * x2 * s ) * x2
747 * Server: K = ( Xc - X2 * x4 * s ) * x4
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200748 * Unified: K = ( Xp - Xp2 * xm2 * s ) * xm2
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200749 */
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200750 MBEDTLS_MPI_CHK( ecjpake_mul_secret( &m_xm2_s, -1, &ctx->xm2, &ctx->s,
751 &ctx->grp.N, f_rng, p_rng ) );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200752 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( &ctx->grp, &K,
753 &one, &ctx->Xp,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200754 &m_xm2_s, &ctx->Xp2 ) );
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200755 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &K, &ctx->xm2, &K,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200756 f_rng, p_rng ) );
757
758 /* PMS = SHA-256( K.X ) */
759 x_bytes = ( ctx->grp.pbits + 7 ) / 8;
760 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &K.X, kx, x_bytes ) );
761 MBEDTLS_MPI_CHK( mbedtls_md( ctx->md_info, kx, x_bytes, buf ) );
762
763cleanup:
764 mbedtls_ecp_point_free( &K );
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200765 mbedtls_mpi_free( &m_xm2_s );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200766 mbedtls_mpi_free( &one );
767
768 return( ret );
769}
770
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200771#undef ID_MINE
772#undef ID_PEER
773
Hanno Becker616d1ca2018-01-24 10:25:05 +0000774#endif /* ! MBEDTLS_ECJPAKE_ALT */
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200775
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200776#if defined(MBEDTLS_SELF_TEST)
777
778#if defined(MBEDTLS_PLATFORM_C)
779#include "mbedtls/platform.h"
780#else
781#include <stdio.h>
782#define mbedtls_printf printf
783#endif
784
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200785#if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
786 !defined(MBEDTLS_SHA256_C)
787int mbedtls_ecjpake_self_test( int verbose )
788{
789 (void) verbose;
790 return( 0 );
791}
792#else
793
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200794static const unsigned char ecjpake_test_password[] = {
795 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x6a, 0x70, 0x61, 0x6b, 0x65, 0x74,
796 0x65, 0x73, 0x74
797};
798
Steven Cooreman64f27732021-01-11 17:20:10 +0100799#if !defined(MBEDTLS_ECJPAKE_ALT)
800
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200801static const unsigned char ecjpake_test_x1[] = {
802 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
803 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
804 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21
805};
806
807static const unsigned char ecjpake_test_x2[] = {
808 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
809 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
810 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
811};
812
813static const unsigned char ecjpake_test_x3[] = {
814 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
815 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
816 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
817};
818
819static const unsigned char ecjpake_test_x4[] = {
820 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc,
821 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
822 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1
823};
824
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200825static const unsigned char ecjpake_test_cli_one[] = {
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200826 0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19,
827 0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44,
828 0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad,
829 0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62,
830 0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9,
831 0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d,
832 0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e,
833 0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e,
834 0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73,
835 0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22,
836 0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce,
837 0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00,
838 0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200839 0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e,
840 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62,
841 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5,
842 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb,
843 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35,
844 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0,
845 0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb,
846 0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47,
847 0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39,
848 0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97,
849 0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40,
850 0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d,
851 0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa,
852 0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d,
853 0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200854};
855
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200856static const unsigned char ecjpake_test_srv_one[] = {
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200857 0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb,
858 0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18,
859 0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47,
860 0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f,
861 0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7,
862 0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d,
863 0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64,
864 0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36,
865 0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2,
866 0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec,
867 0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16,
868 0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96,
869 0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3,
870 0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19,
871 0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f,
872 0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8,
873 0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7,
874 0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea,
875 0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5,
876 0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6,
877 0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31,
878 0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d,
879 0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8,
880 0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee,
881 0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84,
882 0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f,
883 0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80,
884 0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12
885};
886
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200887static const unsigned char ecjpake_test_srv_two[] = {
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200888 0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23,
889 0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c,
890 0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f,
891 0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca,
892 0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26,
893 0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55,
894 0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38,
895 0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6,
896 0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9,
897 0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4,
898 0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2,
899 0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8,
900 0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd,
901 0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c
902};
903
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200904static const unsigned char ecjpake_test_cli_two[] = {
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +0200905 0x41, 0x04, 0x69, 0xd5, 0x4e, 0xe8, 0x5e, 0x90, 0xce, 0x3f, 0x12, 0x46,
906 0x74, 0x2d, 0xe5, 0x07, 0xe9, 0x39, 0xe8, 0x1d, 0x1d, 0xc1, 0xc5, 0xcb,
907 0x98, 0x8b, 0x58, 0xc3, 0x10, 0xc9, 0xfd, 0xd9, 0x52, 0x4d, 0x93, 0x72,
908 0x0b, 0x45, 0x54, 0x1c, 0x83, 0xee, 0x88, 0x41, 0x19, 0x1d, 0xa7, 0xce,
909 0xd8, 0x6e, 0x33, 0x12, 0xd4, 0x36, 0x23, 0xc1, 0xd6, 0x3e, 0x74, 0x98,
910 0x9a, 0xba, 0x4a, 0xff, 0xd1, 0xee, 0x41, 0x04, 0x07, 0x7e, 0x8c, 0x31,
911 0xe2, 0x0e, 0x6b, 0xed, 0xb7, 0x60, 0xc1, 0x35, 0x93, 0xe6, 0x9f, 0x15,
912 0xbe, 0x85, 0xc2, 0x7d, 0x68, 0xcd, 0x09, 0xcc, 0xb8, 0xc4, 0x18, 0x36,
913 0x08, 0x91, 0x7c, 0x5c, 0x3d, 0x40, 0x9f, 0xac, 0x39, 0xfe, 0xfe, 0xe8,
914 0x2f, 0x72, 0x92, 0xd3, 0x6f, 0x0d, 0x23, 0xe0, 0x55, 0x91, 0x3f, 0x45,
915 0xa5, 0x2b, 0x85, 0xdd, 0x8a, 0x20, 0x52, 0xe9, 0xe1, 0x29, 0xbb, 0x4d,
916 0x20, 0x0f, 0x01, 0x1f, 0x19, 0x48, 0x35, 0x35, 0xa6, 0xe8, 0x9a, 0x58,
917 0x0c, 0x9b, 0x00, 0x03, 0xba, 0xf2, 0x14, 0x62, 0xec, 0xe9, 0x1a, 0x82,
918 0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c
919};
920
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200921static const unsigned char ecjpake_test_pms[] = {
922 0xf3, 0xd4, 0x7f, 0x59, 0x98, 0x44, 0xdb, 0x92, 0xa5, 0x69, 0xbb, 0xe7,
923 0x98, 0x1e, 0x39, 0xd9, 0x31, 0xfd, 0x74, 0x3b, 0xf2, 0x2e, 0x98, 0xf9,
924 0xb4, 0x38, 0xf7, 0x19, 0xd3, 0xc4, 0xf3, 0x51
925};
926
Manuel Pégourié-Gonnardaa3ed6f2021-06-15 11:29:26 +0200927/*
928 * PRNG for test - !!!INSECURE NEVER USE IN PRODUCTION!!!
929 *
930 * This is the linear congruential generator from numerical recipes,
931 * except we only use the low byte as the output. See
932 * https://en.wikipedia.org/wiki/Linear_congruential_generator#Parameters_in_common_use
933 */
934static int self_test_rng( void *ctx, unsigned char *out, size_t len )
935{
936 static uint32_t state = 42;
937
938 (void) ctx;
939
940 for( size_t i = 0; i < len; i++ )
941 {
942 state = state * 1664525u + 1013904223u;
943 out[i] = (unsigned char) state;
944 }
945
946 return( 0 );
947}
948
Antonin Décimo36e89b52019-01-23 15:24:37 +0100949/* Load my private keys and generate the corresponding public keys */
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +0200950static int ecjpake_test_load( mbedtls_ecjpake_context *ctx,
951 const unsigned char *xm1, size_t len1,
952 const unsigned char *xm2, size_t len2 )
953{
Janos Follath24eed8d2019-11-22 13:21:35 +0000954 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +0200955
956 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm1, xm1, len1 ) );
957 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm2, xm2, len2 ) );
958 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm1, &ctx->xm1,
Manuel Pégourié-Gonnardaa3ed6f2021-06-15 11:29:26 +0200959 &ctx->grp.G, self_test_rng, NULL ) );
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +0200960 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm2, &ctx->xm2,
Manuel Pégourié-Gonnardaa3ed6f2021-06-15 11:29:26 +0200961 &ctx->grp.G, self_test_rng, NULL ) );
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +0200962
963cleanup:
964 return( ret );
965}
966
Steven Cooreman64f27732021-01-11 17:20:10 +0100967#endif /* ! MBEDTLS_ECJPAKE_ALT */
968
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200969/* For tests we don't need a secure RNG;
970 * use the LGC from Numerical Recipes for simplicity */
971static int ecjpake_lgc( void *p, unsigned char *out, size_t len )
972{
973 static uint32_t x = 42;
974 (void) p;
975
976 while( len > 0 )
977 {
978 size_t use_len = len > 4 ? 4 : len;
979 x = 1664525 * x + 1013904223;
980 memcpy( out, &x, use_len );
981 out += use_len;
982 len -= use_len;
983 }
984
985 return( 0 );
986}
987
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200988#define TEST_ASSERT( x ) \
989 do { \
990 if( x ) \
991 ret = 0; \
992 else \
993 { \
994 ret = 1; \
995 goto cleanup; \
996 } \
997 } while( 0 )
998
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200999/*
1000 * Checkup routine
1001 */
1002int mbedtls_ecjpake_self_test( int verbose )
1003{
Janos Follath24eed8d2019-11-22 13:21:35 +00001004 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001005 mbedtls_ecjpake_context cli;
1006 mbedtls_ecjpake_context srv;
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001007 unsigned char buf[512], pms[32];
1008 size_t len, pmslen;
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001009
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001010 mbedtls_ecjpake_init( &cli );
1011 mbedtls_ecjpake_init( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001012
1013 if( verbose != 0 )
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001014 mbedtls_printf( " ECJPAKE test #0 (setup): " );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +02001015
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +02001016 TEST_ASSERT( mbedtls_ecjpake_setup( &cli, MBEDTLS_ECJPAKE_CLIENT,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001017 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1018 ecjpake_test_password,
1019 sizeof( ecjpake_test_password ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001020
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +02001021 TEST_ASSERT( mbedtls_ecjpake_setup( &srv, MBEDTLS_ECJPAKE_SERVER,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001022 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1023 ecjpake_test_password,
1024 sizeof( ecjpake_test_password ) ) == 0 );
1025
1026 if( verbose != 0 )
1027 mbedtls_printf( "passed\n" );
1028
1029 if( verbose != 0 )
1030 mbedtls_printf( " ECJPAKE test #1 (random handshake): " );
1031
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001032 TEST_ASSERT( mbedtls_ecjpake_write_round_one( &cli,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001033 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1034
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001035 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv, buf, len ) == 0 );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001036
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001037 TEST_ASSERT( mbedtls_ecjpake_write_round_one( &srv,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001038 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1039
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001040 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli, buf, len ) == 0 );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001041
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001042 TEST_ASSERT( mbedtls_ecjpake_write_round_two( &srv,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +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( &cli, buf, len ) == 0 );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +02001046
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001047 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001048 pms, sizeof( pms ), &pmslen, ecjpake_lgc, NULL ) == 0 );
1049
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001050 TEST_ASSERT( mbedtls_ecjpake_write_round_two( &cli,
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +02001051 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1052
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001053 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv, buf, len ) == 0 );
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +02001054
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001055 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001056 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1057
1058 TEST_ASSERT( len == pmslen );
1059 TEST_ASSERT( memcmp( buf, pms, len ) == 0 );
1060
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001061 if( verbose != 0 )
1062 mbedtls_printf( "passed\n" );
1063
Steven Cooreman64f27732021-01-11 17:20:10 +01001064#if !defined(MBEDTLS_ECJPAKE_ALT)
1065 /* 'reference handshake' tests can only be run against implementations
1066 * for which we have 100% control over how the random ephemeral keys
1067 * are generated. This is only the case for the internal mbed TLS
1068 * implementation, so these tests are skipped in case the internal
1069 * implementation is swapped out for an alternative one. */
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001070 if( verbose != 0 )
1071 mbedtls_printf( " ECJPAKE test #2 (reference handshake): " );
1072
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001073 /* Simulate generation of round one */
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001074 MBEDTLS_MPI_CHK( ecjpake_test_load( &cli,
1075 ecjpake_test_x1, sizeof( ecjpake_test_x1 ),
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001076 ecjpake_test_x2, sizeof( ecjpake_test_x2 ) ) );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001077
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001078 MBEDTLS_MPI_CHK( ecjpake_test_load( &srv,
1079 ecjpake_test_x3, sizeof( ecjpake_test_x3 ),
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001080 ecjpake_test_x4, sizeof( ecjpake_test_x4 ) ) );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001081
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001082 /* Read round one */
1083 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv,
1084 ecjpake_test_cli_one,
1085 sizeof( ecjpake_test_cli_one ) ) == 0 );
1086
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001087 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001088 ecjpake_test_srv_one,
1089 sizeof( ecjpake_test_srv_one ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001090
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001091 /* Skip generation of round two, read round two */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001092 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001093 ecjpake_test_srv_two,
1094 sizeof( ecjpake_test_srv_two ) ) == 0 );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +02001095
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001096 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001097 ecjpake_test_cli_two,
1098 sizeof( ecjpake_test_cli_two ) ) == 0 );
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +02001099
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001100 /* Server derives PMS */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001101 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001102 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1103
1104 TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
1105 TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
1106
1107 memset( buf, 0, len ); /* Avoid interferences with next step */
1108
1109 /* Client derives PMS */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001110 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001111 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1112
1113 TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
1114 TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
1115
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001116 if( verbose != 0 )
1117 mbedtls_printf( "passed\n" );
Steven Cooreman64f27732021-01-11 17:20:10 +01001118#endif /* ! MBEDTLS_ECJPAKE_ALT */
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001119
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001120cleanup:
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001121 mbedtls_ecjpake_free( &cli );
1122 mbedtls_ecjpake_free( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001123
1124 if( ret != 0 )
1125 {
1126 if( verbose != 0 )
1127 mbedtls_printf( "failed\n" );
1128
1129 ret = 1;
1130 }
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001131
1132 if( verbose != 0 )
1133 mbedtls_printf( "\n" );
1134
1135 return( ret );
1136}
1137
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +02001138#undef TEST_ASSERT
1139
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001140#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_SHA256_C */
1141
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001142#endif /* MBEDTLS_SELF_TEST */
1143
1144#endif /* MBEDTLS_ECJPAKE_C */