blob: d467a6540afbd7ce8f73fe0db55df45b5dd35008 [file] [log] [blame]
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001/*
2 * Elliptic curve J-PAKE
3 *
Bence Szépkúti1e148272020-08-07 13:07:28 +02004 * Copyright The Mbed TLS Contributors
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +020018 */
19
20/*
Manuel Pégourié-Gonnard6b798b92015-08-14 11:18:30 +020021 * References in the code are to the Thread v1.0 Specification,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +020022 * available to members of the Thread Group http://threadgroup.org/
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +020023 */
24
Gilles Peskinedb09ef62020-06-03 01:43:33 +020025#include "common.h"
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +020026
27#if defined(MBEDTLS_ECJPAKE_C)
28
29#include "mbedtls/ecjpake.h"
Hanno Becker71c8e1b2018-12-14 17:09:39 +000030#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000031#include "mbedtls/error.h"
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +020032
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +020033#include <string.h>
34
Hanno Becker616d1ca2018-01-24 10:25:05 +000035#if !defined(MBEDTLS_ECJPAKE_ALT)
36
Hanno Becker71c8e1b2018-12-14 17:09:39 +000037/* Parameter validation macros based on platform_util.h */
38#define ECJPAKE_VALIDATE_RET( cond ) \
39 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA )
40#define ECJPAKE_VALIDATE( cond ) \
41 MBEDTLS_INTERNAL_VALIDATE( cond )
42
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +020043/*
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +020044 * Convert a mbedtls_ecjpake_role to identifier string
45 */
46static const char * const ecjpake_id[] = {
47 "client",
48 "server"
49};
50
51#define ID_MINE ( ecjpake_id[ ctx->role ] )
52#define ID_PEER ( ecjpake_id[ 1 - ctx->role ] )
53
54/*
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020055 * Initialize context
56 */
57void mbedtls_ecjpake_init( mbedtls_ecjpake_context *ctx )
58{
Hanno Becker71c8e1b2018-12-14 17:09:39 +000059 ECJPAKE_VALIDATE( ctx != NULL );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020060
61 ctx->md_info = NULL;
62 mbedtls_ecp_group_init( &ctx->grp );
Manuel Pégourié-Gonnardb7da1942015-10-19 13:35:22 +020063 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020064
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +020065 mbedtls_ecp_point_init( &ctx->Xm1 );
66 mbedtls_ecp_point_init( &ctx->Xm2 );
67 mbedtls_ecp_point_init( &ctx->Xp1 );
68 mbedtls_ecp_point_init( &ctx->Xp2 );
69 mbedtls_ecp_point_init( &ctx->Xp );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020070
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +020071 mbedtls_mpi_init( &ctx->xm1 );
72 mbedtls_mpi_init( &ctx->xm2 );
73 mbedtls_mpi_init( &ctx->s );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020074}
75
76/*
77 * Free context
78 */
79void mbedtls_ecjpake_free( mbedtls_ecjpake_context *ctx )
80{
81 if( ctx == NULL )
82 return;
83
84 ctx->md_info = NULL;
85 mbedtls_ecp_group_free( &ctx->grp );
86
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +020087 mbedtls_ecp_point_free( &ctx->Xm1 );
88 mbedtls_ecp_point_free( &ctx->Xm2 );
89 mbedtls_ecp_point_free( &ctx->Xp1 );
90 mbedtls_ecp_point_free( &ctx->Xp2 );
91 mbedtls_ecp_point_free( &ctx->Xp );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020092
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +020093 mbedtls_mpi_free( &ctx->xm1 );
94 mbedtls_mpi_free( &ctx->xm2 );
95 mbedtls_mpi_free( &ctx->s );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020096}
97
98/*
99 * Setup context
100 */
101int mbedtls_ecjpake_setup( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +0200102 mbedtls_ecjpake_role role,
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200103 mbedtls_md_type_t hash,
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200104 mbedtls_ecp_group_id curve,
105 const unsigned char *secret,
106 size_t len )
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200107{
Janos Follath24eed8d2019-11-22 13:21:35 +0000108 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker185e5162018-12-19 09:48:50 +0000109
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000110 ECJPAKE_VALIDATE_RET( ctx != NULL );
111 ECJPAKE_VALIDATE_RET( role == MBEDTLS_ECJPAKE_CLIENT ||
112 role == MBEDTLS_ECJPAKE_SERVER );
113 ECJPAKE_VALIDATE_RET( secret != NULL || len == 0 );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200114
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +0200115 ctx->role = role;
116
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200117 if( ( ctx->md_info = mbedtls_md_info_from_type( hash ) ) == NULL )
118 return( MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE );
119
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200120 MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ctx->grp, curve ) );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200121
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200122 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->s, secret, len ) );
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200123
124cleanup:
125 if( ret != 0 )
126 mbedtls_ecjpake_free( ctx );
127
128 return( ret );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200129}
130
Gilles Peskinecd07e222021-05-27 23:17:34 +0200131int mbedtls_ecjpake_set_point_format( mbedtls_ecjpake_context *ctx,
132 int point_format )
133{
134 switch( point_format )
135 {
136 case MBEDTLS_ECP_PF_UNCOMPRESSED:
137 case MBEDTLS_ECP_PF_COMPRESSED:
138 ctx->point_format = point_format;
139 return( 0 );
140 default:
141 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
142 }
143}
144
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200145/*
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200146 * Check if context is ready for use
147 */
148int mbedtls_ecjpake_check( const mbedtls_ecjpake_context *ctx )
149{
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000150 ECJPAKE_VALIDATE_RET( ctx != NULL );
151
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200152 if( ctx->md_info == NULL ||
153 ctx->grp.id == MBEDTLS_ECP_DP_NONE ||
154 ctx->s.p == NULL )
155 {
156 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
157 }
158
159 return( 0 );
160}
161
162/*
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200163 * Write a point plus its length to a buffer
164 */
165static int ecjpake_write_len_point( unsigned char **p,
166 const unsigned char *end,
167 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100168 const int pf,
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200169 const mbedtls_ecp_point *P )
170{
Janos Follath24eed8d2019-11-22 13:21:35 +0000171 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200172 size_t len;
173
174 /* Need at least 4 for length plus 1 for point */
175 if( end < *p || end - *p < 5 )
176 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
177
Robert Cragie7cdad772015-10-02 13:31:41 +0100178 ret = mbedtls_ecp_point_write_binary( grp, P, pf,
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200179 &len, *p + 4, end - ( *p + 4 ) );
180 if( ret != 0 )
181 return( ret );
182
Joe Subbiania5cb0d22021-08-23 11:35:25 +0100183 MBEDTLS_PUT_UINT32_BE( len, *p, 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200184
185 *p += 4 + len;
186
187 return( 0 );
188}
189
190/*
191 * Size of the temporary buffer for ecjpake_hash:
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200192 * 3 EC points plus their length, plus ID and its length (4 + 6 bytes)
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200193 */
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200194#define ECJPAKE_HASH_BUF_LEN ( 3 * ( 4 + MBEDTLS_ECP_MAX_PT_LEN ) + 4 + 6 )
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200195
196/*
197 * Compute hash for ZKP (7.4.2.2.2.1)
198 */
199static int ecjpake_hash( const mbedtls_md_info_t *md_info,
200 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100201 const int pf,
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200202 const mbedtls_ecp_point *G,
203 const mbedtls_ecp_point *V,
204 const mbedtls_ecp_point *X,
205 const char *id,
206 mbedtls_mpi *h )
207{
Janos Follath24eed8d2019-11-22 13:21:35 +0000208 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200209 unsigned char buf[ECJPAKE_HASH_BUF_LEN];
210 unsigned char *p = buf;
211 const unsigned char *end = buf + sizeof( buf );
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200212 const size_t id_len = strlen( id );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200213 unsigned char hash[MBEDTLS_MD_MAX_SIZE];
214
215 /* Write things to temporary buffer */
Robert Cragie7cdad772015-10-02 13:31:41 +0100216 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, G ) );
217 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, V ) );
218 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, X ) );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200219
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200220 if( end - p < 4 )
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200221 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
222
Joe Subbiania5cb0d22021-08-23 11:35:25 +0100223 MBEDTLS_PUT_UINT32_BE( id_len, p, 0 );
224 p += 4;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200225
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200226 if( end < p || (size_t)( end - p ) < id_len )
227 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
228
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200229 memcpy( p, id, id_len );
230 p += id_len;
231
232 /* Compute hash */
k-stachowiak41503352019-06-28 14:14:02 +0200233 MBEDTLS_MPI_CHK( mbedtls_md( md_info, buf, p - buf, hash ) );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200234
235 /* Turn it into an integer mod n */
236 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( h, hash,
237 mbedtls_md_get_size( md_info ) ) );
238 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( h, h, &grp->N ) );
239
240cleanup:
241 return( ret );
242}
243
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200244/*
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200245 * Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3)
246 */
247static int ecjpake_zkp_read( const mbedtls_md_info_t *md_info,
248 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100249 const int pf,
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200250 const mbedtls_ecp_point *G,
251 const mbedtls_ecp_point *X,
252 const char *id,
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200253 const unsigned char **p,
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200254 const unsigned char *end )
255{
Janos Follath24eed8d2019-11-22 13:21:35 +0000256 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200257 mbedtls_ecp_point V, VV;
258 mbedtls_mpi r, h;
259 size_t r_len;
260
261 mbedtls_ecp_point_init( &V );
262 mbedtls_ecp_point_init( &VV );
263 mbedtls_mpi_init( &r );
264 mbedtls_mpi_init( &h );
265
266 /*
267 * struct {
268 * ECPoint V;
269 * opaque r<1..2^8-1>;
270 * } ECSchnorrZKP;
271 */
272 if( end < *p )
273 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
274
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200275 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, &V, p, end - *p ) );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200276
277 if( end < *p || (size_t)( end - *p ) < 1 )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200278 {
279 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
280 goto cleanup;
281 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200282
283 r_len = *(*p)++;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200284
TRodziewicz782a7ea2021-03-17 11:35:16 +0100285 if( end < *p || (size_t)( end - *p ) < r_len || r_len == 0 )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200286 {
287 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
288 goto cleanup;
289 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200290
291 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &r, *p, r_len ) );
292 *p += r_len;
293
294 /*
295 * Verification
296 */
Robert Cragie7cdad772015-10-02 13:31:41 +0100297 MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200298 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( (mbedtls_ecp_group *) grp,
299 &VV, &h, X, &r, G ) );
300
301 if( mbedtls_ecp_point_cmp( &VV, &V ) != 0 )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200302 {
303 ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
304 goto cleanup;
305 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200306
307cleanup:
308 mbedtls_ecp_point_free( &V );
309 mbedtls_ecp_point_free( &VV );
310 mbedtls_mpi_free( &r );
311 mbedtls_mpi_free( &h );
312
313 return( ret );
314}
315
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200316/*
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200317 * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2)
318 */
319static int ecjpake_zkp_write( const mbedtls_md_info_t *md_info,
320 const mbedtls_ecp_group *grp,
Darryl Green11999bb2018-03-13 15:22:58 +0000321 const int pf,
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200322 const mbedtls_ecp_point *G,
323 const mbedtls_mpi *x,
324 const mbedtls_ecp_point *X,
325 const char *id,
326 unsigned char **p,
327 const unsigned char *end,
328 int (*f_rng)(void *, unsigned char *, size_t),
329 void *p_rng )
330{
Janos Follath24eed8d2019-11-22 13:21:35 +0000331 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200332 mbedtls_ecp_point V;
333 mbedtls_mpi v;
334 mbedtls_mpi h; /* later recycled to hold r */
335 size_t len;
336
337 if( end < *p )
338 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
339
340 mbedtls_ecp_point_init( &V );
341 mbedtls_mpi_init( &v );
342 mbedtls_mpi_init( &h );
343
344 /* Compute signature */
345 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp,
346 G, &v, &V, f_rng, p_rng ) );
Robert Cragie7cdad772015-10-02 13:31:41 +0100347 MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) );
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200348 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &h, &h, x ) ); /* x*h */
349 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &h, &v, &h ) ); /* v - x*h */
350 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &h, &h, &grp->N ) ); /* r */
351
352 /* Write it out */
353 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, &V,
Robert Cragie7cdad772015-10-02 13:31:41 +0100354 pf, &len, *p, end - *p ) );
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200355 *p += len;
356
357 len = mbedtls_mpi_size( &h ); /* actually r */
358 if( end < *p || (size_t)( end - *p ) < 1 + len || len > 255 )
359 {
360 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
361 goto cleanup;
362 }
363
Joe Subbiani2194dc42021-07-14 12:31:31 +0100364 *(*p)++ = MBEDTLS_BYTE_0( len );
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200365 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, *p, len ) ); /* r */
366 *p += len;
367
368cleanup:
369 mbedtls_ecp_point_free( &V );
370 mbedtls_mpi_free( &v );
371 mbedtls_mpi_free( &h );
372
373 return( ret );
374}
375
376/*
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200377 * Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof
378 * Output: verified public key X
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200379 */
380static int ecjpake_kkp_read( const mbedtls_md_info_t *md_info,
381 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100382 const int pf,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200383 const mbedtls_ecp_point *G,
384 mbedtls_ecp_point *X,
385 const char *id,
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200386 const unsigned char **p,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200387 const unsigned char *end )
388{
Janos Follath24eed8d2019-11-22 13:21:35 +0000389 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200390
391 if( end < *p )
392 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
393
394 /*
395 * struct {
396 * ECPoint X;
397 * ECSchnorrZKP zkp;
398 * } ECJPAKEKeyKP;
399 */
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200400 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, X, p, end - *p ) );
Manuel Pégourié-Gonnard30590952015-08-17 10:37:40 +0200401 if( mbedtls_ecp_is_zero( X ) )
402 {
403 ret = MBEDTLS_ERR_ECP_INVALID_KEY;
404 goto cleanup;
405 }
406
Robert Cragie7cdad772015-10-02 13:31:41 +0100407 MBEDTLS_MPI_CHK( ecjpake_zkp_read( md_info, grp, pf, G, X, id, p, end ) );
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200408
409cleanup:
410 return( ret );
411}
412
413/*
414 * Generate an ECJPAKEKeyKP
415 * Output: the serialized structure, plus private/public key pair
416 */
417static int ecjpake_kkp_write( const mbedtls_md_info_t *md_info,
418 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100419 const int pf,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200420 const mbedtls_ecp_point *G,
421 mbedtls_mpi *x,
422 mbedtls_ecp_point *X,
423 const char *id,
424 unsigned char **p,
425 const unsigned char *end,
426 int (*f_rng)(void *, unsigned char *, size_t),
427 void *p_rng )
428{
Janos Follath24eed8d2019-11-22 13:21:35 +0000429 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200430 size_t len;
431
432 if( end < *p )
433 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
434
435 /* Generate key (7.4.2.3.1) and write it out */
436 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp, G, x, X,
437 f_rng, p_rng ) );
438 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, X,
Robert Cragie7cdad772015-10-02 13:31:41 +0100439 pf, &len, *p, end - *p ) );
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200440 *p += len;
441
442 /* Generate and write proof */
Robert Cragie7cdad772015-10-02 13:31:41 +0100443 MBEDTLS_MPI_CHK( ecjpake_zkp_write( md_info, grp, pf, G, x, X, id,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200444 p, end, f_rng, p_rng ) );
445
446cleanup:
447 return( ret );
448}
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200449
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200450/*
451 * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs
Shaun Case8b0ecbc2021-12-20 21:14:10 -0800452 * Outputs: verified peer public keys Xa, Xb
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200453 */
454static int ecjpake_kkpp_read( const mbedtls_md_info_t *md_info,
455 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100456 const int pf,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200457 const mbedtls_ecp_point *G,
458 mbedtls_ecp_point *Xa,
459 mbedtls_ecp_point *Xb,
460 const char *id,
461 const unsigned char *buf,
462 size_t len )
463{
Janos Follath24eed8d2019-11-22 13:21:35 +0000464 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200465 const unsigned char *p = buf;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200466 const unsigned char *end = buf + len;
467
468 /*
469 * struct {
470 * ECJPAKEKeyKP ecjpake_key_kp_pair_list[2];
471 * } ECJPAKEKeyKPPairList;
472 */
Robert Cragie7cdad772015-10-02 13:31:41 +0100473 MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xa, id, &p, end ) );
474 MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xb, id, &p, end ) );
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200475
476 if( p != end )
477 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
478
479cleanup:
480 return( ret );
481}
482
483/*
484 * Generate a ECJPAKEKeyKPPairList
485 * Outputs: the serialized structure, plus two private/public key pairs
486 */
487static int ecjpake_kkpp_write( const mbedtls_md_info_t *md_info,
488 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100489 const int pf,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200490 const mbedtls_ecp_point *G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200491 mbedtls_mpi *xm1,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200492 mbedtls_ecp_point *Xa,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200493 mbedtls_mpi *xm2,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200494 mbedtls_ecp_point *Xb,
495 const char *id,
496 unsigned char *buf,
497 size_t len,
498 size_t *olen,
499 int (*f_rng)(void *, unsigned char *, size_t),
500 void *p_rng )
501{
Janos Follath24eed8d2019-11-22 13:21:35 +0000502 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200503 unsigned char *p = buf;
504 const unsigned char *end = buf + len;
505
Robert Cragie7cdad772015-10-02 13:31:41 +0100506 MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm1, Xa, id,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200507 &p, end, f_rng, p_rng ) );
Robert Cragie7cdad772015-10-02 13:31:41 +0100508 MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm2, Xb, id,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200509 &p, end, f_rng, p_rng ) );
510
511 *olen = p - buf;
512
513cleanup:
514 return( ret );
515}
516
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200517/*
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200518 * Read and process the first round message
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200519 */
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200520int mbedtls_ecjpake_read_round_one( mbedtls_ecjpake_context *ctx,
521 const unsigned char *buf,
522 size_t len )
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200523{
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000524 ECJPAKE_VALIDATE_RET( ctx != NULL );
525 ECJPAKE_VALIDATE_RET( buf != NULL );
526
Robert Cragie7cdad772015-10-02 13:31:41 +0100527 return( ecjpake_kkpp_read( ctx->md_info, &ctx->grp, ctx->point_format,
528 &ctx->grp.G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200529 &ctx->Xp1, &ctx->Xp2, ID_PEER,
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200530 buf, len ) );
531}
532
533/*
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200534 * Generate and write the first round message
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200535 */
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200536int mbedtls_ecjpake_write_round_one( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200537 unsigned char *buf, size_t len, size_t *olen,
538 int (*f_rng)(void *, unsigned char *, size_t),
539 void *p_rng )
540{
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000541 ECJPAKE_VALIDATE_RET( ctx != NULL );
542 ECJPAKE_VALIDATE_RET( buf != NULL );
543 ECJPAKE_VALIDATE_RET( olen != NULL );
544 ECJPAKE_VALIDATE_RET( f_rng != NULL );
545
Robert Cragie7cdad772015-10-02 13:31:41 +0100546 return( ecjpake_kkpp_write( ctx->md_info, &ctx->grp, ctx->point_format,
547 &ctx->grp.G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200548 &ctx->xm1, &ctx->Xm1, &ctx->xm2, &ctx->Xm2,
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200549 ID_MINE, buf, len, olen, f_rng, p_rng ) );
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200550}
551
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200552/*
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200553 * Compute the sum of three points R = A + B + C
554 */
555static int ecjpake_ecp_add3( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
556 const mbedtls_ecp_point *A,
557 const mbedtls_ecp_point *B,
558 const mbedtls_ecp_point *C )
559{
Janos Follath24eed8d2019-11-22 13:21:35 +0000560 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200561 mbedtls_mpi one;
562
563 mbedtls_mpi_init( &one );
564
565 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
566 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, A, &one, B ) );
567 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, R, &one, C ) );
568
569cleanup:
570 mbedtls_mpi_free( &one );
571
572 return( ret );
573}
574
575/*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200576 * 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 +0200577 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200578int mbedtls_ecjpake_read_round_two( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200579 const unsigned char *buf,
580 size_t len )
581{
Janos Follath24eed8d2019-11-22 13:21:35 +0000582 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200583 const unsigned char *p = buf;
584 const unsigned char *end = buf + len;
585 mbedtls_ecp_group grp;
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200586 mbedtls_ecp_point G; /* C: GB, S: GA */
Hanno Becker185e5162018-12-19 09:48:50 +0000587
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000588 ECJPAKE_VALIDATE_RET( ctx != NULL );
589 ECJPAKE_VALIDATE_RET( buf != NULL );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200590
591 mbedtls_ecp_group_init( &grp );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200592 mbedtls_ecp_point_init( &G );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200593
594 /*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200595 * Server: GA = X3 + X4 + X1 (7.4.2.6.1)
596 * Client: GB = X1 + X2 + X3 (7.4.2.5.1)
597 * Unified: G = Xm1 + Xm2 + Xp1
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200598 * We need that before parsing in order to check Xp as we read it
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200599 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200600 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200601 &ctx->Xm1, &ctx->Xm2, &ctx->Xp1 ) );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200602
603 /*
604 * struct {
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200605 * ECParameters curve_params; // only client reading server msg
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200606 * ECJPAKEKeyKP ecjpake_key_kp;
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200607 * } Client/ServerECJPAKEParams;
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200608 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200609 if( ctx->role == MBEDTLS_ECJPAKE_CLIENT )
Manuel Pégourié-Gonnardd9802af2015-08-17 12:47:38 +0200610 {
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200611 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_group( &grp, &p, len ) );
Manuel Pégourié-Gonnardd9802af2015-08-17 12:47:38 +0200612 if( grp.id != ctx->grp.id )
613 {
614 ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
615 goto cleanup;
616 }
617 }
618
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200619 MBEDTLS_MPI_CHK( ecjpake_kkp_read( ctx->md_info, &ctx->grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100620 ctx->point_format,
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200621 &G, &ctx->Xp, ID_PEER, &p, end ) );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200622
623 if( p != end )
624 {
625 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
626 goto cleanup;
627 }
628
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200629cleanup:
630 mbedtls_ecp_group_free( &grp );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200631 mbedtls_ecp_point_free( &G );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200632
633 return( ret );
634}
635
636/*
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200637 * Compute R = +/- X * S mod N, taking care not to leak S
638 */
639static int ecjpake_mul_secret( mbedtls_mpi *R, int sign,
640 const mbedtls_mpi *X,
641 const mbedtls_mpi *S,
642 const mbedtls_mpi *N,
643 int (*f_rng)(void *, unsigned char *, size_t),
644 void *p_rng )
645{
Janos Follath24eed8d2019-11-22 13:21:35 +0000646 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200647 mbedtls_mpi b; /* Blinding value, then s + N * blinding */
648
649 mbedtls_mpi_init( &b );
650
651 /* b = s + rnd-128-bit * N */
652 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &b, 16, f_rng, p_rng ) );
653 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &b, &b, N ) );
654 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &b, &b, S ) );
655
656 /* R = sign * X * b mod N */
657 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( R, X, &b ) );
658 R->s *= sign;
659 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( R, R, N ) );
660
661cleanup:
662 mbedtls_mpi_free( &b );
663
664 return( ret );
665}
666
667/*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200668 * 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 +0200669 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200670int mbedtls_ecjpake_write_round_two( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200671 unsigned char *buf, size_t len, size_t *olen,
672 int (*f_rng)(void *, unsigned char *, size_t),
673 void *p_rng )
674{
Janos Follath24eed8d2019-11-22 13:21:35 +0000675 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200676 mbedtls_ecp_point G; /* C: GA, S: GB */
677 mbedtls_ecp_point Xm; /* C: Xc, S: Xs */
678 mbedtls_mpi xm; /* C: xc, S: xs */
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200679 unsigned char *p = buf;
680 const unsigned char *end = buf + len;
681 size_t ec_len;
Hanno Becker185e5162018-12-19 09:48:50 +0000682
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000683 ECJPAKE_VALIDATE_RET( ctx != NULL );
684 ECJPAKE_VALIDATE_RET( buf != NULL );
685 ECJPAKE_VALIDATE_RET( olen != NULL );
686 ECJPAKE_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200687
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200688 mbedtls_ecp_point_init( &G );
689 mbedtls_ecp_point_init( &Xm );
690 mbedtls_mpi_init( &xm );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200691
692 /*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200693 * 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 +0200694 *
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200695 * Client: GA = X1 + X3 + X4 | xs = x2 * s | Xc = xc * GA
696 * Server: GB = X3 + X1 + X2 | xs = x4 * s | Xs = xs * GB
697 * Unified: G = Xm1 + Xp1 + Xp2 | xm = xm2 * s | Xm = xm * G
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200698 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200699 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200700 &ctx->Xp1, &ctx->Xp2, &ctx->Xm1 ) );
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200701 MBEDTLS_MPI_CHK( ecjpake_mul_secret( &xm, 1, &ctx->xm2, &ctx->s,
702 &ctx->grp.N, f_rng, p_rng ) );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200703 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &Xm, &xm, &G, f_rng, p_rng ) );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200704
705 /*
706 * Now write things out
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200707 *
708 * struct {
709 * ECParameters curve_params; // only server writing its message
710 * ECJPAKEKeyKP ecjpake_key_kp;
711 * } Client/ServerECJPAKEParams;
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200712 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200713 if( ctx->role == MBEDTLS_ECJPAKE_SERVER )
714 {
715 if( end < p )
716 {
717 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
718 goto cleanup;
719 }
720 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_group( &ctx->grp, &ec_len,
721 p, end - p ) );
722 p += ec_len;
723 }
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200724
725 if( end < p )
726 {
727 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
728 goto cleanup;
729 }
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200730 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( &ctx->grp, &Xm,
Robert Cragie7cdad772015-10-02 13:31:41 +0100731 ctx->point_format, &ec_len, p, end - p ) );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200732 p += ec_len;
733
734 MBEDTLS_MPI_CHK( ecjpake_zkp_write( ctx->md_info, &ctx->grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100735 ctx->point_format,
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200736 &G, &xm, &Xm, ID_MINE,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200737 &p, end, f_rng, p_rng ) );
738
739 *olen = p - buf;
740
741cleanup:
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200742 mbedtls_ecp_point_free( &G );
743 mbedtls_ecp_point_free( &Xm );
744 mbedtls_mpi_free( &xm );
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +0200745
746 return( ret );
747}
748
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200749/*
750 * Derive PMS (7.4.2.7 / 7.4.2.8)
751 */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +0200752int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200753 unsigned char *buf, size_t len, size_t *olen,
754 int (*f_rng)(void *, unsigned char *, size_t),
755 void *p_rng )
756{
Janos Follath24eed8d2019-11-22 13:21:35 +0000757 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200758 mbedtls_ecp_point K;
759 mbedtls_mpi m_xm2_s, one;
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200760 unsigned char kx[MBEDTLS_ECP_MAX_BYTES];
761 size_t x_bytes;
Hanno Becker185e5162018-12-19 09:48:50 +0000762
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000763 ECJPAKE_VALIDATE_RET( ctx != NULL );
764 ECJPAKE_VALIDATE_RET( buf != NULL );
765 ECJPAKE_VALIDATE_RET( olen != NULL );
766 ECJPAKE_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200767
768 *olen = mbedtls_md_get_size( ctx->md_info );
769 if( len < *olen )
770 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
771
772 mbedtls_ecp_point_init( &K );
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200773 mbedtls_mpi_init( &m_xm2_s );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200774 mbedtls_mpi_init( &one );
775
776 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200777
778 /*
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200779 * Client: K = ( Xs - X4 * x2 * s ) * x2
780 * Server: K = ( Xc - X2 * x4 * s ) * x4
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200781 * Unified: K = ( Xp - Xp2 * xm2 * s ) * xm2
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200782 */
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200783 MBEDTLS_MPI_CHK( ecjpake_mul_secret( &m_xm2_s, -1, &ctx->xm2, &ctx->s,
784 &ctx->grp.N, f_rng, p_rng ) );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200785 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( &ctx->grp, &K,
786 &one, &ctx->Xp,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200787 &m_xm2_s, &ctx->Xp2 ) );
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200788 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &K, &ctx->xm2, &K,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200789 f_rng, p_rng ) );
790
791 /* PMS = SHA-256( K.X ) */
792 x_bytes = ( ctx->grp.pbits + 7 ) / 8;
793 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &K.X, kx, x_bytes ) );
794 MBEDTLS_MPI_CHK( mbedtls_md( ctx->md_info, kx, x_bytes, buf ) );
795
796cleanup:
797 mbedtls_ecp_point_free( &K );
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200798 mbedtls_mpi_free( &m_xm2_s );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200799 mbedtls_mpi_free( &one );
800
801 return( ret );
802}
803
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200804#undef ID_MINE
805#undef ID_PEER
806
Hanno Becker616d1ca2018-01-24 10:25:05 +0000807#endif /* ! MBEDTLS_ECJPAKE_ALT */
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200808
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200809#if defined(MBEDTLS_SELF_TEST)
810
811#if defined(MBEDTLS_PLATFORM_C)
812#include "mbedtls/platform.h"
813#else
814#include <stdio.h>
815#define mbedtls_printf printf
816#endif
817
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200818#if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
819 !defined(MBEDTLS_SHA256_C)
820int mbedtls_ecjpake_self_test( int verbose )
821{
822 (void) verbose;
823 return( 0 );
824}
825#else
826
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200827static const unsigned char ecjpake_test_password[] = {
828 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x6a, 0x70, 0x61, 0x6b, 0x65, 0x74,
829 0x65, 0x73, 0x74
830};
831
Steven Cooreman64f27732021-01-11 17:20:10 +0100832#if !defined(MBEDTLS_ECJPAKE_ALT)
833
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200834static const unsigned char ecjpake_test_x1[] = {
835 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
836 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
837 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21
838};
839
840static const unsigned char ecjpake_test_x2[] = {
841 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
842 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
843 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
844};
845
846static const unsigned char ecjpake_test_x3[] = {
847 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
848 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
849 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
850};
851
852static const unsigned char ecjpake_test_x4[] = {
853 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc,
854 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
855 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1
856};
857
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200858static const unsigned char ecjpake_test_cli_one[] = {
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200859 0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19,
860 0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44,
861 0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad,
862 0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62,
863 0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9,
864 0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d,
865 0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e,
866 0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e,
867 0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73,
868 0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22,
869 0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce,
870 0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00,
871 0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200872 0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e,
873 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62,
874 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5,
875 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb,
876 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35,
877 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0,
878 0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb,
879 0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47,
880 0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39,
881 0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97,
882 0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40,
883 0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d,
884 0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa,
885 0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d,
886 0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200887};
888
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200889static const unsigned char ecjpake_test_srv_one[] = {
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200890 0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb,
891 0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18,
892 0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47,
893 0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f,
894 0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7,
895 0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d,
896 0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64,
897 0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36,
898 0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2,
899 0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec,
900 0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16,
901 0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96,
902 0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3,
903 0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19,
904 0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f,
905 0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8,
906 0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7,
907 0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea,
908 0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5,
909 0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6,
910 0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31,
911 0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d,
912 0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8,
913 0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee,
914 0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84,
915 0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f,
916 0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80,
917 0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12
918};
919
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200920static const unsigned char ecjpake_test_srv_two[] = {
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200921 0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23,
922 0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c,
923 0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f,
924 0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca,
925 0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26,
926 0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55,
927 0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38,
928 0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6,
929 0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9,
930 0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4,
931 0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2,
932 0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8,
933 0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd,
934 0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c
935};
936
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200937static const unsigned char ecjpake_test_cli_two[] = {
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +0200938 0x41, 0x04, 0x69, 0xd5, 0x4e, 0xe8, 0x5e, 0x90, 0xce, 0x3f, 0x12, 0x46,
939 0x74, 0x2d, 0xe5, 0x07, 0xe9, 0x39, 0xe8, 0x1d, 0x1d, 0xc1, 0xc5, 0xcb,
940 0x98, 0x8b, 0x58, 0xc3, 0x10, 0xc9, 0xfd, 0xd9, 0x52, 0x4d, 0x93, 0x72,
941 0x0b, 0x45, 0x54, 0x1c, 0x83, 0xee, 0x88, 0x41, 0x19, 0x1d, 0xa7, 0xce,
942 0xd8, 0x6e, 0x33, 0x12, 0xd4, 0x36, 0x23, 0xc1, 0xd6, 0x3e, 0x74, 0x98,
943 0x9a, 0xba, 0x4a, 0xff, 0xd1, 0xee, 0x41, 0x04, 0x07, 0x7e, 0x8c, 0x31,
944 0xe2, 0x0e, 0x6b, 0xed, 0xb7, 0x60, 0xc1, 0x35, 0x93, 0xe6, 0x9f, 0x15,
945 0xbe, 0x85, 0xc2, 0x7d, 0x68, 0xcd, 0x09, 0xcc, 0xb8, 0xc4, 0x18, 0x36,
946 0x08, 0x91, 0x7c, 0x5c, 0x3d, 0x40, 0x9f, 0xac, 0x39, 0xfe, 0xfe, 0xe8,
947 0x2f, 0x72, 0x92, 0xd3, 0x6f, 0x0d, 0x23, 0xe0, 0x55, 0x91, 0x3f, 0x45,
948 0xa5, 0x2b, 0x85, 0xdd, 0x8a, 0x20, 0x52, 0xe9, 0xe1, 0x29, 0xbb, 0x4d,
949 0x20, 0x0f, 0x01, 0x1f, 0x19, 0x48, 0x35, 0x35, 0xa6, 0xe8, 0x9a, 0x58,
950 0x0c, 0x9b, 0x00, 0x03, 0xba, 0xf2, 0x14, 0x62, 0xec, 0xe9, 0x1a, 0x82,
951 0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c
952};
953
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200954static const unsigned char ecjpake_test_pms[] = {
955 0xf3, 0xd4, 0x7f, 0x59, 0x98, 0x44, 0xdb, 0x92, 0xa5, 0x69, 0xbb, 0xe7,
956 0x98, 0x1e, 0x39, 0xd9, 0x31, 0xfd, 0x74, 0x3b, 0xf2, 0x2e, 0x98, 0xf9,
957 0xb4, 0x38, 0xf7, 0x19, 0xd3, 0xc4, 0xf3, 0x51
958};
959
Manuel Pégourié-Gonnardaa3ed6f2021-06-15 11:29:26 +0200960/*
961 * PRNG for test - !!!INSECURE NEVER USE IN PRODUCTION!!!
962 *
963 * This is the linear congruential generator from numerical recipes,
964 * except we only use the low byte as the output. See
965 * https://en.wikipedia.org/wiki/Linear_congruential_generator#Parameters_in_common_use
966 */
967static int self_test_rng( void *ctx, unsigned char *out, size_t len )
968{
969 static uint32_t state = 42;
970
971 (void) ctx;
972
973 for( size_t i = 0; i < len; i++ )
974 {
975 state = state * 1664525u + 1013904223u;
976 out[i] = (unsigned char) state;
977 }
978
979 return( 0 );
980}
981
Antonin Décimo36e89b52019-01-23 15:24:37 +0100982/* Load my private keys and generate the corresponding public keys */
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +0200983static int ecjpake_test_load( mbedtls_ecjpake_context *ctx,
984 const unsigned char *xm1, size_t len1,
985 const unsigned char *xm2, size_t len2 )
986{
Janos Follath24eed8d2019-11-22 13:21:35 +0000987 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +0200988
989 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm1, xm1, len1 ) );
990 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm2, xm2, len2 ) );
991 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm1, &ctx->xm1,
Manuel Pégourié-Gonnardaa3ed6f2021-06-15 11:29:26 +0200992 &ctx->grp.G, self_test_rng, NULL ) );
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +0200993 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm2, &ctx->xm2,
Manuel Pégourié-Gonnardaa3ed6f2021-06-15 11:29:26 +0200994 &ctx->grp.G, self_test_rng, NULL ) );
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +0200995
996cleanup:
997 return( ret );
998}
999
Steven Cooreman64f27732021-01-11 17:20:10 +01001000#endif /* ! MBEDTLS_ECJPAKE_ALT */
1001
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001002/* For tests we don't need a secure RNG;
1003 * use the LGC from Numerical Recipes for simplicity */
1004static int ecjpake_lgc( void *p, unsigned char *out, size_t len )
1005{
1006 static uint32_t x = 42;
1007 (void) p;
1008
1009 while( len > 0 )
1010 {
1011 size_t use_len = len > 4 ? 4 : len;
1012 x = 1664525 * x + 1013904223;
1013 memcpy( out, &x, use_len );
1014 out += use_len;
1015 len -= use_len;
1016 }
1017
1018 return( 0 );
1019}
1020
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +02001021#define TEST_ASSERT( x ) \
1022 do { \
1023 if( x ) \
1024 ret = 0; \
1025 else \
1026 { \
1027 ret = 1; \
1028 goto cleanup; \
1029 } \
1030 } while( 0 )
1031
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001032/*
1033 * Checkup routine
1034 */
1035int mbedtls_ecjpake_self_test( int verbose )
1036{
Janos Follath24eed8d2019-11-22 13:21:35 +00001037 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001038 mbedtls_ecjpake_context cli;
1039 mbedtls_ecjpake_context srv;
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001040 unsigned char buf[512], pms[32];
1041 size_t len, pmslen;
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001042
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001043 mbedtls_ecjpake_init( &cli );
1044 mbedtls_ecjpake_init( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001045
1046 if( verbose != 0 )
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001047 mbedtls_printf( " ECJPAKE test #0 (setup): " );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +02001048
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +02001049 TEST_ASSERT( mbedtls_ecjpake_setup( &cli, MBEDTLS_ECJPAKE_CLIENT,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001050 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1051 ecjpake_test_password,
1052 sizeof( ecjpake_test_password ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001053
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +02001054 TEST_ASSERT( mbedtls_ecjpake_setup( &srv, MBEDTLS_ECJPAKE_SERVER,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001055 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1056 ecjpake_test_password,
1057 sizeof( ecjpake_test_password ) ) == 0 );
1058
1059 if( verbose != 0 )
1060 mbedtls_printf( "passed\n" );
1061
1062 if( verbose != 0 )
1063 mbedtls_printf( " ECJPAKE test #1 (random handshake): " );
1064
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001065 TEST_ASSERT( mbedtls_ecjpake_write_round_one( &cli,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001066 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1067
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001068 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv, buf, len ) == 0 );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001069
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001070 TEST_ASSERT( mbedtls_ecjpake_write_round_one( &srv,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001071 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1072
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001073 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli, buf, len ) == 0 );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001074
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001075 TEST_ASSERT( mbedtls_ecjpake_write_round_two( &srv,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +02001076 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1077
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001078 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli, buf, len ) == 0 );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +02001079
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001080 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001081 pms, sizeof( pms ), &pmslen, ecjpake_lgc, NULL ) == 0 );
1082
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001083 TEST_ASSERT( mbedtls_ecjpake_write_round_two( &cli,
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +02001084 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1085
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001086 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv, buf, len ) == 0 );
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +02001087
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001088 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001089 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1090
1091 TEST_ASSERT( len == pmslen );
1092 TEST_ASSERT( memcmp( buf, pms, len ) == 0 );
1093
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001094 if( verbose != 0 )
1095 mbedtls_printf( "passed\n" );
1096
Steven Cooreman64f27732021-01-11 17:20:10 +01001097#if !defined(MBEDTLS_ECJPAKE_ALT)
1098 /* 'reference handshake' tests can only be run against implementations
1099 * for which we have 100% control over how the random ephemeral keys
1100 * are generated. This is only the case for the internal mbed TLS
1101 * implementation, so these tests are skipped in case the internal
1102 * implementation is swapped out for an alternative one. */
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001103 if( verbose != 0 )
1104 mbedtls_printf( " ECJPAKE test #2 (reference handshake): " );
1105
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001106 /* Simulate generation of round one */
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001107 MBEDTLS_MPI_CHK( ecjpake_test_load( &cli,
1108 ecjpake_test_x1, sizeof( ecjpake_test_x1 ),
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001109 ecjpake_test_x2, sizeof( ecjpake_test_x2 ) ) );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001110
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001111 MBEDTLS_MPI_CHK( ecjpake_test_load( &srv,
1112 ecjpake_test_x3, sizeof( ecjpake_test_x3 ),
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001113 ecjpake_test_x4, sizeof( ecjpake_test_x4 ) ) );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001114
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001115 /* Read round one */
1116 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv,
1117 ecjpake_test_cli_one,
1118 sizeof( ecjpake_test_cli_one ) ) == 0 );
1119
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001120 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001121 ecjpake_test_srv_one,
1122 sizeof( ecjpake_test_srv_one ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001123
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001124 /* Skip generation of round two, read round two */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001125 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001126 ecjpake_test_srv_two,
1127 sizeof( ecjpake_test_srv_two ) ) == 0 );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +02001128
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001129 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001130 ecjpake_test_cli_two,
1131 sizeof( ecjpake_test_cli_two ) ) == 0 );
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +02001132
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001133 /* Server derives PMS */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001134 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001135 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1136
1137 TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
1138 TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
1139
1140 memset( buf, 0, len ); /* Avoid interferences with next step */
1141
1142 /* Client derives PMS */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001143 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001144 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1145
1146 TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
1147 TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
1148
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001149 if( verbose != 0 )
1150 mbedtls_printf( "passed\n" );
Steven Cooreman64f27732021-01-11 17:20:10 +01001151#endif /* ! MBEDTLS_ECJPAKE_ALT */
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001152
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001153cleanup:
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001154 mbedtls_ecjpake_free( &cli );
1155 mbedtls_ecjpake_free( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001156
1157 if( ret != 0 )
1158 {
1159 if( verbose != 0 )
1160 mbedtls_printf( "failed\n" );
1161
1162 ret = 1;
1163 }
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001164
1165 if( verbose != 0 )
1166 mbedtls_printf( "\n" );
1167
1168 return( ret );
1169}
1170
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +02001171#undef TEST_ASSERT
1172
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001173#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_SHA256_C */
1174
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001175#endif /* MBEDTLS_SELF_TEST */
1176
1177#endif /* MBEDTLS_ECJPAKE_C */