blob: a607851686705f63a9857a8730842e31b3792cb2 [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
Gilles Peskinedb09ef62020-06-03 01:43:33 +020027#include "common.h"
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +020028
29#if defined(MBEDTLS_ECJPAKE_C)
30
31#include "mbedtls/ecjpake.h"
Hanno Becker71c8e1b2018-12-14 17:09:39 +000032#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000033#include "mbedtls/error.h"
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +020034
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +020035#include <string.h>
36
Hanno Becker616d1ca2018-01-24 10:25:05 +000037#if !defined(MBEDTLS_ECJPAKE_ALT)
38
Hanno Becker71c8e1b2018-12-14 17:09:39 +000039/* Parameter validation macros based on platform_util.h */
40#define ECJPAKE_VALIDATE_RET( cond ) \
41 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA )
42#define ECJPAKE_VALIDATE( cond ) \
43 MBEDTLS_INTERNAL_VALIDATE( cond )
44
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +020045/*
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +020046 * Convert a mbedtls_ecjpake_role to identifier string
47 */
48static const char * const ecjpake_id[] = {
49 "client",
50 "server"
51};
52
53#define ID_MINE ( ecjpake_id[ ctx->role ] )
54#define ID_PEER ( ecjpake_id[ 1 - ctx->role ] )
55
56/*
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020057 * Initialize context
58 */
59void mbedtls_ecjpake_init( mbedtls_ecjpake_context *ctx )
60{
Hanno Becker71c8e1b2018-12-14 17:09:39 +000061 ECJPAKE_VALIDATE( ctx != NULL );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020062
63 ctx->md_info = NULL;
64 mbedtls_ecp_group_init( &ctx->grp );
Manuel Pégourié-Gonnardb7da1942015-10-19 13:35:22 +020065 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020066
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +020067 mbedtls_ecp_point_init( &ctx->Xm1 );
68 mbedtls_ecp_point_init( &ctx->Xm2 );
69 mbedtls_ecp_point_init( &ctx->Xp1 );
70 mbedtls_ecp_point_init( &ctx->Xp2 );
71 mbedtls_ecp_point_init( &ctx->Xp );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020072
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +020073 mbedtls_mpi_init( &ctx->xm1 );
74 mbedtls_mpi_init( &ctx->xm2 );
75 mbedtls_mpi_init( &ctx->s );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020076}
77
78/*
79 * Free context
80 */
81void mbedtls_ecjpake_free( mbedtls_ecjpake_context *ctx )
82{
83 if( ctx == NULL )
84 return;
85
86 ctx->md_info = NULL;
87 mbedtls_ecp_group_free( &ctx->grp );
88
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +020089 mbedtls_ecp_point_free( &ctx->Xm1 );
90 mbedtls_ecp_point_free( &ctx->Xm2 );
91 mbedtls_ecp_point_free( &ctx->Xp1 );
92 mbedtls_ecp_point_free( &ctx->Xp2 );
93 mbedtls_ecp_point_free( &ctx->Xp );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020094
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +020095 mbedtls_mpi_free( &ctx->xm1 );
96 mbedtls_mpi_free( &ctx->xm2 );
97 mbedtls_mpi_free( &ctx->s );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020098}
99
100/*
101 * Setup context
102 */
103int mbedtls_ecjpake_setup( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +0200104 mbedtls_ecjpake_role role,
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200105 mbedtls_md_type_t hash,
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200106 mbedtls_ecp_group_id curve,
107 const unsigned char *secret,
108 size_t len )
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200109{
Janos Follath24eed8d2019-11-22 13:21:35 +0000110 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker185e5162018-12-19 09:48:50 +0000111
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000112 ECJPAKE_VALIDATE_RET( ctx != NULL );
113 ECJPAKE_VALIDATE_RET( role == MBEDTLS_ECJPAKE_CLIENT ||
114 role == MBEDTLS_ECJPAKE_SERVER );
115 ECJPAKE_VALIDATE_RET( secret != NULL || len == 0 );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200116
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +0200117 ctx->role = role;
118
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200119 if( ( ctx->md_info = mbedtls_md_info_from_type( hash ) ) == NULL )
120 return( MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE );
121
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200122 MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ctx->grp, curve ) );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200123
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200124 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->s, secret, len ) );
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200125
126cleanup:
127 if( ret != 0 )
128 mbedtls_ecjpake_free( ctx );
129
130 return( ret );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200131}
132
133/*
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200134 * Check if context is ready for use
135 */
136int mbedtls_ecjpake_check( const mbedtls_ecjpake_context *ctx )
137{
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000138 ECJPAKE_VALIDATE_RET( ctx != NULL );
139
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200140 if( ctx->md_info == NULL ||
141 ctx->grp.id == MBEDTLS_ECP_DP_NONE ||
142 ctx->s.p == NULL )
143 {
144 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
145 }
146
147 return( 0 );
148}
149
150/*
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200151 * Write a point plus its length to a buffer
152 */
153static int ecjpake_write_len_point( unsigned char **p,
154 const unsigned char *end,
155 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100156 const int pf,
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200157 const mbedtls_ecp_point *P )
158{
Janos Follath24eed8d2019-11-22 13:21:35 +0000159 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200160 size_t len;
161
162 /* Need at least 4 for length plus 1 for point */
163 if( end < *p || end - *p < 5 )
164 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
165
Robert Cragie7cdad772015-10-02 13:31:41 +0100166 ret = mbedtls_ecp_point_write_binary( grp, P, pf,
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200167 &len, *p + 4, end - ( *p + 4 ) );
168 if( ret != 0 )
169 return( ret );
170
171 (*p)[0] = (unsigned char)( ( len >> 24 ) & 0xFF );
172 (*p)[1] = (unsigned char)( ( len >> 16 ) & 0xFF );
173 (*p)[2] = (unsigned char)( ( len >> 8 ) & 0xFF );
174 (*p)[3] = (unsigned char)( ( len ) & 0xFF );
175
176 *p += 4 + len;
177
178 return( 0 );
179}
180
181/*
182 * Size of the temporary buffer for ecjpake_hash:
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200183 * 3 EC points plus their length, plus ID and its length (4 + 6 bytes)
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200184 */
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200185#define ECJPAKE_HASH_BUF_LEN ( 3 * ( 4 + MBEDTLS_ECP_MAX_PT_LEN ) + 4 + 6 )
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200186
187/*
188 * Compute hash for ZKP (7.4.2.2.2.1)
189 */
190static int ecjpake_hash( const mbedtls_md_info_t *md_info,
191 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100192 const int pf,
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200193 const mbedtls_ecp_point *G,
194 const mbedtls_ecp_point *V,
195 const mbedtls_ecp_point *X,
196 const char *id,
197 mbedtls_mpi *h )
198{
Janos Follath24eed8d2019-11-22 13:21:35 +0000199 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200200 unsigned char buf[ECJPAKE_HASH_BUF_LEN];
201 unsigned char *p = buf;
202 const unsigned char *end = buf + sizeof( buf );
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200203 const size_t id_len = strlen( id );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200204 unsigned char hash[MBEDTLS_MD_MAX_SIZE];
205
206 /* Write things to temporary buffer */
Robert Cragie7cdad772015-10-02 13:31:41 +0100207 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, G ) );
208 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, V ) );
209 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, X ) );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200210
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200211 if( end - p < 4 )
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200212 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
213
214 *p++ = (unsigned char)( ( id_len >> 24 ) & 0xFF );
215 *p++ = (unsigned char)( ( id_len >> 16 ) & 0xFF );
216 *p++ = (unsigned char)( ( id_len >> 8 ) & 0xFF );
217 *p++ = (unsigned char)( ( id_len ) & 0xFF );
218
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200219 if( end < p || (size_t)( end - p ) < id_len )
220 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
221
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200222 memcpy( p, id, id_len );
223 p += id_len;
224
225 /* Compute hash */
k-stachowiak41503352019-06-28 14:14:02 +0200226 MBEDTLS_MPI_CHK( mbedtls_md( md_info, buf, p - buf, hash ) );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200227
228 /* Turn it into an integer mod n */
229 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( h, hash,
230 mbedtls_md_get_size( md_info ) ) );
231 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( h, h, &grp->N ) );
232
233cleanup:
234 return( ret );
235}
236
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200237/*
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200238 * Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3)
239 */
240static int ecjpake_zkp_read( const mbedtls_md_info_t *md_info,
241 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100242 const int pf,
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200243 const mbedtls_ecp_point *G,
244 const mbedtls_ecp_point *X,
245 const char *id,
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200246 const unsigned char **p,
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200247 const unsigned char *end )
248{
Janos Follath24eed8d2019-11-22 13:21:35 +0000249 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200250 mbedtls_ecp_point V, VV;
251 mbedtls_mpi r, h;
252 size_t r_len;
253
254 mbedtls_ecp_point_init( &V );
255 mbedtls_ecp_point_init( &VV );
256 mbedtls_mpi_init( &r );
257 mbedtls_mpi_init( &h );
258
259 /*
260 * struct {
261 * ECPoint V;
262 * opaque r<1..2^8-1>;
263 * } ECSchnorrZKP;
264 */
265 if( end < *p )
266 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
267
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200268 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, &V, p, end - *p ) );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200269
270 if( end < *p || (size_t)( end - *p ) < 1 )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200271 {
272 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
273 goto cleanup;
274 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200275
276 r_len = *(*p)++;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200277
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200278 if( end < *p || (size_t)( end - *p ) < r_len )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200279 {
280 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
281 goto cleanup;
282 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200283
284 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &r, *p, r_len ) );
285 *p += r_len;
286
287 /*
288 * Verification
289 */
Robert Cragie7cdad772015-10-02 13:31:41 +0100290 MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200291 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( (mbedtls_ecp_group *) grp,
292 &VV, &h, X, &r, G ) );
293
294 if( mbedtls_ecp_point_cmp( &VV, &V ) != 0 )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200295 {
296 ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
297 goto cleanup;
298 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200299
300cleanup:
301 mbedtls_ecp_point_free( &V );
302 mbedtls_ecp_point_free( &VV );
303 mbedtls_mpi_free( &r );
304 mbedtls_mpi_free( &h );
305
306 return( ret );
307}
308
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200309/*
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200310 * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2)
311 */
312static int ecjpake_zkp_write( const mbedtls_md_info_t *md_info,
313 const mbedtls_ecp_group *grp,
Darryl Green11999bb2018-03-13 15:22:58 +0000314 const int pf,
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200315 const mbedtls_ecp_point *G,
316 const mbedtls_mpi *x,
317 const mbedtls_ecp_point *X,
318 const char *id,
319 unsigned char **p,
320 const unsigned char *end,
321 int (*f_rng)(void *, unsigned char *, size_t),
322 void *p_rng )
323{
Janos Follath24eed8d2019-11-22 13:21:35 +0000324 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200325 mbedtls_ecp_point V;
326 mbedtls_mpi v;
327 mbedtls_mpi h; /* later recycled to hold r */
328 size_t len;
329
330 if( end < *p )
331 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
332
333 mbedtls_ecp_point_init( &V );
334 mbedtls_mpi_init( &v );
335 mbedtls_mpi_init( &h );
336
337 /* Compute signature */
338 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp,
339 G, &v, &V, f_rng, p_rng ) );
Robert Cragie7cdad772015-10-02 13:31:41 +0100340 MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) );
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200341 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &h, &h, x ) ); /* x*h */
342 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &h, &v, &h ) ); /* v - x*h */
343 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &h, &h, &grp->N ) ); /* r */
344
345 /* Write it out */
346 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, &V,
Robert Cragie7cdad772015-10-02 13:31:41 +0100347 pf, &len, *p, end - *p ) );
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200348 *p += len;
349
350 len = mbedtls_mpi_size( &h ); /* actually r */
351 if( end < *p || (size_t)( end - *p ) < 1 + len || len > 255 )
352 {
353 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
354 goto cleanup;
355 }
356
357 *(*p)++ = (unsigned char)( len & 0xFF );
358 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, *p, len ) ); /* r */
359 *p += len;
360
361cleanup:
362 mbedtls_ecp_point_free( &V );
363 mbedtls_mpi_free( &v );
364 mbedtls_mpi_free( &h );
365
366 return( ret );
367}
368
369/*
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200370 * Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof
371 * Output: verified public key X
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200372 */
373static int ecjpake_kkp_read( const mbedtls_md_info_t *md_info,
374 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100375 const int pf,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200376 const mbedtls_ecp_point *G,
377 mbedtls_ecp_point *X,
378 const char *id,
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200379 const unsigned char **p,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200380 const unsigned char *end )
381{
Janos Follath24eed8d2019-11-22 13:21:35 +0000382 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200383
384 if( end < *p )
385 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
386
387 /*
388 * struct {
389 * ECPoint X;
390 * ECSchnorrZKP zkp;
391 * } ECJPAKEKeyKP;
392 */
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200393 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, X, p, end - *p ) );
Manuel Pégourié-Gonnard30590952015-08-17 10:37:40 +0200394 if( mbedtls_ecp_is_zero( X ) )
395 {
396 ret = MBEDTLS_ERR_ECP_INVALID_KEY;
397 goto cleanup;
398 }
399
Robert Cragie7cdad772015-10-02 13:31:41 +0100400 MBEDTLS_MPI_CHK( ecjpake_zkp_read( md_info, grp, pf, G, X, id, p, end ) );
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200401
402cleanup:
403 return( ret );
404}
405
406/*
407 * Generate an ECJPAKEKeyKP
408 * Output: the serialized structure, plus private/public key pair
409 */
410static int ecjpake_kkp_write( const mbedtls_md_info_t *md_info,
411 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100412 const int pf,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200413 const mbedtls_ecp_point *G,
414 mbedtls_mpi *x,
415 mbedtls_ecp_point *X,
416 const char *id,
417 unsigned char **p,
418 const unsigned char *end,
419 int (*f_rng)(void *, unsigned char *, size_t),
420 void *p_rng )
421{
Janos Follath24eed8d2019-11-22 13:21:35 +0000422 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200423 size_t len;
424
425 if( end < *p )
426 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
427
428 /* Generate key (7.4.2.3.1) and write it out */
429 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp, G, x, X,
430 f_rng, p_rng ) );
431 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, X,
Robert Cragie7cdad772015-10-02 13:31:41 +0100432 pf, &len, *p, end - *p ) );
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200433 *p += len;
434
435 /* Generate and write proof */
Robert Cragie7cdad772015-10-02 13:31:41 +0100436 MBEDTLS_MPI_CHK( ecjpake_zkp_write( md_info, grp, pf, G, x, X, id,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200437 p, end, f_rng, p_rng ) );
438
439cleanup:
440 return( ret );
441}
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200442
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200443/*
444 * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs
445 * Ouputs: verified peer public keys Xa, Xb
446 */
447static int ecjpake_kkpp_read( const mbedtls_md_info_t *md_info,
448 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100449 const int pf,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200450 const mbedtls_ecp_point *G,
451 mbedtls_ecp_point *Xa,
452 mbedtls_ecp_point *Xb,
453 const char *id,
454 const unsigned char *buf,
455 size_t len )
456{
Janos Follath24eed8d2019-11-22 13:21:35 +0000457 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200458 const unsigned char *p = buf;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200459 const unsigned char *end = buf + len;
460
461 /*
462 * struct {
463 * ECJPAKEKeyKP ecjpake_key_kp_pair_list[2];
464 * } ECJPAKEKeyKPPairList;
465 */
Robert Cragie7cdad772015-10-02 13:31:41 +0100466 MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xa, id, &p, end ) );
467 MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xb, id, &p, end ) );
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200468
469 if( p != end )
470 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
471
472cleanup:
473 return( ret );
474}
475
476/*
477 * Generate a ECJPAKEKeyKPPairList
478 * Outputs: the serialized structure, plus two private/public key pairs
479 */
480static int ecjpake_kkpp_write( const mbedtls_md_info_t *md_info,
481 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100482 const int pf,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200483 const mbedtls_ecp_point *G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200484 mbedtls_mpi *xm1,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200485 mbedtls_ecp_point *Xa,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200486 mbedtls_mpi *xm2,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200487 mbedtls_ecp_point *Xb,
488 const char *id,
489 unsigned char *buf,
490 size_t len,
491 size_t *olen,
492 int (*f_rng)(void *, unsigned char *, size_t),
493 void *p_rng )
494{
Janos Follath24eed8d2019-11-22 13:21:35 +0000495 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200496 unsigned char *p = buf;
497 const unsigned char *end = buf + len;
498
Robert Cragie7cdad772015-10-02 13:31:41 +0100499 MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm1, Xa, id,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200500 &p, end, f_rng, p_rng ) );
Robert Cragie7cdad772015-10-02 13:31:41 +0100501 MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm2, Xb, id,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200502 &p, end, f_rng, p_rng ) );
503
504 *olen = p - buf;
505
506cleanup:
507 return( ret );
508}
509
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200510/*
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200511 * Read and process the first round message
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200512 */
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200513int mbedtls_ecjpake_read_round_one( mbedtls_ecjpake_context *ctx,
514 const unsigned char *buf,
515 size_t len )
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200516{
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000517 ECJPAKE_VALIDATE_RET( ctx != NULL );
518 ECJPAKE_VALIDATE_RET( buf != NULL );
519
Robert Cragie7cdad772015-10-02 13:31:41 +0100520 return( ecjpake_kkpp_read( ctx->md_info, &ctx->grp, ctx->point_format,
521 &ctx->grp.G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200522 &ctx->Xp1, &ctx->Xp2, ID_PEER,
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200523 buf, len ) );
524}
525
526/*
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200527 * Generate and write the first round message
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200528 */
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200529int mbedtls_ecjpake_write_round_one( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200530 unsigned char *buf, size_t len, size_t *olen,
531 int (*f_rng)(void *, unsigned char *, size_t),
532 void *p_rng )
533{
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000534 ECJPAKE_VALIDATE_RET( ctx != NULL );
535 ECJPAKE_VALIDATE_RET( buf != NULL );
536 ECJPAKE_VALIDATE_RET( olen != NULL );
537 ECJPAKE_VALIDATE_RET( f_rng != NULL );
538
Robert Cragie7cdad772015-10-02 13:31:41 +0100539 return( ecjpake_kkpp_write( ctx->md_info, &ctx->grp, ctx->point_format,
540 &ctx->grp.G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200541 &ctx->xm1, &ctx->Xm1, &ctx->xm2, &ctx->Xm2,
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200542 ID_MINE, buf, len, olen, f_rng, p_rng ) );
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200543}
544
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200545/*
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200546 * Compute the sum of three points R = A + B + C
547 */
548static int ecjpake_ecp_add3( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
549 const mbedtls_ecp_point *A,
550 const mbedtls_ecp_point *B,
551 const mbedtls_ecp_point *C )
552{
Janos Follath24eed8d2019-11-22 13:21:35 +0000553 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200554 mbedtls_mpi one;
555
556 mbedtls_mpi_init( &one );
557
558 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
559 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, A, &one, B ) );
560 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, R, &one, C ) );
561
562cleanup:
563 mbedtls_mpi_free( &one );
564
565 return( ret );
566}
567
568/*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200569 * 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 +0200570 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200571int mbedtls_ecjpake_read_round_two( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200572 const unsigned char *buf,
573 size_t len )
574{
Janos Follath24eed8d2019-11-22 13:21:35 +0000575 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200576 const unsigned char *p = buf;
577 const unsigned char *end = buf + len;
578 mbedtls_ecp_group grp;
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200579 mbedtls_ecp_point G; /* C: GB, S: GA */
Hanno Becker185e5162018-12-19 09:48:50 +0000580
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000581 ECJPAKE_VALIDATE_RET( ctx != NULL );
582 ECJPAKE_VALIDATE_RET( buf != NULL );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200583
584 mbedtls_ecp_group_init( &grp );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200585 mbedtls_ecp_point_init( &G );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200586
587 /*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200588 * Server: GA = X3 + X4 + X1 (7.4.2.6.1)
589 * Client: GB = X1 + X2 + X3 (7.4.2.5.1)
590 * Unified: G = Xm1 + Xm2 + Xp1
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200591 * We need that before parsing in order to check Xp as we read it
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200592 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200593 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200594 &ctx->Xm1, &ctx->Xm2, &ctx->Xp1 ) );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200595
596 /*
597 * struct {
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200598 * ECParameters curve_params; // only client reading server msg
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200599 * ECJPAKEKeyKP ecjpake_key_kp;
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200600 * } Client/ServerECJPAKEParams;
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200601 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200602 if( ctx->role == MBEDTLS_ECJPAKE_CLIENT )
Manuel Pégourié-Gonnardd9802af2015-08-17 12:47:38 +0200603 {
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200604 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_group( &grp, &p, len ) );
Manuel Pégourié-Gonnardd9802af2015-08-17 12:47:38 +0200605 if( grp.id != ctx->grp.id )
606 {
607 ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
608 goto cleanup;
609 }
610 }
611
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200612 MBEDTLS_MPI_CHK( ecjpake_kkp_read( ctx->md_info, &ctx->grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100613 ctx->point_format,
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200614 &G, &ctx->Xp, ID_PEER, &p, end ) );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200615
616 if( p != end )
617 {
618 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
619 goto cleanup;
620 }
621
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200622cleanup:
623 mbedtls_ecp_group_free( &grp );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200624 mbedtls_ecp_point_free( &G );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200625
626 return( ret );
627}
628
629/*
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200630 * Compute R = +/- X * S mod N, taking care not to leak S
631 */
632static int ecjpake_mul_secret( mbedtls_mpi *R, int sign,
633 const mbedtls_mpi *X,
634 const mbedtls_mpi *S,
635 const mbedtls_mpi *N,
636 int (*f_rng)(void *, unsigned char *, size_t),
637 void *p_rng )
638{
Janos Follath24eed8d2019-11-22 13:21:35 +0000639 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200640 mbedtls_mpi b; /* Blinding value, then s + N * blinding */
641
642 mbedtls_mpi_init( &b );
643
644 /* b = s + rnd-128-bit * N */
645 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &b, 16, f_rng, p_rng ) );
646 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &b, &b, N ) );
647 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &b, &b, S ) );
648
649 /* R = sign * X * b mod N */
650 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( R, X, &b ) );
651 R->s *= sign;
652 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( R, R, N ) );
653
654cleanup:
655 mbedtls_mpi_free( &b );
656
657 return( ret );
658}
659
660/*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200661 * 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 +0200662 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200663int mbedtls_ecjpake_write_round_two( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200664 unsigned char *buf, size_t len, size_t *olen,
665 int (*f_rng)(void *, unsigned char *, size_t),
666 void *p_rng )
667{
Janos Follath24eed8d2019-11-22 13:21:35 +0000668 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200669 mbedtls_ecp_point G; /* C: GA, S: GB */
670 mbedtls_ecp_point Xm; /* C: Xc, S: Xs */
671 mbedtls_mpi xm; /* C: xc, S: xs */
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200672 unsigned char *p = buf;
673 const unsigned char *end = buf + len;
674 size_t ec_len;
Hanno Becker185e5162018-12-19 09:48:50 +0000675
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000676 ECJPAKE_VALIDATE_RET( ctx != NULL );
677 ECJPAKE_VALIDATE_RET( buf != NULL );
678 ECJPAKE_VALIDATE_RET( olen != NULL );
679 ECJPAKE_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200680
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200681 mbedtls_ecp_point_init( &G );
682 mbedtls_ecp_point_init( &Xm );
683 mbedtls_mpi_init( &xm );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200684
685 /*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200686 * 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 +0200687 *
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200688 * Client: GA = X1 + X3 + X4 | xs = x2 * s | Xc = xc * GA
689 * Server: GB = X3 + X1 + X2 | xs = x4 * s | Xs = xs * GB
690 * Unified: G = Xm1 + Xp1 + Xp2 | xm = xm2 * s | Xm = xm * G
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200691 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200692 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200693 &ctx->Xp1, &ctx->Xp2, &ctx->Xm1 ) );
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200694 MBEDTLS_MPI_CHK( ecjpake_mul_secret( &xm, 1, &ctx->xm2, &ctx->s,
695 &ctx->grp.N, f_rng, p_rng ) );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200696 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &Xm, &xm, &G, f_rng, p_rng ) );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200697
698 /*
699 * Now write things out
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200700 *
701 * struct {
702 * ECParameters curve_params; // only server writing its message
703 * ECJPAKEKeyKP ecjpake_key_kp;
704 * } Client/ServerECJPAKEParams;
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200705 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200706 if( ctx->role == MBEDTLS_ECJPAKE_SERVER )
707 {
708 if( end < p )
709 {
710 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
711 goto cleanup;
712 }
713 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_group( &ctx->grp, &ec_len,
714 p, end - p ) );
715 p += ec_len;
716 }
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200717
718 if( end < p )
719 {
720 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
721 goto cleanup;
722 }
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200723 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( &ctx->grp, &Xm,
Robert Cragie7cdad772015-10-02 13:31:41 +0100724 ctx->point_format, &ec_len, p, end - p ) );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200725 p += ec_len;
726
727 MBEDTLS_MPI_CHK( ecjpake_zkp_write( ctx->md_info, &ctx->grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100728 ctx->point_format,
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200729 &G, &xm, &Xm, ID_MINE,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200730 &p, end, f_rng, p_rng ) );
731
732 *olen = p - buf;
733
734cleanup:
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200735 mbedtls_ecp_point_free( &G );
736 mbedtls_ecp_point_free( &Xm );
737 mbedtls_mpi_free( &xm );
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +0200738
739 return( ret );
740}
741
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200742/*
743 * Derive PMS (7.4.2.7 / 7.4.2.8)
744 */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +0200745int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200746 unsigned char *buf, size_t len, size_t *olen,
747 int (*f_rng)(void *, unsigned char *, size_t),
748 void *p_rng )
749{
Janos Follath24eed8d2019-11-22 13:21:35 +0000750 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200751 mbedtls_ecp_point K;
752 mbedtls_mpi m_xm2_s, one;
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200753 unsigned char kx[MBEDTLS_ECP_MAX_BYTES];
754 size_t x_bytes;
Hanno Becker185e5162018-12-19 09:48:50 +0000755
Hanno Becker71c8e1b2018-12-14 17:09:39 +0000756 ECJPAKE_VALIDATE_RET( ctx != NULL );
757 ECJPAKE_VALIDATE_RET( buf != NULL );
758 ECJPAKE_VALIDATE_RET( olen != NULL );
759 ECJPAKE_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200760
761 *olen = mbedtls_md_get_size( ctx->md_info );
762 if( len < *olen )
763 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
764
765 mbedtls_ecp_point_init( &K );
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200766 mbedtls_mpi_init( &m_xm2_s );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200767 mbedtls_mpi_init( &one );
768
769 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200770
771 /*
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200772 * Client: K = ( Xs - X4 * x2 * s ) * x2
773 * Server: K = ( Xc - X2 * x4 * s ) * x4
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200774 * Unified: K = ( Xp - Xp2 * xm2 * s ) * xm2
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200775 */
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200776 MBEDTLS_MPI_CHK( ecjpake_mul_secret( &m_xm2_s, -1, &ctx->xm2, &ctx->s,
777 &ctx->grp.N, f_rng, p_rng ) );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200778 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( &ctx->grp, &K,
779 &one, &ctx->Xp,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200780 &m_xm2_s, &ctx->Xp2 ) );
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200781 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &K, &ctx->xm2, &K,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200782 f_rng, p_rng ) );
783
784 /* PMS = SHA-256( K.X ) */
785 x_bytes = ( ctx->grp.pbits + 7 ) / 8;
786 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &K.X, kx, x_bytes ) );
787 MBEDTLS_MPI_CHK( mbedtls_md( ctx->md_info, kx, x_bytes, buf ) );
788
789cleanup:
790 mbedtls_ecp_point_free( &K );
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200791 mbedtls_mpi_free( &m_xm2_s );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200792 mbedtls_mpi_free( &one );
793
794 return( ret );
795}
796
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200797#undef ID_MINE
798#undef ID_PEER
799
Hanno Becker616d1ca2018-01-24 10:25:05 +0000800#endif /* ! MBEDTLS_ECJPAKE_ALT */
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200801
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200802#if defined(MBEDTLS_SELF_TEST)
803
804#if defined(MBEDTLS_PLATFORM_C)
805#include "mbedtls/platform.h"
806#else
807#include <stdio.h>
808#define mbedtls_printf printf
809#endif
810
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200811#if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
812 !defined(MBEDTLS_SHA256_C)
813int mbedtls_ecjpake_self_test( int verbose )
814{
815 (void) verbose;
816 return( 0 );
817}
818#else
819
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200820static const unsigned char ecjpake_test_password[] = {
821 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x6a, 0x70, 0x61, 0x6b, 0x65, 0x74,
822 0x65, 0x73, 0x74
823};
824
825static const unsigned char ecjpake_test_x1[] = {
826 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
827 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
828 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21
829};
830
831static const unsigned char ecjpake_test_x2[] = {
832 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
833 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
834 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
835};
836
837static const unsigned char ecjpake_test_x3[] = {
838 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
839 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
840 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
841};
842
843static const unsigned char ecjpake_test_x4[] = {
844 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc,
845 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
846 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1
847};
848
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200849static const unsigned char ecjpake_test_cli_one[] = {
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200850 0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19,
851 0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44,
852 0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad,
853 0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62,
854 0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9,
855 0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d,
856 0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e,
857 0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e,
858 0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73,
859 0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22,
860 0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce,
861 0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00,
862 0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200863 0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e,
864 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62,
865 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5,
866 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb,
867 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35,
868 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0,
869 0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb,
870 0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47,
871 0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39,
872 0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97,
873 0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40,
874 0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d,
875 0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa,
876 0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d,
877 0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200878};
879
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200880static const unsigned char ecjpake_test_srv_one[] = {
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200881 0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb,
882 0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18,
883 0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47,
884 0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f,
885 0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7,
886 0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d,
887 0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64,
888 0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36,
889 0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2,
890 0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec,
891 0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16,
892 0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96,
893 0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3,
894 0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19,
895 0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f,
896 0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8,
897 0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7,
898 0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea,
899 0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5,
900 0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6,
901 0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31,
902 0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d,
903 0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8,
904 0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee,
905 0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84,
906 0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f,
907 0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80,
908 0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12
909};
910
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200911static const unsigned char ecjpake_test_srv_two[] = {
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200912 0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23,
913 0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c,
914 0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f,
915 0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca,
916 0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26,
917 0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55,
918 0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38,
919 0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6,
920 0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9,
921 0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4,
922 0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2,
923 0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8,
924 0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd,
925 0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c
926};
927
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200928static const unsigned char ecjpake_test_cli_two[] = {
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +0200929 0x41, 0x04, 0x69, 0xd5, 0x4e, 0xe8, 0x5e, 0x90, 0xce, 0x3f, 0x12, 0x46,
930 0x74, 0x2d, 0xe5, 0x07, 0xe9, 0x39, 0xe8, 0x1d, 0x1d, 0xc1, 0xc5, 0xcb,
931 0x98, 0x8b, 0x58, 0xc3, 0x10, 0xc9, 0xfd, 0xd9, 0x52, 0x4d, 0x93, 0x72,
932 0x0b, 0x45, 0x54, 0x1c, 0x83, 0xee, 0x88, 0x41, 0x19, 0x1d, 0xa7, 0xce,
933 0xd8, 0x6e, 0x33, 0x12, 0xd4, 0x36, 0x23, 0xc1, 0xd6, 0x3e, 0x74, 0x98,
934 0x9a, 0xba, 0x4a, 0xff, 0xd1, 0xee, 0x41, 0x04, 0x07, 0x7e, 0x8c, 0x31,
935 0xe2, 0x0e, 0x6b, 0xed, 0xb7, 0x60, 0xc1, 0x35, 0x93, 0xe6, 0x9f, 0x15,
936 0xbe, 0x85, 0xc2, 0x7d, 0x68, 0xcd, 0x09, 0xcc, 0xb8, 0xc4, 0x18, 0x36,
937 0x08, 0x91, 0x7c, 0x5c, 0x3d, 0x40, 0x9f, 0xac, 0x39, 0xfe, 0xfe, 0xe8,
938 0x2f, 0x72, 0x92, 0xd3, 0x6f, 0x0d, 0x23, 0xe0, 0x55, 0x91, 0x3f, 0x45,
939 0xa5, 0x2b, 0x85, 0xdd, 0x8a, 0x20, 0x52, 0xe9, 0xe1, 0x29, 0xbb, 0x4d,
940 0x20, 0x0f, 0x01, 0x1f, 0x19, 0x48, 0x35, 0x35, 0xa6, 0xe8, 0x9a, 0x58,
941 0x0c, 0x9b, 0x00, 0x03, 0xba, 0xf2, 0x14, 0x62, 0xec, 0xe9, 0x1a, 0x82,
942 0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c
943};
944
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200945static const unsigned char ecjpake_test_pms[] = {
946 0xf3, 0xd4, 0x7f, 0x59, 0x98, 0x44, 0xdb, 0x92, 0xa5, 0x69, 0xbb, 0xe7,
947 0x98, 0x1e, 0x39, 0xd9, 0x31, 0xfd, 0x74, 0x3b, 0xf2, 0x2e, 0x98, 0xf9,
948 0xb4, 0x38, 0xf7, 0x19, 0xd3, 0xc4, 0xf3, 0x51
949};
950
Antonin Décimo36e89b52019-01-23 15:24:37 +0100951/* Load my private keys and generate the corresponding public keys */
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +0200952static int ecjpake_test_load( mbedtls_ecjpake_context *ctx,
953 const unsigned char *xm1, size_t len1,
954 const unsigned char *xm2, size_t len2 )
955{
Janos Follath24eed8d2019-11-22 13:21:35 +0000956 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +0200957
958 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm1, xm1, len1 ) );
959 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm2, xm2, len2 ) );
960 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm1, &ctx->xm1,
961 &ctx->grp.G, NULL, NULL ) );
962 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm2, &ctx->xm2,
963 &ctx->grp.G, NULL, NULL ) );
964
965cleanup:
966 return( ret );
967}
968
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200969/* For tests we don't need a secure RNG;
970 * use the LGC from Numerical Recipes for simplicity */
971static int ecjpake_lgc( void *p, unsigned char *out, size_t len )
972{
973 static uint32_t x = 42;
974 (void) p;
975
976 while( len > 0 )
977 {
978 size_t use_len = len > 4 ? 4 : len;
979 x = 1664525 * x + 1013904223;
980 memcpy( out, &x, use_len );
981 out += use_len;
982 len -= use_len;
983 }
984
985 return( 0 );
986}
987
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200988#define TEST_ASSERT( x ) \
989 do { \
990 if( x ) \
991 ret = 0; \
992 else \
993 { \
994 ret = 1; \
995 goto cleanup; \
996 } \
997 } while( 0 )
998
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200999/*
1000 * Checkup routine
1001 */
1002int mbedtls_ecjpake_self_test( int verbose )
1003{
Janos Follath24eed8d2019-11-22 13:21:35 +00001004 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001005 mbedtls_ecjpake_context cli;
1006 mbedtls_ecjpake_context srv;
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001007 unsigned char buf[512], pms[32];
1008 size_t len, pmslen;
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001009
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001010 mbedtls_ecjpake_init( &cli );
1011 mbedtls_ecjpake_init( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001012
1013 if( verbose != 0 )
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001014 mbedtls_printf( " ECJPAKE test #0 (setup): " );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +02001015
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +02001016 TEST_ASSERT( mbedtls_ecjpake_setup( &cli, MBEDTLS_ECJPAKE_CLIENT,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001017 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1018 ecjpake_test_password,
1019 sizeof( ecjpake_test_password ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001020
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +02001021 TEST_ASSERT( mbedtls_ecjpake_setup( &srv, MBEDTLS_ECJPAKE_SERVER,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001022 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1023 ecjpake_test_password,
1024 sizeof( ecjpake_test_password ) ) == 0 );
1025
1026 if( verbose != 0 )
1027 mbedtls_printf( "passed\n" );
1028
1029 if( verbose != 0 )
1030 mbedtls_printf( " ECJPAKE test #1 (random handshake): " );
1031
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001032 TEST_ASSERT( mbedtls_ecjpake_write_round_one( &cli,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001033 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1034
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001035 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv, buf, len ) == 0 );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001036
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001037 TEST_ASSERT( mbedtls_ecjpake_write_round_one( &srv,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001038 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1039
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001040 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli, buf, len ) == 0 );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001041
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001042 TEST_ASSERT( mbedtls_ecjpake_write_round_two( &srv,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +02001043 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1044
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001045 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli, buf, len ) == 0 );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +02001046
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001047 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001048 pms, sizeof( pms ), &pmslen, ecjpake_lgc, NULL ) == 0 );
1049
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001050 TEST_ASSERT( mbedtls_ecjpake_write_round_two( &cli,
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +02001051 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1052
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001053 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv, buf, len ) == 0 );
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +02001054
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001055 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001056 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1057
1058 TEST_ASSERT( len == pmslen );
1059 TEST_ASSERT( memcmp( buf, pms, len ) == 0 );
1060
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001061 if( verbose != 0 )
1062 mbedtls_printf( "passed\n" );
1063
1064 if( verbose != 0 )
1065 mbedtls_printf( " ECJPAKE test #2 (reference handshake): " );
1066
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001067 /* Simulate generation of round one */
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001068 MBEDTLS_MPI_CHK( ecjpake_test_load( &cli,
1069 ecjpake_test_x1, sizeof( ecjpake_test_x1 ),
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001070 ecjpake_test_x2, sizeof( ecjpake_test_x2 ) ) );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001071
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001072 MBEDTLS_MPI_CHK( ecjpake_test_load( &srv,
1073 ecjpake_test_x3, sizeof( ecjpake_test_x3 ),
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001074 ecjpake_test_x4, sizeof( ecjpake_test_x4 ) ) );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001075
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001076 /* Read round one */
1077 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv,
1078 ecjpake_test_cli_one,
1079 sizeof( ecjpake_test_cli_one ) ) == 0 );
1080
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001081 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001082 ecjpake_test_srv_one,
1083 sizeof( ecjpake_test_srv_one ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001084
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001085 /* Skip generation of round two, read round two */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001086 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001087 ecjpake_test_srv_two,
1088 sizeof( ecjpake_test_srv_two ) ) == 0 );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +02001089
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001090 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001091 ecjpake_test_cli_two,
1092 sizeof( ecjpake_test_cli_two ) ) == 0 );
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +02001093
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001094 /* Server derives PMS */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001095 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001096 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1097
1098 TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
1099 TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
1100
1101 memset( buf, 0, len ); /* Avoid interferences with next step */
1102
1103 /* Client derives PMS */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001104 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001105 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1106
1107 TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
1108 TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
1109
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001110 if( verbose != 0 )
1111 mbedtls_printf( "passed\n" );
1112
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001113cleanup:
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001114 mbedtls_ecjpake_free( &cli );
1115 mbedtls_ecjpake_free( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001116
1117 if( ret != 0 )
1118 {
1119 if( verbose != 0 )
1120 mbedtls_printf( "failed\n" );
1121
1122 ret = 1;
1123 }
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001124
1125 if( verbose != 0 )
1126 mbedtls_printf( "\n" );
1127
1128 return( ret );
1129}
1130
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +02001131#undef TEST_ASSERT
1132
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001133#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_SHA256_C */
1134
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001135#endif /* MBEDTLS_SELF_TEST */
1136
1137#endif /* MBEDTLS_ECJPAKE_C */