blob: b835ac1c21ceed58b0a51ec66072e08058dc0879 [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
131/*
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200132 * Check if context is ready for use
133 */
134int mbedtls_ecjpake_check( const mbedtls_ecjpake_context *ctx )
135{
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000136 ECJPAKE_VALIDATE_RET( ctx != NULL );
137
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200138 if( ctx->md_info == NULL ||
139 ctx->grp.id == MBEDTLS_ECP_DP_NONE ||
140 ctx->s.p == NULL )
141 {
142 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
143 }
144
145 return( 0 );
146}
147
148/*
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200149 * Write a point plus its length to a buffer
150 */
151static int ecjpake_write_len_point( unsigned char **p,
152 const unsigned char *end,
153 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100154 const int pf,
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200155 const mbedtls_ecp_point *P )
156{
Janos Follath24eed8d2019-11-22 13:21:35 +0000157 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200158 size_t len;
159
160 /* Need at least 4 for length plus 1 for point */
161 if( end < *p || end - *p < 5 )
162 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
163
Robert Cragie7cdad772015-10-02 13:31:41 +0100164 ret = mbedtls_ecp_point_write_binary( grp, P, pf,
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200165 &len, *p + 4, end - ( *p + 4 ) );
166 if( ret != 0 )
167 return( ret );
168
169 (*p)[0] = (unsigned char)( ( len >> 24 ) & 0xFF );
170 (*p)[1] = (unsigned char)( ( len >> 16 ) & 0xFF );
171 (*p)[2] = (unsigned char)( ( len >> 8 ) & 0xFF );
172 (*p)[3] = (unsigned char)( ( len ) & 0xFF );
173
174 *p += 4 + len;
175
176 return( 0 );
177}
178
179/*
180 * Size of the temporary buffer for ecjpake_hash:
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200181 * 3 EC points plus their length, plus ID and its length (4 + 6 bytes)
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200182 */
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200183#define ECJPAKE_HASH_BUF_LEN ( 3 * ( 4 + MBEDTLS_ECP_MAX_PT_LEN ) + 4 + 6 )
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200184
185/*
186 * Compute hash for ZKP (7.4.2.2.2.1)
187 */
188static int ecjpake_hash( const mbedtls_md_info_t *md_info,
189 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100190 const int pf,
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200191 const mbedtls_ecp_point *G,
192 const mbedtls_ecp_point *V,
193 const mbedtls_ecp_point *X,
194 const char *id,
195 mbedtls_mpi *h )
196{
Janos Follath24eed8d2019-11-22 13:21:35 +0000197 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200198 unsigned char buf[ECJPAKE_HASH_BUF_LEN];
199 unsigned char *p = buf;
200 const unsigned char *end = buf + sizeof( buf );
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200201 const size_t id_len = strlen( id );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200202 unsigned char hash[MBEDTLS_MD_MAX_SIZE];
203
204 /* Write things to temporary buffer */
Robert Cragie7cdad772015-10-02 13:31:41 +0100205 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, G ) );
206 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, V ) );
207 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, X ) );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200208
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200209 if( end - p < 4 )
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200210 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
211
212 *p++ = (unsigned char)( ( id_len >> 24 ) & 0xFF );
213 *p++ = (unsigned char)( ( id_len >> 16 ) & 0xFF );
214 *p++ = (unsigned char)( ( id_len >> 8 ) & 0xFF );
215 *p++ = (unsigned char)( ( id_len ) & 0xFF );
216
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200217 if( end < p || (size_t)( end - p ) < id_len )
218 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
219
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200220 memcpy( p, id, id_len );
221 p += id_len;
222
223 /* Compute hash */
k-stachowiak41503352019-06-28 14:14:02 +0200224 MBEDTLS_MPI_CHK( mbedtls_md( md_info, buf, p - buf, hash ) );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200225
226 /* Turn it into an integer mod n */
227 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( h, hash,
228 mbedtls_md_get_size( md_info ) ) );
229 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( h, h, &grp->N ) );
230
231cleanup:
232 return( ret );
233}
234
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200235/*
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200236 * Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3)
237 */
238static int ecjpake_zkp_read( const mbedtls_md_info_t *md_info,
239 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100240 const int pf,
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200241 const mbedtls_ecp_point *G,
242 const mbedtls_ecp_point *X,
243 const char *id,
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200244 const unsigned char **p,
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200245 const unsigned char *end )
246{
Janos Follath24eed8d2019-11-22 13:21:35 +0000247 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200248 mbedtls_ecp_point V, VV;
249 mbedtls_mpi r, h;
250 size_t r_len;
251
252 mbedtls_ecp_point_init( &V );
253 mbedtls_ecp_point_init( &VV );
254 mbedtls_mpi_init( &r );
255 mbedtls_mpi_init( &h );
256
257 /*
258 * struct {
259 * ECPoint V;
260 * opaque r<1..2^8-1>;
261 * } ECSchnorrZKP;
262 */
263 if( end < *p )
264 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
265
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200266 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, &V, p, end - *p ) );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200267
268 if( end < *p || (size_t)( end - *p ) < 1 )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200269 {
270 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
271 goto cleanup;
272 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200273
274 r_len = *(*p)++;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200275
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200276 if( end < *p || (size_t)( end - *p ) < r_len )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200277 {
278 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
279 goto cleanup;
280 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200281
282 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &r, *p, r_len ) );
283 *p += r_len;
284
285 /*
286 * Verification
287 */
Robert Cragie7cdad772015-10-02 13:31:41 +0100288 MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) );
TRodziewicz28b61072021-02-24 14:01:40 +0100289
290 if( mbedtls_mpi_cmp_int( &r,0 ) == 0 )
291 {
292 ret = MBEDTLS_ERR_ECP_INVALID_KEY;
293 goto cleanup;
294 }
295
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200296 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( (mbedtls_ecp_group *) grp,
297 &VV, &h, X, &r, G ) );
298
299 if( mbedtls_ecp_point_cmp( &VV, &V ) != 0 )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200300 {
301 ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
302 goto cleanup;
303 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200304
305cleanup:
306 mbedtls_ecp_point_free( &V );
307 mbedtls_ecp_point_free( &VV );
308 mbedtls_mpi_free( &r );
309 mbedtls_mpi_free( &h );
310
311 return( ret );
312}
313
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200314/*
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200315 * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2)
316 */
317static int ecjpake_zkp_write( const mbedtls_md_info_t *md_info,
318 const mbedtls_ecp_group *grp,
Darryl Green11999bb2018-03-13 15:22:58 +0000319 const int pf,
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200320 const mbedtls_ecp_point *G,
321 const mbedtls_mpi *x,
322 const mbedtls_ecp_point *X,
323 const char *id,
324 unsigned char **p,
325 const unsigned char *end,
326 int (*f_rng)(void *, unsigned char *, size_t),
327 void *p_rng )
328{
Janos Follath24eed8d2019-11-22 13:21:35 +0000329 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200330 mbedtls_ecp_point V;
331 mbedtls_mpi v;
332 mbedtls_mpi h; /* later recycled to hold r */
333 size_t len;
334
335 if( end < *p )
336 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
337
338 mbedtls_ecp_point_init( &V );
339 mbedtls_mpi_init( &v );
340 mbedtls_mpi_init( &h );
341
342 /* Compute signature */
343 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp,
344 G, &v, &V, f_rng, p_rng ) );
Robert Cragie7cdad772015-10-02 13:31:41 +0100345 MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) );
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200346 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &h, &h, x ) ); /* x*h */
347 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &h, &v, &h ) ); /* v - x*h */
348 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &h, &h, &grp->N ) ); /* r */
349
350 /* Write it out */
351 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, &V,
Robert Cragie7cdad772015-10-02 13:31:41 +0100352 pf, &len, *p, end - *p ) );
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200353 *p += len;
354
355 len = mbedtls_mpi_size( &h ); /* actually r */
356 if( end < *p || (size_t)( end - *p ) < 1 + len || len > 255 )
357 {
358 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
359 goto cleanup;
360 }
361
362 *(*p)++ = (unsigned char)( len & 0xFF );
363 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, *p, len ) ); /* r */
364 *p += len;
365
366cleanup:
367 mbedtls_ecp_point_free( &V );
368 mbedtls_mpi_free( &v );
369 mbedtls_mpi_free( &h );
370
371 return( ret );
372}
373
374/*
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200375 * Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof
376 * Output: verified public key X
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200377 */
378static int ecjpake_kkp_read( const mbedtls_md_info_t *md_info,
379 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100380 const int pf,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200381 const mbedtls_ecp_point *G,
382 mbedtls_ecp_point *X,
383 const char *id,
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200384 const unsigned char **p,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200385 const unsigned char *end )
386{
Janos Follath24eed8d2019-11-22 13:21:35 +0000387 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200388
389 if( end < *p )
390 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
391
392 /*
393 * struct {
394 * ECPoint X;
395 * ECSchnorrZKP zkp;
396 * } ECJPAKEKeyKP;
397 */
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200398 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, X, p, end - *p ) );
Manuel Pégourié-Gonnard30590952015-08-17 10:37:40 +0200399 if( mbedtls_ecp_is_zero( X ) )
400 {
401 ret = MBEDTLS_ERR_ECP_INVALID_KEY;
402 goto cleanup;
403 }
404
Robert Cragie7cdad772015-10-02 13:31:41 +0100405 MBEDTLS_MPI_CHK( ecjpake_zkp_read( md_info, grp, pf, G, X, id, p, end ) );
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200406
407cleanup:
408 return( ret );
409}
410
411/*
412 * Generate an ECJPAKEKeyKP
413 * Output: the serialized structure, plus private/public key pair
414 */
415static int ecjpake_kkp_write( const mbedtls_md_info_t *md_info,
416 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100417 const int pf,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200418 const mbedtls_ecp_point *G,
419 mbedtls_mpi *x,
420 mbedtls_ecp_point *X,
421 const char *id,
422 unsigned char **p,
423 const unsigned char *end,
424 int (*f_rng)(void *, unsigned char *, size_t),
425 void *p_rng )
426{
Janos Follath24eed8d2019-11-22 13:21:35 +0000427 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200428 size_t len;
429
430 if( end < *p )
431 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
432
433 /* Generate key (7.4.2.3.1) and write it out */
434 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp, G, x, X,
435 f_rng, p_rng ) );
436 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, X,
Robert Cragie7cdad772015-10-02 13:31:41 +0100437 pf, &len, *p, end - *p ) );
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200438 *p += len;
439
440 /* Generate and write proof */
Robert Cragie7cdad772015-10-02 13:31:41 +0100441 MBEDTLS_MPI_CHK( ecjpake_zkp_write( md_info, grp, pf, G, x, X, id,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200442 p, end, f_rng, p_rng ) );
443
444cleanup:
445 return( ret );
446}
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200447
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200448/*
449 * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs
450 * Ouputs: verified peer public keys Xa, Xb
451 */
452static int ecjpake_kkpp_read( const mbedtls_md_info_t *md_info,
453 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100454 const int pf,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200455 const mbedtls_ecp_point *G,
456 mbedtls_ecp_point *Xa,
457 mbedtls_ecp_point *Xb,
458 const char *id,
459 const unsigned char *buf,
460 size_t len )
461{
Janos Follath24eed8d2019-11-22 13:21:35 +0000462 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200463 const unsigned char *p = buf;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200464 const unsigned char *end = buf + len;
465
466 /*
467 * struct {
468 * ECJPAKEKeyKP ecjpake_key_kp_pair_list[2];
469 * } ECJPAKEKeyKPPairList;
470 */
Robert Cragie7cdad772015-10-02 13:31:41 +0100471 MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xa, id, &p, end ) );
472 MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xb, id, &p, end ) );
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200473
474 if( p != end )
475 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
476
477cleanup:
478 return( ret );
479}
480
481/*
482 * Generate a ECJPAKEKeyKPPairList
483 * Outputs: the serialized structure, plus two private/public key pairs
484 */
485static int ecjpake_kkpp_write( const mbedtls_md_info_t *md_info,
486 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100487 const int pf,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200488 const mbedtls_ecp_point *G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200489 mbedtls_mpi *xm1,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200490 mbedtls_ecp_point *Xa,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200491 mbedtls_mpi *xm2,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200492 mbedtls_ecp_point *Xb,
493 const char *id,
494 unsigned char *buf,
495 size_t len,
496 size_t *olen,
497 int (*f_rng)(void *, unsigned char *, size_t),
498 void *p_rng )
499{
Janos Follath24eed8d2019-11-22 13:21:35 +0000500 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200501 unsigned char *p = buf;
502 const unsigned char *end = buf + len;
503
Robert Cragie7cdad772015-10-02 13:31:41 +0100504 MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm1, Xa, id,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200505 &p, end, f_rng, p_rng ) );
Robert Cragie7cdad772015-10-02 13:31:41 +0100506 MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm2, Xb, id,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200507 &p, end, f_rng, p_rng ) );
508
509 *olen = p - buf;
510
511cleanup:
512 return( ret );
513}
514
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200515/*
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200516 * Read and process the first round message
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200517 */
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200518int mbedtls_ecjpake_read_round_one( mbedtls_ecjpake_context *ctx,
519 const unsigned char *buf,
520 size_t len )
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200521{
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000522 ECJPAKE_VALIDATE_RET( ctx != NULL );
523 ECJPAKE_VALIDATE_RET( buf != NULL );
524
Robert Cragie7cdad772015-10-02 13:31:41 +0100525 return( ecjpake_kkpp_read( ctx->md_info, &ctx->grp, ctx->point_format,
526 &ctx->grp.G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200527 &ctx->Xp1, &ctx->Xp2, ID_PEER,
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200528 buf, len ) );
529}
530
531/*
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200532 * Generate and write the first round message
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200533 */
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200534int mbedtls_ecjpake_write_round_one( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200535 unsigned char *buf, size_t len, size_t *olen,
536 int (*f_rng)(void *, unsigned char *, size_t),
537 void *p_rng )
538{
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000539 ECJPAKE_VALIDATE_RET( ctx != NULL );
540 ECJPAKE_VALIDATE_RET( buf != NULL );
541 ECJPAKE_VALIDATE_RET( olen != NULL );
542 ECJPAKE_VALIDATE_RET( f_rng != NULL );
543
Robert Cragie7cdad772015-10-02 13:31:41 +0100544 return( ecjpake_kkpp_write( ctx->md_info, &ctx->grp, ctx->point_format,
545 &ctx->grp.G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200546 &ctx->xm1, &ctx->Xm1, &ctx->xm2, &ctx->Xm2,
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200547 ID_MINE, buf, len, olen, f_rng, p_rng ) );
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200548}
549
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200550/*
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200551 * Compute the sum of three points R = A + B + C
552 */
553static int ecjpake_ecp_add3( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
554 const mbedtls_ecp_point *A,
555 const mbedtls_ecp_point *B,
556 const mbedtls_ecp_point *C )
557{
Janos Follath24eed8d2019-11-22 13:21:35 +0000558 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200559 mbedtls_mpi one;
560
561 mbedtls_mpi_init( &one );
562
563 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
564 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, A, &one, B ) );
565 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, R, &one, C ) );
566
567cleanup:
568 mbedtls_mpi_free( &one );
569
570 return( ret );
571}
572
573/*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200574 * 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 +0200575 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200576int mbedtls_ecjpake_read_round_two( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200577 const unsigned char *buf,
578 size_t len )
579{
Janos Follath24eed8d2019-11-22 13:21:35 +0000580 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200581 const unsigned char *p = buf;
582 const unsigned char *end = buf + len;
583 mbedtls_ecp_group grp;
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200584 mbedtls_ecp_point G; /* C: GB, S: GA */
Hanno Becker185e5162018-12-19 09:48:50 +0000585
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000586 ECJPAKE_VALIDATE_RET( ctx != NULL );
587 ECJPAKE_VALIDATE_RET( buf != NULL );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200588
589 mbedtls_ecp_group_init( &grp );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200590 mbedtls_ecp_point_init( &G );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200591
592 /*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200593 * Server: GA = X3 + X4 + X1 (7.4.2.6.1)
594 * Client: GB = X1 + X2 + X3 (7.4.2.5.1)
595 * Unified: G = Xm1 + Xm2 + Xp1
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200596 * We need that before parsing in order to check Xp as we read it
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200597 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200598 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200599 &ctx->Xm1, &ctx->Xm2, &ctx->Xp1 ) );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200600
601 /*
602 * struct {
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200603 * ECParameters curve_params; // only client reading server msg
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200604 * ECJPAKEKeyKP ecjpake_key_kp;
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200605 * } Client/ServerECJPAKEParams;
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200606 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200607 if( ctx->role == MBEDTLS_ECJPAKE_CLIENT )
Manuel Pégourié-Gonnardd9802af2015-08-17 12:47:38 +0200608 {
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200609 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_group( &grp, &p, len ) );
Manuel Pégourié-Gonnardd9802af2015-08-17 12:47:38 +0200610 if( grp.id != ctx->grp.id )
611 {
612 ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
613 goto cleanup;
614 }
615 }
616
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200617 MBEDTLS_MPI_CHK( ecjpake_kkp_read( ctx->md_info, &ctx->grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100618 ctx->point_format,
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200619 &G, &ctx->Xp, ID_PEER, &p, end ) );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200620
621 if( p != end )
622 {
623 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
624 goto cleanup;
625 }
626
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200627cleanup:
628 mbedtls_ecp_group_free( &grp );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200629 mbedtls_ecp_point_free( &G );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200630
631 return( ret );
632}
633
634/*
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200635 * Compute R = +/- X * S mod N, taking care not to leak S
636 */
637static int ecjpake_mul_secret( mbedtls_mpi *R, int sign,
638 const mbedtls_mpi *X,
639 const mbedtls_mpi *S,
640 const mbedtls_mpi *N,
641 int (*f_rng)(void *, unsigned char *, size_t),
642 void *p_rng )
643{
Janos Follath24eed8d2019-11-22 13:21:35 +0000644 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200645 mbedtls_mpi b; /* Blinding value, then s + N * blinding */
646
647 mbedtls_mpi_init( &b );
648
649 /* b = s + rnd-128-bit * N */
650 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &b, 16, f_rng, p_rng ) );
651 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &b, &b, N ) );
652 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &b, &b, S ) );
653
654 /* R = sign * X * b mod N */
655 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( R, X, &b ) );
656 R->s *= sign;
657 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( R, R, N ) );
658
659cleanup:
660 mbedtls_mpi_free( &b );
661
662 return( ret );
663}
664
665/*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200666 * 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 +0200667 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200668int mbedtls_ecjpake_write_round_two( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200669 unsigned char *buf, size_t len, size_t *olen,
670 int (*f_rng)(void *, unsigned char *, size_t),
671 void *p_rng )
672{
Janos Follath24eed8d2019-11-22 13:21:35 +0000673 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200674 mbedtls_ecp_point G; /* C: GA, S: GB */
675 mbedtls_ecp_point Xm; /* C: Xc, S: Xs */
676 mbedtls_mpi xm; /* C: xc, S: xs */
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200677 unsigned char *p = buf;
678 const unsigned char *end = buf + len;
679 size_t ec_len;
Hanno Becker185e5162018-12-19 09:48:50 +0000680
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000681 ECJPAKE_VALIDATE_RET( ctx != NULL );
682 ECJPAKE_VALIDATE_RET( buf != NULL );
683 ECJPAKE_VALIDATE_RET( olen != NULL );
684 ECJPAKE_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200685
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200686 mbedtls_ecp_point_init( &G );
687 mbedtls_ecp_point_init( &Xm );
688 mbedtls_mpi_init( &xm );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200689
690 /*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200691 * 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 +0200692 *
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200693 * Client: GA = X1 + X3 + X4 | xs = x2 * s | Xc = xc * GA
694 * Server: GB = X3 + X1 + X2 | xs = x4 * s | Xs = xs * GB
695 * Unified: G = Xm1 + Xp1 + Xp2 | xm = xm2 * s | Xm = xm * G
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200696 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200697 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200698 &ctx->Xp1, &ctx->Xp2, &ctx->Xm1 ) );
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200699 MBEDTLS_MPI_CHK( ecjpake_mul_secret( &xm, 1, &ctx->xm2, &ctx->s,
700 &ctx->grp.N, f_rng, p_rng ) );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200701 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &Xm, &xm, &G, f_rng, p_rng ) );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200702
703 /*
704 * Now write things out
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200705 *
706 * struct {
707 * ECParameters curve_params; // only server writing its message
708 * ECJPAKEKeyKP ecjpake_key_kp;
709 * } Client/ServerECJPAKEParams;
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200710 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200711 if( ctx->role == MBEDTLS_ECJPAKE_SERVER )
712 {
713 if( end < p )
714 {
715 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
716 goto cleanup;
717 }
718 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_group( &ctx->grp, &ec_len,
719 p, end - p ) );
720 p += ec_len;
721 }
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200722
723 if( end < p )
724 {
725 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
726 goto cleanup;
727 }
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200728 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( &ctx->grp, &Xm,
Robert Cragie7cdad772015-10-02 13:31:41 +0100729 ctx->point_format, &ec_len, p, end - p ) );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200730 p += ec_len;
731
732 MBEDTLS_MPI_CHK( ecjpake_zkp_write( ctx->md_info, &ctx->grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100733 ctx->point_format,
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200734 &G, &xm, &Xm, ID_MINE,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200735 &p, end, f_rng, p_rng ) );
736
737 *olen = p - buf;
738
739cleanup:
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200740 mbedtls_ecp_point_free( &G );
741 mbedtls_ecp_point_free( &Xm );
742 mbedtls_mpi_free( &xm );
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +0200743
744 return( ret );
745}
746
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200747/*
748 * Derive PMS (7.4.2.7 / 7.4.2.8)
749 */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +0200750int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200751 unsigned char *buf, size_t len, size_t *olen,
752 int (*f_rng)(void *, unsigned char *, size_t),
753 void *p_rng )
754{
Janos Follath24eed8d2019-11-22 13:21:35 +0000755 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200756 mbedtls_ecp_point K;
757 mbedtls_mpi m_xm2_s, one;
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200758 unsigned char kx[MBEDTLS_ECP_MAX_BYTES];
759 size_t x_bytes;
Hanno Becker185e5162018-12-19 09:48:50 +0000760
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000761 ECJPAKE_VALIDATE_RET( ctx != NULL );
762 ECJPAKE_VALIDATE_RET( buf != NULL );
763 ECJPAKE_VALIDATE_RET( olen != NULL );
764 ECJPAKE_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200765
766 *olen = mbedtls_md_get_size( ctx->md_info );
767 if( len < *olen )
768 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
769
770 mbedtls_ecp_point_init( &K );
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200771 mbedtls_mpi_init( &m_xm2_s );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200772 mbedtls_mpi_init( &one );
773
774 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200775
776 /*
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200777 * Client: K = ( Xs - X4 * x2 * s ) * x2
778 * Server: K = ( Xc - X2 * x4 * s ) * x4
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200779 * Unified: K = ( Xp - Xp2 * xm2 * s ) * xm2
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200780 */
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200781 MBEDTLS_MPI_CHK( ecjpake_mul_secret( &m_xm2_s, -1, &ctx->xm2, &ctx->s,
782 &ctx->grp.N, f_rng, p_rng ) );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200783 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( &ctx->grp, &K,
784 &one, &ctx->Xp,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200785 &m_xm2_s, &ctx->Xp2 ) );
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200786 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &K, &ctx->xm2, &K,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200787 f_rng, p_rng ) );
788
789 /* PMS = SHA-256( K.X ) */
790 x_bytes = ( ctx->grp.pbits + 7 ) / 8;
791 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &K.X, kx, x_bytes ) );
792 MBEDTLS_MPI_CHK( mbedtls_md( ctx->md_info, kx, x_bytes, buf ) );
793
794cleanup:
795 mbedtls_ecp_point_free( &K );
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200796 mbedtls_mpi_free( &m_xm2_s );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200797 mbedtls_mpi_free( &one );
798
799 return( ret );
800}
801
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200802#undef ID_MINE
803#undef ID_PEER
804
Hanno Becker616d1ca2018-01-24 10:25:05 +0000805#endif /* ! MBEDTLS_ECJPAKE_ALT */
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200806
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200807#if defined(MBEDTLS_SELF_TEST)
808
809#if defined(MBEDTLS_PLATFORM_C)
810#include "mbedtls/platform.h"
811#else
812#include <stdio.h>
813#define mbedtls_printf printf
814#endif
815
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200816#if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
817 !defined(MBEDTLS_SHA256_C)
818int mbedtls_ecjpake_self_test( int verbose )
819{
820 (void) verbose;
821 return( 0 );
822}
823#else
824
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200825static const unsigned char ecjpake_test_password[] = {
826 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x6a, 0x70, 0x61, 0x6b, 0x65, 0x74,
827 0x65, 0x73, 0x74
828};
829
Steven Cooreman64f27732021-01-11 17:20:10 +0100830#if !defined(MBEDTLS_ECJPAKE_ALT)
831
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200832static const unsigned char ecjpake_test_x1[] = {
833 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
834 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
835 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21
836};
837
838static const unsigned char ecjpake_test_x2[] = {
839 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
840 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
841 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
842};
843
844static const unsigned char ecjpake_test_x3[] = {
845 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
846 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
847 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
848};
849
850static const unsigned char ecjpake_test_x4[] = {
851 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc,
852 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
853 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1
854};
855
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200856static const unsigned char ecjpake_test_cli_one[] = {
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200857 0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19,
858 0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44,
859 0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad,
860 0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62,
861 0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9,
862 0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d,
863 0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e,
864 0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e,
865 0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73,
866 0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22,
867 0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce,
868 0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00,
869 0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200870 0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e,
871 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62,
872 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5,
873 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb,
874 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35,
875 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0,
876 0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb,
877 0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47,
878 0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39,
879 0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97,
880 0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40,
881 0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d,
882 0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa,
883 0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d,
884 0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200885};
886
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200887static const unsigned char ecjpake_test_srv_one[] = {
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200888 0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb,
889 0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18,
890 0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47,
891 0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f,
892 0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7,
893 0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d,
894 0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64,
895 0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36,
896 0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2,
897 0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec,
898 0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16,
899 0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96,
900 0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3,
901 0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19,
902 0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f,
903 0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8,
904 0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7,
905 0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea,
906 0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5,
907 0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6,
908 0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31,
909 0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d,
910 0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8,
911 0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee,
912 0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84,
913 0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f,
914 0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80,
915 0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12
916};
917
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200918static const unsigned char ecjpake_test_srv_two[] = {
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200919 0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23,
920 0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c,
921 0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f,
922 0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca,
923 0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26,
924 0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55,
925 0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38,
926 0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6,
927 0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9,
928 0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4,
929 0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2,
930 0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8,
931 0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd,
932 0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c
933};
934
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200935static const unsigned char ecjpake_test_cli_two[] = {
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +0200936 0x41, 0x04, 0x69, 0xd5, 0x4e, 0xe8, 0x5e, 0x90, 0xce, 0x3f, 0x12, 0x46,
937 0x74, 0x2d, 0xe5, 0x07, 0xe9, 0x39, 0xe8, 0x1d, 0x1d, 0xc1, 0xc5, 0xcb,
938 0x98, 0x8b, 0x58, 0xc3, 0x10, 0xc9, 0xfd, 0xd9, 0x52, 0x4d, 0x93, 0x72,
939 0x0b, 0x45, 0x54, 0x1c, 0x83, 0xee, 0x88, 0x41, 0x19, 0x1d, 0xa7, 0xce,
940 0xd8, 0x6e, 0x33, 0x12, 0xd4, 0x36, 0x23, 0xc1, 0xd6, 0x3e, 0x74, 0x98,
941 0x9a, 0xba, 0x4a, 0xff, 0xd1, 0xee, 0x41, 0x04, 0x07, 0x7e, 0x8c, 0x31,
942 0xe2, 0x0e, 0x6b, 0xed, 0xb7, 0x60, 0xc1, 0x35, 0x93, 0xe6, 0x9f, 0x15,
943 0xbe, 0x85, 0xc2, 0x7d, 0x68, 0xcd, 0x09, 0xcc, 0xb8, 0xc4, 0x18, 0x36,
944 0x08, 0x91, 0x7c, 0x5c, 0x3d, 0x40, 0x9f, 0xac, 0x39, 0xfe, 0xfe, 0xe8,
945 0x2f, 0x72, 0x92, 0xd3, 0x6f, 0x0d, 0x23, 0xe0, 0x55, 0x91, 0x3f, 0x45,
946 0xa5, 0x2b, 0x85, 0xdd, 0x8a, 0x20, 0x52, 0xe9, 0xe1, 0x29, 0xbb, 0x4d,
947 0x20, 0x0f, 0x01, 0x1f, 0x19, 0x48, 0x35, 0x35, 0xa6, 0xe8, 0x9a, 0x58,
948 0x0c, 0x9b, 0x00, 0x03, 0xba, 0xf2, 0x14, 0x62, 0xec, 0xe9, 0x1a, 0x82,
949 0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c
950};
951
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200952static const unsigned char ecjpake_test_pms[] = {
953 0xf3, 0xd4, 0x7f, 0x59, 0x98, 0x44, 0xdb, 0x92, 0xa5, 0x69, 0xbb, 0xe7,
954 0x98, 0x1e, 0x39, 0xd9, 0x31, 0xfd, 0x74, 0x3b, 0xf2, 0x2e, 0x98, 0xf9,
955 0xb4, 0x38, 0xf7, 0x19, 0xd3, 0xc4, 0xf3, 0x51
956};
957
Antonin Décimo36e89b52019-01-23 15:24:37 +0100958/* Load my private keys and generate the corresponding public keys */
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +0200959static int ecjpake_test_load( mbedtls_ecjpake_context *ctx,
960 const unsigned char *xm1, size_t len1,
961 const unsigned char *xm2, size_t len2 )
962{
Janos Follath24eed8d2019-11-22 13:21:35 +0000963 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +0200964
965 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm1, xm1, len1 ) );
966 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm2, xm2, len2 ) );
967 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm1, &ctx->xm1,
968 &ctx->grp.G, NULL, NULL ) );
969 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm2, &ctx->xm2,
970 &ctx->grp.G, NULL, NULL ) );
971
972cleanup:
973 return( ret );
974}
975
Steven Cooreman64f27732021-01-11 17:20:10 +0100976#endif /* ! MBEDTLS_ECJPAKE_ALT */
977
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200978/* For tests we don't need a secure RNG;
979 * use the LGC from Numerical Recipes for simplicity */
980static int ecjpake_lgc( void *p, unsigned char *out, size_t len )
981{
982 static uint32_t x = 42;
983 (void) p;
984
985 while( len > 0 )
986 {
987 size_t use_len = len > 4 ? 4 : len;
988 x = 1664525 * x + 1013904223;
989 memcpy( out, &x, use_len );
990 out += use_len;
991 len -= use_len;
992 }
993
994 return( 0 );
995}
996
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200997#define TEST_ASSERT( x ) \
998 do { \
999 if( x ) \
1000 ret = 0; \
1001 else \
1002 { \
1003 ret = 1; \
1004 goto cleanup; \
1005 } \
1006 } while( 0 )
1007
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001008/*
1009 * Checkup routine
1010 */
1011int mbedtls_ecjpake_self_test( int verbose )
1012{
Janos Follath24eed8d2019-11-22 13:21:35 +00001013 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001014 mbedtls_ecjpake_context cli;
1015 mbedtls_ecjpake_context srv;
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001016 unsigned char buf[512], pms[32];
1017 size_t len, pmslen;
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001018
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001019 mbedtls_ecjpake_init( &cli );
1020 mbedtls_ecjpake_init( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001021
1022 if( verbose != 0 )
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001023 mbedtls_printf( " ECJPAKE test #0 (setup): " );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +02001024
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +02001025 TEST_ASSERT( mbedtls_ecjpake_setup( &cli, MBEDTLS_ECJPAKE_CLIENT,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001026 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1027 ecjpake_test_password,
1028 sizeof( ecjpake_test_password ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001029
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +02001030 TEST_ASSERT( mbedtls_ecjpake_setup( &srv, MBEDTLS_ECJPAKE_SERVER,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001031 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1032 ecjpake_test_password,
1033 sizeof( ecjpake_test_password ) ) == 0 );
1034
1035 if( verbose != 0 )
1036 mbedtls_printf( "passed\n" );
1037
1038 if( verbose != 0 )
1039 mbedtls_printf( " ECJPAKE test #1 (random handshake): " );
1040
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001041 TEST_ASSERT( mbedtls_ecjpake_write_round_one( &cli,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001042 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1043
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001044 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv, buf, len ) == 0 );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001045
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001046 TEST_ASSERT( mbedtls_ecjpake_write_round_one( &srv,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001047 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1048
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001049 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli, buf, len ) == 0 );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001050
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001051 TEST_ASSERT( mbedtls_ecjpake_write_round_two( &srv,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +02001052 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1053
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001054 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli, buf, len ) == 0 );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +02001055
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001056 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001057 pms, sizeof( pms ), &pmslen, ecjpake_lgc, NULL ) == 0 );
1058
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001059 TEST_ASSERT( mbedtls_ecjpake_write_round_two( &cli,
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +02001060 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1061
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001062 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv, buf, len ) == 0 );
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +02001063
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001064 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001065 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1066
1067 TEST_ASSERT( len == pmslen );
1068 TEST_ASSERT( memcmp( buf, pms, len ) == 0 );
1069
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001070 if( verbose != 0 )
1071 mbedtls_printf( "passed\n" );
1072
Steven Cooreman64f27732021-01-11 17:20:10 +01001073#if !defined(MBEDTLS_ECJPAKE_ALT)
1074 /* 'reference handshake' tests can only be run against implementations
1075 * for which we have 100% control over how the random ephemeral keys
1076 * are generated. This is only the case for the internal mbed TLS
1077 * implementation, so these tests are skipped in case the internal
1078 * implementation is swapped out for an alternative one. */
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001079 if( verbose != 0 )
1080 mbedtls_printf( " ECJPAKE test #2 (reference handshake): " );
1081
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001082 /* Simulate generation of round one */
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001083 MBEDTLS_MPI_CHK( ecjpake_test_load( &cli,
1084 ecjpake_test_x1, sizeof( ecjpake_test_x1 ),
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001085 ecjpake_test_x2, sizeof( ecjpake_test_x2 ) ) );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001086
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001087 MBEDTLS_MPI_CHK( ecjpake_test_load( &srv,
1088 ecjpake_test_x3, sizeof( ecjpake_test_x3 ),
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001089 ecjpake_test_x4, sizeof( ecjpake_test_x4 ) ) );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001090
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001091 /* Read round one */
1092 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv,
1093 ecjpake_test_cli_one,
1094 sizeof( ecjpake_test_cli_one ) ) == 0 );
1095
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001096 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001097 ecjpake_test_srv_one,
1098 sizeof( ecjpake_test_srv_one ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001099
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001100 /* Skip generation of round two, read round two */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001101 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001102 ecjpake_test_srv_two,
1103 sizeof( ecjpake_test_srv_two ) ) == 0 );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +02001104
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001105 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001106 ecjpake_test_cli_two,
1107 sizeof( ecjpake_test_cli_two ) ) == 0 );
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +02001108
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001109 /* Server derives PMS */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001110 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001111 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1112
1113 TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
1114 TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
1115
1116 memset( buf, 0, len ); /* Avoid interferences with next step */
1117
1118 /* Client derives PMS */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001119 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001120 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1121
1122 TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
1123 TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
1124
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001125 if( verbose != 0 )
1126 mbedtls_printf( "passed\n" );
Steven Cooreman64f27732021-01-11 17:20:10 +01001127#endif /* ! MBEDTLS_ECJPAKE_ALT */
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001128
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001129cleanup:
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001130 mbedtls_ecjpake_free( &cli );
1131 mbedtls_ecjpake_free( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001132
1133 if( ret != 0 )
1134 {
1135 if( verbose != 0 )
1136 mbedtls_printf( "failed\n" );
1137
1138 ret = 1;
1139 }
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001140
1141 if( verbose != 0 )
1142 mbedtls_printf( "\n" );
1143
1144 return( ret );
1145}
1146
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +02001147#undef TEST_ASSERT
1148
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001149#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_SHA256_C */
1150
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001151#endif /* MBEDTLS_SELF_TEST */
1152
1153#endif /* MBEDTLS_ECJPAKE_C */