blob: 10286c27d7b91507deed36a2646fd6b3d913d6a7 [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
Neil Armstrong0d763412022-08-11 10:32:22 +020033#include "hash_info.h"
34
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +020035#include <string.h>
36
Hanno Becker616d1ca2018-01-24 10:25:05 +000037#if !defined(MBEDTLS_ECJPAKE_ALT)
38
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +020039/*
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +020040 * Convert a mbedtls_ecjpake_role to identifier string
41 */
42static const char * const ecjpake_id[] = {
43 "client",
44 "server"
45};
46
47#define ID_MINE ( ecjpake_id[ ctx->role ] )
48#define ID_PEER ( ecjpake_id[ 1 - ctx->role ] )
49
50/*
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020051 * Initialize context
52 */
53void mbedtls_ecjpake_init( mbedtls_ecjpake_context *ctx )
54{
Neil Armstrong0d763412022-08-11 10:32:22 +020055 ctx->md_type = MBEDTLS_MD_NONE;
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020056 mbedtls_ecp_group_init( &ctx->grp );
Manuel Pégourié-Gonnardb7da1942015-10-19 13:35:22 +020057 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020058
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +020059 mbedtls_ecp_point_init( &ctx->Xm1 );
60 mbedtls_ecp_point_init( &ctx->Xm2 );
61 mbedtls_ecp_point_init( &ctx->Xp1 );
62 mbedtls_ecp_point_init( &ctx->Xp2 );
63 mbedtls_ecp_point_init( &ctx->Xp );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020064
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +020065 mbedtls_mpi_init( &ctx->xm1 );
66 mbedtls_mpi_init( &ctx->xm2 );
67 mbedtls_mpi_init( &ctx->s );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020068}
69
70/*
71 * Free context
72 */
73void mbedtls_ecjpake_free( mbedtls_ecjpake_context *ctx )
74{
75 if( ctx == NULL )
76 return;
77
Neil Armstrong0d763412022-08-11 10:32:22 +020078 ctx->md_type = MBEDTLS_MD_NONE;
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020079 mbedtls_ecp_group_free( &ctx->grp );
80
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +020081 mbedtls_ecp_point_free( &ctx->Xm1 );
82 mbedtls_ecp_point_free( &ctx->Xm2 );
83 mbedtls_ecp_point_free( &ctx->Xp1 );
84 mbedtls_ecp_point_free( &ctx->Xp2 );
85 mbedtls_ecp_point_free( &ctx->Xp );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020086
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +020087 mbedtls_mpi_free( &ctx->xm1 );
88 mbedtls_mpi_free( &ctx->xm2 );
89 mbedtls_mpi_free( &ctx->s );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020090}
91
92/*
93 * Setup context
94 */
95int mbedtls_ecjpake_setup( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +020096 mbedtls_ecjpake_role role,
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020097 mbedtls_md_type_t hash,
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +020098 mbedtls_ecp_group_id curve,
99 const unsigned char *secret,
100 size_t len )
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200101{
Janos Follath24eed8d2019-11-22 13:21:35 +0000102 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker185e5162018-12-19 09:48:50 +0000103
Tuvshinzaya Erdenekhuua891f832022-07-27 15:13:04 +0100104 if( role != MBEDTLS_ECJPAKE_CLIENT && role != MBEDTLS_ECJPAKE_SERVER )
105 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200106
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +0200107 ctx->role = role;
108
Neil Armstrong0d763412022-08-11 10:32:22 +0200109 if( ( mbedtls_md_info_from_type( hash ) ) == NULL )
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200110 return( MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE );
111
Neil Armstrong0d763412022-08-11 10:32:22 +0200112 ctx->md_type = hash;
113
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200114 MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ctx->grp, curve ) );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200115
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200116 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->s, secret, len ) );
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200117
118cleanup:
119 if( ret != 0 )
120 mbedtls_ecjpake_free( ctx );
121
122 return( ret );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200123}
124
Gilles Peskinecd07e222021-05-27 23:17:34 +0200125int mbedtls_ecjpake_set_point_format( mbedtls_ecjpake_context *ctx,
126 int point_format )
127{
128 switch( point_format )
129 {
130 case MBEDTLS_ECP_PF_UNCOMPRESSED:
131 case MBEDTLS_ECP_PF_COMPRESSED:
132 ctx->point_format = point_format;
133 return( 0 );
134 default:
135 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
136 }
137}
138
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200139/*
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200140 * Check if context is ready for use
141 */
142int mbedtls_ecjpake_check( const mbedtls_ecjpake_context *ctx )
143{
Neil Armstrong0d763412022-08-11 10:32:22 +0200144 if( ctx->md_type == MBEDTLS_MD_NONE ||
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200145 ctx->grp.id == MBEDTLS_ECP_DP_NONE ||
146 ctx->s.p == NULL )
147 {
148 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
149 }
150
151 return( 0 );
152}
153
154/*
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200155 * Write a point plus its length to a buffer
156 */
157static int ecjpake_write_len_point( unsigned char **p,
158 const unsigned char *end,
159 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100160 const int pf,
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200161 const mbedtls_ecp_point *P )
162{
Janos Follath24eed8d2019-11-22 13:21:35 +0000163 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200164 size_t len;
165
166 /* Need at least 4 for length plus 1 for point */
167 if( end < *p || end - *p < 5 )
168 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
169
Robert Cragie7cdad772015-10-02 13:31:41 +0100170 ret = mbedtls_ecp_point_write_binary( grp, P, pf,
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200171 &len, *p + 4, end - ( *p + 4 ) );
172 if( ret != 0 )
173 return( ret );
174
Joe Subbiania5cb0d22021-08-23 11:35:25 +0100175 MBEDTLS_PUT_UINT32_BE( len, *p, 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200176
177 *p += 4 + len;
178
179 return( 0 );
180}
181
182/*
183 * Size of the temporary buffer for ecjpake_hash:
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200184 * 3 EC points plus their length, plus ID and its length (4 + 6 bytes)
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200185 */
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200186#define ECJPAKE_HASH_BUF_LEN ( 3 * ( 4 + MBEDTLS_ECP_MAX_PT_LEN ) + 4 + 6 )
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200187
188/*
189 * Compute hash for ZKP (7.4.2.2.2.1)
190 */
Neil Armstrong0d763412022-08-11 10:32:22 +0200191static int ecjpake_hash( const mbedtls_md_type_t md_type,
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200192 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100193 const int pf,
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200194 const mbedtls_ecp_point *G,
195 const mbedtls_ecp_point *V,
196 const mbedtls_ecp_point *X,
197 const char *id,
198 mbedtls_mpi *h )
199{
Janos Follath24eed8d2019-11-22 13:21:35 +0000200 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200201 unsigned char buf[ECJPAKE_HASH_BUF_LEN];
202 unsigned char *p = buf;
203 const unsigned char *end = buf + sizeof( buf );
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200204 const size_t id_len = strlen( id );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200205 unsigned char hash[MBEDTLS_MD_MAX_SIZE];
206
207 /* Write things to temporary buffer */
Robert Cragie7cdad772015-10-02 13:31:41 +0100208 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, G ) );
209 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, V ) );
210 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, X ) );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200211
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200212 if( end - p < 4 )
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200213 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
214
Joe Subbiania5cb0d22021-08-23 11:35:25 +0100215 MBEDTLS_PUT_UINT32_BE( id_len, p, 0 );
216 p += 4;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200217
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200218 if( end < p || (size_t)( end - p ) < id_len )
219 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
220
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200221 memcpy( p, id, id_len );
222 p += id_len;
223
224 /* Compute hash */
Neil Armstrong0d763412022-08-11 10:32:22 +0200225 MBEDTLS_MPI_CHK( mbedtls_md( mbedtls_md_info_from_type( md_type ),
226 buf, p - buf, hash ) );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200227
228 /* Turn it into an integer mod n */
229 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( h, hash,
Neil Armstrong0d763412022-08-11 10:32:22 +0200230 mbedtls_hash_info_get_size( md_type ) ) );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200231 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( h, h, &grp->N ) );
232
233cleanup:
234 return( ret );
235}
236
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200237/*
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200238 * Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3)
239 */
Neil Armstrong0d763412022-08-11 10:32:22 +0200240static int ecjpake_zkp_read( const mbedtls_md_type_t md_type,
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200241 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100242 const int pf,
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200243 const mbedtls_ecp_point *G,
244 const mbedtls_ecp_point *X,
245 const char *id,
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200246 const unsigned char **p,
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200247 const unsigned char *end )
248{
Janos Follath24eed8d2019-11-22 13:21:35 +0000249 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200250 mbedtls_ecp_point V, VV;
251 mbedtls_mpi r, h;
252 size_t r_len;
253
254 mbedtls_ecp_point_init( &V );
255 mbedtls_ecp_point_init( &VV );
256 mbedtls_mpi_init( &r );
257 mbedtls_mpi_init( &h );
258
259 /*
260 * struct {
261 * ECPoint V;
262 * opaque r<1..2^8-1>;
263 * } ECSchnorrZKP;
264 */
265 if( end < *p )
266 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
267
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200268 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, &V, p, end - *p ) );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200269
270 if( end < *p || (size_t)( end - *p ) < 1 )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200271 {
272 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
273 goto cleanup;
274 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200275
276 r_len = *(*p)++;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200277
TRodziewicz782a7ea2021-03-17 11:35:16 +0100278 if( end < *p || (size_t)( end - *p ) < r_len || r_len == 0 )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200279 {
280 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
281 goto cleanup;
282 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200283
284 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &r, *p, r_len ) );
285 *p += r_len;
286
287 /*
288 * Verification
289 */
Neil Armstrong0d763412022-08-11 10:32:22 +0200290 MBEDTLS_MPI_CHK( ecjpake_hash( md_type, grp, pf, G, &V, X, id, &h ) );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200291 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( (mbedtls_ecp_group *) grp,
292 &VV, &h, X, &r, G ) );
293
294 if( mbedtls_ecp_point_cmp( &VV, &V ) != 0 )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200295 {
296 ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
297 goto cleanup;
298 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200299
300cleanup:
301 mbedtls_ecp_point_free( &V );
302 mbedtls_ecp_point_free( &VV );
303 mbedtls_mpi_free( &r );
304 mbedtls_mpi_free( &h );
305
306 return( ret );
307}
308
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200309/*
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200310 * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2)
311 */
Neil Armstrong0d763412022-08-11 10:32:22 +0200312static int ecjpake_zkp_write( const mbedtls_md_type_t md_type,
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200313 const mbedtls_ecp_group *grp,
Darryl Green11999bb2018-03-13 15:22:58 +0000314 const int pf,
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200315 const mbedtls_ecp_point *G,
316 const mbedtls_mpi *x,
317 const mbedtls_ecp_point *X,
318 const char *id,
319 unsigned char **p,
320 const unsigned char *end,
321 int (*f_rng)(void *, unsigned char *, size_t),
322 void *p_rng )
323{
Janos Follath24eed8d2019-11-22 13:21:35 +0000324 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200325 mbedtls_ecp_point V;
326 mbedtls_mpi v;
327 mbedtls_mpi h; /* later recycled to hold r */
328 size_t len;
329
330 if( end < *p )
331 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
332
333 mbedtls_ecp_point_init( &V );
334 mbedtls_mpi_init( &v );
335 mbedtls_mpi_init( &h );
336
337 /* Compute signature */
338 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp,
339 G, &v, &V, f_rng, p_rng ) );
Neil Armstrong0d763412022-08-11 10:32:22 +0200340 MBEDTLS_MPI_CHK( ecjpake_hash( md_type, grp, pf, G, &V, X, id, &h ) );
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200341 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &h, &h, x ) ); /* x*h */
342 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &h, &v, &h ) ); /* v - x*h */
343 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &h, &h, &grp->N ) ); /* r */
344
345 /* Write it out */
346 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, &V,
Robert Cragie7cdad772015-10-02 13:31:41 +0100347 pf, &len, *p, end - *p ) );
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200348 *p += len;
349
350 len = mbedtls_mpi_size( &h ); /* actually r */
351 if( end < *p || (size_t)( end - *p ) < 1 + len || len > 255 )
352 {
353 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
354 goto cleanup;
355 }
356
Joe Subbiani2194dc42021-07-14 12:31:31 +0100357 *(*p)++ = MBEDTLS_BYTE_0( len );
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200358 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, *p, len ) ); /* r */
359 *p += len;
360
361cleanup:
362 mbedtls_ecp_point_free( &V );
363 mbedtls_mpi_free( &v );
364 mbedtls_mpi_free( &h );
365
366 return( ret );
367}
368
369/*
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200370 * Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof
371 * Output: verified public key X
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200372 */
Neil Armstrong0d763412022-08-11 10:32:22 +0200373static int ecjpake_kkp_read( const mbedtls_md_type_t md_type,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200374 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100375 const int pf,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200376 const mbedtls_ecp_point *G,
377 mbedtls_ecp_point *X,
378 const char *id,
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200379 const unsigned char **p,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200380 const unsigned char *end )
381{
Janos Follath24eed8d2019-11-22 13:21:35 +0000382 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200383
384 if( end < *p )
385 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
386
387 /*
388 * struct {
389 * ECPoint X;
390 * ECSchnorrZKP zkp;
391 * } ECJPAKEKeyKP;
392 */
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200393 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, X, p, end - *p ) );
Manuel Pégourié-Gonnard30590952015-08-17 10:37:40 +0200394 if( mbedtls_ecp_is_zero( X ) )
395 {
396 ret = MBEDTLS_ERR_ECP_INVALID_KEY;
397 goto cleanup;
398 }
399
Neil Armstrong0d763412022-08-11 10:32:22 +0200400 MBEDTLS_MPI_CHK( ecjpake_zkp_read( md_type, grp, pf, G, X, id, p, end ) );
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200401
402cleanup:
403 return( ret );
404}
405
406/*
407 * Generate an ECJPAKEKeyKP
408 * Output: the serialized structure, plus private/public key pair
409 */
Neil Armstrong0d763412022-08-11 10:32:22 +0200410static int ecjpake_kkp_write( const mbedtls_md_type_t md_type,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200411 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100412 const int pf,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200413 const mbedtls_ecp_point *G,
414 mbedtls_mpi *x,
415 mbedtls_ecp_point *X,
416 const char *id,
417 unsigned char **p,
418 const unsigned char *end,
419 int (*f_rng)(void *, unsigned char *, size_t),
420 void *p_rng )
421{
Janos Follath24eed8d2019-11-22 13:21:35 +0000422 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200423 size_t len;
424
425 if( end < *p )
426 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
427
428 /* Generate key (7.4.2.3.1) and write it out */
429 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp, G, x, X,
430 f_rng, p_rng ) );
431 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, X,
Robert Cragie7cdad772015-10-02 13:31:41 +0100432 pf, &len, *p, end - *p ) );
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200433 *p += len;
434
435 /* Generate and write proof */
Neil Armstrong0d763412022-08-11 10:32:22 +0200436 MBEDTLS_MPI_CHK( ecjpake_zkp_write( md_type, grp, pf, G, x, X, id,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200437 p, end, f_rng, p_rng ) );
438
439cleanup:
440 return( ret );
441}
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200442
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200443/*
444 * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs
Shaun Case8b0ecbc2021-12-20 21:14:10 -0800445 * Outputs: verified peer public keys Xa, Xb
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200446 */
Neil Armstrong0d763412022-08-11 10:32:22 +0200447static int ecjpake_kkpp_read( const mbedtls_md_type_t md_type,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200448 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100449 const int pf,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200450 const mbedtls_ecp_point *G,
451 mbedtls_ecp_point *Xa,
452 mbedtls_ecp_point *Xb,
453 const char *id,
454 const unsigned char *buf,
455 size_t len )
456{
Janos Follath24eed8d2019-11-22 13:21:35 +0000457 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200458 const unsigned char *p = buf;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200459 const unsigned char *end = buf + len;
460
461 /*
462 * struct {
463 * ECJPAKEKeyKP ecjpake_key_kp_pair_list[2];
464 * } ECJPAKEKeyKPPairList;
465 */
Neil Armstrong0d763412022-08-11 10:32:22 +0200466 MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_type, grp, pf, G, Xa, id, &p, end ) );
467 MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_type, grp, pf, G, Xb, id, &p, end ) );
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200468
469 if( p != end )
470 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
471
472cleanup:
473 return( ret );
474}
475
476/*
477 * Generate a ECJPAKEKeyKPPairList
478 * Outputs: the serialized structure, plus two private/public key pairs
479 */
Neil Armstrong0d763412022-08-11 10:32:22 +0200480static int ecjpake_kkpp_write( const mbedtls_md_type_t md_type,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200481 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100482 const int pf,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200483 const mbedtls_ecp_point *G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200484 mbedtls_mpi *xm1,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200485 mbedtls_ecp_point *Xa,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200486 mbedtls_mpi *xm2,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200487 mbedtls_ecp_point *Xb,
488 const char *id,
489 unsigned char *buf,
490 size_t len,
491 size_t *olen,
492 int (*f_rng)(void *, unsigned char *, size_t),
493 void *p_rng )
494{
Janos Follath24eed8d2019-11-22 13:21:35 +0000495 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200496 unsigned char *p = buf;
497 const unsigned char *end = buf + len;
498
Neil Armstrong0d763412022-08-11 10:32:22 +0200499 MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_type, grp, pf, G, xm1, Xa, id,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200500 &p, end, f_rng, p_rng ) );
Neil Armstrong0d763412022-08-11 10:32:22 +0200501 MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_type, grp, pf, G, xm2, Xb, id,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200502 &p, end, f_rng, p_rng ) );
503
504 *olen = p - buf;
505
506cleanup:
507 return( ret );
508}
509
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200510/*
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200511 * Read and process the first round message
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200512 */
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200513int mbedtls_ecjpake_read_round_one( mbedtls_ecjpake_context *ctx,
514 const unsigned char *buf,
515 size_t len )
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200516{
Neil Armstrong0d763412022-08-11 10:32:22 +0200517 return( ecjpake_kkpp_read( ctx->md_type, &ctx->grp, ctx->point_format,
Robert Cragie7cdad772015-10-02 13:31:41 +0100518 &ctx->grp.G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200519 &ctx->Xp1, &ctx->Xp2, ID_PEER,
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200520 buf, len ) );
521}
522
523/*
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200524 * Generate and write the first round message
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200525 */
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200526int mbedtls_ecjpake_write_round_one( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200527 unsigned char *buf, size_t len, size_t *olen,
528 int (*f_rng)(void *, unsigned char *, size_t),
529 void *p_rng )
530{
Neil Armstrong0d763412022-08-11 10:32:22 +0200531 return( ecjpake_kkpp_write( ctx->md_type, &ctx->grp, ctx->point_format,
Robert Cragie7cdad772015-10-02 13:31:41 +0100532 &ctx->grp.G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200533 &ctx->xm1, &ctx->Xm1, &ctx->xm2, &ctx->Xm2,
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200534 ID_MINE, buf, len, olen, f_rng, p_rng ) );
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200535}
536
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200537/*
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200538 * Compute the sum of three points R = A + B + C
539 */
540static int ecjpake_ecp_add3( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
541 const mbedtls_ecp_point *A,
542 const mbedtls_ecp_point *B,
543 const mbedtls_ecp_point *C )
544{
Janos Follath24eed8d2019-11-22 13:21:35 +0000545 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200546 mbedtls_mpi one;
547
548 mbedtls_mpi_init( &one );
549
550 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
551 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, A, &one, B ) );
552 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, R, &one, C ) );
553
554cleanup:
555 mbedtls_mpi_free( &one );
556
557 return( ret );
558}
559
560/*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200561 * 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 +0200562 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200563int mbedtls_ecjpake_read_round_two( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200564 const unsigned char *buf,
565 size_t len )
566{
Janos Follath24eed8d2019-11-22 13:21:35 +0000567 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200568 const unsigned char *p = buf;
569 const unsigned char *end = buf + len;
570 mbedtls_ecp_group grp;
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200571 mbedtls_ecp_point G; /* C: GB, S: GA */
Hanno Becker185e5162018-12-19 09:48:50 +0000572
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200573 mbedtls_ecp_group_init( &grp );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200574 mbedtls_ecp_point_init( &G );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200575
576 /*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200577 * Server: GA = X3 + X4 + X1 (7.4.2.6.1)
578 * Client: GB = X1 + X2 + X3 (7.4.2.5.1)
579 * Unified: G = Xm1 + Xm2 + Xp1
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200580 * We need that before parsing in order to check Xp as we read it
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200581 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200582 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200583 &ctx->Xm1, &ctx->Xm2, &ctx->Xp1 ) );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200584
585 /*
586 * struct {
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200587 * ECParameters curve_params; // only client reading server msg
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200588 * ECJPAKEKeyKP ecjpake_key_kp;
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200589 * } Client/ServerECJPAKEParams;
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200590 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200591 if( ctx->role == MBEDTLS_ECJPAKE_CLIENT )
Manuel Pégourié-Gonnardd9802af2015-08-17 12:47:38 +0200592 {
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200593 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_group( &grp, &p, len ) );
Manuel Pégourié-Gonnardd9802af2015-08-17 12:47:38 +0200594 if( grp.id != ctx->grp.id )
595 {
596 ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
597 goto cleanup;
598 }
599 }
600
Neil Armstrong0d763412022-08-11 10:32:22 +0200601 MBEDTLS_MPI_CHK( ecjpake_kkp_read( ctx->md_type, &ctx->grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100602 ctx->point_format,
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200603 &G, &ctx->Xp, ID_PEER, &p, end ) );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200604
605 if( p != end )
606 {
607 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
608 goto cleanup;
609 }
610
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200611cleanup:
612 mbedtls_ecp_group_free( &grp );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200613 mbedtls_ecp_point_free( &G );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200614
615 return( ret );
616}
617
618/*
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200619 * Compute R = +/- X * S mod N, taking care not to leak S
620 */
621static int ecjpake_mul_secret( mbedtls_mpi *R, int sign,
622 const mbedtls_mpi *X,
623 const mbedtls_mpi *S,
624 const mbedtls_mpi *N,
625 int (*f_rng)(void *, unsigned char *, size_t),
626 void *p_rng )
627{
Janos Follath24eed8d2019-11-22 13:21:35 +0000628 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200629 mbedtls_mpi b; /* Blinding value, then s + N * blinding */
630
631 mbedtls_mpi_init( &b );
632
633 /* b = s + rnd-128-bit * N */
634 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &b, 16, f_rng, p_rng ) );
635 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &b, &b, N ) );
636 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &b, &b, S ) );
637
638 /* R = sign * X * b mod N */
639 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( R, X, &b ) );
640 R->s *= sign;
641 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( R, R, N ) );
642
643cleanup:
644 mbedtls_mpi_free( &b );
645
646 return( ret );
647}
648
649/*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200650 * 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 +0200651 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200652int mbedtls_ecjpake_write_round_two( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200653 unsigned char *buf, size_t len, size_t *olen,
654 int (*f_rng)(void *, unsigned char *, size_t),
655 void *p_rng )
656{
Janos Follath24eed8d2019-11-22 13:21:35 +0000657 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200658 mbedtls_ecp_point G; /* C: GA, S: GB */
659 mbedtls_ecp_point Xm; /* C: Xc, S: Xs */
660 mbedtls_mpi xm; /* C: xc, S: xs */
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200661 unsigned char *p = buf;
662 const unsigned char *end = buf + len;
663 size_t ec_len;
Hanno Becker185e5162018-12-19 09:48:50 +0000664
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200665 mbedtls_ecp_point_init( &G );
666 mbedtls_ecp_point_init( &Xm );
667 mbedtls_mpi_init( &xm );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200668
669 /*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200670 * 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 +0200671 *
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200672 * Client: GA = X1 + X3 + X4 | xs = x2 * s | Xc = xc * GA
673 * Server: GB = X3 + X1 + X2 | xs = x4 * s | Xs = xs * GB
674 * Unified: G = Xm1 + Xp1 + Xp2 | xm = xm2 * s | Xm = xm * G
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200675 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200676 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200677 &ctx->Xp1, &ctx->Xp2, &ctx->Xm1 ) );
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200678 MBEDTLS_MPI_CHK( ecjpake_mul_secret( &xm, 1, &ctx->xm2, &ctx->s,
679 &ctx->grp.N, f_rng, p_rng ) );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200680 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &Xm, &xm, &G, f_rng, p_rng ) );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200681
682 /*
683 * Now write things out
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200684 *
685 * struct {
686 * ECParameters curve_params; // only server writing its message
687 * ECJPAKEKeyKP ecjpake_key_kp;
688 * } Client/ServerECJPAKEParams;
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200689 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200690 if( ctx->role == MBEDTLS_ECJPAKE_SERVER )
691 {
692 if( end < p )
693 {
694 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
695 goto cleanup;
696 }
697 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_group( &ctx->grp, &ec_len,
698 p, end - p ) );
699 p += ec_len;
700 }
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200701
702 if( end < p )
703 {
704 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
705 goto cleanup;
706 }
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200707 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( &ctx->grp, &Xm,
Robert Cragie7cdad772015-10-02 13:31:41 +0100708 ctx->point_format, &ec_len, p, end - p ) );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200709 p += ec_len;
710
Neil Armstrong0d763412022-08-11 10:32:22 +0200711 MBEDTLS_MPI_CHK( ecjpake_zkp_write( ctx->md_type, &ctx->grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100712 ctx->point_format,
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200713 &G, &xm, &Xm, ID_MINE,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200714 &p, end, f_rng, p_rng ) );
715
716 *olen = p - buf;
717
718cleanup:
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200719 mbedtls_ecp_point_free( &G );
720 mbedtls_ecp_point_free( &Xm );
721 mbedtls_mpi_free( &xm );
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +0200722
723 return( ret );
724}
725
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200726/*
727 * Derive PMS (7.4.2.7 / 7.4.2.8)
728 */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +0200729int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200730 unsigned char *buf, size_t len, size_t *olen,
731 int (*f_rng)(void *, unsigned char *, size_t),
732 void *p_rng )
733{
Janos Follath24eed8d2019-11-22 13:21:35 +0000734 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200735 mbedtls_ecp_point K;
736 mbedtls_mpi m_xm2_s, one;
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200737 unsigned char kx[MBEDTLS_ECP_MAX_BYTES];
738 size_t x_bytes;
Hanno Becker185e5162018-12-19 09:48:50 +0000739
Neil Armstrong0d763412022-08-11 10:32:22 +0200740 *olen = mbedtls_hash_info_get_size( ctx->md_type );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200741 if( len < *olen )
742 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
743
744 mbedtls_ecp_point_init( &K );
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200745 mbedtls_mpi_init( &m_xm2_s );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200746 mbedtls_mpi_init( &one );
747
748 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200749
750 /*
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200751 * Client: K = ( Xs - X4 * x2 * s ) * x2
752 * Server: K = ( Xc - X2 * x4 * s ) * x4
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200753 * Unified: K = ( Xp - Xp2 * xm2 * s ) * xm2
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200754 */
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200755 MBEDTLS_MPI_CHK( ecjpake_mul_secret( &m_xm2_s, -1, &ctx->xm2, &ctx->s,
756 &ctx->grp.N, f_rng, p_rng ) );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200757 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( &ctx->grp, &K,
758 &one, &ctx->Xp,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200759 &m_xm2_s, &ctx->Xp2 ) );
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200760 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &K, &ctx->xm2, &K,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200761 f_rng, p_rng ) );
762
763 /* PMS = SHA-256( K.X ) */
764 x_bytes = ( ctx->grp.pbits + 7 ) / 8;
765 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &K.X, kx, x_bytes ) );
Neil Armstrong0d763412022-08-11 10:32:22 +0200766 MBEDTLS_MPI_CHK( mbedtls_md( mbedtls_md_info_from_type( ctx->md_type ),
767 kx, x_bytes, buf ) );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200768
769cleanup:
770 mbedtls_ecp_point_free( &K );
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200771 mbedtls_mpi_free( &m_xm2_s );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200772 mbedtls_mpi_free( &one );
773
774 return( ret );
775}
776
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200777#undef ID_MINE
778#undef ID_PEER
779
Hanno Becker616d1ca2018-01-24 10:25:05 +0000780#endif /* ! MBEDTLS_ECJPAKE_ALT */
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200781
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200782#if defined(MBEDTLS_SELF_TEST)
783
784#if defined(MBEDTLS_PLATFORM_C)
785#include "mbedtls/platform.h"
786#else
787#include <stdio.h>
788#define mbedtls_printf printf
789#endif
790
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200791#if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
792 !defined(MBEDTLS_SHA256_C)
793int mbedtls_ecjpake_self_test( int verbose )
794{
795 (void) verbose;
796 return( 0 );
797}
798#else
799
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200800static const unsigned char ecjpake_test_password[] = {
801 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x6a, 0x70, 0x61, 0x6b, 0x65, 0x74,
802 0x65, 0x73, 0x74
803};
804
Steven Cooreman64f27732021-01-11 17:20:10 +0100805#if !defined(MBEDTLS_ECJPAKE_ALT)
806
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200807static const unsigned char ecjpake_test_x1[] = {
808 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
809 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
810 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21
811};
812
813static const unsigned char ecjpake_test_x2[] = {
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_x3[] = {
820 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
821 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
822 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
823};
824
825static const unsigned char ecjpake_test_x4[] = {
826 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc,
827 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
828 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1
829};
830
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200831static const unsigned char ecjpake_test_cli_one[] = {
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200832 0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19,
833 0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44,
834 0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad,
835 0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62,
836 0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9,
837 0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d,
838 0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e,
839 0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e,
840 0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73,
841 0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22,
842 0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce,
843 0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00,
844 0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200845 0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e,
846 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62,
847 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5,
848 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb,
849 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35,
850 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0,
851 0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb,
852 0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47,
853 0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39,
854 0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97,
855 0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40,
856 0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d,
857 0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa,
858 0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d,
859 0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200860};
861
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200862static const unsigned char ecjpake_test_srv_one[] = {
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200863 0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb,
864 0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18,
865 0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47,
866 0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f,
867 0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7,
868 0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d,
869 0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64,
870 0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36,
871 0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2,
872 0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec,
873 0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16,
874 0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96,
875 0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3,
876 0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19,
877 0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f,
878 0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8,
879 0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7,
880 0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea,
881 0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5,
882 0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6,
883 0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31,
884 0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d,
885 0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8,
886 0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee,
887 0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84,
888 0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f,
889 0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80,
890 0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12
891};
892
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200893static const unsigned char ecjpake_test_srv_two[] = {
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200894 0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23,
895 0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c,
896 0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f,
897 0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca,
898 0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26,
899 0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55,
900 0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38,
901 0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6,
902 0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9,
903 0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4,
904 0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2,
905 0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8,
906 0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd,
907 0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c
908};
909
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200910static const unsigned char ecjpake_test_cli_two[] = {
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +0200911 0x41, 0x04, 0x69, 0xd5, 0x4e, 0xe8, 0x5e, 0x90, 0xce, 0x3f, 0x12, 0x46,
912 0x74, 0x2d, 0xe5, 0x07, 0xe9, 0x39, 0xe8, 0x1d, 0x1d, 0xc1, 0xc5, 0xcb,
913 0x98, 0x8b, 0x58, 0xc3, 0x10, 0xc9, 0xfd, 0xd9, 0x52, 0x4d, 0x93, 0x72,
914 0x0b, 0x45, 0x54, 0x1c, 0x83, 0xee, 0x88, 0x41, 0x19, 0x1d, 0xa7, 0xce,
915 0xd8, 0x6e, 0x33, 0x12, 0xd4, 0x36, 0x23, 0xc1, 0xd6, 0x3e, 0x74, 0x98,
916 0x9a, 0xba, 0x4a, 0xff, 0xd1, 0xee, 0x41, 0x04, 0x07, 0x7e, 0x8c, 0x31,
917 0xe2, 0x0e, 0x6b, 0xed, 0xb7, 0x60, 0xc1, 0x35, 0x93, 0xe6, 0x9f, 0x15,
918 0xbe, 0x85, 0xc2, 0x7d, 0x68, 0xcd, 0x09, 0xcc, 0xb8, 0xc4, 0x18, 0x36,
919 0x08, 0x91, 0x7c, 0x5c, 0x3d, 0x40, 0x9f, 0xac, 0x39, 0xfe, 0xfe, 0xe8,
920 0x2f, 0x72, 0x92, 0xd3, 0x6f, 0x0d, 0x23, 0xe0, 0x55, 0x91, 0x3f, 0x45,
921 0xa5, 0x2b, 0x85, 0xdd, 0x8a, 0x20, 0x52, 0xe9, 0xe1, 0x29, 0xbb, 0x4d,
922 0x20, 0x0f, 0x01, 0x1f, 0x19, 0x48, 0x35, 0x35, 0xa6, 0xe8, 0x9a, 0x58,
923 0x0c, 0x9b, 0x00, 0x03, 0xba, 0xf2, 0x14, 0x62, 0xec, 0xe9, 0x1a, 0x82,
924 0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c
925};
926
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200927static const unsigned char ecjpake_test_pms[] = {
928 0xf3, 0xd4, 0x7f, 0x59, 0x98, 0x44, 0xdb, 0x92, 0xa5, 0x69, 0xbb, 0xe7,
929 0x98, 0x1e, 0x39, 0xd9, 0x31, 0xfd, 0x74, 0x3b, 0xf2, 0x2e, 0x98, 0xf9,
930 0xb4, 0x38, 0xf7, 0x19, 0xd3, 0xc4, 0xf3, 0x51
931};
932
Manuel Pégourié-Gonnardaa3ed6f2021-06-15 11:29:26 +0200933/*
934 * PRNG for test - !!!INSECURE NEVER USE IN PRODUCTION!!!
935 *
936 * This is the linear congruential generator from numerical recipes,
937 * except we only use the low byte as the output. See
938 * https://en.wikipedia.org/wiki/Linear_congruential_generator#Parameters_in_common_use
939 */
940static int self_test_rng( void *ctx, unsigned char *out, size_t len )
941{
942 static uint32_t state = 42;
943
944 (void) ctx;
945
946 for( size_t i = 0; i < len; i++ )
947 {
948 state = state * 1664525u + 1013904223u;
949 out[i] = (unsigned char) state;
950 }
951
952 return( 0 );
953}
954
Antonin Décimo36e89b52019-01-23 15:24:37 +0100955/* Load my private keys and generate the corresponding public keys */
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +0200956static int ecjpake_test_load( mbedtls_ecjpake_context *ctx,
957 const unsigned char *xm1, size_t len1,
958 const unsigned char *xm2, size_t len2 )
959{
Janos Follath24eed8d2019-11-22 13:21:35 +0000960 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +0200961
962 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm1, xm1, len1 ) );
963 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm2, xm2, len2 ) );
964 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm1, &ctx->xm1,
Manuel Pégourié-Gonnardaa3ed6f2021-06-15 11:29:26 +0200965 &ctx->grp.G, self_test_rng, NULL ) );
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +0200966 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm2, &ctx->xm2,
Manuel Pégourié-Gonnardaa3ed6f2021-06-15 11:29:26 +0200967 &ctx->grp.G, self_test_rng, NULL ) );
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +0200968
969cleanup:
970 return( ret );
971}
972
Steven Cooreman64f27732021-01-11 17:20:10 +0100973#endif /* ! MBEDTLS_ECJPAKE_ALT */
974
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200975/* For tests we don't need a secure RNG;
976 * use the LGC from Numerical Recipes for simplicity */
977static int ecjpake_lgc( void *p, unsigned char *out, size_t len )
978{
979 static uint32_t x = 42;
980 (void) p;
981
982 while( len > 0 )
983 {
984 size_t use_len = len > 4 ? 4 : len;
985 x = 1664525 * x + 1013904223;
986 memcpy( out, &x, use_len );
987 out += use_len;
988 len -= use_len;
989 }
990
991 return( 0 );
992}
993
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200994#define TEST_ASSERT( x ) \
995 do { \
996 if( x ) \
997 ret = 0; \
998 else \
999 { \
1000 ret = 1; \
1001 goto cleanup; \
1002 } \
1003 } while( 0 )
1004
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001005/*
1006 * Checkup routine
1007 */
1008int mbedtls_ecjpake_self_test( int verbose )
1009{
Janos Follath24eed8d2019-11-22 13:21:35 +00001010 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001011 mbedtls_ecjpake_context cli;
1012 mbedtls_ecjpake_context srv;
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001013 unsigned char buf[512], pms[32];
1014 size_t len, pmslen;
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001015
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001016 mbedtls_ecjpake_init( &cli );
1017 mbedtls_ecjpake_init( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001018
1019 if( verbose != 0 )
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001020 mbedtls_printf( " ECJPAKE test #0 (setup): " );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +02001021
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +02001022 TEST_ASSERT( mbedtls_ecjpake_setup( &cli, MBEDTLS_ECJPAKE_CLIENT,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001023 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1024 ecjpake_test_password,
1025 sizeof( ecjpake_test_password ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001026
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +02001027 TEST_ASSERT( mbedtls_ecjpake_setup( &srv, MBEDTLS_ECJPAKE_SERVER,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001028 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1029 ecjpake_test_password,
1030 sizeof( ecjpake_test_password ) ) == 0 );
1031
1032 if( verbose != 0 )
1033 mbedtls_printf( "passed\n" );
1034
1035 if( verbose != 0 )
1036 mbedtls_printf( " ECJPAKE test #1 (random handshake): " );
1037
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001038 TEST_ASSERT( mbedtls_ecjpake_write_round_one( &cli,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001039 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1040
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001041 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv, buf, len ) == 0 );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001042
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001043 TEST_ASSERT( mbedtls_ecjpake_write_round_one( &srv,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001044 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1045
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001046 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli, buf, len ) == 0 );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001047
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001048 TEST_ASSERT( mbedtls_ecjpake_write_round_two( &srv,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +02001049 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1050
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001051 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli, buf, len ) == 0 );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +02001052
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001053 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001054 pms, sizeof( pms ), &pmslen, ecjpake_lgc, NULL ) == 0 );
1055
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001056 TEST_ASSERT( mbedtls_ecjpake_write_round_two( &cli,
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +02001057 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1058
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001059 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv, buf, len ) == 0 );
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +02001060
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001061 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001062 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1063
1064 TEST_ASSERT( len == pmslen );
1065 TEST_ASSERT( memcmp( buf, pms, len ) == 0 );
1066
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001067 if( verbose != 0 )
1068 mbedtls_printf( "passed\n" );
1069
Steven Cooreman64f27732021-01-11 17:20:10 +01001070#if !defined(MBEDTLS_ECJPAKE_ALT)
1071 /* 'reference handshake' tests can only be run against implementations
1072 * for which we have 100% control over how the random ephemeral keys
1073 * are generated. This is only the case for the internal mbed TLS
1074 * implementation, so these tests are skipped in case the internal
1075 * implementation is swapped out for an alternative one. */
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001076 if( verbose != 0 )
1077 mbedtls_printf( " ECJPAKE test #2 (reference handshake): " );
1078
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001079 /* Simulate generation of round one */
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001080 MBEDTLS_MPI_CHK( ecjpake_test_load( &cli,
1081 ecjpake_test_x1, sizeof( ecjpake_test_x1 ),
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001082 ecjpake_test_x2, sizeof( ecjpake_test_x2 ) ) );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001083
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001084 MBEDTLS_MPI_CHK( ecjpake_test_load( &srv,
1085 ecjpake_test_x3, sizeof( ecjpake_test_x3 ),
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001086 ecjpake_test_x4, sizeof( ecjpake_test_x4 ) ) );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001087
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001088 /* Read round one */
1089 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv,
1090 ecjpake_test_cli_one,
1091 sizeof( ecjpake_test_cli_one ) ) == 0 );
1092
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001093 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001094 ecjpake_test_srv_one,
1095 sizeof( ecjpake_test_srv_one ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001096
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001097 /* Skip generation of round two, read round two */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001098 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001099 ecjpake_test_srv_two,
1100 sizeof( ecjpake_test_srv_two ) ) == 0 );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +02001101
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001102 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001103 ecjpake_test_cli_two,
1104 sizeof( ecjpake_test_cli_two ) ) == 0 );
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +02001105
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001106 /* Server derives PMS */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001107 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv,
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
1113 memset( buf, 0, len ); /* Avoid interferences with next step */
1114
1115 /* Client derives PMS */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001116 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001117 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1118
1119 TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
1120 TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
1121
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001122 if( verbose != 0 )
1123 mbedtls_printf( "passed\n" );
Steven Cooreman64f27732021-01-11 17:20:10 +01001124#endif /* ! MBEDTLS_ECJPAKE_ALT */
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001125
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001126cleanup:
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001127 mbedtls_ecjpake_free( &cli );
1128 mbedtls_ecjpake_free( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001129
1130 if( ret != 0 )
1131 {
1132 if( verbose != 0 )
1133 mbedtls_printf( "failed\n" );
1134
1135 ret = 1;
1136 }
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001137
1138 if( verbose != 0 )
1139 mbedtls_printf( "\n" );
1140
1141 return( ret );
1142}
1143
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +02001144#undef TEST_ASSERT
1145
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001146#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_SHA256_C */
1147
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001148#endif /* MBEDTLS_SELF_TEST */
1149
1150#endif /* MBEDTLS_ECJPAKE_C */