blob: 6f60e82e95c45c32821c9859000c9300552d8dfb [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{
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020059 ctx->md_info = NULL;
60 mbedtls_ecp_group_init( &ctx->grp );
Manuel Pégourié-Gonnardb7da1942015-10-19 13:35:22 +020061 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020062
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +020063 mbedtls_ecp_point_init( &ctx->Xm1 );
64 mbedtls_ecp_point_init( &ctx->Xm2 );
65 mbedtls_ecp_point_init( &ctx->Xp1 );
66 mbedtls_ecp_point_init( &ctx->Xp2 );
67 mbedtls_ecp_point_init( &ctx->Xp );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020068
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +020069 mbedtls_mpi_init( &ctx->xm1 );
70 mbedtls_mpi_init( &ctx->xm2 );
71 mbedtls_mpi_init( &ctx->s );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020072}
73
74/*
75 * Free context
76 */
77void mbedtls_ecjpake_free( mbedtls_ecjpake_context *ctx )
78{
79 if( ctx == NULL )
80 return;
81
82 ctx->md_info = NULL;
83 mbedtls_ecp_group_free( &ctx->grp );
84
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +020085 mbedtls_ecp_point_free( &ctx->Xm1 );
86 mbedtls_ecp_point_free( &ctx->Xm2 );
87 mbedtls_ecp_point_free( &ctx->Xp1 );
88 mbedtls_ecp_point_free( &ctx->Xp2 );
89 mbedtls_ecp_point_free( &ctx->Xp );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020090
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +020091 mbedtls_mpi_free( &ctx->xm1 );
92 mbedtls_mpi_free( &ctx->xm2 );
93 mbedtls_mpi_free( &ctx->s );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020094}
95
96/*
97 * Setup context
98 */
99int mbedtls_ecjpake_setup( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +0200100 mbedtls_ecjpake_role role,
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200101 mbedtls_md_type_t hash,
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200102 mbedtls_ecp_group_id curve,
103 const unsigned char *secret,
104 size_t len )
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200105{
Janos Follath24eed8d2019-11-22 13:21:35 +0000106 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker185e5162018-12-19 09:48:50 +0000107
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000108 ECJPAKE_VALIDATE_RET( role == MBEDTLS_ECJPAKE_CLIENT ||
109 role == MBEDTLS_ECJPAKE_SERVER );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200110
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +0200111 ctx->role = role;
112
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200113 if( ( ctx->md_info = mbedtls_md_info_from_type( hash ) ) == NULL )
114 return( MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE );
115
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200116 MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ctx->grp, curve ) );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200117
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200118 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->s, secret, len ) );
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200119
120cleanup:
121 if( ret != 0 )
122 mbedtls_ecjpake_free( ctx );
123
124 return( ret );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200125}
126
Gilles Peskinecd07e222021-05-27 23:17:34 +0200127int mbedtls_ecjpake_set_point_format( mbedtls_ecjpake_context *ctx,
128 int point_format )
129{
130 switch( point_format )
131 {
132 case MBEDTLS_ECP_PF_UNCOMPRESSED:
133 case MBEDTLS_ECP_PF_COMPRESSED:
134 ctx->point_format = point_format;
135 return( 0 );
136 default:
137 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
138 }
139}
140
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200141/*
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200142 * Check if context is ready for use
143 */
144int mbedtls_ecjpake_check( const mbedtls_ecjpake_context *ctx )
145{
146 if( ctx->md_info == NULL ||
147 ctx->grp.id == MBEDTLS_ECP_DP_NONE ||
148 ctx->s.p == NULL )
149 {
150 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
151 }
152
153 return( 0 );
154}
155
156/*
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200157 * Write a point plus its length to a buffer
158 */
159static int ecjpake_write_len_point( unsigned char **p,
160 const unsigned char *end,
161 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100162 const int pf,
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200163 const mbedtls_ecp_point *P )
164{
Janos Follath24eed8d2019-11-22 13:21:35 +0000165 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200166 size_t len;
167
168 /* Need at least 4 for length plus 1 for point */
169 if( end < *p || end - *p < 5 )
170 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
171
Robert Cragie7cdad772015-10-02 13:31:41 +0100172 ret = mbedtls_ecp_point_write_binary( grp, P, pf,
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200173 &len, *p + 4, end - ( *p + 4 ) );
174 if( ret != 0 )
175 return( ret );
176
Joe Subbiania5cb0d22021-08-23 11:35:25 +0100177 MBEDTLS_PUT_UINT32_BE( len, *p, 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200178
179 *p += 4 + len;
180
181 return( 0 );
182}
183
184/*
185 * Size of the temporary buffer for ecjpake_hash:
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200186 * 3 EC points plus their length, plus ID and its length (4 + 6 bytes)
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200187 */
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200188#define ECJPAKE_HASH_BUF_LEN ( 3 * ( 4 + MBEDTLS_ECP_MAX_PT_LEN ) + 4 + 6 )
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200189
190/*
191 * Compute hash for ZKP (7.4.2.2.2.1)
192 */
193static int ecjpake_hash( const mbedtls_md_info_t *md_info,
194 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100195 const int pf,
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200196 const mbedtls_ecp_point *G,
197 const mbedtls_ecp_point *V,
198 const mbedtls_ecp_point *X,
199 const char *id,
200 mbedtls_mpi *h )
201{
Janos Follath24eed8d2019-11-22 13:21:35 +0000202 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200203 unsigned char buf[ECJPAKE_HASH_BUF_LEN];
204 unsigned char *p = buf;
205 const unsigned char *end = buf + sizeof( buf );
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200206 const size_t id_len = strlen( id );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200207 unsigned char hash[MBEDTLS_MD_MAX_SIZE];
208
209 /* Write things to temporary buffer */
Robert Cragie7cdad772015-10-02 13:31:41 +0100210 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, G ) );
211 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, V ) );
212 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, X ) );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200213
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200214 if( end - p < 4 )
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200215 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
216
Joe Subbiania5cb0d22021-08-23 11:35:25 +0100217 MBEDTLS_PUT_UINT32_BE( id_len, p, 0 );
218 p += 4;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200219
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200220 if( end < p || (size_t)( end - p ) < id_len )
221 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
222
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200223 memcpy( p, id, id_len );
224 p += id_len;
225
226 /* Compute hash */
k-stachowiak41503352019-06-28 14:14:02 +0200227 MBEDTLS_MPI_CHK( mbedtls_md( md_info, buf, p - buf, hash ) );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200228
229 /* Turn it into an integer mod n */
230 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( h, hash,
231 mbedtls_md_get_size( md_info ) ) );
232 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( h, h, &grp->N ) );
233
234cleanup:
235 return( ret );
236}
237
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200238/*
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200239 * Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3)
240 */
241static int ecjpake_zkp_read( const mbedtls_md_info_t *md_info,
242 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100243 const int pf,
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200244 const mbedtls_ecp_point *G,
245 const mbedtls_ecp_point *X,
246 const char *id,
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200247 const unsigned char **p,
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200248 const unsigned char *end )
249{
Janos Follath24eed8d2019-11-22 13:21:35 +0000250 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200251 mbedtls_ecp_point V, VV;
252 mbedtls_mpi r, h;
253 size_t r_len;
254
255 mbedtls_ecp_point_init( &V );
256 mbedtls_ecp_point_init( &VV );
257 mbedtls_mpi_init( &r );
258 mbedtls_mpi_init( &h );
259
260 /*
261 * struct {
262 * ECPoint V;
263 * opaque r<1..2^8-1>;
264 * } ECSchnorrZKP;
265 */
266 if( end < *p )
267 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
268
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200269 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, &V, p, end - *p ) );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200270
271 if( end < *p || (size_t)( end - *p ) < 1 )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200272 {
273 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
274 goto cleanup;
275 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200276
277 r_len = *(*p)++;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200278
TRodziewicz782a7ea2021-03-17 11:35:16 +0100279 if( end < *p || (size_t)( end - *p ) < r_len || r_len == 0 )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200280 {
281 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
282 goto cleanup;
283 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200284
285 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &r, *p, r_len ) );
286 *p += r_len;
287
288 /*
289 * Verification
290 */
Robert Cragie7cdad772015-10-02 13:31:41 +0100291 MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200292 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( (mbedtls_ecp_group *) grp,
293 &VV, &h, X, &r, G ) );
294
295 if( mbedtls_ecp_point_cmp( &VV, &V ) != 0 )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200296 {
297 ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
298 goto cleanup;
299 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200300
301cleanup:
302 mbedtls_ecp_point_free( &V );
303 mbedtls_ecp_point_free( &VV );
304 mbedtls_mpi_free( &r );
305 mbedtls_mpi_free( &h );
306
307 return( ret );
308}
309
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200310/*
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200311 * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2)
312 */
313static int ecjpake_zkp_write( const mbedtls_md_info_t *md_info,
314 const mbedtls_ecp_group *grp,
Darryl Green11999bb2018-03-13 15:22:58 +0000315 const int pf,
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200316 const mbedtls_ecp_point *G,
317 const mbedtls_mpi *x,
318 const mbedtls_ecp_point *X,
319 const char *id,
320 unsigned char **p,
321 const unsigned char *end,
322 int (*f_rng)(void *, unsigned char *, size_t),
323 void *p_rng )
324{
Janos Follath24eed8d2019-11-22 13:21:35 +0000325 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200326 mbedtls_ecp_point V;
327 mbedtls_mpi v;
328 mbedtls_mpi h; /* later recycled to hold r */
329 size_t len;
330
331 if( end < *p )
332 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
333
334 mbedtls_ecp_point_init( &V );
335 mbedtls_mpi_init( &v );
336 mbedtls_mpi_init( &h );
337
338 /* Compute signature */
339 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp,
340 G, &v, &V, f_rng, p_rng ) );
Robert Cragie7cdad772015-10-02 13:31:41 +0100341 MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) );
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200342 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &h, &h, x ) ); /* x*h */
343 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &h, &v, &h ) ); /* v - x*h */
344 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &h, &h, &grp->N ) ); /* r */
345
346 /* Write it out */
347 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, &V,
Robert Cragie7cdad772015-10-02 13:31:41 +0100348 pf, &len, *p, end - *p ) );
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200349 *p += len;
350
351 len = mbedtls_mpi_size( &h ); /* actually r */
352 if( end < *p || (size_t)( end - *p ) < 1 + len || len > 255 )
353 {
354 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
355 goto cleanup;
356 }
357
Joe Subbiani2194dc42021-07-14 12:31:31 +0100358 *(*p)++ = MBEDTLS_BYTE_0( len );
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200359 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, *p, len ) ); /* r */
360 *p += len;
361
362cleanup:
363 mbedtls_ecp_point_free( &V );
364 mbedtls_mpi_free( &v );
365 mbedtls_mpi_free( &h );
366
367 return( ret );
368}
369
370/*
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200371 * Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof
372 * Output: verified public key X
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200373 */
374static int ecjpake_kkp_read( const mbedtls_md_info_t *md_info,
375 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100376 const int pf,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200377 const mbedtls_ecp_point *G,
378 mbedtls_ecp_point *X,
379 const char *id,
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200380 const unsigned char **p,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200381 const unsigned char *end )
382{
Janos Follath24eed8d2019-11-22 13:21:35 +0000383 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200384
385 if( end < *p )
386 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
387
388 /*
389 * struct {
390 * ECPoint X;
391 * ECSchnorrZKP zkp;
392 * } ECJPAKEKeyKP;
393 */
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200394 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, X, p, end - *p ) );
Manuel Pégourié-Gonnard30590952015-08-17 10:37:40 +0200395 if( mbedtls_ecp_is_zero( X ) )
396 {
397 ret = MBEDTLS_ERR_ECP_INVALID_KEY;
398 goto cleanup;
399 }
400
Robert Cragie7cdad772015-10-02 13:31:41 +0100401 MBEDTLS_MPI_CHK( ecjpake_zkp_read( md_info, grp, pf, G, X, id, p, end ) );
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200402
403cleanup:
404 return( ret );
405}
406
407/*
408 * Generate an ECJPAKEKeyKP
409 * Output: the serialized structure, plus private/public key pair
410 */
411static int ecjpake_kkp_write( const mbedtls_md_info_t *md_info,
412 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100413 const int pf,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200414 const mbedtls_ecp_point *G,
415 mbedtls_mpi *x,
416 mbedtls_ecp_point *X,
417 const char *id,
418 unsigned char **p,
419 const unsigned char *end,
420 int (*f_rng)(void *, unsigned char *, size_t),
421 void *p_rng )
422{
Janos Follath24eed8d2019-11-22 13:21:35 +0000423 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200424 size_t len;
425
426 if( end < *p )
427 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
428
429 /* Generate key (7.4.2.3.1) and write it out */
430 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp, G, x, X,
431 f_rng, p_rng ) );
432 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, X,
Robert Cragie7cdad772015-10-02 13:31:41 +0100433 pf, &len, *p, end - *p ) );
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200434 *p += len;
435
436 /* Generate and write proof */
Robert Cragie7cdad772015-10-02 13:31:41 +0100437 MBEDTLS_MPI_CHK( ecjpake_zkp_write( md_info, grp, pf, G, x, X, id,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200438 p, end, f_rng, p_rng ) );
439
440cleanup:
441 return( ret );
442}
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200443
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200444/*
445 * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs
Shaun Case8b0ecbc2021-12-20 21:14:10 -0800446 * Outputs: verified peer public keys Xa, Xb
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200447 */
448static int ecjpake_kkpp_read( const mbedtls_md_info_t *md_info,
449 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100450 const int pf,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200451 const mbedtls_ecp_point *G,
452 mbedtls_ecp_point *Xa,
453 mbedtls_ecp_point *Xb,
454 const char *id,
455 const unsigned char *buf,
456 size_t len )
457{
Janos Follath24eed8d2019-11-22 13:21:35 +0000458 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200459 const unsigned char *p = buf;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200460 const unsigned char *end = buf + len;
461
462 /*
463 * struct {
464 * ECJPAKEKeyKP ecjpake_key_kp_pair_list[2];
465 * } ECJPAKEKeyKPPairList;
466 */
Robert Cragie7cdad772015-10-02 13:31:41 +0100467 MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xa, id, &p, end ) );
468 MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xb, id, &p, end ) );
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200469
470 if( p != end )
471 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
472
473cleanup:
474 return( ret );
475}
476
477/*
478 * Generate a ECJPAKEKeyKPPairList
479 * Outputs: the serialized structure, plus two private/public key pairs
480 */
481static int ecjpake_kkpp_write( const mbedtls_md_info_t *md_info,
482 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100483 const int pf,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200484 const mbedtls_ecp_point *G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200485 mbedtls_mpi *xm1,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200486 mbedtls_ecp_point *Xa,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200487 mbedtls_mpi *xm2,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200488 mbedtls_ecp_point *Xb,
489 const char *id,
490 unsigned char *buf,
491 size_t len,
492 size_t *olen,
493 int (*f_rng)(void *, unsigned char *, size_t),
494 void *p_rng )
495{
Janos Follath24eed8d2019-11-22 13:21:35 +0000496 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200497 unsigned char *p = buf;
498 const unsigned char *end = buf + len;
499
Robert Cragie7cdad772015-10-02 13:31:41 +0100500 MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm1, Xa, id,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200501 &p, end, f_rng, p_rng ) );
Robert Cragie7cdad772015-10-02 13:31:41 +0100502 MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm2, Xb, id,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200503 &p, end, f_rng, p_rng ) );
504
505 *olen = p - buf;
506
507cleanup:
508 return( ret );
509}
510
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200511/*
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200512 * Read and process the first round message
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200513 */
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200514int mbedtls_ecjpake_read_round_one( mbedtls_ecjpake_context *ctx,
515 const unsigned char *buf,
516 size_t len )
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200517{
Robert Cragie7cdad772015-10-02 13:31:41 +0100518 return( ecjpake_kkpp_read( ctx->md_info, &ctx->grp, ctx->point_format,
519 &ctx->grp.G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200520 &ctx->Xp1, &ctx->Xp2, ID_PEER,
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200521 buf, len ) );
522}
523
524/*
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200525 * Generate and write the first round message
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200526 */
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200527int mbedtls_ecjpake_write_round_one( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200528 unsigned char *buf, size_t len, size_t *olen,
529 int (*f_rng)(void *, unsigned char *, size_t),
530 void *p_rng )
531{
Robert Cragie7cdad772015-10-02 13:31:41 +0100532 return( ecjpake_kkpp_write( ctx->md_info, &ctx->grp, ctx->point_format,
533 &ctx->grp.G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200534 &ctx->xm1, &ctx->Xm1, &ctx->xm2, &ctx->Xm2,
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200535 ID_MINE, buf, len, olen, f_rng, p_rng ) );
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200536}
537
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200538/*
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200539 * Compute the sum of three points R = A + B + C
540 */
541static int ecjpake_ecp_add3( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
542 const mbedtls_ecp_point *A,
543 const mbedtls_ecp_point *B,
544 const mbedtls_ecp_point *C )
545{
Janos Follath24eed8d2019-11-22 13:21:35 +0000546 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200547 mbedtls_mpi one;
548
549 mbedtls_mpi_init( &one );
550
551 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
552 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, A, &one, B ) );
553 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, R, &one, C ) );
554
555cleanup:
556 mbedtls_mpi_free( &one );
557
558 return( ret );
559}
560
561/*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200562 * Read and process second round message (C: 7.4.2.5, S: 7.4.2.6)
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200563 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200564int mbedtls_ecjpake_read_round_two( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200565 const unsigned char *buf,
566 size_t len )
567{
Janos Follath24eed8d2019-11-22 13:21:35 +0000568 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200569 const unsigned char *p = buf;
570 const unsigned char *end = buf + len;
571 mbedtls_ecp_group grp;
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200572 mbedtls_ecp_point G; /* C: GB, S: GA */
Hanno Becker185e5162018-12-19 09:48:50 +0000573
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200574 mbedtls_ecp_group_init( &grp );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200575 mbedtls_ecp_point_init( &G );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200576
577 /*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200578 * Server: GA = X3 + X4 + X1 (7.4.2.6.1)
579 * Client: GB = X1 + X2 + X3 (7.4.2.5.1)
580 * Unified: G = Xm1 + Xm2 + Xp1
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200581 * We need that before parsing in order to check Xp as we read it
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200582 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200583 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200584 &ctx->Xm1, &ctx->Xm2, &ctx->Xp1 ) );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200585
586 /*
587 * struct {
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200588 * ECParameters curve_params; // only client reading server msg
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200589 * ECJPAKEKeyKP ecjpake_key_kp;
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200590 * } Client/ServerECJPAKEParams;
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200591 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200592 if( ctx->role == MBEDTLS_ECJPAKE_CLIENT )
Manuel Pégourié-Gonnardd9802af2015-08-17 12:47:38 +0200593 {
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200594 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_group( &grp, &p, len ) );
Manuel Pégourié-Gonnardd9802af2015-08-17 12:47:38 +0200595 if( grp.id != ctx->grp.id )
596 {
597 ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
598 goto cleanup;
599 }
600 }
601
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200602 MBEDTLS_MPI_CHK( ecjpake_kkp_read( ctx->md_info, &ctx->grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100603 ctx->point_format,
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200604 &G, &ctx->Xp, ID_PEER, &p, end ) );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200605
606 if( p != end )
607 {
608 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
609 goto cleanup;
610 }
611
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200612cleanup:
613 mbedtls_ecp_group_free( &grp );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200614 mbedtls_ecp_point_free( &G );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200615
616 return( ret );
617}
618
619/*
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200620 * Compute R = +/- X * S mod N, taking care not to leak S
621 */
622static int ecjpake_mul_secret( mbedtls_mpi *R, int sign,
623 const mbedtls_mpi *X,
624 const mbedtls_mpi *S,
625 const mbedtls_mpi *N,
626 int (*f_rng)(void *, unsigned char *, size_t),
627 void *p_rng )
628{
Janos Follath24eed8d2019-11-22 13:21:35 +0000629 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200630 mbedtls_mpi b; /* Blinding value, then s + N * blinding */
631
632 mbedtls_mpi_init( &b );
633
634 /* b = s + rnd-128-bit * N */
635 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &b, 16, f_rng, p_rng ) );
636 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &b, &b, N ) );
637 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &b, &b, S ) );
638
639 /* R = sign * X * b mod N */
640 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( R, X, &b ) );
641 R->s *= sign;
642 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( R, R, N ) );
643
644cleanup:
645 mbedtls_mpi_free( &b );
646
647 return( ret );
648}
649
650/*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200651 * 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 +0200652 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200653int mbedtls_ecjpake_write_round_two( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200654 unsigned char *buf, size_t len, size_t *olen,
655 int (*f_rng)(void *, unsigned char *, size_t),
656 void *p_rng )
657{
Janos Follath24eed8d2019-11-22 13:21:35 +0000658 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200659 mbedtls_ecp_point G; /* C: GA, S: GB */
660 mbedtls_ecp_point Xm; /* C: Xc, S: Xs */
661 mbedtls_mpi xm; /* C: xc, S: xs */
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200662 unsigned char *p = buf;
663 const unsigned char *end = buf + len;
664 size_t ec_len;
Hanno Becker185e5162018-12-19 09:48:50 +0000665
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200666 mbedtls_ecp_point_init( &G );
667 mbedtls_ecp_point_init( &Xm );
668 mbedtls_mpi_init( &xm );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200669
670 /*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200671 * 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 +0200672 *
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200673 * Client: GA = X1 + X3 + X4 | xs = x2 * s | Xc = xc * GA
674 * Server: GB = X3 + X1 + X2 | xs = x4 * s | Xs = xs * GB
675 * Unified: G = Xm1 + Xp1 + Xp2 | xm = xm2 * s | Xm = xm * G
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200676 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200677 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200678 &ctx->Xp1, &ctx->Xp2, &ctx->Xm1 ) );
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200679 MBEDTLS_MPI_CHK( ecjpake_mul_secret( &xm, 1, &ctx->xm2, &ctx->s,
680 &ctx->grp.N, f_rng, p_rng ) );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200681 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &Xm, &xm, &G, f_rng, p_rng ) );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200682
683 /*
684 * Now write things out
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200685 *
686 * struct {
687 * ECParameters curve_params; // only server writing its message
688 * ECJPAKEKeyKP ecjpake_key_kp;
689 * } Client/ServerECJPAKEParams;
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200690 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200691 if( ctx->role == MBEDTLS_ECJPAKE_SERVER )
692 {
693 if( end < p )
694 {
695 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
696 goto cleanup;
697 }
698 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_group( &ctx->grp, &ec_len,
699 p, end - p ) );
700 p += ec_len;
701 }
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200702
703 if( end < p )
704 {
705 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
706 goto cleanup;
707 }
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200708 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( &ctx->grp, &Xm,
Robert Cragie7cdad772015-10-02 13:31:41 +0100709 ctx->point_format, &ec_len, p, end - p ) );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200710 p += ec_len;
711
712 MBEDTLS_MPI_CHK( ecjpake_zkp_write( ctx->md_info, &ctx->grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100713 ctx->point_format,
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200714 &G, &xm, &Xm, ID_MINE,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200715 &p, end, f_rng, p_rng ) );
716
717 *olen = p - buf;
718
719cleanup:
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200720 mbedtls_ecp_point_free( &G );
721 mbedtls_ecp_point_free( &Xm );
722 mbedtls_mpi_free( &xm );
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +0200723
724 return( ret );
725}
726
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200727/*
728 * Derive PMS (7.4.2.7 / 7.4.2.8)
729 */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +0200730int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200731 unsigned char *buf, size_t len, size_t *olen,
732 int (*f_rng)(void *, unsigned char *, size_t),
733 void *p_rng )
734{
Janos Follath24eed8d2019-11-22 13:21:35 +0000735 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200736 mbedtls_ecp_point K;
737 mbedtls_mpi m_xm2_s, one;
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200738 unsigned char kx[MBEDTLS_ECP_MAX_BYTES];
739 size_t x_bytes;
Hanno Becker185e5162018-12-19 09:48:50 +0000740
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200741 *olen = mbedtls_md_get_size( ctx->md_info );
742 if( len < *olen )
743 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
744
745 mbedtls_ecp_point_init( &K );
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200746 mbedtls_mpi_init( &m_xm2_s );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200747 mbedtls_mpi_init( &one );
748
749 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200750
751 /*
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200752 * Client: K = ( Xs - X4 * x2 * s ) * x2
753 * Server: K = ( Xc - X2 * x4 * s ) * x4
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200754 * Unified: K = ( Xp - Xp2 * xm2 * s ) * xm2
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200755 */
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200756 MBEDTLS_MPI_CHK( ecjpake_mul_secret( &m_xm2_s, -1, &ctx->xm2, &ctx->s,
757 &ctx->grp.N, f_rng, p_rng ) );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200758 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( &ctx->grp, &K,
759 &one, &ctx->Xp,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200760 &m_xm2_s, &ctx->Xp2 ) );
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200761 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &K, &ctx->xm2, &K,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200762 f_rng, p_rng ) );
763
764 /* PMS = SHA-256( K.X ) */
765 x_bytes = ( ctx->grp.pbits + 7 ) / 8;
766 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &K.X, kx, x_bytes ) );
767 MBEDTLS_MPI_CHK( mbedtls_md( ctx->md_info, kx, x_bytes, buf ) );
768
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 */