blob: 79ea3cbec474076abff48d94b9925f538b0dffd0 [file] [log] [blame]
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001/*
2 * Elliptic curve J-PAKE
3 *
4 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
5 * 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.
18 *
19 * This file is part of mbed TLS (https://tls.mbed.org)
20 */
21
22/*
Manuel Pégourié-Gonnard6b798b92015-08-14 11:18:30 +020023 * References in the code are to the Thread v1.0 Specification,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +020024 * available to members of the Thread Group http://threadgroup.org/
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +020025 */
26
27#if !defined(MBEDTLS_CONFIG_FILE)
28#include "mbedtls/config.h"
29#else
30#include MBEDTLS_CONFIG_FILE
31#endif
32
33#if defined(MBEDTLS_ECJPAKE_C)
34
35#include "mbedtls/ecjpake.h"
Hanno Becker71c8e1b2018-12-14 17:09:39 +000036#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000037#include "mbedtls/error.h"
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +020038
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +020039#include <string.h>
40
Hanno Becker616d1ca2018-01-24 10:25:05 +000041#if !defined(MBEDTLS_ECJPAKE_ALT)
42
Hanno Becker71c8e1b2018-12-14 17:09:39 +000043/* Parameter validation macros based on platform_util.h */
44#define ECJPAKE_VALIDATE_RET( cond ) \
45 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA )
46#define ECJPAKE_VALIDATE( cond ) \
47 MBEDTLS_INTERNAL_VALIDATE( cond )
48
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +020049/*
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +020050 * Convert a mbedtls_ecjpake_role to identifier string
51 */
52static const char * const ecjpake_id[] = {
53 "client",
54 "server"
55};
56
57#define ID_MINE ( ecjpake_id[ ctx->role ] )
58#define ID_PEER ( ecjpake_id[ 1 - ctx->role ] )
59
60/*
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020061 * Initialize context
62 */
63void mbedtls_ecjpake_init( mbedtls_ecjpake_context *ctx )
64{
Hanno Becker71c8e1b2018-12-14 17:09:39 +000065 ECJPAKE_VALIDATE( ctx != NULL );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020066
67 ctx->md_info = NULL;
68 mbedtls_ecp_group_init( &ctx->grp );
Manuel Pégourié-Gonnardb7da1942015-10-19 13:35:22 +020069 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020070
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +020071 mbedtls_ecp_point_init( &ctx->Xm1 );
72 mbedtls_ecp_point_init( &ctx->Xm2 );
73 mbedtls_ecp_point_init( &ctx->Xp1 );
74 mbedtls_ecp_point_init( &ctx->Xp2 );
75 mbedtls_ecp_point_init( &ctx->Xp );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020076
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +020077 mbedtls_mpi_init( &ctx->xm1 );
78 mbedtls_mpi_init( &ctx->xm2 );
79 mbedtls_mpi_init( &ctx->s );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020080}
81
82/*
83 * Free context
84 */
85void mbedtls_ecjpake_free( mbedtls_ecjpake_context *ctx )
86{
87 if( ctx == NULL )
88 return;
89
90 ctx->md_info = NULL;
91 mbedtls_ecp_group_free( &ctx->grp );
92
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +020093 mbedtls_ecp_point_free( &ctx->Xm1 );
94 mbedtls_ecp_point_free( &ctx->Xm2 );
95 mbedtls_ecp_point_free( &ctx->Xp1 );
96 mbedtls_ecp_point_free( &ctx->Xp2 );
97 mbedtls_ecp_point_free( &ctx->Xp );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020098
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +020099 mbedtls_mpi_free( &ctx->xm1 );
100 mbedtls_mpi_free( &ctx->xm2 );
101 mbedtls_mpi_free( &ctx->s );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200102}
103
104/*
105 * Setup context
106 */
107int mbedtls_ecjpake_setup( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +0200108 mbedtls_ecjpake_role role,
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200109 mbedtls_md_type_t hash,
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200110 mbedtls_ecp_group_id curve,
111 const unsigned char *secret,
112 size_t len )
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200113{
Janos Follath24eed8d2019-11-22 13:21:35 +0000114 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker185e5162018-12-19 09:48:50 +0000115
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000116 ECJPAKE_VALIDATE_RET( ctx != NULL );
117 ECJPAKE_VALIDATE_RET( role == MBEDTLS_ECJPAKE_CLIENT ||
118 role == MBEDTLS_ECJPAKE_SERVER );
119 ECJPAKE_VALIDATE_RET( secret != NULL || len == 0 );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200120
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +0200121 ctx->role = role;
122
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200123 if( ( ctx->md_info = mbedtls_md_info_from_type( hash ) ) == NULL )
124 return( MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE );
125
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200126 MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ctx->grp, curve ) );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200127
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200128 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->s, secret, len ) );
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200129
130cleanup:
131 if( ret != 0 )
132 mbedtls_ecjpake_free( ctx );
133
134 return( ret );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200135}
136
137/*
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200138 * Check if context is ready for use
139 */
140int mbedtls_ecjpake_check( const mbedtls_ecjpake_context *ctx )
141{
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000142 ECJPAKE_VALIDATE_RET( ctx != NULL );
143
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200144 if( ctx->md_info == NULL ||
145 ctx->grp.id == MBEDTLS_ECP_DP_NONE ||
146 ctx->s.p == NULL )
147 {
148 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
149 }
150
151 return( 0 );
152}
153
154/*
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200155 * Write a point plus its length to a buffer
156 */
157static int ecjpake_write_len_point( unsigned char **p,
158 const unsigned char *end,
159 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100160 const int pf,
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200161 const mbedtls_ecp_point *P )
162{
Janos Follath24eed8d2019-11-22 13:21:35 +0000163 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200164 size_t len;
165
166 /* Need at least 4 for length plus 1 for point */
167 if( end < *p || end - *p < 5 )
168 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
169
Robert Cragie7cdad772015-10-02 13:31:41 +0100170 ret = mbedtls_ecp_point_write_binary( grp, P, pf,
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200171 &len, *p + 4, end - ( *p + 4 ) );
172 if( ret != 0 )
173 return( ret );
174
175 (*p)[0] = (unsigned char)( ( len >> 24 ) & 0xFF );
176 (*p)[1] = (unsigned char)( ( len >> 16 ) & 0xFF );
177 (*p)[2] = (unsigned char)( ( len >> 8 ) & 0xFF );
178 (*p)[3] = (unsigned char)( ( len ) & 0xFF );
179
180 *p += 4 + len;
181
182 return( 0 );
183}
184
185/*
186 * Size of the temporary buffer for ecjpake_hash:
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200187 * 3 EC points plus their length, plus ID and its length (4 + 6 bytes)
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200188 */
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200189#define ECJPAKE_HASH_BUF_LEN ( 3 * ( 4 + MBEDTLS_ECP_MAX_PT_LEN ) + 4 + 6 )
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200190
191/*
192 * Compute hash for ZKP (7.4.2.2.2.1)
193 */
194static int ecjpake_hash( const mbedtls_md_info_t *md_info,
195 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100196 const int pf,
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200197 const mbedtls_ecp_point *G,
198 const mbedtls_ecp_point *V,
199 const mbedtls_ecp_point *X,
200 const char *id,
201 mbedtls_mpi *h )
202{
Janos Follath24eed8d2019-11-22 13:21:35 +0000203 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200204 unsigned char buf[ECJPAKE_HASH_BUF_LEN];
205 unsigned char *p = buf;
206 const unsigned char *end = buf + sizeof( buf );
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200207 const size_t id_len = strlen( id );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200208 unsigned char hash[MBEDTLS_MD_MAX_SIZE];
209
210 /* Write things to temporary buffer */
Robert Cragie7cdad772015-10-02 13:31:41 +0100211 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, G ) );
212 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, V ) );
213 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, X ) );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200214
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200215 if( end - p < 4 )
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200216 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
217
218 *p++ = (unsigned char)( ( id_len >> 24 ) & 0xFF );
219 *p++ = (unsigned char)( ( id_len >> 16 ) & 0xFF );
220 *p++ = (unsigned char)( ( id_len >> 8 ) & 0xFF );
221 *p++ = (unsigned char)( ( id_len ) & 0xFF );
222
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200223 if( end < p || (size_t)( end - p ) < id_len )
224 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
225
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200226 memcpy( p, id, id_len );
227 p += id_len;
228
229 /* Compute hash */
k-stachowiak41503352019-06-28 14:14:02 +0200230 MBEDTLS_MPI_CHK( mbedtls_md( md_info, buf, p - buf, hash ) );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200231
232 /* Turn it into an integer mod n */
233 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( h, hash,
234 mbedtls_md_get_size( md_info ) ) );
235 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( h, h, &grp->N ) );
236
237cleanup:
238 return( ret );
239}
240
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200241/*
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200242 * Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3)
243 */
244static int ecjpake_zkp_read( const mbedtls_md_info_t *md_info,
245 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100246 const int pf,
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200247 const mbedtls_ecp_point *G,
248 const mbedtls_ecp_point *X,
249 const char *id,
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200250 const unsigned char **p,
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200251 const unsigned char *end )
252{
Janos Follath24eed8d2019-11-22 13:21:35 +0000253 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200254 mbedtls_ecp_point V, VV;
255 mbedtls_mpi r, h;
256 size_t r_len;
257
258 mbedtls_ecp_point_init( &V );
259 mbedtls_ecp_point_init( &VV );
260 mbedtls_mpi_init( &r );
261 mbedtls_mpi_init( &h );
262
263 /*
264 * struct {
265 * ECPoint V;
266 * opaque r<1..2^8-1>;
267 * } ECSchnorrZKP;
268 */
269 if( end < *p )
270 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
271
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200272 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, &V, p, end - *p ) );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200273
274 if( end < *p || (size_t)( end - *p ) < 1 )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200275 {
276 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
277 goto cleanup;
278 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200279
280 r_len = *(*p)++;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200281
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200282 if( end < *p || (size_t)( end - *p ) < r_len )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200283 {
284 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
285 goto cleanup;
286 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200287
288 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &r, *p, r_len ) );
289 *p += r_len;
290
291 /*
292 * Verification
293 */
Robert Cragie7cdad772015-10-02 13:31:41 +0100294 MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200295 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( (mbedtls_ecp_group *) grp,
296 &VV, &h, X, &r, G ) );
297
298 if( mbedtls_ecp_point_cmp( &VV, &V ) != 0 )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200299 {
300 ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
301 goto cleanup;
302 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200303
304cleanup:
305 mbedtls_ecp_point_free( &V );
306 mbedtls_ecp_point_free( &VV );
307 mbedtls_mpi_free( &r );
308 mbedtls_mpi_free( &h );
309
310 return( ret );
311}
312
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200313/*
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200314 * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2)
315 */
316static int ecjpake_zkp_write( const mbedtls_md_info_t *md_info,
317 const mbedtls_ecp_group *grp,
Darryl Green11999bb2018-03-13 15:22:58 +0000318 const int pf,
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200319 const mbedtls_ecp_point *G,
320 const mbedtls_mpi *x,
321 const mbedtls_ecp_point *X,
322 const char *id,
323 unsigned char **p,
324 const unsigned char *end,
325 int (*f_rng)(void *, unsigned char *, size_t),
326 void *p_rng )
327{
Janos Follath24eed8d2019-11-22 13:21:35 +0000328 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200329 mbedtls_ecp_point V;
330 mbedtls_mpi v;
331 mbedtls_mpi h; /* later recycled to hold r */
332 size_t len;
333
334 if( end < *p )
335 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
336
337 mbedtls_ecp_point_init( &V );
338 mbedtls_mpi_init( &v );
339 mbedtls_mpi_init( &h );
340
341 /* Compute signature */
342 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp,
343 G, &v, &V, f_rng, p_rng ) );
Robert Cragie7cdad772015-10-02 13:31:41 +0100344 MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) );
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200345 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &h, &h, x ) ); /* x*h */
346 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &h, &v, &h ) ); /* v - x*h */
347 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &h, &h, &grp->N ) ); /* r */
348
349 /* Write it out */
350 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, &V,
Robert Cragie7cdad772015-10-02 13:31:41 +0100351 pf, &len, *p, end - *p ) );
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200352 *p += len;
353
354 len = mbedtls_mpi_size( &h ); /* actually r */
355 if( end < *p || (size_t)( end - *p ) < 1 + len || len > 255 )
356 {
357 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
358 goto cleanup;
359 }
360
361 *(*p)++ = (unsigned char)( len & 0xFF );
362 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, *p, len ) ); /* r */
363 *p += len;
364
365cleanup:
366 mbedtls_ecp_point_free( &V );
367 mbedtls_mpi_free( &v );
368 mbedtls_mpi_free( &h );
369
370 return( ret );
371}
372
373/*
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200374 * Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof
375 * Output: verified public key X
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200376 */
377static int ecjpake_kkp_read( const mbedtls_md_info_t *md_info,
378 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100379 const int pf,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200380 const mbedtls_ecp_point *G,
381 mbedtls_ecp_point *X,
382 const char *id,
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200383 const unsigned char **p,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200384 const unsigned char *end )
385{
Janos Follath24eed8d2019-11-22 13:21:35 +0000386 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200387
388 if( end < *p )
389 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
390
391 /*
392 * struct {
393 * ECPoint X;
394 * ECSchnorrZKP zkp;
395 * } ECJPAKEKeyKP;
396 */
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200397 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, X, p, end - *p ) );
Manuel Pégourié-Gonnard30590952015-08-17 10:37:40 +0200398 if( mbedtls_ecp_is_zero( X ) )
399 {
400 ret = MBEDTLS_ERR_ECP_INVALID_KEY;
401 goto cleanup;
402 }
403
Robert Cragie7cdad772015-10-02 13:31:41 +0100404 MBEDTLS_MPI_CHK( ecjpake_zkp_read( md_info, grp, pf, G, X, id, p, end ) );
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200405
406cleanup:
407 return( ret );
408}
409
410/*
411 * Generate an ECJPAKEKeyKP
412 * Output: the serialized structure, plus private/public key pair
413 */
414static int ecjpake_kkp_write( const mbedtls_md_info_t *md_info,
415 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100416 const int pf,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200417 const mbedtls_ecp_point *G,
418 mbedtls_mpi *x,
419 mbedtls_ecp_point *X,
420 const char *id,
421 unsigned char **p,
422 const unsigned char *end,
423 int (*f_rng)(void *, unsigned char *, size_t),
424 void *p_rng )
425{
Janos Follath24eed8d2019-11-22 13:21:35 +0000426 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200427 size_t len;
428
429 if( end < *p )
430 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
431
432 /* Generate key (7.4.2.3.1) and write it out */
433 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp, G, x, X,
434 f_rng, p_rng ) );
435 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, X,
Robert Cragie7cdad772015-10-02 13:31:41 +0100436 pf, &len, *p, end - *p ) );
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200437 *p += len;
438
439 /* Generate and write proof */
Robert Cragie7cdad772015-10-02 13:31:41 +0100440 MBEDTLS_MPI_CHK( ecjpake_zkp_write( md_info, grp, pf, G, x, X, id,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200441 p, end, f_rng, p_rng ) );
442
443cleanup:
444 return( ret );
445}
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200446
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200447/*
448 * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs
449 * Ouputs: verified peer public keys Xa, Xb
450 */
451static int ecjpake_kkpp_read( const mbedtls_md_info_t *md_info,
452 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100453 const int pf,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200454 const mbedtls_ecp_point *G,
455 mbedtls_ecp_point *Xa,
456 mbedtls_ecp_point *Xb,
457 const char *id,
458 const unsigned char *buf,
459 size_t len )
460{
Janos Follath24eed8d2019-11-22 13:21:35 +0000461 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200462 const unsigned char *p = buf;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200463 const unsigned char *end = buf + len;
464
465 /*
466 * struct {
467 * ECJPAKEKeyKP ecjpake_key_kp_pair_list[2];
468 * } ECJPAKEKeyKPPairList;
469 */
Robert Cragie7cdad772015-10-02 13:31:41 +0100470 MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xa, id, &p, end ) );
471 MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xb, id, &p, end ) );
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200472
473 if( p != end )
474 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
475
476cleanup:
477 return( ret );
478}
479
480/*
481 * Generate a ECJPAKEKeyKPPairList
482 * Outputs: the serialized structure, plus two private/public key pairs
483 */
484static int ecjpake_kkpp_write( const mbedtls_md_info_t *md_info,
485 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100486 const int pf,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200487 const mbedtls_ecp_point *G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200488 mbedtls_mpi *xm1,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200489 mbedtls_ecp_point *Xa,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200490 mbedtls_mpi *xm2,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200491 mbedtls_ecp_point *Xb,
492 const char *id,
493 unsigned char *buf,
494 size_t len,
495 size_t *olen,
496 int (*f_rng)(void *, unsigned char *, size_t),
497 void *p_rng )
498{
Janos Follath24eed8d2019-11-22 13:21:35 +0000499 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200500 unsigned char *p = buf;
501 const unsigned char *end = buf + len;
502
Robert Cragie7cdad772015-10-02 13:31:41 +0100503 MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm1, Xa, id,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200504 &p, end, f_rng, p_rng ) );
Robert Cragie7cdad772015-10-02 13:31:41 +0100505 MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm2, Xb, id,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200506 &p, end, f_rng, p_rng ) );
507
508 *olen = p - buf;
509
510cleanup:
511 return( ret );
512}
513
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200514/*
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200515 * Read and process the first round message
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200516 */
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200517int mbedtls_ecjpake_read_round_one( mbedtls_ecjpake_context *ctx,
518 const unsigned char *buf,
519 size_t len )
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200520{
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000521 ECJPAKE_VALIDATE_RET( ctx != NULL );
522 ECJPAKE_VALIDATE_RET( buf != NULL );
523
Robert Cragie7cdad772015-10-02 13:31:41 +0100524 return( ecjpake_kkpp_read( ctx->md_info, &ctx->grp, ctx->point_format,
525 &ctx->grp.G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200526 &ctx->Xp1, &ctx->Xp2, ID_PEER,
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200527 buf, len ) );
528}
529
530/*
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200531 * Generate and write the first round message
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200532 */
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200533int mbedtls_ecjpake_write_round_one( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200534 unsigned char *buf, size_t len, size_t *olen,
535 int (*f_rng)(void *, unsigned char *, size_t),
536 void *p_rng )
537{
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000538 ECJPAKE_VALIDATE_RET( ctx != NULL );
539 ECJPAKE_VALIDATE_RET( buf != NULL );
540 ECJPAKE_VALIDATE_RET( olen != NULL );
541 ECJPAKE_VALIDATE_RET( f_rng != NULL );
542
Robert Cragie7cdad772015-10-02 13:31:41 +0100543 return( ecjpake_kkpp_write( ctx->md_info, &ctx->grp, ctx->point_format,
544 &ctx->grp.G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200545 &ctx->xm1, &ctx->Xm1, &ctx->xm2, &ctx->Xm2,
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200546 ID_MINE, buf, len, olen, f_rng, p_rng ) );
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200547}
548
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200549/*
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200550 * Compute the sum of three points R = A + B + C
551 */
552static int ecjpake_ecp_add3( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
553 const mbedtls_ecp_point *A,
554 const mbedtls_ecp_point *B,
555 const mbedtls_ecp_point *C )
556{
Janos Follath24eed8d2019-11-22 13:21:35 +0000557 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200558 mbedtls_mpi one;
559
560 mbedtls_mpi_init( &one );
561
562 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
563 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, A, &one, B ) );
564 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, R, &one, C ) );
565
566cleanup:
567 mbedtls_mpi_free( &one );
568
569 return( ret );
570}
571
572/*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200573 * 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 +0200574 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200575int mbedtls_ecjpake_read_round_two( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200576 const unsigned char *buf,
577 size_t len )
578{
Janos Follath24eed8d2019-11-22 13:21:35 +0000579 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200580 const unsigned char *p = buf;
581 const unsigned char *end = buf + len;
582 mbedtls_ecp_group grp;
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200583 mbedtls_ecp_point G; /* C: GB, S: GA */
Hanno Becker185e5162018-12-19 09:48:50 +0000584
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000585 ECJPAKE_VALIDATE_RET( ctx != NULL );
586 ECJPAKE_VALIDATE_RET( buf != NULL );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200587
588 mbedtls_ecp_group_init( &grp );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200589 mbedtls_ecp_point_init( &G );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200590
591 /*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200592 * Server: GA = X3 + X4 + X1 (7.4.2.6.1)
593 * Client: GB = X1 + X2 + X3 (7.4.2.5.1)
594 * Unified: G = Xm1 + Xm2 + Xp1
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200595 * We need that before parsing in order to check Xp as we read it
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200596 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200597 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200598 &ctx->Xm1, &ctx->Xm2, &ctx->Xp1 ) );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200599
600 /*
601 * struct {
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200602 * ECParameters curve_params; // only client reading server msg
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200603 * ECJPAKEKeyKP ecjpake_key_kp;
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200604 * } Client/ServerECJPAKEParams;
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200605 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200606 if( ctx->role == MBEDTLS_ECJPAKE_CLIENT )
Manuel Pégourié-Gonnardd9802af2015-08-17 12:47:38 +0200607 {
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200608 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_group( &grp, &p, len ) );
Manuel Pégourié-Gonnardd9802af2015-08-17 12:47:38 +0200609 if( grp.id != ctx->grp.id )
610 {
611 ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
612 goto cleanup;
613 }
614 }
615
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200616 MBEDTLS_MPI_CHK( ecjpake_kkp_read( ctx->md_info, &ctx->grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100617 ctx->point_format,
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200618 &G, &ctx->Xp, ID_PEER, &p, end ) );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200619
620 if( p != end )
621 {
622 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
623 goto cleanup;
624 }
625
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200626cleanup:
627 mbedtls_ecp_group_free( &grp );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200628 mbedtls_ecp_point_free( &G );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200629
630 return( ret );
631}
632
633/*
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200634 * Compute R = +/- X * S mod N, taking care not to leak S
635 */
636static int ecjpake_mul_secret( mbedtls_mpi *R, int sign,
637 const mbedtls_mpi *X,
638 const mbedtls_mpi *S,
639 const mbedtls_mpi *N,
640 int (*f_rng)(void *, unsigned char *, size_t),
641 void *p_rng )
642{
Janos Follath24eed8d2019-11-22 13:21:35 +0000643 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200644 mbedtls_mpi b; /* Blinding value, then s + N * blinding */
645
646 mbedtls_mpi_init( &b );
647
648 /* b = s + rnd-128-bit * N */
649 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &b, 16, f_rng, p_rng ) );
650 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &b, &b, N ) );
651 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &b, &b, S ) );
652
653 /* R = sign * X * b mod N */
654 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( R, X, &b ) );
655 R->s *= sign;
656 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( R, R, N ) );
657
658cleanup:
659 mbedtls_mpi_free( &b );
660
661 return( ret );
662}
663
664/*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200665 * 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 +0200666 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200667int mbedtls_ecjpake_write_round_two( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200668 unsigned char *buf, size_t len, size_t *olen,
669 int (*f_rng)(void *, unsigned char *, size_t),
670 void *p_rng )
671{
Janos Follath24eed8d2019-11-22 13:21:35 +0000672 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200673 mbedtls_ecp_point G; /* C: GA, S: GB */
674 mbedtls_ecp_point Xm; /* C: Xc, S: Xs */
675 mbedtls_mpi xm; /* C: xc, S: xs */
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200676 unsigned char *p = buf;
677 const unsigned char *end = buf + len;
678 size_t ec_len;
Hanno Becker185e5162018-12-19 09:48:50 +0000679
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000680 ECJPAKE_VALIDATE_RET( ctx != NULL );
681 ECJPAKE_VALIDATE_RET( buf != NULL );
682 ECJPAKE_VALIDATE_RET( olen != NULL );
683 ECJPAKE_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200684
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200685 mbedtls_ecp_point_init( &G );
686 mbedtls_ecp_point_init( &Xm );
687 mbedtls_mpi_init( &xm );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200688
689 /*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200690 * 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 +0200691 *
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200692 * Client: GA = X1 + X3 + X4 | xs = x2 * s | Xc = xc * GA
693 * Server: GB = X3 + X1 + X2 | xs = x4 * s | Xs = xs * GB
694 * Unified: G = Xm1 + Xp1 + Xp2 | xm = xm2 * s | Xm = xm * G
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200695 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200696 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200697 &ctx->Xp1, &ctx->Xp2, &ctx->Xm1 ) );
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200698 MBEDTLS_MPI_CHK( ecjpake_mul_secret( &xm, 1, &ctx->xm2, &ctx->s,
699 &ctx->grp.N, f_rng, p_rng ) );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200700 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &Xm, &xm, &G, f_rng, p_rng ) );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200701
702 /*
703 * Now write things out
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200704 *
705 * struct {
706 * ECParameters curve_params; // only server writing its message
707 * ECJPAKEKeyKP ecjpake_key_kp;
708 * } Client/ServerECJPAKEParams;
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200709 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200710 if( ctx->role == MBEDTLS_ECJPAKE_SERVER )
711 {
712 if( end < p )
713 {
714 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
715 goto cleanup;
716 }
717 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_group( &ctx->grp, &ec_len,
718 p, end - p ) );
719 p += ec_len;
720 }
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200721
722 if( end < p )
723 {
724 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
725 goto cleanup;
726 }
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200727 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( &ctx->grp, &Xm,
Robert Cragie7cdad772015-10-02 13:31:41 +0100728 ctx->point_format, &ec_len, p, end - p ) );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200729 p += ec_len;
730
731 MBEDTLS_MPI_CHK( ecjpake_zkp_write( ctx->md_info, &ctx->grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100732 ctx->point_format,
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200733 &G, &xm, &Xm, ID_MINE,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200734 &p, end, f_rng, p_rng ) );
735
736 *olen = p - buf;
737
738cleanup:
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200739 mbedtls_ecp_point_free( &G );
740 mbedtls_ecp_point_free( &Xm );
741 mbedtls_mpi_free( &xm );
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +0200742
743 return( ret );
744}
745
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200746/*
747 * Derive PMS (7.4.2.7 / 7.4.2.8)
748 */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +0200749int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200750 unsigned char *buf, size_t len, size_t *olen,
751 int (*f_rng)(void *, unsigned char *, size_t),
752 void *p_rng )
753{
Janos Follath24eed8d2019-11-22 13:21:35 +0000754 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200755 mbedtls_ecp_point K;
756 mbedtls_mpi m_xm2_s, one;
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200757 unsigned char kx[MBEDTLS_ECP_MAX_BYTES];
758 size_t x_bytes;
Hanno Becker185e5162018-12-19 09:48:50 +0000759
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000760 ECJPAKE_VALIDATE_RET( ctx != NULL );
761 ECJPAKE_VALIDATE_RET( buf != NULL );
762 ECJPAKE_VALIDATE_RET( olen != NULL );
763 ECJPAKE_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200764
765 *olen = mbedtls_md_get_size( ctx->md_info );
766 if( len < *olen )
767 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
768
769 mbedtls_ecp_point_init( &K );
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200770 mbedtls_mpi_init( &m_xm2_s );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200771 mbedtls_mpi_init( &one );
772
773 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200774
775 /*
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200776 * Client: K = ( Xs - X4 * x2 * s ) * x2
777 * Server: K = ( Xc - X2 * x4 * s ) * x4
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200778 * Unified: K = ( Xp - Xp2 * xm2 * s ) * xm2
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200779 */
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200780 MBEDTLS_MPI_CHK( ecjpake_mul_secret( &m_xm2_s, -1, &ctx->xm2, &ctx->s,
781 &ctx->grp.N, f_rng, p_rng ) );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200782 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( &ctx->grp, &K,
783 &one, &ctx->Xp,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200784 &m_xm2_s, &ctx->Xp2 ) );
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200785 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &K, &ctx->xm2, &K,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200786 f_rng, p_rng ) );
787
788 /* PMS = SHA-256( K.X ) */
789 x_bytes = ( ctx->grp.pbits + 7 ) / 8;
790 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &K.X, kx, x_bytes ) );
791 MBEDTLS_MPI_CHK( mbedtls_md( ctx->md_info, kx, x_bytes, buf ) );
792
793cleanup:
794 mbedtls_ecp_point_free( &K );
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200795 mbedtls_mpi_free( &m_xm2_s );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200796 mbedtls_mpi_free( &one );
797
798 return( ret );
799}
800
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200801#undef ID_MINE
802#undef ID_PEER
803
Hanno Becker616d1ca2018-01-24 10:25:05 +0000804#endif /* ! MBEDTLS_ECJPAKE_ALT */
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200805
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200806#if defined(MBEDTLS_SELF_TEST)
807
808#if defined(MBEDTLS_PLATFORM_C)
809#include "mbedtls/platform.h"
810#else
811#include <stdio.h>
812#define mbedtls_printf printf
813#endif
814
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200815#if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
816 !defined(MBEDTLS_SHA256_C)
817int mbedtls_ecjpake_self_test( int verbose )
818{
819 (void) verbose;
820 return( 0 );
821}
822#else
823
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200824static const unsigned char ecjpake_test_password[] = {
825 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x6a, 0x70, 0x61, 0x6b, 0x65, 0x74,
826 0x65, 0x73, 0x74
827};
828
829static const unsigned char ecjpake_test_x1[] = {
830 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
831 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
832 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21
833};
834
835static const unsigned char ecjpake_test_x2[] = {
836 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
837 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
838 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
839};
840
841static const unsigned char ecjpake_test_x3[] = {
842 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
843 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
844 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
845};
846
847static const unsigned char ecjpake_test_x4[] = {
848 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc,
849 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
850 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1
851};
852
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200853static const unsigned char ecjpake_test_cli_one[] = {
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200854 0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19,
855 0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44,
856 0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad,
857 0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62,
858 0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9,
859 0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d,
860 0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e,
861 0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e,
862 0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73,
863 0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22,
864 0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce,
865 0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00,
866 0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200867 0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e,
868 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62,
869 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5,
870 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb,
871 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35,
872 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0,
873 0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb,
874 0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47,
875 0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39,
876 0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97,
877 0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40,
878 0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d,
879 0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa,
880 0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d,
881 0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200882};
883
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200884static const unsigned char ecjpake_test_srv_one[] = {
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200885 0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb,
886 0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18,
887 0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47,
888 0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f,
889 0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7,
890 0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d,
891 0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64,
892 0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36,
893 0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2,
894 0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec,
895 0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16,
896 0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96,
897 0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3,
898 0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19,
899 0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f,
900 0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8,
901 0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7,
902 0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea,
903 0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5,
904 0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6,
905 0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31,
906 0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d,
907 0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8,
908 0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee,
909 0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84,
910 0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f,
911 0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80,
912 0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12
913};
914
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200915static const unsigned char ecjpake_test_srv_two[] = {
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200916 0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23,
917 0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c,
918 0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f,
919 0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca,
920 0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26,
921 0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55,
922 0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38,
923 0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6,
924 0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9,
925 0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4,
926 0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2,
927 0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8,
928 0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd,
929 0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c
930};
931
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200932static const unsigned char ecjpake_test_cli_two[] = {
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +0200933 0x41, 0x04, 0x69, 0xd5, 0x4e, 0xe8, 0x5e, 0x90, 0xce, 0x3f, 0x12, 0x46,
934 0x74, 0x2d, 0xe5, 0x07, 0xe9, 0x39, 0xe8, 0x1d, 0x1d, 0xc1, 0xc5, 0xcb,
935 0x98, 0x8b, 0x58, 0xc3, 0x10, 0xc9, 0xfd, 0xd9, 0x52, 0x4d, 0x93, 0x72,
936 0x0b, 0x45, 0x54, 0x1c, 0x83, 0xee, 0x88, 0x41, 0x19, 0x1d, 0xa7, 0xce,
937 0xd8, 0x6e, 0x33, 0x12, 0xd4, 0x36, 0x23, 0xc1, 0xd6, 0x3e, 0x74, 0x98,
938 0x9a, 0xba, 0x4a, 0xff, 0xd1, 0xee, 0x41, 0x04, 0x07, 0x7e, 0x8c, 0x31,
939 0xe2, 0x0e, 0x6b, 0xed, 0xb7, 0x60, 0xc1, 0x35, 0x93, 0xe6, 0x9f, 0x15,
940 0xbe, 0x85, 0xc2, 0x7d, 0x68, 0xcd, 0x09, 0xcc, 0xb8, 0xc4, 0x18, 0x36,
941 0x08, 0x91, 0x7c, 0x5c, 0x3d, 0x40, 0x9f, 0xac, 0x39, 0xfe, 0xfe, 0xe8,
942 0x2f, 0x72, 0x92, 0xd3, 0x6f, 0x0d, 0x23, 0xe0, 0x55, 0x91, 0x3f, 0x45,
943 0xa5, 0x2b, 0x85, 0xdd, 0x8a, 0x20, 0x52, 0xe9, 0xe1, 0x29, 0xbb, 0x4d,
944 0x20, 0x0f, 0x01, 0x1f, 0x19, 0x48, 0x35, 0x35, 0xa6, 0xe8, 0x9a, 0x58,
945 0x0c, 0x9b, 0x00, 0x03, 0xba, 0xf2, 0x14, 0x62, 0xec, 0xe9, 0x1a, 0x82,
946 0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c
947};
948
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200949static const unsigned char ecjpake_test_pms[] = {
950 0xf3, 0xd4, 0x7f, 0x59, 0x98, 0x44, 0xdb, 0x92, 0xa5, 0x69, 0xbb, 0xe7,
951 0x98, 0x1e, 0x39, 0xd9, 0x31, 0xfd, 0x74, 0x3b, 0xf2, 0x2e, 0x98, 0xf9,
952 0xb4, 0x38, 0xf7, 0x19, 0xd3, 0xc4, 0xf3, 0x51
953};
954
Antonin Décimo36e89b52019-01-23 15:24:37 +0100955/* Load my private keys and generate the corresponding public keys */
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +0200956static int ecjpake_test_load( mbedtls_ecjpake_context *ctx,
957 const unsigned char *xm1, size_t len1,
958 const unsigned char *xm2, size_t len2 )
959{
Janos Follath24eed8d2019-11-22 13:21:35 +0000960 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +0200961
962 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm1, xm1, len1 ) );
963 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm2, xm2, len2 ) );
964 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm1, &ctx->xm1,
965 &ctx->grp.G, NULL, NULL ) );
966 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm2, &ctx->xm2,
967 &ctx->grp.G, NULL, NULL ) );
968
969cleanup:
970 return( ret );
971}
972
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200973/* For tests we don't need a secure RNG;
974 * use the LGC from Numerical Recipes for simplicity */
975static int ecjpake_lgc( void *p, unsigned char *out, size_t len )
976{
977 static uint32_t x = 42;
978 (void) p;
979
980 while( len > 0 )
981 {
982 size_t use_len = len > 4 ? 4 : len;
983 x = 1664525 * x + 1013904223;
984 memcpy( out, &x, use_len );
985 out += use_len;
986 len -= use_len;
987 }
988
989 return( 0 );
990}
991
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200992#define TEST_ASSERT( x ) \
993 do { \
994 if( x ) \
995 ret = 0; \
996 else \
997 { \
998 ret = 1; \
999 goto cleanup; \
1000 } \
1001 } while( 0 )
1002
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001003/*
1004 * Checkup routine
1005 */
1006int mbedtls_ecjpake_self_test( int verbose )
1007{
Janos Follath24eed8d2019-11-22 13:21:35 +00001008 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001009 mbedtls_ecjpake_context cli;
1010 mbedtls_ecjpake_context srv;
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001011 unsigned char buf[512], pms[32];
1012 size_t len, pmslen;
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001013
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001014 mbedtls_ecjpake_init( &cli );
1015 mbedtls_ecjpake_init( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001016
1017 if( verbose != 0 )
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001018 mbedtls_printf( " ECJPAKE test #0 (setup): " );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +02001019
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +02001020 TEST_ASSERT( mbedtls_ecjpake_setup( &cli, MBEDTLS_ECJPAKE_CLIENT,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001021 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1022 ecjpake_test_password,
1023 sizeof( ecjpake_test_password ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001024
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +02001025 TEST_ASSERT( mbedtls_ecjpake_setup( &srv, MBEDTLS_ECJPAKE_SERVER,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001026 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1027 ecjpake_test_password,
1028 sizeof( ecjpake_test_password ) ) == 0 );
1029
1030 if( verbose != 0 )
1031 mbedtls_printf( "passed\n" );
1032
1033 if( verbose != 0 )
1034 mbedtls_printf( " ECJPAKE test #1 (random handshake): " );
1035
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001036 TEST_ASSERT( mbedtls_ecjpake_write_round_one( &cli,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001037 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1038
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001039 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv, buf, len ) == 0 );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001040
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001041 TEST_ASSERT( mbedtls_ecjpake_write_round_one( &srv,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001042 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1043
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001044 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli, buf, len ) == 0 );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001045
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001046 TEST_ASSERT( mbedtls_ecjpake_write_round_two( &srv,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +02001047 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1048
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001049 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli, buf, len ) == 0 );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +02001050
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001051 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001052 pms, sizeof( pms ), &pmslen, ecjpake_lgc, NULL ) == 0 );
1053
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001054 TEST_ASSERT( mbedtls_ecjpake_write_round_two( &cli,
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +02001055 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1056
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001057 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv, buf, len ) == 0 );
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +02001058
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001059 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001060 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1061
1062 TEST_ASSERT( len == pmslen );
1063 TEST_ASSERT( memcmp( buf, pms, len ) == 0 );
1064
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001065 if( verbose != 0 )
1066 mbedtls_printf( "passed\n" );
1067
1068 if( verbose != 0 )
1069 mbedtls_printf( " ECJPAKE test #2 (reference handshake): " );
1070
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001071 /* Simulate generation of round one */
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001072 MBEDTLS_MPI_CHK( ecjpake_test_load( &cli,
1073 ecjpake_test_x1, sizeof( ecjpake_test_x1 ),
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001074 ecjpake_test_x2, sizeof( ecjpake_test_x2 ) ) );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001075
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001076 MBEDTLS_MPI_CHK( ecjpake_test_load( &srv,
1077 ecjpake_test_x3, sizeof( ecjpake_test_x3 ),
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001078 ecjpake_test_x4, sizeof( ecjpake_test_x4 ) ) );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001079
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001080 /* Read round one */
1081 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv,
1082 ecjpake_test_cli_one,
1083 sizeof( ecjpake_test_cli_one ) ) == 0 );
1084
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001085 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001086 ecjpake_test_srv_one,
1087 sizeof( ecjpake_test_srv_one ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001088
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001089 /* Skip generation of round two, read round two */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001090 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001091 ecjpake_test_srv_two,
1092 sizeof( ecjpake_test_srv_two ) ) == 0 );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +02001093
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001094 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001095 ecjpake_test_cli_two,
1096 sizeof( ecjpake_test_cli_two ) ) == 0 );
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +02001097
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001098 /* Server derives PMS */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001099 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001100 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1101
1102 TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
1103 TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
1104
1105 memset( buf, 0, len ); /* Avoid interferences with next step */
1106
1107 /* Client derives PMS */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001108 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001109 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1110
1111 TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
1112 TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
1113
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001114 if( verbose != 0 )
1115 mbedtls_printf( "passed\n" );
1116
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001117cleanup:
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001118 mbedtls_ecjpake_free( &cli );
1119 mbedtls_ecjpake_free( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001120
1121 if( ret != 0 )
1122 {
1123 if( verbose != 0 )
1124 mbedtls_printf( "failed\n" );
1125
1126 ret = 1;
1127 }
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001128
1129 if( verbose != 0 )
1130 mbedtls_printf( "\n" );
1131
1132 return( ret );
1133}
1134
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +02001135#undef TEST_ASSERT
1136
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001137#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_SHA256_C */
1138
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001139#endif /* MBEDTLS_SELF_TEST */
1140
1141#endif /* MBEDTLS_ECJPAKE_C */