blob: 17d04387d43777787275f7b95d06034ee79e31e9 [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
Neil Armstrongecaba1c2022-08-11 10:47:08 +020033/* We use MD first if it's available (for compatibility reasons)
34 * and "fall back" to PSA otherwise (which needs psa_crypto_init()). */
35#if !defined(MBEDTLS_MD_C)
36#include "psa/crypto.h"
37#include "mbedtls/psa_util.h"
38#endif /* !MBEDTLS_MD_C */
39
Neil Armstrong0d763412022-08-11 10:32:22 +020040#include "hash_info.h"
41
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +020042#include <string.h>
43
Hanno Becker616d1ca2018-01-24 10:25:05 +000044#if !defined(MBEDTLS_ECJPAKE_ALT)
45
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +020046/*
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +020047 * Convert a mbedtls_ecjpake_role to identifier string
48 */
49static const char * const ecjpake_id[] = {
50 "client",
51 "server"
52};
53
54#define ID_MINE ( ecjpake_id[ ctx->role ] )
55#define ID_PEER ( ecjpake_id[ 1 - ctx->role ] )
56
Neil Armstrongecaba1c2022-08-11 10:47:08 +020057/**
58 * Helper to Compute a hash from md_type
59 */
60static int mbedtls_ecjpake_compute_hash( mbedtls_md_type_t md_type,
61 const unsigned char *input, size_t ilen,
62 unsigned char *output )
63{
64#if defined(MBEDTLS_MD_C)
65 return( mbedtls_md( mbedtls_md_info_from_type( md_type ),
66 input, ilen, output ) );
67#else
68 psa_algorithm_t alg = mbedtls_psa_translate_md( md_type );
69 psa_status_t status;
70 size_t out_size = PSA_HASH_LENGTH( alg );
71 size_t out_len;
72
73 status = psa_hash_compute( alg, input, ilen, output, out_size, &out_len );
74
75 return( mbedtls_md_error_from_psa( status ) );
76#endif /* !MBEDTLS_MD_C */
77}
78
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +020079/*
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020080 * Initialize context
81 */
82void mbedtls_ecjpake_init( mbedtls_ecjpake_context *ctx )
83{
Neil Armstrong0d763412022-08-11 10:32:22 +020084 ctx->md_type = MBEDTLS_MD_NONE;
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020085 mbedtls_ecp_group_init( &ctx->grp );
Manuel Pégourié-Gonnardb7da1942015-10-19 13:35:22 +020086 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020087
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +020088 mbedtls_ecp_point_init( &ctx->Xm1 );
89 mbedtls_ecp_point_init( &ctx->Xm2 );
90 mbedtls_ecp_point_init( &ctx->Xp1 );
91 mbedtls_ecp_point_init( &ctx->Xp2 );
92 mbedtls_ecp_point_init( &ctx->Xp );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020093
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +020094 mbedtls_mpi_init( &ctx->xm1 );
95 mbedtls_mpi_init( &ctx->xm2 );
96 mbedtls_mpi_init( &ctx->s );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020097}
98
99/*
100 * Free context
101 */
102void mbedtls_ecjpake_free( mbedtls_ecjpake_context *ctx )
103{
104 if( ctx == NULL )
105 return;
106
Neil Armstrong0d763412022-08-11 10:32:22 +0200107 ctx->md_type = MBEDTLS_MD_NONE;
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200108 mbedtls_ecp_group_free( &ctx->grp );
109
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200110 mbedtls_ecp_point_free( &ctx->Xm1 );
111 mbedtls_ecp_point_free( &ctx->Xm2 );
112 mbedtls_ecp_point_free( &ctx->Xp1 );
113 mbedtls_ecp_point_free( &ctx->Xp2 );
114 mbedtls_ecp_point_free( &ctx->Xp );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200115
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200116 mbedtls_mpi_free( &ctx->xm1 );
117 mbedtls_mpi_free( &ctx->xm2 );
118 mbedtls_mpi_free( &ctx->s );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200119}
120
121/*
122 * Setup context
123 */
124int mbedtls_ecjpake_setup( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +0200125 mbedtls_ecjpake_role role,
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200126 mbedtls_md_type_t hash,
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200127 mbedtls_ecp_group_id curve,
128 const unsigned char *secret,
129 size_t len )
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200130{
Janos Follath24eed8d2019-11-22 13:21:35 +0000131 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker185e5162018-12-19 09:48:50 +0000132
Tuvshinzaya Erdenekhuua891f832022-07-27 15:13:04 +0100133 if( role != MBEDTLS_ECJPAKE_CLIENT && role != MBEDTLS_ECJPAKE_SERVER )
134 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200135
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +0200136 ctx->role = role;
137
Neil Armstrongecaba1c2022-08-11 10:47:08 +0200138#if defined(MBEDTLS_MD_C)
Neil Armstrong0d763412022-08-11 10:32:22 +0200139 if( ( mbedtls_md_info_from_type( hash ) ) == NULL )
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200140 return( MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE );
Neil Armstrongecaba1c2022-08-11 10:47:08 +0200141#else
142 if( mbedtls_psa_translate_md( hash ) == MBEDTLS_MD_NONE )
143 return( MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE );
144#endif
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200145
Neil Armstrong0d763412022-08-11 10:32:22 +0200146 ctx->md_type = hash;
147
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200148 MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ctx->grp, curve ) );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200149
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200150 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->s, secret, len ) );
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200151
152cleanup:
153 if( ret != 0 )
154 mbedtls_ecjpake_free( ctx );
155
156 return( ret );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200157}
158
Gilles Peskinecd07e222021-05-27 23:17:34 +0200159int mbedtls_ecjpake_set_point_format( mbedtls_ecjpake_context *ctx,
160 int point_format )
161{
162 switch( point_format )
163 {
164 case MBEDTLS_ECP_PF_UNCOMPRESSED:
165 case MBEDTLS_ECP_PF_COMPRESSED:
166 ctx->point_format = point_format;
167 return( 0 );
168 default:
169 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
170 }
171}
172
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200173/*
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200174 * Check if context is ready for use
175 */
176int mbedtls_ecjpake_check( const mbedtls_ecjpake_context *ctx )
177{
Neil Armstrong0d763412022-08-11 10:32:22 +0200178 if( ctx->md_type == MBEDTLS_MD_NONE ||
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200179 ctx->grp.id == MBEDTLS_ECP_DP_NONE ||
180 ctx->s.p == NULL )
181 {
182 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
183 }
184
185 return( 0 );
186}
187
188/*
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200189 * Write a point plus its length to a buffer
190 */
191static int ecjpake_write_len_point( unsigned char **p,
192 const unsigned char *end,
193 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100194 const int pf,
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200195 const mbedtls_ecp_point *P )
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 size_t len;
199
200 /* Need at least 4 for length plus 1 for point */
201 if( end < *p || end - *p < 5 )
202 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
203
Robert Cragie7cdad772015-10-02 13:31:41 +0100204 ret = mbedtls_ecp_point_write_binary( grp, P, pf,
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200205 &len, *p + 4, end - ( *p + 4 ) );
206 if( ret != 0 )
207 return( ret );
208
Joe Subbiania5cb0d22021-08-23 11:35:25 +0100209 MBEDTLS_PUT_UINT32_BE( len, *p, 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200210
211 *p += 4 + len;
212
213 return( 0 );
214}
215
216/*
217 * Size of the temporary buffer for ecjpake_hash:
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200218 * 3 EC points plus their length, plus ID and its length (4 + 6 bytes)
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200219 */
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200220#define ECJPAKE_HASH_BUF_LEN ( 3 * ( 4 + MBEDTLS_ECP_MAX_PT_LEN ) + 4 + 6 )
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200221
222/*
223 * Compute hash for ZKP (7.4.2.2.2.1)
224 */
Neil Armstrong0d763412022-08-11 10:32:22 +0200225static int ecjpake_hash( const mbedtls_md_type_t md_type,
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200226 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100227 const int pf,
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200228 const mbedtls_ecp_point *G,
229 const mbedtls_ecp_point *V,
230 const mbedtls_ecp_point *X,
231 const char *id,
232 mbedtls_mpi *h )
233{
Janos Follath24eed8d2019-11-22 13:21:35 +0000234 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200235 unsigned char buf[ECJPAKE_HASH_BUF_LEN];
236 unsigned char *p = buf;
237 const unsigned char *end = buf + sizeof( buf );
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200238 const size_t id_len = strlen( id );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200239 unsigned char hash[MBEDTLS_MD_MAX_SIZE];
240
241 /* Write things to temporary buffer */
Robert Cragie7cdad772015-10-02 13:31:41 +0100242 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, G ) );
243 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, V ) );
244 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, X ) );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200245
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200246 if( end - p < 4 )
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200247 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
248
Joe Subbiania5cb0d22021-08-23 11:35:25 +0100249 MBEDTLS_PUT_UINT32_BE( id_len, p, 0 );
250 p += 4;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200251
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200252 if( end < p || (size_t)( end - p ) < id_len )
253 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
254
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200255 memcpy( p, id, id_len );
256 p += id_len;
257
258 /* Compute hash */
Neil Armstrongecaba1c2022-08-11 10:47:08 +0200259 MBEDTLS_MPI_CHK( mbedtls_ecjpake_compute_hash( md_type,
260 buf, p - buf, hash ) );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200261
262 /* Turn it into an integer mod n */
263 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( h, hash,
Neil Armstrong0d763412022-08-11 10:32:22 +0200264 mbedtls_hash_info_get_size( md_type ) ) );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200265 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( h, h, &grp->N ) );
266
267cleanup:
268 return( ret );
269}
270
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200271/*
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200272 * Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3)
273 */
Neil Armstrong0d763412022-08-11 10:32:22 +0200274static int ecjpake_zkp_read( const mbedtls_md_type_t md_type,
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200275 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100276 const int pf,
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200277 const mbedtls_ecp_point *G,
278 const mbedtls_ecp_point *X,
279 const char *id,
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200280 const unsigned char **p,
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200281 const unsigned char *end )
282{
Janos Follath24eed8d2019-11-22 13:21:35 +0000283 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200284 mbedtls_ecp_point V, VV;
285 mbedtls_mpi r, h;
286 size_t r_len;
287
288 mbedtls_ecp_point_init( &V );
289 mbedtls_ecp_point_init( &VV );
290 mbedtls_mpi_init( &r );
291 mbedtls_mpi_init( &h );
292
293 /*
294 * struct {
295 * ECPoint V;
296 * opaque r<1..2^8-1>;
297 * } ECSchnorrZKP;
298 */
299 if( end < *p )
300 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
301
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200302 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, &V, p, end - *p ) );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200303
304 if( end < *p || (size_t)( end - *p ) < 1 )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200305 {
306 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
307 goto cleanup;
308 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200309
310 r_len = *(*p)++;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200311
TRodziewicz782a7ea2021-03-17 11:35:16 +0100312 if( end < *p || (size_t)( end - *p ) < r_len || r_len == 0 )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200313 {
314 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
315 goto cleanup;
316 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200317
318 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &r, *p, r_len ) );
319 *p += r_len;
320
321 /*
322 * Verification
323 */
Neil Armstrong0d763412022-08-11 10:32:22 +0200324 MBEDTLS_MPI_CHK( ecjpake_hash( md_type, grp, pf, G, &V, X, id, &h ) );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200325 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( (mbedtls_ecp_group *) grp,
326 &VV, &h, X, &r, G ) );
327
328 if( mbedtls_ecp_point_cmp( &VV, &V ) != 0 )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200329 {
330 ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
331 goto cleanup;
332 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200333
334cleanup:
335 mbedtls_ecp_point_free( &V );
336 mbedtls_ecp_point_free( &VV );
337 mbedtls_mpi_free( &r );
338 mbedtls_mpi_free( &h );
339
340 return( ret );
341}
342
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200343/*
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200344 * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2)
345 */
Neil Armstrong0d763412022-08-11 10:32:22 +0200346static int ecjpake_zkp_write( const mbedtls_md_type_t md_type,
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200347 const mbedtls_ecp_group *grp,
Darryl Green11999bb2018-03-13 15:22:58 +0000348 const int pf,
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200349 const mbedtls_ecp_point *G,
350 const mbedtls_mpi *x,
351 const mbedtls_ecp_point *X,
352 const char *id,
353 unsigned char **p,
354 const unsigned char *end,
355 int (*f_rng)(void *, unsigned char *, size_t),
356 void *p_rng )
357{
Janos Follath24eed8d2019-11-22 13:21:35 +0000358 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200359 mbedtls_ecp_point V;
360 mbedtls_mpi v;
361 mbedtls_mpi h; /* later recycled to hold r */
362 size_t len;
363
364 if( end < *p )
365 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
366
367 mbedtls_ecp_point_init( &V );
368 mbedtls_mpi_init( &v );
369 mbedtls_mpi_init( &h );
370
371 /* Compute signature */
372 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp,
373 G, &v, &V, f_rng, p_rng ) );
Neil Armstrong0d763412022-08-11 10:32:22 +0200374 MBEDTLS_MPI_CHK( ecjpake_hash( md_type, grp, pf, G, &V, X, id, &h ) );
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200375 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &h, &h, x ) ); /* x*h */
376 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &h, &v, &h ) ); /* v - x*h */
377 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &h, &h, &grp->N ) ); /* r */
378
379 /* Write it out */
380 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, &V,
Robert Cragie7cdad772015-10-02 13:31:41 +0100381 pf, &len, *p, end - *p ) );
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200382 *p += len;
383
384 len = mbedtls_mpi_size( &h ); /* actually r */
385 if( end < *p || (size_t)( end - *p ) < 1 + len || len > 255 )
386 {
387 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
388 goto cleanup;
389 }
390
Joe Subbiani2194dc42021-07-14 12:31:31 +0100391 *(*p)++ = MBEDTLS_BYTE_0( len );
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200392 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, *p, len ) ); /* r */
393 *p += len;
394
395cleanup:
396 mbedtls_ecp_point_free( &V );
397 mbedtls_mpi_free( &v );
398 mbedtls_mpi_free( &h );
399
400 return( ret );
401}
402
403/*
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200404 * Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof
405 * Output: verified public key X
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200406 */
Neil Armstrong0d763412022-08-11 10:32:22 +0200407static int ecjpake_kkp_read( const mbedtls_md_type_t md_type,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200408 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100409 const int pf,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200410 const mbedtls_ecp_point *G,
411 mbedtls_ecp_point *X,
412 const char *id,
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200413 const unsigned char **p,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200414 const unsigned char *end )
415{
Janos Follath24eed8d2019-11-22 13:21:35 +0000416 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200417
418 if( end < *p )
419 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
420
421 /*
422 * struct {
423 * ECPoint X;
424 * ECSchnorrZKP zkp;
425 * } ECJPAKEKeyKP;
426 */
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200427 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, X, p, end - *p ) );
Manuel Pégourié-Gonnard30590952015-08-17 10:37:40 +0200428 if( mbedtls_ecp_is_zero( X ) )
429 {
430 ret = MBEDTLS_ERR_ECP_INVALID_KEY;
431 goto cleanup;
432 }
433
Neil Armstrong0d763412022-08-11 10:32:22 +0200434 MBEDTLS_MPI_CHK( ecjpake_zkp_read( md_type, grp, pf, G, X, id, p, end ) );
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200435
436cleanup:
437 return( ret );
438}
439
440/*
441 * Generate an ECJPAKEKeyKP
442 * Output: the serialized structure, plus private/public key pair
443 */
Neil Armstrong0d763412022-08-11 10:32:22 +0200444static int ecjpake_kkp_write( const mbedtls_md_type_t md_type,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200445 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100446 const int pf,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200447 const mbedtls_ecp_point *G,
448 mbedtls_mpi *x,
449 mbedtls_ecp_point *X,
450 const char *id,
451 unsigned char **p,
452 const unsigned char *end,
453 int (*f_rng)(void *, unsigned char *, size_t),
454 void *p_rng )
455{
Janos Follath24eed8d2019-11-22 13:21:35 +0000456 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200457 size_t len;
458
459 if( end < *p )
460 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
461
462 /* Generate key (7.4.2.3.1) and write it out */
463 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp, G, x, X,
464 f_rng, p_rng ) );
465 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, X,
Robert Cragie7cdad772015-10-02 13:31:41 +0100466 pf, &len, *p, end - *p ) );
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200467 *p += len;
468
469 /* Generate and write proof */
Neil Armstrong0d763412022-08-11 10:32:22 +0200470 MBEDTLS_MPI_CHK( ecjpake_zkp_write( md_type, grp, pf, G, x, X, id,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200471 p, end, f_rng, p_rng ) );
472
473cleanup:
474 return( ret );
475}
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200476
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200477/*
478 * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs
Shaun Case8b0ecbc2021-12-20 21:14:10 -0800479 * Outputs: verified peer public keys Xa, Xb
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200480 */
Neil Armstrong0d763412022-08-11 10:32:22 +0200481static int ecjpake_kkpp_read( const mbedtls_md_type_t md_type,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200482 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100483 const int pf,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200484 const mbedtls_ecp_point *G,
485 mbedtls_ecp_point *Xa,
486 mbedtls_ecp_point *Xb,
487 const char *id,
488 const unsigned char *buf,
489 size_t len )
490{
Janos Follath24eed8d2019-11-22 13:21:35 +0000491 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200492 const unsigned char *p = buf;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200493 const unsigned char *end = buf + len;
494
495 /*
496 * struct {
497 * ECJPAKEKeyKP ecjpake_key_kp_pair_list[2];
498 * } ECJPAKEKeyKPPairList;
499 */
Neil Armstrong0d763412022-08-11 10:32:22 +0200500 MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_type, grp, pf, G, Xa, id, &p, end ) );
501 MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_type, grp, pf, G, Xb, id, &p, end ) );
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200502
503 if( p != end )
504 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
505
506cleanup:
507 return( ret );
508}
509
510/*
511 * Generate a ECJPAKEKeyKPPairList
512 * Outputs: the serialized structure, plus two private/public key pairs
513 */
Neil Armstrong0d763412022-08-11 10:32:22 +0200514static int ecjpake_kkpp_write( const mbedtls_md_type_t md_type,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200515 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100516 const int pf,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200517 const mbedtls_ecp_point *G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200518 mbedtls_mpi *xm1,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200519 mbedtls_ecp_point *Xa,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200520 mbedtls_mpi *xm2,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200521 mbedtls_ecp_point *Xb,
522 const char *id,
523 unsigned char *buf,
524 size_t len,
525 size_t *olen,
526 int (*f_rng)(void *, unsigned char *, size_t),
527 void *p_rng )
528{
Janos Follath24eed8d2019-11-22 13:21:35 +0000529 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200530 unsigned char *p = buf;
531 const unsigned char *end = buf + len;
532
Neil Armstrong0d763412022-08-11 10:32:22 +0200533 MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_type, grp, pf, G, xm1, Xa, id,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200534 &p, end, f_rng, p_rng ) );
Neil Armstrong0d763412022-08-11 10:32:22 +0200535 MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_type, grp, pf, G, xm2, Xb, id,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200536 &p, end, f_rng, p_rng ) );
537
538 *olen = p - buf;
539
540cleanup:
541 return( ret );
542}
543
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200544/*
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200545 * Read and process the first round message
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200546 */
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200547int mbedtls_ecjpake_read_round_one( mbedtls_ecjpake_context *ctx,
548 const unsigned char *buf,
549 size_t len )
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200550{
Neil Armstrong0d763412022-08-11 10:32:22 +0200551 return( ecjpake_kkpp_read( ctx->md_type, &ctx->grp, ctx->point_format,
Robert Cragie7cdad772015-10-02 13:31:41 +0100552 &ctx->grp.G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200553 &ctx->Xp1, &ctx->Xp2, ID_PEER,
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200554 buf, len ) );
555}
556
557/*
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200558 * Generate and write the first round message
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200559 */
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200560int mbedtls_ecjpake_write_round_one( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200561 unsigned char *buf, size_t len, size_t *olen,
562 int (*f_rng)(void *, unsigned char *, size_t),
563 void *p_rng )
564{
Neil Armstrong0d763412022-08-11 10:32:22 +0200565 return( ecjpake_kkpp_write( ctx->md_type, &ctx->grp, ctx->point_format,
Robert Cragie7cdad772015-10-02 13:31:41 +0100566 &ctx->grp.G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200567 &ctx->xm1, &ctx->Xm1, &ctx->xm2, &ctx->Xm2,
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200568 ID_MINE, buf, len, olen, f_rng, p_rng ) );
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200569}
570
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200571/*
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200572 * Compute the sum of three points R = A + B + C
573 */
574static int ecjpake_ecp_add3( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
575 const mbedtls_ecp_point *A,
576 const mbedtls_ecp_point *B,
577 const mbedtls_ecp_point *C )
578{
Janos Follath24eed8d2019-11-22 13:21:35 +0000579 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200580 mbedtls_mpi one;
581
582 mbedtls_mpi_init( &one );
583
584 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
585 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, A, &one, B ) );
586 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, R, &one, C ) );
587
588cleanup:
589 mbedtls_mpi_free( &one );
590
591 return( ret );
592}
593
594/*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200595 * 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 +0200596 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200597int mbedtls_ecjpake_read_round_two( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200598 const unsigned char *buf,
599 size_t len )
600{
Janos Follath24eed8d2019-11-22 13:21:35 +0000601 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200602 const unsigned char *p = buf;
603 const unsigned char *end = buf + len;
604 mbedtls_ecp_group grp;
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200605 mbedtls_ecp_point G; /* C: GB, S: GA */
Hanno Becker185e5162018-12-19 09:48:50 +0000606
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200607 mbedtls_ecp_group_init( &grp );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200608 mbedtls_ecp_point_init( &G );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200609
610 /*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200611 * Server: GA = X3 + X4 + X1 (7.4.2.6.1)
612 * Client: GB = X1 + X2 + X3 (7.4.2.5.1)
613 * Unified: G = Xm1 + Xm2 + Xp1
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200614 * We need that before parsing in order to check Xp as we read it
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200615 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200616 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200617 &ctx->Xm1, &ctx->Xm2, &ctx->Xp1 ) );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200618
619 /*
620 * struct {
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200621 * ECParameters curve_params; // only client reading server msg
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200622 * ECJPAKEKeyKP ecjpake_key_kp;
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200623 * } Client/ServerECJPAKEParams;
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200624 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200625 if( ctx->role == MBEDTLS_ECJPAKE_CLIENT )
Manuel Pégourié-Gonnardd9802af2015-08-17 12:47:38 +0200626 {
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200627 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_group( &grp, &p, len ) );
Manuel Pégourié-Gonnardd9802af2015-08-17 12:47:38 +0200628 if( grp.id != ctx->grp.id )
629 {
630 ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
631 goto cleanup;
632 }
633 }
634
Neil Armstrong0d763412022-08-11 10:32:22 +0200635 MBEDTLS_MPI_CHK( ecjpake_kkp_read( ctx->md_type, &ctx->grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100636 ctx->point_format,
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200637 &G, &ctx->Xp, ID_PEER, &p, end ) );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200638
639 if( p != end )
640 {
641 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
642 goto cleanup;
643 }
644
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200645cleanup:
646 mbedtls_ecp_group_free( &grp );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200647 mbedtls_ecp_point_free( &G );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200648
649 return( ret );
650}
651
652/*
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200653 * Compute R = +/- X * S mod N, taking care not to leak S
654 */
655static int ecjpake_mul_secret( mbedtls_mpi *R, int sign,
656 const mbedtls_mpi *X,
657 const mbedtls_mpi *S,
658 const mbedtls_mpi *N,
659 int (*f_rng)(void *, unsigned char *, size_t),
660 void *p_rng )
661{
Janos Follath24eed8d2019-11-22 13:21:35 +0000662 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200663 mbedtls_mpi b; /* Blinding value, then s + N * blinding */
664
665 mbedtls_mpi_init( &b );
666
667 /* b = s + rnd-128-bit * N */
668 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &b, 16, f_rng, p_rng ) );
669 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &b, &b, N ) );
670 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &b, &b, S ) );
671
672 /* R = sign * X * b mod N */
673 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( R, X, &b ) );
674 R->s *= sign;
675 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( R, R, N ) );
676
677cleanup:
678 mbedtls_mpi_free( &b );
679
680 return( ret );
681}
682
683/*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200684 * 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 +0200685 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200686int mbedtls_ecjpake_write_round_two( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200687 unsigned char *buf, size_t len, size_t *olen,
688 int (*f_rng)(void *, unsigned char *, size_t),
689 void *p_rng )
690{
Janos Follath24eed8d2019-11-22 13:21:35 +0000691 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200692 mbedtls_ecp_point G; /* C: GA, S: GB */
693 mbedtls_ecp_point Xm; /* C: Xc, S: Xs */
694 mbedtls_mpi xm; /* C: xc, S: xs */
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200695 unsigned char *p = buf;
696 const unsigned char *end = buf + len;
697 size_t ec_len;
Hanno Becker185e5162018-12-19 09:48:50 +0000698
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200699 mbedtls_ecp_point_init( &G );
700 mbedtls_ecp_point_init( &Xm );
701 mbedtls_mpi_init( &xm );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200702
703 /*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200704 * 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 +0200705 *
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200706 * Client: GA = X1 + X3 + X4 | xs = x2 * s | Xc = xc * GA
707 * Server: GB = X3 + X1 + X2 | xs = x4 * s | Xs = xs * GB
708 * Unified: G = Xm1 + Xp1 + Xp2 | xm = xm2 * s | Xm = xm * G
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200709 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200710 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200711 &ctx->Xp1, &ctx->Xp2, &ctx->Xm1 ) );
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200712 MBEDTLS_MPI_CHK( ecjpake_mul_secret( &xm, 1, &ctx->xm2, &ctx->s,
713 &ctx->grp.N, f_rng, p_rng ) );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200714 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &Xm, &xm, &G, f_rng, p_rng ) );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200715
716 /*
717 * Now write things out
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200718 *
719 * struct {
720 * ECParameters curve_params; // only server writing its message
721 * ECJPAKEKeyKP ecjpake_key_kp;
722 * } Client/ServerECJPAKEParams;
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200723 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200724 if( ctx->role == MBEDTLS_ECJPAKE_SERVER )
725 {
726 if( end < p )
727 {
728 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
729 goto cleanup;
730 }
731 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_group( &ctx->grp, &ec_len,
732 p, end - p ) );
733 p += ec_len;
734 }
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200735
736 if( end < p )
737 {
738 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
739 goto cleanup;
740 }
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200741 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( &ctx->grp, &Xm,
Robert Cragie7cdad772015-10-02 13:31:41 +0100742 ctx->point_format, &ec_len, p, end - p ) );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200743 p += ec_len;
744
Neil Armstrong0d763412022-08-11 10:32:22 +0200745 MBEDTLS_MPI_CHK( ecjpake_zkp_write( ctx->md_type, &ctx->grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100746 ctx->point_format,
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200747 &G, &xm, &Xm, ID_MINE,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200748 &p, end, f_rng, p_rng ) );
749
750 *olen = p - buf;
751
752cleanup:
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200753 mbedtls_ecp_point_free( &G );
754 mbedtls_ecp_point_free( &Xm );
755 mbedtls_mpi_free( &xm );
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +0200756
757 return( ret );
758}
759
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200760/*
761 * Derive PMS (7.4.2.7 / 7.4.2.8)
762 */
Neil Armstrong12663092022-06-15 16:00:00 +0200763static int mbedtls_ecjpake_derive_k( mbedtls_ecjpake_context *ctx,
764 mbedtls_ecp_point *K,
765 int (*f_rng)(void *, unsigned char *, size_t),
766 void *p_rng )
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200767{
Janos Follath24eed8d2019-11-22 13:21:35 +0000768 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200769 mbedtls_mpi m_xm2_s, one;
Hanno Becker185e5162018-12-19 09:48:50 +0000770
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 ) );
Neil Armstrong12663092022-06-15 16:00:00 +0200783 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( &ctx->grp, K,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200784 &one, &ctx->Xp,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200785 &m_xm2_s, &ctx->Xp2 ) );
Neil Armstrong12663092022-06-15 16:00:00 +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
Neil Armstrong12663092022-06-15 16:00:00 +0200789cleanup:
790 mbedtls_mpi_free( &m_xm2_s );
791 mbedtls_mpi_free( &one );
792
793 return( ret );
794}
795
796int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx,
797 unsigned char *buf, size_t len, size_t *olen,
798 int (*f_rng)(void *, unsigned char *, size_t),
799 void *p_rng )
800{
801 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
802 mbedtls_ecp_point K;
803 unsigned char kx[MBEDTLS_ECP_MAX_BYTES];
804 size_t x_bytes;
805
806 *olen = mbedtls_hash_info_get_size( ctx->md_type );
807 if( len < *olen )
808 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
809
810 mbedtls_ecp_point_init( &K );
811
812 ret = mbedtls_ecjpake_derive_k(ctx, &K, f_rng, p_rng);
813 if( ret )
814 goto cleanup;
815
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200816 /* PMS = SHA-256( K.X ) */
817 x_bytes = ( ctx->grp.pbits + 7 ) / 8;
818 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &K.X, kx, x_bytes ) );
Neil Armstrongecaba1c2022-08-11 10:47:08 +0200819 MBEDTLS_MPI_CHK( mbedtls_ecjpake_compute_hash( ctx->md_type,
820 kx, x_bytes, buf ) );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200821
822cleanup:
823 mbedtls_ecp_point_free( &K );
Neil Armstrong12663092022-06-15 16:00:00 +0200824
825 return( ret );
826}
827
828int mbedtls_ecjpake_write_shared_key( mbedtls_ecjpake_context *ctx,
829 unsigned char *buf, size_t len, size_t *olen,
830 int (*f_rng)(void *, unsigned char *, size_t),
831 void *p_rng )
832{
833 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
834 mbedtls_ecp_point K;
835
836 mbedtls_ecp_point_init( &K );
837
838 ret = mbedtls_ecjpake_derive_k(ctx, &K, f_rng, p_rng);
839 if( ret )
840 goto cleanup;
841
842 ret = mbedtls_ecp_point_write_binary( &ctx->grp, &K, ctx->point_format,
843 olen, buf, len );
844 if( ret != 0 )
845 goto cleanup;
846
847cleanup:
848 mbedtls_ecp_point_free( &K );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200849
850 return( ret );
851}
852
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200853#undef ID_MINE
854#undef ID_PEER
855
Hanno Becker616d1ca2018-01-24 10:25:05 +0000856#endif /* ! MBEDTLS_ECJPAKE_ALT */
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200857
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200858#if defined(MBEDTLS_SELF_TEST)
859
860#if defined(MBEDTLS_PLATFORM_C)
861#include "mbedtls/platform.h"
862#else
863#include <stdio.h>
864#define mbedtls_printf printf
865#endif
866
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200867#if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
868 !defined(MBEDTLS_SHA256_C)
869int mbedtls_ecjpake_self_test( int verbose )
870{
871 (void) verbose;
872 return( 0 );
873}
874#else
875
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200876static const unsigned char ecjpake_test_password[] = {
877 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x6a, 0x70, 0x61, 0x6b, 0x65, 0x74,
878 0x65, 0x73, 0x74
879};
880
Steven Cooreman64f27732021-01-11 17:20:10 +0100881#if !defined(MBEDTLS_ECJPAKE_ALT)
882
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200883static const unsigned char ecjpake_test_x1[] = {
884 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
885 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
886 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21
887};
888
889static const unsigned char ecjpake_test_x2[] = {
890 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
891 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
892 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
893};
894
895static const unsigned char ecjpake_test_x3[] = {
896 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
897 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
898 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
899};
900
901static const unsigned char ecjpake_test_x4[] = {
902 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc,
903 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
904 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1
905};
906
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200907static const unsigned char ecjpake_test_cli_one[] = {
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200908 0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19,
909 0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44,
910 0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad,
911 0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62,
912 0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9,
913 0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d,
914 0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e,
915 0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e,
916 0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73,
917 0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22,
918 0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce,
919 0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00,
920 0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200921 0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e,
922 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62,
923 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5,
924 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb,
925 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35,
926 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0,
927 0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb,
928 0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47,
929 0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39,
930 0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97,
931 0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40,
932 0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d,
933 0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa,
934 0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d,
935 0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200936};
937
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200938static const unsigned char ecjpake_test_srv_one[] = {
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200939 0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb,
940 0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18,
941 0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47,
942 0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f,
943 0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7,
944 0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d,
945 0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64,
946 0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36,
947 0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2,
948 0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec,
949 0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16,
950 0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96,
951 0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3,
952 0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19,
953 0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f,
954 0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8,
955 0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7,
956 0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea,
957 0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5,
958 0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6,
959 0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31,
960 0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d,
961 0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8,
962 0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee,
963 0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84,
964 0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f,
965 0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80,
966 0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12
967};
968
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200969static const unsigned char ecjpake_test_srv_two[] = {
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200970 0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23,
971 0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c,
972 0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f,
973 0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca,
974 0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26,
975 0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55,
976 0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38,
977 0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6,
978 0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9,
979 0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4,
980 0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2,
981 0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8,
982 0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd,
983 0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c
984};
985
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200986static const unsigned char ecjpake_test_cli_two[] = {
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +0200987 0x41, 0x04, 0x69, 0xd5, 0x4e, 0xe8, 0x5e, 0x90, 0xce, 0x3f, 0x12, 0x46,
988 0x74, 0x2d, 0xe5, 0x07, 0xe9, 0x39, 0xe8, 0x1d, 0x1d, 0xc1, 0xc5, 0xcb,
989 0x98, 0x8b, 0x58, 0xc3, 0x10, 0xc9, 0xfd, 0xd9, 0x52, 0x4d, 0x93, 0x72,
990 0x0b, 0x45, 0x54, 0x1c, 0x83, 0xee, 0x88, 0x41, 0x19, 0x1d, 0xa7, 0xce,
991 0xd8, 0x6e, 0x33, 0x12, 0xd4, 0x36, 0x23, 0xc1, 0xd6, 0x3e, 0x74, 0x98,
992 0x9a, 0xba, 0x4a, 0xff, 0xd1, 0xee, 0x41, 0x04, 0x07, 0x7e, 0x8c, 0x31,
993 0xe2, 0x0e, 0x6b, 0xed, 0xb7, 0x60, 0xc1, 0x35, 0x93, 0xe6, 0x9f, 0x15,
994 0xbe, 0x85, 0xc2, 0x7d, 0x68, 0xcd, 0x09, 0xcc, 0xb8, 0xc4, 0x18, 0x36,
995 0x08, 0x91, 0x7c, 0x5c, 0x3d, 0x40, 0x9f, 0xac, 0x39, 0xfe, 0xfe, 0xe8,
996 0x2f, 0x72, 0x92, 0xd3, 0x6f, 0x0d, 0x23, 0xe0, 0x55, 0x91, 0x3f, 0x45,
997 0xa5, 0x2b, 0x85, 0xdd, 0x8a, 0x20, 0x52, 0xe9, 0xe1, 0x29, 0xbb, 0x4d,
998 0x20, 0x0f, 0x01, 0x1f, 0x19, 0x48, 0x35, 0x35, 0xa6, 0xe8, 0x9a, 0x58,
999 0x0c, 0x9b, 0x00, 0x03, 0xba, 0xf2, 0x14, 0x62, 0xec, 0xe9, 0x1a, 0x82,
1000 0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c
1001};
1002
Neil Armstrong12663092022-06-15 16:00:00 +02001003static const unsigned char ecjpake_test_shared_key[] = {
1004 0x04, 0x01, 0xab, 0xe9, 0xf2, 0xc7, 0x3a, 0x99, 0x14, 0xcb, 0x1f, 0x80,
1005 0xfb, 0x9d, 0xdb, 0x7e, 0x00, 0x12, 0xa8, 0x9c, 0x2f, 0x39, 0x27, 0x79,
1006 0xf9, 0x64, 0x40, 0x14, 0x75, 0xea, 0xc1, 0x31, 0x28, 0x43, 0x8f, 0xe1,
1007 0x12, 0x41, 0xd6, 0xc1, 0xe5, 0x5f, 0x7b, 0x80, 0x88, 0x94, 0xc9, 0xc0,
1008 0x27, 0xa3, 0x34, 0x41, 0xf5, 0xcb, 0xa1, 0xfe, 0x6c, 0xc7, 0xe6, 0x12,
1009 0x17, 0xc3, 0xde, 0x27, 0xb4,
1010};
1011
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001012static const unsigned char ecjpake_test_pms[] = {
1013 0xf3, 0xd4, 0x7f, 0x59, 0x98, 0x44, 0xdb, 0x92, 0xa5, 0x69, 0xbb, 0xe7,
1014 0x98, 0x1e, 0x39, 0xd9, 0x31, 0xfd, 0x74, 0x3b, 0xf2, 0x2e, 0x98, 0xf9,
1015 0xb4, 0x38, 0xf7, 0x19, 0xd3, 0xc4, 0xf3, 0x51
1016};
1017
Manuel Pégourié-Gonnardaa3ed6f2021-06-15 11:29:26 +02001018/*
1019 * PRNG for test - !!!INSECURE NEVER USE IN PRODUCTION!!!
1020 *
1021 * This is the linear congruential generator from numerical recipes,
1022 * except we only use the low byte as the output. See
1023 * https://en.wikipedia.org/wiki/Linear_congruential_generator#Parameters_in_common_use
1024 */
1025static int self_test_rng( void *ctx, unsigned char *out, size_t len )
1026{
1027 static uint32_t state = 42;
1028
1029 (void) ctx;
1030
1031 for( size_t i = 0; i < len; i++ )
1032 {
1033 state = state * 1664525u + 1013904223u;
1034 out[i] = (unsigned char) state;
1035 }
1036
1037 return( 0 );
1038}
1039
Antonin Décimo36e89b52019-01-23 15:24:37 +01001040/* Load my private keys and generate the corresponding public keys */
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001041static int ecjpake_test_load( mbedtls_ecjpake_context *ctx,
1042 const unsigned char *xm1, size_t len1,
1043 const unsigned char *xm2, size_t len2 )
1044{
Janos Follath24eed8d2019-11-22 13:21:35 +00001045 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001046
1047 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm1, xm1, len1 ) );
1048 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm2, xm2, len2 ) );
1049 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm1, &ctx->xm1,
Manuel Pégourié-Gonnardaa3ed6f2021-06-15 11:29:26 +02001050 &ctx->grp.G, self_test_rng, NULL ) );
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001051 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm2, &ctx->xm2,
Manuel Pégourié-Gonnardaa3ed6f2021-06-15 11:29:26 +02001052 &ctx->grp.G, self_test_rng, NULL ) );
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001053
1054cleanup:
1055 return( ret );
1056}
1057
Steven Cooreman64f27732021-01-11 17:20:10 +01001058#endif /* ! MBEDTLS_ECJPAKE_ALT */
1059
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001060/* For tests we don't need a secure RNG;
1061 * use the LGC from Numerical Recipes for simplicity */
1062static int ecjpake_lgc( void *p, unsigned char *out, size_t len )
1063{
1064 static uint32_t x = 42;
1065 (void) p;
1066
1067 while( len > 0 )
1068 {
1069 size_t use_len = len > 4 ? 4 : len;
1070 x = 1664525 * x + 1013904223;
1071 memcpy( out, &x, use_len );
1072 out += use_len;
1073 len -= use_len;
1074 }
1075
1076 return( 0 );
1077}
1078
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +02001079#define TEST_ASSERT( x ) \
1080 do { \
1081 if( x ) \
1082 ret = 0; \
1083 else \
1084 { \
1085 ret = 1; \
1086 goto cleanup; \
1087 } \
1088 } while( 0 )
1089
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001090/*
1091 * Checkup routine
1092 */
1093int mbedtls_ecjpake_self_test( int verbose )
1094{
Janos Follath24eed8d2019-11-22 13:21:35 +00001095 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001096 mbedtls_ecjpake_context cli;
1097 mbedtls_ecjpake_context srv;
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001098 unsigned char buf[512], pms[32];
1099 size_t len, pmslen;
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001100
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001101 mbedtls_ecjpake_init( &cli );
1102 mbedtls_ecjpake_init( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001103
1104 if( verbose != 0 )
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001105 mbedtls_printf( " ECJPAKE test #0 (setup): " );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +02001106
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +02001107 TEST_ASSERT( mbedtls_ecjpake_setup( &cli, MBEDTLS_ECJPAKE_CLIENT,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001108 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1109 ecjpake_test_password,
1110 sizeof( ecjpake_test_password ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001111
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +02001112 TEST_ASSERT( mbedtls_ecjpake_setup( &srv, MBEDTLS_ECJPAKE_SERVER,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001113 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1114 ecjpake_test_password,
1115 sizeof( ecjpake_test_password ) ) == 0 );
1116
1117 if( verbose != 0 )
1118 mbedtls_printf( "passed\n" );
1119
1120 if( verbose != 0 )
1121 mbedtls_printf( " ECJPAKE test #1 (random handshake): " );
1122
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001123 TEST_ASSERT( mbedtls_ecjpake_write_round_one( &cli,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001124 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1125
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001126 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv, buf, len ) == 0 );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001127
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001128 TEST_ASSERT( mbedtls_ecjpake_write_round_one( &srv,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001129 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1130
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001131 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli, buf, len ) == 0 );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001132
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001133 TEST_ASSERT( mbedtls_ecjpake_write_round_two( &srv,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +02001134 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1135
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001136 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli, buf, len ) == 0 );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +02001137
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001138 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001139 pms, sizeof( pms ), &pmslen, ecjpake_lgc, NULL ) == 0 );
1140
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001141 TEST_ASSERT( mbedtls_ecjpake_write_round_two( &cli,
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +02001142 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1143
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001144 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv, buf, len ) == 0 );
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +02001145
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001146 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001147 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1148
1149 TEST_ASSERT( len == pmslen );
1150 TEST_ASSERT( memcmp( buf, pms, len ) == 0 );
1151
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001152 if( verbose != 0 )
1153 mbedtls_printf( "passed\n" );
1154
Steven Cooreman64f27732021-01-11 17:20:10 +01001155#if !defined(MBEDTLS_ECJPAKE_ALT)
1156 /* 'reference handshake' tests can only be run against implementations
1157 * for which we have 100% control over how the random ephemeral keys
1158 * are generated. This is only the case for the internal mbed TLS
1159 * implementation, so these tests are skipped in case the internal
1160 * implementation is swapped out for an alternative one. */
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001161 if( verbose != 0 )
1162 mbedtls_printf( " ECJPAKE test #2 (reference handshake): " );
1163
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001164 /* Simulate generation of round one */
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001165 MBEDTLS_MPI_CHK( ecjpake_test_load( &cli,
1166 ecjpake_test_x1, sizeof( ecjpake_test_x1 ),
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001167 ecjpake_test_x2, sizeof( ecjpake_test_x2 ) ) );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001168
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001169 MBEDTLS_MPI_CHK( ecjpake_test_load( &srv,
1170 ecjpake_test_x3, sizeof( ecjpake_test_x3 ),
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001171 ecjpake_test_x4, sizeof( ecjpake_test_x4 ) ) );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001172
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001173 /* Read round one */
1174 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv,
1175 ecjpake_test_cli_one,
1176 sizeof( ecjpake_test_cli_one ) ) == 0 );
1177
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001178 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001179 ecjpake_test_srv_one,
1180 sizeof( ecjpake_test_srv_one ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001181
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001182 /* Skip generation of round two, read round two */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001183 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001184 ecjpake_test_srv_two,
1185 sizeof( ecjpake_test_srv_two ) ) == 0 );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +02001186
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001187 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001188 ecjpake_test_cli_two,
1189 sizeof( ecjpake_test_cli_two ) ) == 0 );
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +02001190
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001191 /* Server derives PMS */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001192 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001193 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1194
1195 TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
1196 TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
1197
Neil Armstrong12663092022-06-15 16:00:00 +02001198 /* Server derives K as unsigned binary data */
1199 TEST_ASSERT( mbedtls_ecjpake_write_shared_key( &srv,
1200 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1201
1202 TEST_ASSERT( len == sizeof( ecjpake_test_shared_key ) );
1203 TEST_ASSERT( memcmp( buf, ecjpake_test_shared_key, len ) == 0 );
1204
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001205 memset( buf, 0, len ); /* Avoid interferences with next step */
1206
1207 /* Client derives PMS */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001208 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001209 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1210
1211 TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
1212 TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
1213
Neil Armstrong12663092022-06-15 16:00:00 +02001214 /* Client derives K as unsigned binary data */
1215 TEST_ASSERT( mbedtls_ecjpake_write_shared_key( &cli,
1216 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1217
1218 TEST_ASSERT( len == sizeof( ecjpake_test_shared_key ) );
1219 TEST_ASSERT( memcmp( buf, ecjpake_test_shared_key, len ) == 0 );
1220
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001221 if( verbose != 0 )
1222 mbedtls_printf( "passed\n" );
Steven Cooreman64f27732021-01-11 17:20:10 +01001223#endif /* ! MBEDTLS_ECJPAKE_ALT */
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001224
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001225cleanup:
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001226 mbedtls_ecjpake_free( &cli );
1227 mbedtls_ecjpake_free( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001228
1229 if( ret != 0 )
1230 {
1231 if( verbose != 0 )
1232 mbedtls_printf( "failed\n" );
1233
1234 ret = 1;
1235 }
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001236
1237 if( verbose != 0 )
1238 mbedtls_printf( "\n" );
1239
1240 return( ret );
1241}
1242
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +02001243#undef TEST_ASSERT
1244
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001245#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_SHA256_C */
1246
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001247#endif /* MBEDTLS_SELF_TEST */
1248
1249#endif /* MBEDTLS_ECJPAKE_C */