blob: a599b1ba485f91245a73661e5bdd927194896871 [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 Subbiani2194dc42021-07-14 12:31:31 +0100183 (*p)[0] = MBEDTLS_BYTE_3( len );
184 (*p)[1] = MBEDTLS_BYTE_2( len );
185 (*p)[2] = MBEDTLS_BYTE_1( len );
186 (*p)[3] = MBEDTLS_BYTE_0( len );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200187
188 *p += 4 + len;
189
190 return( 0 );
191}
192
193/*
194 * Size of the temporary buffer for ecjpake_hash:
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200195 * 3 EC points plus their length, plus ID and its length (4 + 6 bytes)
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200196 */
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200197#define ECJPAKE_HASH_BUF_LEN ( 3 * ( 4 + MBEDTLS_ECP_MAX_PT_LEN ) + 4 + 6 )
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200198
199/*
200 * Compute hash for ZKP (7.4.2.2.2.1)
201 */
202static int ecjpake_hash( const mbedtls_md_info_t *md_info,
203 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100204 const int pf,
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200205 const mbedtls_ecp_point *G,
206 const mbedtls_ecp_point *V,
207 const mbedtls_ecp_point *X,
208 const char *id,
209 mbedtls_mpi *h )
210{
Janos Follath24eed8d2019-11-22 13:21:35 +0000211 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200212 unsigned char buf[ECJPAKE_HASH_BUF_LEN];
213 unsigned char *p = buf;
214 const unsigned char *end = buf + sizeof( buf );
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200215 const size_t id_len = strlen( id );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200216 unsigned char hash[MBEDTLS_MD_MAX_SIZE];
217
218 /* Write things to temporary buffer */
Robert Cragie7cdad772015-10-02 13:31:41 +0100219 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, G ) );
220 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, V ) );
221 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, X ) );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200222
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200223 if( end - p < 4 )
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200224 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
225
Joe Subbiani2194dc42021-07-14 12:31:31 +0100226 *p++ = MBEDTLS_BYTE_3( id_len );
227 *p++ = MBEDTLS_BYTE_2( id_len );
228 *p++ = MBEDTLS_BYTE_1( id_len );
229 *p++ = MBEDTLS_BYTE_0( id_len );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200230
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200231 if( end < p || (size_t)( end - p ) < id_len )
232 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
233
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200234 memcpy( p, id, id_len );
235 p += id_len;
236
237 /* Compute hash */
k-stachowiak41503352019-06-28 14:14:02 +0200238 MBEDTLS_MPI_CHK( mbedtls_md( md_info, buf, p - buf, hash ) );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200239
240 /* Turn it into an integer mod n */
241 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( h, hash,
242 mbedtls_md_get_size( md_info ) ) );
243 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( h, h, &grp->N ) );
244
245cleanup:
246 return( ret );
247}
248
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200249/*
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200250 * Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3)
251 */
252static int ecjpake_zkp_read( const mbedtls_md_info_t *md_info,
253 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100254 const int pf,
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200255 const mbedtls_ecp_point *G,
256 const mbedtls_ecp_point *X,
257 const char *id,
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200258 const unsigned char **p,
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200259 const unsigned char *end )
260{
Janos Follath24eed8d2019-11-22 13:21:35 +0000261 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200262 mbedtls_ecp_point V, VV;
263 mbedtls_mpi r, h;
264 size_t r_len;
265
266 mbedtls_ecp_point_init( &V );
267 mbedtls_ecp_point_init( &VV );
268 mbedtls_mpi_init( &r );
269 mbedtls_mpi_init( &h );
270
271 /*
272 * struct {
273 * ECPoint V;
274 * opaque r<1..2^8-1>;
275 * } ECSchnorrZKP;
276 */
277 if( end < *p )
278 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
279
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200280 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, &V, p, end - *p ) );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200281
282 if( end < *p || (size_t)( end - *p ) < 1 )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200283 {
284 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
285 goto cleanup;
286 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200287
288 r_len = *(*p)++;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200289
TRodziewicz782a7ea2021-03-17 11:35:16 +0100290 if( end < *p || (size_t)( end - *p ) < r_len || r_len == 0 )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200291 {
292 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
293 goto cleanup;
294 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200295
296 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &r, *p, r_len ) );
297 *p += r_len;
298
299 /*
300 * Verification
301 */
Robert Cragie7cdad772015-10-02 13:31:41 +0100302 MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200303 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( (mbedtls_ecp_group *) grp,
304 &VV, &h, X, &r, G ) );
305
306 if( mbedtls_ecp_point_cmp( &VV, &V ) != 0 )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200307 {
308 ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
309 goto cleanup;
310 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200311
312cleanup:
313 mbedtls_ecp_point_free( &V );
314 mbedtls_ecp_point_free( &VV );
315 mbedtls_mpi_free( &r );
316 mbedtls_mpi_free( &h );
317
318 return( ret );
319}
320
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200321/*
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200322 * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2)
323 */
324static int ecjpake_zkp_write( const mbedtls_md_info_t *md_info,
325 const mbedtls_ecp_group *grp,
Darryl Green11999bb2018-03-13 15:22:58 +0000326 const int pf,
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200327 const mbedtls_ecp_point *G,
328 const mbedtls_mpi *x,
329 const mbedtls_ecp_point *X,
330 const char *id,
331 unsigned char **p,
332 const unsigned char *end,
333 int (*f_rng)(void *, unsigned char *, size_t),
334 void *p_rng )
335{
Janos Follath24eed8d2019-11-22 13:21:35 +0000336 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200337 mbedtls_ecp_point V;
338 mbedtls_mpi v;
339 mbedtls_mpi h; /* later recycled to hold r */
340 size_t len;
341
342 if( end < *p )
343 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
344
345 mbedtls_ecp_point_init( &V );
346 mbedtls_mpi_init( &v );
347 mbedtls_mpi_init( &h );
348
349 /* Compute signature */
350 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp,
351 G, &v, &V, f_rng, p_rng ) );
Robert Cragie7cdad772015-10-02 13:31:41 +0100352 MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) );
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200353 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &h, &h, x ) ); /* x*h */
354 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &h, &v, &h ) ); /* v - x*h */
355 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &h, &h, &grp->N ) ); /* r */
356
357 /* Write it out */
358 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, &V,
Robert Cragie7cdad772015-10-02 13:31:41 +0100359 pf, &len, *p, end - *p ) );
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200360 *p += len;
361
362 len = mbedtls_mpi_size( &h ); /* actually r */
363 if( end < *p || (size_t)( end - *p ) < 1 + len || len > 255 )
364 {
365 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
366 goto cleanup;
367 }
368
Joe Subbiani2194dc42021-07-14 12:31:31 +0100369 *(*p)++ = MBEDTLS_BYTE_0( len );
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200370 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, *p, len ) ); /* r */
371 *p += len;
372
373cleanup:
374 mbedtls_ecp_point_free( &V );
375 mbedtls_mpi_free( &v );
376 mbedtls_mpi_free( &h );
377
378 return( ret );
379}
380
381/*
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200382 * Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof
383 * Output: verified public key X
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200384 */
385static int ecjpake_kkp_read( const mbedtls_md_info_t *md_info,
386 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100387 const int pf,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200388 const mbedtls_ecp_point *G,
389 mbedtls_ecp_point *X,
390 const char *id,
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200391 const unsigned char **p,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200392 const unsigned char *end )
393{
Janos Follath24eed8d2019-11-22 13:21:35 +0000394 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200395
396 if( end < *p )
397 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
398
399 /*
400 * struct {
401 * ECPoint X;
402 * ECSchnorrZKP zkp;
403 * } ECJPAKEKeyKP;
404 */
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200405 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, X, p, end - *p ) );
Manuel Pégourié-Gonnard30590952015-08-17 10:37:40 +0200406 if( mbedtls_ecp_is_zero( X ) )
407 {
408 ret = MBEDTLS_ERR_ECP_INVALID_KEY;
409 goto cleanup;
410 }
411
Robert Cragie7cdad772015-10-02 13:31:41 +0100412 MBEDTLS_MPI_CHK( ecjpake_zkp_read( md_info, grp, pf, G, X, id, p, end ) );
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200413
414cleanup:
415 return( ret );
416}
417
418/*
419 * Generate an ECJPAKEKeyKP
420 * Output: the serialized structure, plus private/public key pair
421 */
422static int ecjpake_kkp_write( const mbedtls_md_info_t *md_info,
423 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100424 const int pf,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200425 const mbedtls_ecp_point *G,
426 mbedtls_mpi *x,
427 mbedtls_ecp_point *X,
428 const char *id,
429 unsigned char **p,
430 const unsigned char *end,
431 int (*f_rng)(void *, unsigned char *, size_t),
432 void *p_rng )
433{
Janos Follath24eed8d2019-11-22 13:21:35 +0000434 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200435 size_t len;
436
437 if( end < *p )
438 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
439
440 /* Generate key (7.4.2.3.1) and write it out */
441 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp, G, x, X,
442 f_rng, p_rng ) );
443 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, X,
Robert Cragie7cdad772015-10-02 13:31:41 +0100444 pf, &len, *p, end - *p ) );
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200445 *p += len;
446
447 /* Generate and write proof */
Robert Cragie7cdad772015-10-02 13:31:41 +0100448 MBEDTLS_MPI_CHK( ecjpake_zkp_write( md_info, grp, pf, G, x, X, id,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200449 p, end, f_rng, p_rng ) );
450
451cleanup:
452 return( ret );
453}
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200454
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200455/*
456 * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs
457 * Ouputs: verified peer public keys Xa, Xb
458 */
459static int ecjpake_kkpp_read( const mbedtls_md_info_t *md_info,
460 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100461 const int pf,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200462 const mbedtls_ecp_point *G,
463 mbedtls_ecp_point *Xa,
464 mbedtls_ecp_point *Xb,
465 const char *id,
466 const unsigned char *buf,
467 size_t len )
468{
Janos Follath24eed8d2019-11-22 13:21:35 +0000469 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200470 const unsigned char *p = buf;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200471 const unsigned char *end = buf + len;
472
473 /*
474 * struct {
475 * ECJPAKEKeyKP ecjpake_key_kp_pair_list[2];
476 * } ECJPAKEKeyKPPairList;
477 */
Robert Cragie7cdad772015-10-02 13:31:41 +0100478 MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xa, id, &p, end ) );
479 MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xb, id, &p, end ) );
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200480
481 if( p != end )
482 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
483
484cleanup:
485 return( ret );
486}
487
488/*
489 * Generate a ECJPAKEKeyKPPairList
490 * Outputs: the serialized structure, plus two private/public key pairs
491 */
492static int ecjpake_kkpp_write( const mbedtls_md_info_t *md_info,
493 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100494 const int pf,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200495 const mbedtls_ecp_point *G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200496 mbedtls_mpi *xm1,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200497 mbedtls_ecp_point *Xa,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200498 mbedtls_mpi *xm2,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200499 mbedtls_ecp_point *Xb,
500 const char *id,
501 unsigned char *buf,
502 size_t len,
503 size_t *olen,
504 int (*f_rng)(void *, unsigned char *, size_t),
505 void *p_rng )
506{
Janos Follath24eed8d2019-11-22 13:21:35 +0000507 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200508 unsigned char *p = buf;
509 const unsigned char *end = buf + len;
510
Robert Cragie7cdad772015-10-02 13:31:41 +0100511 MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm1, Xa, id,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200512 &p, end, f_rng, p_rng ) );
Robert Cragie7cdad772015-10-02 13:31:41 +0100513 MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm2, Xb, id,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200514 &p, end, f_rng, p_rng ) );
515
516 *olen = p - buf;
517
518cleanup:
519 return( ret );
520}
521
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200522/*
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200523 * Read and process the first round message
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200524 */
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200525int mbedtls_ecjpake_read_round_one( mbedtls_ecjpake_context *ctx,
526 const unsigned char *buf,
527 size_t len )
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200528{
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000529 ECJPAKE_VALIDATE_RET( ctx != NULL );
530 ECJPAKE_VALIDATE_RET( buf != NULL );
531
Robert Cragie7cdad772015-10-02 13:31:41 +0100532 return( ecjpake_kkpp_read( ctx->md_info, &ctx->grp, ctx->point_format,
533 &ctx->grp.G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200534 &ctx->Xp1, &ctx->Xp2, ID_PEER,
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200535 buf, len ) );
536}
537
538/*
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200539 * Generate and write the first round message
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200540 */
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200541int mbedtls_ecjpake_write_round_one( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200542 unsigned char *buf, size_t len, size_t *olen,
543 int (*f_rng)(void *, unsigned char *, size_t),
544 void *p_rng )
545{
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000546 ECJPAKE_VALIDATE_RET( ctx != NULL );
547 ECJPAKE_VALIDATE_RET( buf != NULL );
548 ECJPAKE_VALIDATE_RET( olen != NULL );
549 ECJPAKE_VALIDATE_RET( f_rng != NULL );
550
Robert Cragie7cdad772015-10-02 13:31:41 +0100551 return( ecjpake_kkpp_write( ctx->md_info, &ctx->grp, ctx->point_format,
552 &ctx->grp.G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200553 &ctx->xm1, &ctx->Xm1, &ctx->xm2, &ctx->Xm2,
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200554 ID_MINE, buf, len, olen, f_rng, p_rng ) );
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200555}
556
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200557/*
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200558 * Compute the sum of three points R = A + B + C
559 */
560static int ecjpake_ecp_add3( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
561 const mbedtls_ecp_point *A,
562 const mbedtls_ecp_point *B,
563 const mbedtls_ecp_point *C )
564{
Janos Follath24eed8d2019-11-22 13:21:35 +0000565 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200566 mbedtls_mpi one;
567
568 mbedtls_mpi_init( &one );
569
570 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
571 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, A, &one, B ) );
572 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, R, &one, C ) );
573
574cleanup:
575 mbedtls_mpi_free( &one );
576
577 return( ret );
578}
579
580/*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200581 * 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 +0200582 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200583int mbedtls_ecjpake_read_round_two( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200584 const unsigned char *buf,
585 size_t len )
586{
Janos Follath24eed8d2019-11-22 13:21:35 +0000587 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200588 const unsigned char *p = buf;
589 const unsigned char *end = buf + len;
590 mbedtls_ecp_group grp;
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200591 mbedtls_ecp_point G; /* C: GB, S: GA */
Hanno Becker185e5162018-12-19 09:48:50 +0000592
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000593 ECJPAKE_VALIDATE_RET( ctx != NULL );
594 ECJPAKE_VALIDATE_RET( buf != NULL );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200595
596 mbedtls_ecp_group_init( &grp );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200597 mbedtls_ecp_point_init( &G );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200598
599 /*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200600 * Server: GA = X3 + X4 + X1 (7.4.2.6.1)
601 * Client: GB = X1 + X2 + X3 (7.4.2.5.1)
602 * Unified: G = Xm1 + Xm2 + Xp1
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200603 * We need that before parsing in order to check Xp as we read it
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200604 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200605 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200606 &ctx->Xm1, &ctx->Xm2, &ctx->Xp1 ) );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200607
608 /*
609 * struct {
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200610 * ECParameters curve_params; // only client reading server msg
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200611 * ECJPAKEKeyKP ecjpake_key_kp;
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200612 * } Client/ServerECJPAKEParams;
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200613 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200614 if( ctx->role == MBEDTLS_ECJPAKE_CLIENT )
Manuel Pégourié-Gonnardd9802af2015-08-17 12:47:38 +0200615 {
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200616 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_group( &grp, &p, len ) );
Manuel Pégourié-Gonnardd9802af2015-08-17 12:47:38 +0200617 if( grp.id != ctx->grp.id )
618 {
619 ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
620 goto cleanup;
621 }
622 }
623
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200624 MBEDTLS_MPI_CHK( ecjpake_kkp_read( ctx->md_info, &ctx->grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100625 ctx->point_format,
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200626 &G, &ctx->Xp, ID_PEER, &p, end ) );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200627
628 if( p != end )
629 {
630 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
631 goto cleanup;
632 }
633
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200634cleanup:
635 mbedtls_ecp_group_free( &grp );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200636 mbedtls_ecp_point_free( &G );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200637
638 return( ret );
639}
640
641/*
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200642 * Compute R = +/- X * S mod N, taking care not to leak S
643 */
644static int ecjpake_mul_secret( mbedtls_mpi *R, int sign,
645 const mbedtls_mpi *X,
646 const mbedtls_mpi *S,
647 const mbedtls_mpi *N,
648 int (*f_rng)(void *, unsigned char *, size_t),
649 void *p_rng )
650{
Janos Follath24eed8d2019-11-22 13:21:35 +0000651 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200652 mbedtls_mpi b; /* Blinding value, then s + N * blinding */
653
654 mbedtls_mpi_init( &b );
655
656 /* b = s + rnd-128-bit * N */
657 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &b, 16, f_rng, p_rng ) );
658 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &b, &b, N ) );
659 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &b, &b, S ) );
660
661 /* R = sign * X * b mod N */
662 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( R, X, &b ) );
663 R->s *= sign;
664 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( R, R, N ) );
665
666cleanup:
667 mbedtls_mpi_free( &b );
668
669 return( ret );
670}
671
672/*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200673 * 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 +0200674 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200675int mbedtls_ecjpake_write_round_two( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200676 unsigned char *buf, size_t len, size_t *olen,
677 int (*f_rng)(void *, unsigned char *, size_t),
678 void *p_rng )
679{
Janos Follath24eed8d2019-11-22 13:21:35 +0000680 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200681 mbedtls_ecp_point G; /* C: GA, S: GB */
682 mbedtls_ecp_point Xm; /* C: Xc, S: Xs */
683 mbedtls_mpi xm; /* C: xc, S: xs */
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200684 unsigned char *p = buf;
685 const unsigned char *end = buf + len;
686 size_t ec_len;
Hanno Becker185e5162018-12-19 09:48:50 +0000687
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000688 ECJPAKE_VALIDATE_RET( ctx != NULL );
689 ECJPAKE_VALIDATE_RET( buf != NULL );
690 ECJPAKE_VALIDATE_RET( olen != NULL );
691 ECJPAKE_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200692
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200693 mbedtls_ecp_point_init( &G );
694 mbedtls_ecp_point_init( &Xm );
695 mbedtls_mpi_init( &xm );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200696
697 /*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200698 * 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 +0200699 *
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200700 * Client: GA = X1 + X3 + X4 | xs = x2 * s | Xc = xc * GA
701 * Server: GB = X3 + X1 + X2 | xs = x4 * s | Xs = xs * GB
702 * Unified: G = Xm1 + Xp1 + Xp2 | xm = xm2 * s | Xm = xm * G
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200703 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200704 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200705 &ctx->Xp1, &ctx->Xp2, &ctx->Xm1 ) );
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200706 MBEDTLS_MPI_CHK( ecjpake_mul_secret( &xm, 1, &ctx->xm2, &ctx->s,
707 &ctx->grp.N, f_rng, p_rng ) );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200708 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &Xm, &xm, &G, f_rng, p_rng ) );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200709
710 /*
711 * Now write things out
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200712 *
713 * struct {
714 * ECParameters curve_params; // only server writing its message
715 * ECJPAKEKeyKP ecjpake_key_kp;
716 * } Client/ServerECJPAKEParams;
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200717 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200718 if( ctx->role == MBEDTLS_ECJPAKE_SERVER )
719 {
720 if( end < p )
721 {
722 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
723 goto cleanup;
724 }
725 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_group( &ctx->grp, &ec_len,
726 p, end - p ) );
727 p += ec_len;
728 }
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200729
730 if( end < p )
731 {
732 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
733 goto cleanup;
734 }
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200735 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( &ctx->grp, &Xm,
Robert Cragie7cdad772015-10-02 13:31:41 +0100736 ctx->point_format, &ec_len, p, end - p ) );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200737 p += ec_len;
738
739 MBEDTLS_MPI_CHK( ecjpake_zkp_write( ctx->md_info, &ctx->grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100740 ctx->point_format,
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200741 &G, &xm, &Xm, ID_MINE,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200742 &p, end, f_rng, p_rng ) );
743
744 *olen = p - buf;
745
746cleanup:
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200747 mbedtls_ecp_point_free( &G );
748 mbedtls_ecp_point_free( &Xm );
749 mbedtls_mpi_free( &xm );
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +0200750
751 return( ret );
752}
753
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200754/*
755 * Derive PMS (7.4.2.7 / 7.4.2.8)
756 */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +0200757int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200758 unsigned char *buf, size_t len, size_t *olen,
759 int (*f_rng)(void *, unsigned char *, size_t),
760 void *p_rng )
761{
Janos Follath24eed8d2019-11-22 13:21:35 +0000762 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200763 mbedtls_ecp_point K;
764 mbedtls_mpi m_xm2_s, one;
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200765 unsigned char kx[MBEDTLS_ECP_MAX_BYTES];
766 size_t x_bytes;
Hanno Becker185e5162018-12-19 09:48:50 +0000767
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000768 ECJPAKE_VALIDATE_RET( ctx != NULL );
769 ECJPAKE_VALIDATE_RET( buf != NULL );
770 ECJPAKE_VALIDATE_RET( olen != NULL );
771 ECJPAKE_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200772
773 *olen = mbedtls_md_get_size( ctx->md_info );
774 if( len < *olen )
775 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
776
777 mbedtls_ecp_point_init( &K );
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200778 mbedtls_mpi_init( &m_xm2_s );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200779 mbedtls_mpi_init( &one );
780
781 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200782
783 /*
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200784 * Client: K = ( Xs - X4 * x2 * s ) * x2
785 * Server: K = ( Xc - X2 * x4 * s ) * x4
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200786 * Unified: K = ( Xp - Xp2 * xm2 * s ) * xm2
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200787 */
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200788 MBEDTLS_MPI_CHK( ecjpake_mul_secret( &m_xm2_s, -1, &ctx->xm2, &ctx->s,
789 &ctx->grp.N, f_rng, p_rng ) );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200790 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( &ctx->grp, &K,
791 &one, &ctx->Xp,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200792 &m_xm2_s, &ctx->Xp2 ) );
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200793 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &K, &ctx->xm2, &K,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200794 f_rng, p_rng ) );
795
796 /* PMS = SHA-256( K.X ) */
797 x_bytes = ( ctx->grp.pbits + 7 ) / 8;
798 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &K.X, kx, x_bytes ) );
799 MBEDTLS_MPI_CHK( mbedtls_md( ctx->md_info, kx, x_bytes, buf ) );
800
801cleanup:
802 mbedtls_ecp_point_free( &K );
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200803 mbedtls_mpi_free( &m_xm2_s );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200804 mbedtls_mpi_free( &one );
805
806 return( ret );
807}
808
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200809#undef ID_MINE
810#undef ID_PEER
811
Hanno Becker616d1ca2018-01-24 10:25:05 +0000812#endif /* ! MBEDTLS_ECJPAKE_ALT */
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200813
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200814#if defined(MBEDTLS_SELF_TEST)
815
816#if defined(MBEDTLS_PLATFORM_C)
817#include "mbedtls/platform.h"
818#else
819#include <stdio.h>
820#define mbedtls_printf printf
821#endif
822
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200823#if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
824 !defined(MBEDTLS_SHA256_C)
825int mbedtls_ecjpake_self_test( int verbose )
826{
827 (void) verbose;
828 return( 0 );
829}
830#else
831
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200832static const unsigned char ecjpake_test_password[] = {
833 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x6a, 0x70, 0x61, 0x6b, 0x65, 0x74,
834 0x65, 0x73, 0x74
835};
836
Steven Cooreman64f27732021-01-11 17:20:10 +0100837#if !defined(MBEDTLS_ECJPAKE_ALT)
838
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200839static const unsigned char ecjpake_test_x1[] = {
840 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
841 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
842 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21
843};
844
845static const unsigned char ecjpake_test_x2[] = {
846 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
847 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
848 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
849};
850
851static const unsigned char ecjpake_test_x3[] = {
852 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
853 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
854 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
855};
856
857static const unsigned char ecjpake_test_x4[] = {
858 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc,
859 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
860 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1
861};
862
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200863static const unsigned char ecjpake_test_cli_one[] = {
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200864 0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19,
865 0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44,
866 0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad,
867 0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62,
868 0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9,
869 0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d,
870 0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e,
871 0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e,
872 0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73,
873 0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22,
874 0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce,
875 0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00,
876 0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200877 0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e,
878 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62,
879 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5,
880 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb,
881 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35,
882 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0,
883 0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb,
884 0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47,
885 0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39,
886 0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97,
887 0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40,
888 0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d,
889 0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa,
890 0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d,
891 0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200892};
893
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200894static const unsigned char ecjpake_test_srv_one[] = {
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200895 0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb,
896 0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18,
897 0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47,
898 0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f,
899 0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7,
900 0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d,
901 0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64,
902 0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36,
903 0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2,
904 0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec,
905 0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16,
906 0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96,
907 0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3,
908 0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19,
909 0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f,
910 0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8,
911 0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7,
912 0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea,
913 0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5,
914 0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6,
915 0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31,
916 0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d,
917 0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8,
918 0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee,
919 0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84,
920 0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f,
921 0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80,
922 0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12
923};
924
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200925static const unsigned char ecjpake_test_srv_two[] = {
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200926 0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23,
927 0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c,
928 0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f,
929 0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca,
930 0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26,
931 0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55,
932 0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38,
933 0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6,
934 0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9,
935 0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4,
936 0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2,
937 0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8,
938 0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd,
939 0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c
940};
941
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200942static const unsigned char ecjpake_test_cli_two[] = {
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +0200943 0x41, 0x04, 0x69, 0xd5, 0x4e, 0xe8, 0x5e, 0x90, 0xce, 0x3f, 0x12, 0x46,
944 0x74, 0x2d, 0xe5, 0x07, 0xe9, 0x39, 0xe8, 0x1d, 0x1d, 0xc1, 0xc5, 0xcb,
945 0x98, 0x8b, 0x58, 0xc3, 0x10, 0xc9, 0xfd, 0xd9, 0x52, 0x4d, 0x93, 0x72,
946 0x0b, 0x45, 0x54, 0x1c, 0x83, 0xee, 0x88, 0x41, 0x19, 0x1d, 0xa7, 0xce,
947 0xd8, 0x6e, 0x33, 0x12, 0xd4, 0x36, 0x23, 0xc1, 0xd6, 0x3e, 0x74, 0x98,
948 0x9a, 0xba, 0x4a, 0xff, 0xd1, 0xee, 0x41, 0x04, 0x07, 0x7e, 0x8c, 0x31,
949 0xe2, 0x0e, 0x6b, 0xed, 0xb7, 0x60, 0xc1, 0x35, 0x93, 0xe6, 0x9f, 0x15,
950 0xbe, 0x85, 0xc2, 0x7d, 0x68, 0xcd, 0x09, 0xcc, 0xb8, 0xc4, 0x18, 0x36,
951 0x08, 0x91, 0x7c, 0x5c, 0x3d, 0x40, 0x9f, 0xac, 0x39, 0xfe, 0xfe, 0xe8,
952 0x2f, 0x72, 0x92, 0xd3, 0x6f, 0x0d, 0x23, 0xe0, 0x55, 0x91, 0x3f, 0x45,
953 0xa5, 0x2b, 0x85, 0xdd, 0x8a, 0x20, 0x52, 0xe9, 0xe1, 0x29, 0xbb, 0x4d,
954 0x20, 0x0f, 0x01, 0x1f, 0x19, 0x48, 0x35, 0x35, 0xa6, 0xe8, 0x9a, 0x58,
955 0x0c, 0x9b, 0x00, 0x03, 0xba, 0xf2, 0x14, 0x62, 0xec, 0xe9, 0x1a, 0x82,
956 0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c
957};
958
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200959static const unsigned char ecjpake_test_pms[] = {
960 0xf3, 0xd4, 0x7f, 0x59, 0x98, 0x44, 0xdb, 0x92, 0xa5, 0x69, 0xbb, 0xe7,
961 0x98, 0x1e, 0x39, 0xd9, 0x31, 0xfd, 0x74, 0x3b, 0xf2, 0x2e, 0x98, 0xf9,
962 0xb4, 0x38, 0xf7, 0x19, 0xd3, 0xc4, 0xf3, 0x51
963};
964
Manuel Pégourié-Gonnardaa3ed6f2021-06-15 11:29:26 +0200965/*
966 * PRNG for test - !!!INSECURE NEVER USE IN PRODUCTION!!!
967 *
968 * This is the linear congruential generator from numerical recipes,
969 * except we only use the low byte as the output. See
970 * https://en.wikipedia.org/wiki/Linear_congruential_generator#Parameters_in_common_use
971 */
972static int self_test_rng( void *ctx, unsigned char *out, size_t len )
973{
974 static uint32_t state = 42;
975
976 (void) ctx;
977
978 for( size_t i = 0; i < len; i++ )
979 {
980 state = state * 1664525u + 1013904223u;
981 out[i] = (unsigned char) state;
982 }
983
984 return( 0 );
985}
986
Antonin Décimo36e89b52019-01-23 15:24:37 +0100987/* Load my private keys and generate the corresponding public keys */
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +0200988static int ecjpake_test_load( mbedtls_ecjpake_context *ctx,
989 const unsigned char *xm1, size_t len1,
990 const unsigned char *xm2, size_t len2 )
991{
Janos Follath24eed8d2019-11-22 13:21:35 +0000992 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +0200993
994 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm1, xm1, len1 ) );
995 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm2, xm2, len2 ) );
996 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm1, &ctx->xm1,
Manuel Pégourié-Gonnardaa3ed6f2021-06-15 11:29:26 +0200997 &ctx->grp.G, self_test_rng, NULL ) );
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +0200998 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm2, &ctx->xm2,
Manuel Pégourié-Gonnardaa3ed6f2021-06-15 11:29:26 +0200999 &ctx->grp.G, self_test_rng, NULL ) );
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001000
1001cleanup:
1002 return( ret );
1003}
1004
Steven Cooreman64f27732021-01-11 17:20:10 +01001005#endif /* ! MBEDTLS_ECJPAKE_ALT */
1006
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001007/* For tests we don't need a secure RNG;
1008 * use the LGC from Numerical Recipes for simplicity */
1009static int ecjpake_lgc( void *p, unsigned char *out, size_t len )
1010{
1011 static uint32_t x = 42;
1012 (void) p;
1013
1014 while( len > 0 )
1015 {
1016 size_t use_len = len > 4 ? 4 : len;
1017 x = 1664525 * x + 1013904223;
1018 memcpy( out, &x, use_len );
1019 out += use_len;
1020 len -= use_len;
1021 }
1022
1023 return( 0 );
1024}
1025
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +02001026#define TEST_ASSERT( x ) \
1027 do { \
1028 if( x ) \
1029 ret = 0; \
1030 else \
1031 { \
1032 ret = 1; \
1033 goto cleanup; \
1034 } \
1035 } while( 0 )
1036
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001037/*
1038 * Checkup routine
1039 */
1040int mbedtls_ecjpake_self_test( int verbose )
1041{
Janos Follath24eed8d2019-11-22 13:21:35 +00001042 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001043 mbedtls_ecjpake_context cli;
1044 mbedtls_ecjpake_context srv;
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001045 unsigned char buf[512], pms[32];
1046 size_t len, pmslen;
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001047
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001048 mbedtls_ecjpake_init( &cli );
1049 mbedtls_ecjpake_init( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001050
1051 if( verbose != 0 )
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001052 mbedtls_printf( " ECJPAKE test #0 (setup): " );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +02001053
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +02001054 TEST_ASSERT( mbedtls_ecjpake_setup( &cli, MBEDTLS_ECJPAKE_CLIENT,
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 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001058
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +02001059 TEST_ASSERT( mbedtls_ecjpake_setup( &srv, MBEDTLS_ECJPAKE_SERVER,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001060 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1061 ecjpake_test_password,
1062 sizeof( ecjpake_test_password ) ) == 0 );
1063
1064 if( verbose != 0 )
1065 mbedtls_printf( "passed\n" );
1066
1067 if( verbose != 0 )
1068 mbedtls_printf( " ECJPAKE test #1 (random handshake): " );
1069
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001070 TEST_ASSERT( mbedtls_ecjpake_write_round_one( &cli,
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( &srv, buf, len ) == 0 );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001074
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001075 TEST_ASSERT( mbedtls_ecjpake_write_round_one( &srv,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001076 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1077
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001078 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli, buf, len ) == 0 );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001079
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001080 TEST_ASSERT( mbedtls_ecjpake_write_round_two( &srv,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +02001081 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1082
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001083 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli, buf, len ) == 0 );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +02001084
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001085 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001086 pms, sizeof( pms ), &pmslen, ecjpake_lgc, NULL ) == 0 );
1087
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001088 TEST_ASSERT( mbedtls_ecjpake_write_round_two( &cli,
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +02001089 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1090
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001091 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv, buf, len ) == 0 );
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +02001092
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001093 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001094 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1095
1096 TEST_ASSERT( len == pmslen );
1097 TEST_ASSERT( memcmp( buf, pms, len ) == 0 );
1098
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001099 if( verbose != 0 )
1100 mbedtls_printf( "passed\n" );
1101
Steven Cooreman64f27732021-01-11 17:20:10 +01001102#if !defined(MBEDTLS_ECJPAKE_ALT)
1103 /* 'reference handshake' tests can only be run against implementations
1104 * for which we have 100% control over how the random ephemeral keys
1105 * are generated. This is only the case for the internal mbed TLS
1106 * implementation, so these tests are skipped in case the internal
1107 * implementation is swapped out for an alternative one. */
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001108 if( verbose != 0 )
1109 mbedtls_printf( " ECJPAKE test #2 (reference handshake): " );
1110
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001111 /* Simulate generation of round one */
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001112 MBEDTLS_MPI_CHK( ecjpake_test_load( &cli,
1113 ecjpake_test_x1, sizeof( ecjpake_test_x1 ),
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001114 ecjpake_test_x2, sizeof( ecjpake_test_x2 ) ) );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001115
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001116 MBEDTLS_MPI_CHK( ecjpake_test_load( &srv,
1117 ecjpake_test_x3, sizeof( ecjpake_test_x3 ),
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001118 ecjpake_test_x4, sizeof( ecjpake_test_x4 ) ) );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001119
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001120 /* Read round one */
1121 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv,
1122 ecjpake_test_cli_one,
1123 sizeof( ecjpake_test_cli_one ) ) == 0 );
1124
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001125 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001126 ecjpake_test_srv_one,
1127 sizeof( ecjpake_test_srv_one ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001128
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001129 /* Skip generation of round two, read round two */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001130 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001131 ecjpake_test_srv_two,
1132 sizeof( ecjpake_test_srv_two ) ) == 0 );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +02001133
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001134 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001135 ecjpake_test_cli_two,
1136 sizeof( ecjpake_test_cli_two ) ) == 0 );
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +02001137
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001138 /* Server derives PMS */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001139 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001140 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1141
1142 TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
1143 TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
1144
1145 memset( buf, 0, len ); /* Avoid interferences with next step */
1146
1147 /* Client derives PMS */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001148 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001149 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1150
1151 TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
1152 TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
1153
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001154 if( verbose != 0 )
1155 mbedtls_printf( "passed\n" );
Steven Cooreman64f27732021-01-11 17:20:10 +01001156#endif /* ! MBEDTLS_ECJPAKE_ALT */
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001157
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001158cleanup:
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001159 mbedtls_ecjpake_free( &cli );
1160 mbedtls_ecjpake_free( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001161
1162 if( ret != 0 )
1163 {
1164 if( verbose != 0 )
1165 mbedtls_printf( "failed\n" );
1166
1167 ret = 1;
1168 }
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001169
1170 if( verbose != 0 )
1171 mbedtls_printf( "\n" );
1172
1173 return( ret );
1174}
1175
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +02001176#undef TEST_ASSERT
1177
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001178#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_SHA256_C */
1179
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001180#endif /* MBEDTLS_SELF_TEST */
1181
1182#endif /* MBEDTLS_ECJPAKE_C */