blob: 464ff51cca78e1b2fcce16f60a7c4297846cdf2d [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
TRodziewicz782a7ea2021-03-17 11:35:16 +0100276 if( end < *p || (size_t)( end - *p ) < r_len || r_len == 0 )
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 ) );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200289 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( (mbedtls_ecp_group *) grp,
290 &VV, &h, X, &r, G ) );
291
292 if( mbedtls_ecp_point_cmp( &VV, &V ) != 0 )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200293 {
294 ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
295 goto cleanup;
296 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200297
298cleanup:
299 mbedtls_ecp_point_free( &V );
300 mbedtls_ecp_point_free( &VV );
301 mbedtls_mpi_free( &r );
302 mbedtls_mpi_free( &h );
303
304 return( ret );
305}
306
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200307/*
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200308 * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2)
309 */
310static int ecjpake_zkp_write( const mbedtls_md_info_t *md_info,
311 const mbedtls_ecp_group *grp,
Darryl Green11999bb2018-03-13 15:22:58 +0000312 const int pf,
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200313 const mbedtls_ecp_point *G,
314 const mbedtls_mpi *x,
315 const mbedtls_ecp_point *X,
316 const char *id,
317 unsigned char **p,
318 const unsigned char *end,
319 int (*f_rng)(void *, unsigned char *, size_t),
320 void *p_rng )
321{
Janos Follath24eed8d2019-11-22 13:21:35 +0000322 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200323 mbedtls_ecp_point V;
324 mbedtls_mpi v;
325 mbedtls_mpi h; /* later recycled to hold r */
326 size_t len;
327
328 if( end < *p )
329 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
330
331 mbedtls_ecp_point_init( &V );
332 mbedtls_mpi_init( &v );
333 mbedtls_mpi_init( &h );
334
335 /* Compute signature */
336 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp,
337 G, &v, &V, f_rng, p_rng ) );
Robert Cragie7cdad772015-10-02 13:31:41 +0100338 MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) );
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200339 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &h, &h, x ) ); /* x*h */
340 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &h, &v, &h ) ); /* v - x*h */
341 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &h, &h, &grp->N ) ); /* r */
342
343 /* Write it out */
344 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, &V,
Robert Cragie7cdad772015-10-02 13:31:41 +0100345 pf, &len, *p, end - *p ) );
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200346 *p += len;
347
348 len = mbedtls_mpi_size( &h ); /* actually r */
349 if( end < *p || (size_t)( end - *p ) < 1 + len || len > 255 )
350 {
351 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
352 goto cleanup;
353 }
354
355 *(*p)++ = (unsigned char)( len & 0xFF );
356 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, *p, len ) ); /* r */
357 *p += len;
358
359cleanup:
360 mbedtls_ecp_point_free( &V );
361 mbedtls_mpi_free( &v );
362 mbedtls_mpi_free( &h );
363
364 return( ret );
365}
366
367/*
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200368 * Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof
369 * Output: verified public key X
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200370 */
371static int ecjpake_kkp_read( const mbedtls_md_info_t *md_info,
372 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100373 const int pf,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200374 const mbedtls_ecp_point *G,
375 mbedtls_ecp_point *X,
376 const char *id,
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200377 const unsigned char **p,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200378 const unsigned char *end )
379{
Janos Follath24eed8d2019-11-22 13:21:35 +0000380 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200381
382 if( end < *p )
383 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
384
385 /*
386 * struct {
387 * ECPoint X;
388 * ECSchnorrZKP zkp;
389 * } ECJPAKEKeyKP;
390 */
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200391 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, X, p, end - *p ) );
Manuel Pégourié-Gonnard30590952015-08-17 10:37:40 +0200392 if( mbedtls_ecp_is_zero( X ) )
393 {
394 ret = MBEDTLS_ERR_ECP_INVALID_KEY;
395 goto cleanup;
396 }
397
Robert Cragie7cdad772015-10-02 13:31:41 +0100398 MBEDTLS_MPI_CHK( ecjpake_zkp_read( md_info, grp, pf, G, X, id, p, end ) );
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200399
400cleanup:
401 return( ret );
402}
403
404/*
405 * Generate an ECJPAKEKeyKP
406 * Output: the serialized structure, plus private/public key pair
407 */
408static int ecjpake_kkp_write( const mbedtls_md_info_t *md_info,
409 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100410 const int pf,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200411 const mbedtls_ecp_point *G,
412 mbedtls_mpi *x,
413 mbedtls_ecp_point *X,
414 const char *id,
415 unsigned char **p,
416 const unsigned char *end,
417 int (*f_rng)(void *, unsigned char *, size_t),
418 void *p_rng )
419{
Janos Follath24eed8d2019-11-22 13:21:35 +0000420 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200421 size_t len;
422
423 if( end < *p )
424 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
425
426 /* Generate key (7.4.2.3.1) and write it out */
427 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp, G, x, X,
428 f_rng, p_rng ) );
429 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, X,
Robert Cragie7cdad772015-10-02 13:31:41 +0100430 pf, &len, *p, end - *p ) );
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200431 *p += len;
432
433 /* Generate and write proof */
Robert Cragie7cdad772015-10-02 13:31:41 +0100434 MBEDTLS_MPI_CHK( ecjpake_zkp_write( md_info, grp, pf, G, x, X, id,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200435 p, end, f_rng, p_rng ) );
436
437cleanup:
438 return( ret );
439}
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200440
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200441/*
442 * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs
443 * Ouputs: verified peer public keys Xa, Xb
444 */
445static int ecjpake_kkpp_read( const mbedtls_md_info_t *md_info,
446 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100447 const int pf,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200448 const mbedtls_ecp_point *G,
449 mbedtls_ecp_point *Xa,
450 mbedtls_ecp_point *Xb,
451 const char *id,
452 const unsigned char *buf,
453 size_t len )
454{
Janos Follath24eed8d2019-11-22 13:21:35 +0000455 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200456 const unsigned char *p = buf;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200457 const unsigned char *end = buf + len;
458
459 /*
460 * struct {
461 * ECJPAKEKeyKP ecjpake_key_kp_pair_list[2];
462 * } ECJPAKEKeyKPPairList;
463 */
Robert Cragie7cdad772015-10-02 13:31:41 +0100464 MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xa, id, &p, end ) );
465 MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xb, id, &p, end ) );
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200466
467 if( p != end )
468 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
469
470cleanup:
471 return( ret );
472}
473
474/*
475 * Generate a ECJPAKEKeyKPPairList
476 * Outputs: the serialized structure, plus two private/public key pairs
477 */
478static int ecjpake_kkpp_write( const mbedtls_md_info_t *md_info,
479 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100480 const int pf,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200481 const mbedtls_ecp_point *G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200482 mbedtls_mpi *xm1,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200483 mbedtls_ecp_point *Xa,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200484 mbedtls_mpi *xm2,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200485 mbedtls_ecp_point *Xb,
486 const char *id,
487 unsigned char *buf,
488 size_t len,
489 size_t *olen,
490 int (*f_rng)(void *, unsigned char *, size_t),
491 void *p_rng )
492{
Janos Follath24eed8d2019-11-22 13:21:35 +0000493 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200494 unsigned char *p = buf;
495 const unsigned char *end = buf + len;
496
Robert Cragie7cdad772015-10-02 13:31:41 +0100497 MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm1, Xa, id,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200498 &p, end, f_rng, p_rng ) );
Robert Cragie7cdad772015-10-02 13:31:41 +0100499 MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm2, Xb, id,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200500 &p, end, f_rng, p_rng ) );
501
502 *olen = p - buf;
503
504cleanup:
505 return( ret );
506}
507
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200508/*
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200509 * Read and process the first round message
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200510 */
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200511int mbedtls_ecjpake_read_round_one( mbedtls_ecjpake_context *ctx,
512 const unsigned char *buf,
513 size_t len )
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200514{
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000515 ECJPAKE_VALIDATE_RET( ctx != NULL );
516 ECJPAKE_VALIDATE_RET( buf != NULL );
517
Robert Cragie7cdad772015-10-02 13:31:41 +0100518 return( ecjpake_kkpp_read( ctx->md_info, &ctx->grp, ctx->point_format,
519 &ctx->grp.G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200520 &ctx->Xp1, &ctx->Xp2, ID_PEER,
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200521 buf, len ) );
522}
523
524/*
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200525 * Generate and write the first round message
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200526 */
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200527int mbedtls_ecjpake_write_round_one( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200528 unsigned char *buf, size_t len, size_t *olen,
529 int (*f_rng)(void *, unsigned char *, size_t),
530 void *p_rng )
531{
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000532 ECJPAKE_VALIDATE_RET( ctx != NULL );
533 ECJPAKE_VALIDATE_RET( buf != NULL );
534 ECJPAKE_VALIDATE_RET( olen != NULL );
535 ECJPAKE_VALIDATE_RET( f_rng != NULL );
536
Robert Cragie7cdad772015-10-02 13:31:41 +0100537 return( ecjpake_kkpp_write( ctx->md_info, &ctx->grp, ctx->point_format,
538 &ctx->grp.G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200539 &ctx->xm1, &ctx->Xm1, &ctx->xm2, &ctx->Xm2,
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200540 ID_MINE, buf, len, olen, f_rng, p_rng ) );
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200541}
542
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200543/*
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200544 * Compute the sum of three points R = A + B + C
545 */
546static int ecjpake_ecp_add3( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
547 const mbedtls_ecp_point *A,
548 const mbedtls_ecp_point *B,
549 const mbedtls_ecp_point *C )
550{
Janos Follath24eed8d2019-11-22 13:21:35 +0000551 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200552 mbedtls_mpi one;
553
554 mbedtls_mpi_init( &one );
555
556 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
557 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, A, &one, B ) );
558 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, R, &one, C ) );
559
560cleanup:
561 mbedtls_mpi_free( &one );
562
563 return( ret );
564}
565
566/*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200567 * 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 +0200568 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200569int mbedtls_ecjpake_read_round_two( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200570 const unsigned char *buf,
571 size_t len )
572{
Janos Follath24eed8d2019-11-22 13:21:35 +0000573 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200574 const unsigned char *p = buf;
575 const unsigned char *end = buf + len;
576 mbedtls_ecp_group grp;
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200577 mbedtls_ecp_point G; /* C: GB, S: GA */
Hanno Becker185e5162018-12-19 09:48:50 +0000578
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000579 ECJPAKE_VALIDATE_RET( ctx != NULL );
580 ECJPAKE_VALIDATE_RET( buf != NULL );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200581
582 mbedtls_ecp_group_init( &grp );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200583 mbedtls_ecp_point_init( &G );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200584
585 /*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200586 * Server: GA = X3 + X4 + X1 (7.4.2.6.1)
587 * Client: GB = X1 + X2 + X3 (7.4.2.5.1)
588 * Unified: G = Xm1 + Xm2 + Xp1
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200589 * We need that before parsing in order to check Xp as we read it
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200590 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200591 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200592 &ctx->Xm1, &ctx->Xm2, &ctx->Xp1 ) );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200593
594 /*
595 * struct {
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200596 * ECParameters curve_params; // only client reading server msg
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200597 * ECJPAKEKeyKP ecjpake_key_kp;
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200598 * } Client/ServerECJPAKEParams;
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200599 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200600 if( ctx->role == MBEDTLS_ECJPAKE_CLIENT )
Manuel Pégourié-Gonnardd9802af2015-08-17 12:47:38 +0200601 {
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200602 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_group( &grp, &p, len ) );
Manuel Pégourié-Gonnardd9802af2015-08-17 12:47:38 +0200603 if( grp.id != ctx->grp.id )
604 {
605 ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
606 goto cleanup;
607 }
608 }
609
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200610 MBEDTLS_MPI_CHK( ecjpake_kkp_read( ctx->md_info, &ctx->grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100611 ctx->point_format,
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200612 &G, &ctx->Xp, ID_PEER, &p, end ) );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200613
614 if( p != end )
615 {
616 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
617 goto cleanup;
618 }
619
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200620cleanup:
621 mbedtls_ecp_group_free( &grp );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200622 mbedtls_ecp_point_free( &G );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200623
624 return( ret );
625}
626
627/*
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200628 * Compute R = +/- X * S mod N, taking care not to leak S
629 */
630static int ecjpake_mul_secret( mbedtls_mpi *R, int sign,
631 const mbedtls_mpi *X,
632 const mbedtls_mpi *S,
633 const mbedtls_mpi *N,
634 int (*f_rng)(void *, unsigned char *, size_t),
635 void *p_rng )
636{
Janos Follath24eed8d2019-11-22 13:21:35 +0000637 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200638 mbedtls_mpi b; /* Blinding value, then s + N * blinding */
639
640 mbedtls_mpi_init( &b );
641
642 /* b = s + rnd-128-bit * N */
643 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &b, 16, f_rng, p_rng ) );
644 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &b, &b, N ) );
645 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &b, &b, S ) );
646
647 /* R = sign * X * b mod N */
648 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( R, X, &b ) );
649 R->s *= sign;
650 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( R, R, N ) );
651
652cleanup:
653 mbedtls_mpi_free( &b );
654
655 return( ret );
656}
657
658/*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200659 * 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 +0200660 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200661int mbedtls_ecjpake_write_round_two( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200662 unsigned char *buf, size_t len, size_t *olen,
663 int (*f_rng)(void *, unsigned char *, size_t),
664 void *p_rng )
665{
Janos Follath24eed8d2019-11-22 13:21:35 +0000666 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200667 mbedtls_ecp_point G; /* C: GA, S: GB */
668 mbedtls_ecp_point Xm; /* C: Xc, S: Xs */
669 mbedtls_mpi xm; /* C: xc, S: xs */
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200670 unsigned char *p = buf;
671 const unsigned char *end = buf + len;
672 size_t ec_len;
Hanno Becker185e5162018-12-19 09:48:50 +0000673
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000674 ECJPAKE_VALIDATE_RET( ctx != NULL );
675 ECJPAKE_VALIDATE_RET( buf != NULL );
676 ECJPAKE_VALIDATE_RET( olen != NULL );
677 ECJPAKE_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200678
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200679 mbedtls_ecp_point_init( &G );
680 mbedtls_ecp_point_init( &Xm );
681 mbedtls_mpi_init( &xm );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200682
683 /*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200684 * 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 +0200685 *
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200686 * Client: GA = X1 + X3 + X4 | xs = x2 * s | Xc = xc * GA
687 * Server: GB = X3 + X1 + X2 | xs = x4 * s | Xs = xs * GB
688 * Unified: G = Xm1 + Xp1 + Xp2 | xm = xm2 * s | Xm = xm * G
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200689 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200690 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200691 &ctx->Xp1, &ctx->Xp2, &ctx->Xm1 ) );
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200692 MBEDTLS_MPI_CHK( ecjpake_mul_secret( &xm, 1, &ctx->xm2, &ctx->s,
693 &ctx->grp.N, f_rng, p_rng ) );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200694 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &Xm, &xm, &G, f_rng, p_rng ) );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200695
696 /*
697 * Now write things out
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200698 *
699 * struct {
700 * ECParameters curve_params; // only server writing its message
701 * ECJPAKEKeyKP ecjpake_key_kp;
702 * } Client/ServerECJPAKEParams;
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200703 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200704 if( ctx->role == MBEDTLS_ECJPAKE_SERVER )
705 {
706 if( end < p )
707 {
708 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
709 goto cleanup;
710 }
711 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_group( &ctx->grp, &ec_len,
712 p, end - p ) );
713 p += ec_len;
714 }
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200715
716 if( end < p )
717 {
718 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
719 goto cleanup;
720 }
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200721 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( &ctx->grp, &Xm,
Robert Cragie7cdad772015-10-02 13:31:41 +0100722 ctx->point_format, &ec_len, p, end - p ) );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200723 p += ec_len;
724
725 MBEDTLS_MPI_CHK( ecjpake_zkp_write( ctx->md_info, &ctx->grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100726 ctx->point_format,
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200727 &G, &xm, &Xm, ID_MINE,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200728 &p, end, f_rng, p_rng ) );
729
730 *olen = p - buf;
731
732cleanup:
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200733 mbedtls_ecp_point_free( &G );
734 mbedtls_ecp_point_free( &Xm );
735 mbedtls_mpi_free( &xm );
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +0200736
737 return( ret );
738}
739
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200740/*
741 * Derive PMS (7.4.2.7 / 7.4.2.8)
742 */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +0200743int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200744 unsigned char *buf, size_t len, size_t *olen,
745 int (*f_rng)(void *, unsigned char *, size_t),
746 void *p_rng )
747{
Janos Follath24eed8d2019-11-22 13:21:35 +0000748 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200749 mbedtls_ecp_point K;
750 mbedtls_mpi m_xm2_s, one;
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200751 unsigned char kx[MBEDTLS_ECP_MAX_BYTES];
752 size_t x_bytes;
Hanno Becker185e5162018-12-19 09:48:50 +0000753
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000754 ECJPAKE_VALIDATE_RET( ctx != NULL );
755 ECJPAKE_VALIDATE_RET( buf != NULL );
756 ECJPAKE_VALIDATE_RET( olen != NULL );
757 ECJPAKE_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200758
759 *olen = mbedtls_md_get_size( ctx->md_info );
760 if( len < *olen )
761 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
762
763 mbedtls_ecp_point_init( &K );
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200764 mbedtls_mpi_init( &m_xm2_s );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200765 mbedtls_mpi_init( &one );
766
767 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200768
769 /*
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200770 * Client: K = ( Xs - X4 * x2 * s ) * x2
771 * Server: K = ( Xc - X2 * x4 * s ) * x4
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200772 * Unified: K = ( Xp - Xp2 * xm2 * s ) * xm2
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200773 */
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200774 MBEDTLS_MPI_CHK( ecjpake_mul_secret( &m_xm2_s, -1, &ctx->xm2, &ctx->s,
775 &ctx->grp.N, f_rng, p_rng ) );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200776 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( &ctx->grp, &K,
777 &one, &ctx->Xp,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200778 &m_xm2_s, &ctx->Xp2 ) );
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200779 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &K, &ctx->xm2, &K,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200780 f_rng, p_rng ) );
781
782 /* PMS = SHA-256( K.X ) */
783 x_bytes = ( ctx->grp.pbits + 7 ) / 8;
784 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &K.X, kx, x_bytes ) );
785 MBEDTLS_MPI_CHK( mbedtls_md( ctx->md_info, kx, x_bytes, buf ) );
786
787cleanup:
788 mbedtls_ecp_point_free( &K );
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200789 mbedtls_mpi_free( &m_xm2_s );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200790 mbedtls_mpi_free( &one );
791
792 return( ret );
793}
794
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200795#undef ID_MINE
796#undef ID_PEER
797
Hanno Becker616d1ca2018-01-24 10:25:05 +0000798#endif /* ! MBEDTLS_ECJPAKE_ALT */
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200799
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200800#if defined(MBEDTLS_SELF_TEST)
801
802#if defined(MBEDTLS_PLATFORM_C)
803#include "mbedtls/platform.h"
804#else
805#include <stdio.h>
806#define mbedtls_printf printf
807#endif
808
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200809#if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
810 !defined(MBEDTLS_SHA256_C)
811int mbedtls_ecjpake_self_test( int verbose )
812{
813 (void) verbose;
814 return( 0 );
815}
816#else
817
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200818static const unsigned char ecjpake_test_password[] = {
819 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x6a, 0x70, 0x61, 0x6b, 0x65, 0x74,
820 0x65, 0x73, 0x74
821};
822
Steven Cooreman64f27732021-01-11 17:20:10 +0100823#if !defined(MBEDTLS_ECJPAKE_ALT)
824
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200825static const unsigned char ecjpake_test_x1[] = {
826 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
827 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
828 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21
829};
830
831static const unsigned char ecjpake_test_x2[] = {
832 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
833 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
834 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
835};
836
837static const unsigned char ecjpake_test_x3[] = {
838 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
839 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
840 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
841};
842
843static const unsigned char ecjpake_test_x4[] = {
844 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc,
845 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
846 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1
847};
848
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200849static const unsigned char ecjpake_test_cli_one[] = {
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200850 0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19,
851 0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44,
852 0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad,
853 0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62,
854 0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9,
855 0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d,
856 0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e,
857 0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e,
858 0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73,
859 0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22,
860 0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce,
861 0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00,
862 0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200863 0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e,
864 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62,
865 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5,
866 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb,
867 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35,
868 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0,
869 0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb,
870 0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47,
871 0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39,
872 0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97,
873 0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40,
874 0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d,
875 0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa,
876 0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d,
877 0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200878};
879
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200880static const unsigned char ecjpake_test_srv_one[] = {
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200881 0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb,
882 0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18,
883 0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47,
884 0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f,
885 0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7,
886 0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d,
887 0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64,
888 0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36,
889 0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2,
890 0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec,
891 0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16,
892 0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96,
893 0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3,
894 0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19,
895 0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f,
896 0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8,
897 0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7,
898 0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea,
899 0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5,
900 0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6,
901 0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31,
902 0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d,
903 0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8,
904 0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee,
905 0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84,
906 0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f,
907 0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80,
908 0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12
909};
910
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200911static const unsigned char ecjpake_test_srv_two[] = {
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200912 0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23,
913 0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c,
914 0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f,
915 0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca,
916 0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26,
917 0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55,
918 0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38,
919 0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6,
920 0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9,
921 0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4,
922 0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2,
923 0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8,
924 0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd,
925 0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c
926};
927
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200928static const unsigned char ecjpake_test_cli_two[] = {
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +0200929 0x41, 0x04, 0x69, 0xd5, 0x4e, 0xe8, 0x5e, 0x90, 0xce, 0x3f, 0x12, 0x46,
930 0x74, 0x2d, 0xe5, 0x07, 0xe9, 0x39, 0xe8, 0x1d, 0x1d, 0xc1, 0xc5, 0xcb,
931 0x98, 0x8b, 0x58, 0xc3, 0x10, 0xc9, 0xfd, 0xd9, 0x52, 0x4d, 0x93, 0x72,
932 0x0b, 0x45, 0x54, 0x1c, 0x83, 0xee, 0x88, 0x41, 0x19, 0x1d, 0xa7, 0xce,
933 0xd8, 0x6e, 0x33, 0x12, 0xd4, 0x36, 0x23, 0xc1, 0xd6, 0x3e, 0x74, 0x98,
934 0x9a, 0xba, 0x4a, 0xff, 0xd1, 0xee, 0x41, 0x04, 0x07, 0x7e, 0x8c, 0x31,
935 0xe2, 0x0e, 0x6b, 0xed, 0xb7, 0x60, 0xc1, 0x35, 0x93, 0xe6, 0x9f, 0x15,
936 0xbe, 0x85, 0xc2, 0x7d, 0x68, 0xcd, 0x09, 0xcc, 0xb8, 0xc4, 0x18, 0x36,
937 0x08, 0x91, 0x7c, 0x5c, 0x3d, 0x40, 0x9f, 0xac, 0x39, 0xfe, 0xfe, 0xe8,
938 0x2f, 0x72, 0x92, 0xd3, 0x6f, 0x0d, 0x23, 0xe0, 0x55, 0x91, 0x3f, 0x45,
939 0xa5, 0x2b, 0x85, 0xdd, 0x8a, 0x20, 0x52, 0xe9, 0xe1, 0x29, 0xbb, 0x4d,
940 0x20, 0x0f, 0x01, 0x1f, 0x19, 0x48, 0x35, 0x35, 0xa6, 0xe8, 0x9a, 0x58,
941 0x0c, 0x9b, 0x00, 0x03, 0xba, 0xf2, 0x14, 0x62, 0xec, 0xe9, 0x1a, 0x82,
942 0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c
943};
944
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200945static const unsigned char ecjpake_test_pms[] = {
946 0xf3, 0xd4, 0x7f, 0x59, 0x98, 0x44, 0xdb, 0x92, 0xa5, 0x69, 0xbb, 0xe7,
947 0x98, 0x1e, 0x39, 0xd9, 0x31, 0xfd, 0x74, 0x3b, 0xf2, 0x2e, 0x98, 0xf9,
948 0xb4, 0x38, 0xf7, 0x19, 0xd3, 0xc4, 0xf3, 0x51
949};
950
Antonin Décimo36e89b52019-01-23 15:24:37 +0100951/* Load my private keys and generate the corresponding public keys */
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +0200952static int ecjpake_test_load( mbedtls_ecjpake_context *ctx,
953 const unsigned char *xm1, size_t len1,
954 const unsigned char *xm2, size_t len2 )
955{
Janos Follath24eed8d2019-11-22 13:21:35 +0000956 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +0200957
958 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm1, xm1, len1 ) );
959 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm2, xm2, len2 ) );
960 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm1, &ctx->xm1,
961 &ctx->grp.G, NULL, NULL ) );
962 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm2, &ctx->xm2,
963 &ctx->grp.G, NULL, NULL ) );
964
965cleanup:
966 return( ret );
967}
968
Steven Cooreman64f27732021-01-11 17:20:10 +0100969#endif /* ! MBEDTLS_ECJPAKE_ALT */
970
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200971/* For tests we don't need a secure RNG;
972 * use the LGC from Numerical Recipes for simplicity */
973static int ecjpake_lgc( void *p, unsigned char *out, size_t len )
974{
975 static uint32_t x = 42;
976 (void) p;
977
978 while( len > 0 )
979 {
980 size_t use_len = len > 4 ? 4 : len;
981 x = 1664525 * x + 1013904223;
982 memcpy( out, &x, use_len );
983 out += use_len;
984 len -= use_len;
985 }
986
987 return( 0 );
988}
989
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200990#define TEST_ASSERT( x ) \
991 do { \
992 if( x ) \
993 ret = 0; \
994 else \
995 { \
996 ret = 1; \
997 goto cleanup; \
998 } \
999 } while( 0 )
1000
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001001/*
1002 * Checkup routine
1003 */
1004int mbedtls_ecjpake_self_test( int verbose )
1005{
Janos Follath24eed8d2019-11-22 13:21:35 +00001006 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001007 mbedtls_ecjpake_context cli;
1008 mbedtls_ecjpake_context srv;
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001009 unsigned char buf[512], pms[32];
1010 size_t len, pmslen;
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001011
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001012 mbedtls_ecjpake_init( &cli );
1013 mbedtls_ecjpake_init( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001014
1015 if( verbose != 0 )
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001016 mbedtls_printf( " ECJPAKE test #0 (setup): " );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +02001017
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +02001018 TEST_ASSERT( mbedtls_ecjpake_setup( &cli, MBEDTLS_ECJPAKE_CLIENT,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001019 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1020 ecjpake_test_password,
1021 sizeof( ecjpake_test_password ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001022
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +02001023 TEST_ASSERT( mbedtls_ecjpake_setup( &srv, MBEDTLS_ECJPAKE_SERVER,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001024 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1025 ecjpake_test_password,
1026 sizeof( ecjpake_test_password ) ) == 0 );
1027
1028 if( verbose != 0 )
1029 mbedtls_printf( "passed\n" );
1030
1031 if( verbose != 0 )
1032 mbedtls_printf( " ECJPAKE test #1 (random handshake): " );
1033
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001034 TEST_ASSERT( mbedtls_ecjpake_write_round_one( &cli,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001035 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1036
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001037 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv, buf, len ) == 0 );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001038
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001039 TEST_ASSERT( mbedtls_ecjpake_write_round_one( &srv,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001040 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1041
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001042 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli, buf, len ) == 0 );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001043
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001044 TEST_ASSERT( mbedtls_ecjpake_write_round_two( &srv,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +02001045 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1046
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001047 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli, buf, len ) == 0 );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +02001048
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001049 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001050 pms, sizeof( pms ), &pmslen, ecjpake_lgc, NULL ) == 0 );
1051
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001052 TEST_ASSERT( mbedtls_ecjpake_write_round_two( &cli,
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +02001053 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1054
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001055 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv, buf, len ) == 0 );
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +02001056
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001057 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001058 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1059
1060 TEST_ASSERT( len == pmslen );
1061 TEST_ASSERT( memcmp( buf, pms, len ) == 0 );
1062
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001063 if( verbose != 0 )
1064 mbedtls_printf( "passed\n" );
1065
Steven Cooreman64f27732021-01-11 17:20:10 +01001066#if !defined(MBEDTLS_ECJPAKE_ALT)
1067 /* 'reference handshake' tests can only be run against implementations
1068 * for which we have 100% control over how the random ephemeral keys
1069 * are generated. This is only the case for the internal mbed TLS
1070 * implementation, so these tests are skipped in case the internal
1071 * implementation is swapped out for an alternative one. */
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001072 if( verbose != 0 )
1073 mbedtls_printf( " ECJPAKE test #2 (reference handshake): " );
1074
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001075 /* Simulate generation of round one */
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001076 MBEDTLS_MPI_CHK( ecjpake_test_load( &cli,
1077 ecjpake_test_x1, sizeof( ecjpake_test_x1 ),
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001078 ecjpake_test_x2, sizeof( ecjpake_test_x2 ) ) );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001079
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001080 MBEDTLS_MPI_CHK( ecjpake_test_load( &srv,
1081 ecjpake_test_x3, sizeof( ecjpake_test_x3 ),
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001082 ecjpake_test_x4, sizeof( ecjpake_test_x4 ) ) );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001083
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001084 /* Read round one */
1085 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv,
1086 ecjpake_test_cli_one,
1087 sizeof( ecjpake_test_cli_one ) ) == 0 );
1088
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001089 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001090 ecjpake_test_srv_one,
1091 sizeof( ecjpake_test_srv_one ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001092
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001093 /* Skip generation of round two, read round two */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001094 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001095 ecjpake_test_srv_two,
1096 sizeof( ecjpake_test_srv_two ) ) == 0 );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +02001097
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001098 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001099 ecjpake_test_cli_two,
1100 sizeof( ecjpake_test_cli_two ) ) == 0 );
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +02001101
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001102 /* Server derives PMS */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001103 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001104 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1105
1106 TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
1107 TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
1108
1109 memset( buf, 0, len ); /* Avoid interferences with next step */
1110
1111 /* Client derives PMS */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001112 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001113 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1114
1115 TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
1116 TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
1117
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001118 if( verbose != 0 )
1119 mbedtls_printf( "passed\n" );
Steven Cooreman64f27732021-01-11 17:20:10 +01001120#endif /* ! MBEDTLS_ECJPAKE_ALT */
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001121
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001122cleanup:
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001123 mbedtls_ecjpake_free( &cli );
1124 mbedtls_ecjpake_free( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001125
1126 if( ret != 0 )
1127 {
1128 if( verbose != 0 )
1129 mbedtls_printf( "failed\n" );
1130
1131 ret = 1;
1132 }
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001133
1134 if( verbose != 0 )
1135 mbedtls_printf( "\n" );
1136
1137 return( ret );
1138}
1139
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +02001140#undef TEST_ASSERT
1141
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001142#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_SHA256_C */
1143
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001144#endif /* MBEDTLS_SELF_TEST */
1145
1146#endif /* MBEDTLS_ECJPAKE_C */