blob: 1fa1c2d80153219405d32b98c68fdd4f931cc60a [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"
36
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +020037#include <string.h>
38
39/*
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +020040 * Convert a mbedtls_ecjpake_role to identifier string
41 */
42static const char * const ecjpake_id[] = {
43 "client",
44 "server"
45};
46
47#define ID_MINE ( ecjpake_id[ ctx->role ] )
48#define ID_PEER ( ecjpake_id[ 1 - ctx->role ] )
49
50/*
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020051 * Initialize context
52 */
53void mbedtls_ecjpake_init( mbedtls_ecjpake_context *ctx )
54{
55 if( ctx == NULL )
56 return;
57
58 ctx->md_info = NULL;
59 mbedtls_ecp_group_init( &ctx->grp );
Manuel Pégourié-Gonnardb7da1942015-10-19 13:35:22 +020060 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020061
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +020062 mbedtls_ecp_point_init( &ctx->Xm1 );
63 mbedtls_ecp_point_init( &ctx->Xm2 );
64 mbedtls_ecp_point_init( &ctx->Xp1 );
65 mbedtls_ecp_point_init( &ctx->Xp2 );
66 mbedtls_ecp_point_init( &ctx->Xp );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020067
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +020068 mbedtls_mpi_init( &ctx->xm1 );
69 mbedtls_mpi_init( &ctx->xm2 );
70 mbedtls_mpi_init( &ctx->s );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020071}
72
73/*
74 * Free context
75 */
76void mbedtls_ecjpake_free( mbedtls_ecjpake_context *ctx )
77{
78 if( ctx == NULL )
79 return;
80
81 ctx->md_info = NULL;
82 mbedtls_ecp_group_free( &ctx->grp );
83
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +020084 mbedtls_ecp_point_free( &ctx->Xm1 );
85 mbedtls_ecp_point_free( &ctx->Xm2 );
86 mbedtls_ecp_point_free( &ctx->Xp1 );
87 mbedtls_ecp_point_free( &ctx->Xp2 );
88 mbedtls_ecp_point_free( &ctx->Xp );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020089
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +020090 mbedtls_mpi_free( &ctx->xm1 );
91 mbedtls_mpi_free( &ctx->xm2 );
92 mbedtls_mpi_free( &ctx->s );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020093}
94
95/*
96 * Setup context
97 */
98int mbedtls_ecjpake_setup( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +020099 mbedtls_ecjpake_role role,
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200100 mbedtls_md_type_t hash,
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200101 mbedtls_ecp_group_id curve,
102 const unsigned char *secret,
103 size_t len )
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200104{
105 int ret;
106
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +0200107 ctx->role = role;
108
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200109 if( ( ctx->md_info = mbedtls_md_info_from_type( hash ) ) == NULL )
110 return( MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE );
111
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200112 MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ctx->grp, curve ) );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200113
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200114 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->s, secret, len ) );
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200115
116cleanup:
117 if( ret != 0 )
118 mbedtls_ecjpake_free( ctx );
119
120 return( ret );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200121}
122
123/*
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200124 * Check if context is ready for use
125 */
126int mbedtls_ecjpake_check( const mbedtls_ecjpake_context *ctx )
127{
128 if( ctx->md_info == NULL ||
129 ctx->grp.id == MBEDTLS_ECP_DP_NONE ||
130 ctx->s.p == NULL )
131 {
132 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
133 }
134
135 return( 0 );
136}
137
138/*
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200139 * Write a point plus its length to a buffer
140 */
141static int ecjpake_write_len_point( unsigned char **p,
142 const unsigned char *end,
143 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100144 const int pf,
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200145 const mbedtls_ecp_point *P )
146{
147 int ret;
148 size_t len;
149
150 /* Need at least 4 for length plus 1 for point */
151 if( end < *p || end - *p < 5 )
152 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
153
Robert Cragie7cdad772015-10-02 13:31:41 +0100154 ret = mbedtls_ecp_point_write_binary( grp, P, pf,
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200155 &len, *p + 4, end - ( *p + 4 ) );
156 if( ret != 0 )
157 return( ret );
158
159 (*p)[0] = (unsigned char)( ( len >> 24 ) & 0xFF );
160 (*p)[1] = (unsigned char)( ( len >> 16 ) & 0xFF );
161 (*p)[2] = (unsigned char)( ( len >> 8 ) & 0xFF );
162 (*p)[3] = (unsigned char)( ( len ) & 0xFF );
163
164 *p += 4 + len;
165
166 return( 0 );
167}
168
169/*
170 * Size of the temporary buffer for ecjpake_hash:
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200171 * 3 EC points plus their length, plus ID and its length (4 + 6 bytes)
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200172 */
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200173#define ECJPAKE_HASH_BUF_LEN ( 3 * ( 4 + MBEDTLS_ECP_MAX_PT_LEN ) + 4 + 6 )
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200174
175/*
176 * Compute hash for ZKP (7.4.2.2.2.1)
177 */
178static int ecjpake_hash( const mbedtls_md_info_t *md_info,
179 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100180 const int pf,
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200181 const mbedtls_ecp_point *G,
182 const mbedtls_ecp_point *V,
183 const mbedtls_ecp_point *X,
184 const char *id,
185 mbedtls_mpi *h )
186{
187 int ret;
188 unsigned char buf[ECJPAKE_HASH_BUF_LEN];
189 unsigned char *p = buf;
190 const unsigned char *end = buf + sizeof( buf );
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200191 const size_t id_len = strlen( id );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200192 unsigned char hash[MBEDTLS_MD_MAX_SIZE];
193
194 /* Write things to temporary buffer */
Robert Cragie7cdad772015-10-02 13:31:41 +0100195 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, G ) );
196 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, V ) );
197 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, X ) );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200198
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200199 if( end - p < 4 )
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200200 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
201
202 *p++ = (unsigned char)( ( id_len >> 24 ) & 0xFF );
203 *p++ = (unsigned char)( ( id_len >> 16 ) & 0xFF );
204 *p++ = (unsigned char)( ( id_len >> 8 ) & 0xFF );
205 *p++ = (unsigned char)( ( id_len ) & 0xFF );
206
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200207 if( end < p || (size_t)( end - p ) < id_len )
208 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
209
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200210 memcpy( p, id, id_len );
211 p += id_len;
212
213 /* Compute hash */
214 mbedtls_md( md_info, buf, p - buf, hash );
215
216 /* Turn it into an integer mod n */
217 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( h, hash,
218 mbedtls_md_get_size( md_info ) ) );
219 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( h, h, &grp->N ) );
220
221cleanup:
222 return( ret );
223}
224
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200225/*
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200226 * Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3)
227 */
228static int ecjpake_zkp_read( const mbedtls_md_info_t *md_info,
229 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100230 const int pf,
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200231 const mbedtls_ecp_point *G,
232 const mbedtls_ecp_point *X,
233 const char *id,
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200234 const unsigned char **p,
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200235 const unsigned char *end )
236{
237 int ret;
238 mbedtls_ecp_point V, VV;
239 mbedtls_mpi r, h;
240 size_t r_len;
241
242 mbedtls_ecp_point_init( &V );
243 mbedtls_ecp_point_init( &VV );
244 mbedtls_mpi_init( &r );
245 mbedtls_mpi_init( &h );
246
247 /*
248 * struct {
249 * ECPoint V;
250 * opaque r<1..2^8-1>;
251 * } ECSchnorrZKP;
252 */
253 if( end < *p )
254 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
255
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200256 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, &V, p, end - *p ) );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200257
258 if( end < *p || (size_t)( end - *p ) < 1 )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200259 {
260 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
261 goto cleanup;
262 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200263
264 r_len = *(*p)++;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200265
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200266 if( end < *p || (size_t)( end - *p ) < r_len )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200267 {
268 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
269 goto cleanup;
270 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200271
272 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &r, *p, r_len ) );
273 *p += r_len;
274
275 /*
276 * Verification
277 */
Robert Cragie7cdad772015-10-02 13:31:41 +0100278 MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200279 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( (mbedtls_ecp_group *) grp,
280 &VV, &h, X, &r, G ) );
281
282 if( mbedtls_ecp_point_cmp( &VV, &V ) != 0 )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200283 {
284 ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
285 goto cleanup;
286 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200287
288cleanup:
289 mbedtls_ecp_point_free( &V );
290 mbedtls_ecp_point_free( &VV );
291 mbedtls_mpi_free( &r );
292 mbedtls_mpi_free( &h );
293
294 return( ret );
295}
296
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200297/*
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200298 * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2)
299 */
300static int ecjpake_zkp_write( const mbedtls_md_info_t *md_info,
301 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100302 const int pf,
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200303 const mbedtls_ecp_point *G,
304 const mbedtls_mpi *x,
305 const mbedtls_ecp_point *X,
306 const char *id,
307 unsigned char **p,
308 const unsigned char *end,
309 int (*f_rng)(void *, unsigned char *, size_t),
310 void *p_rng )
311{
312 int ret;
313 mbedtls_ecp_point V;
314 mbedtls_mpi v;
315 mbedtls_mpi h; /* later recycled to hold r */
316 size_t len;
317
318 if( end < *p )
319 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
320
321 mbedtls_ecp_point_init( &V );
322 mbedtls_mpi_init( &v );
323 mbedtls_mpi_init( &h );
324
325 /* Compute signature */
326 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp,
327 G, &v, &V, f_rng, p_rng ) );
Robert Cragie7cdad772015-10-02 13:31:41 +0100328 MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) );
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200329 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &h, &h, x ) ); /* x*h */
330 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &h, &v, &h ) ); /* v - x*h */
331 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &h, &h, &grp->N ) ); /* r */
332
333 /* Write it out */
334 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, &V,
Robert Cragie7cdad772015-10-02 13:31:41 +0100335 pf, &len, *p, end - *p ) );
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200336 *p += len;
337
338 len = mbedtls_mpi_size( &h ); /* actually r */
339 if( end < *p || (size_t)( end - *p ) < 1 + len || len > 255 )
340 {
341 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
342 goto cleanup;
343 }
344
345 *(*p)++ = (unsigned char)( len & 0xFF );
346 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, *p, len ) ); /* r */
347 *p += len;
348
349cleanup:
350 mbedtls_ecp_point_free( &V );
351 mbedtls_mpi_free( &v );
352 mbedtls_mpi_free( &h );
353
354 return( ret );
355}
356
357/*
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200358 * Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof
359 * Output: verified public key X
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200360 */
361static int ecjpake_kkp_read( const mbedtls_md_info_t *md_info,
362 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100363 const int pf,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200364 const mbedtls_ecp_point *G,
365 mbedtls_ecp_point *X,
366 const char *id,
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200367 const unsigned char **p,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200368 const unsigned char *end )
369{
370 int ret;
371
372 if( end < *p )
373 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
374
375 /*
376 * struct {
377 * ECPoint X;
378 * ECSchnorrZKP zkp;
379 * } ECJPAKEKeyKP;
380 */
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200381 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, X, p, end - *p ) );
Manuel Pégourié-Gonnard30590952015-08-17 10:37:40 +0200382 if( mbedtls_ecp_is_zero( X ) )
383 {
384 ret = MBEDTLS_ERR_ECP_INVALID_KEY;
385 goto cleanup;
386 }
387
Robert Cragie7cdad772015-10-02 13:31:41 +0100388 MBEDTLS_MPI_CHK( ecjpake_zkp_read( md_info, grp, pf, G, X, id, p, end ) );
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200389
390cleanup:
391 return( ret );
392}
393
394/*
395 * Generate an ECJPAKEKeyKP
396 * Output: the serialized structure, plus private/public key pair
397 */
398static int ecjpake_kkp_write( const mbedtls_md_info_t *md_info,
399 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100400 const int pf,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200401 const mbedtls_ecp_point *G,
402 mbedtls_mpi *x,
403 mbedtls_ecp_point *X,
404 const char *id,
405 unsigned char **p,
406 const unsigned char *end,
407 int (*f_rng)(void *, unsigned char *, size_t),
408 void *p_rng )
409{
410 int ret;
411 size_t len;
412
413 if( end < *p )
414 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
415
416 /* Generate key (7.4.2.3.1) and write it out */
417 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp, G, x, X,
418 f_rng, p_rng ) );
419 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, X,
Robert Cragie7cdad772015-10-02 13:31:41 +0100420 pf, &len, *p, end - *p ) );
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200421 *p += len;
422
423 /* Generate and write proof */
Robert Cragie7cdad772015-10-02 13:31:41 +0100424 MBEDTLS_MPI_CHK( ecjpake_zkp_write( md_info, grp, pf, G, x, X, id,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200425 p, end, f_rng, p_rng ) );
426
427cleanup:
428 return( ret );
429}
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200430
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200431/*
432 * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs
433 * Ouputs: verified peer public keys Xa, Xb
434 */
435static int ecjpake_kkpp_read( const mbedtls_md_info_t *md_info,
436 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100437 const int pf,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200438 const mbedtls_ecp_point *G,
439 mbedtls_ecp_point *Xa,
440 mbedtls_ecp_point *Xb,
441 const char *id,
442 const unsigned char *buf,
443 size_t len )
444{
445 int ret;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200446 const unsigned char *p = buf;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200447 const unsigned char *end = buf + len;
448
449 /*
450 * struct {
451 * ECJPAKEKeyKP ecjpake_key_kp_pair_list[2];
452 * } ECJPAKEKeyKPPairList;
453 */
Robert Cragie7cdad772015-10-02 13:31:41 +0100454 MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xa, id, &p, end ) );
455 MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xb, id, &p, end ) );
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200456
457 if( p != end )
458 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
459
460cleanup:
461 return( ret );
462}
463
464/*
465 * Generate a ECJPAKEKeyKPPairList
466 * Outputs: the serialized structure, plus two private/public key pairs
467 */
468static int ecjpake_kkpp_write( const mbedtls_md_info_t *md_info,
469 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100470 const int pf,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200471 const mbedtls_ecp_point *G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200472 mbedtls_mpi *xm1,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200473 mbedtls_ecp_point *Xa,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200474 mbedtls_mpi *xm2,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200475 mbedtls_ecp_point *Xb,
476 const char *id,
477 unsigned char *buf,
478 size_t len,
479 size_t *olen,
480 int (*f_rng)(void *, unsigned char *, size_t),
481 void *p_rng )
482{
483 int ret;
484 unsigned char *p = buf;
485 const unsigned char *end = buf + len;
486
Robert Cragie7cdad772015-10-02 13:31:41 +0100487 MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm1, Xa, id,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200488 &p, end, f_rng, p_rng ) );
Robert Cragie7cdad772015-10-02 13:31:41 +0100489 MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm2, Xb, id,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200490 &p, end, f_rng, p_rng ) );
491
492 *olen = p - buf;
493
494cleanup:
495 return( ret );
496}
497
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200498/*
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200499 * Read and process the first round message
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200500 */
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200501int mbedtls_ecjpake_read_round_one( mbedtls_ecjpake_context *ctx,
502 const unsigned char *buf,
503 size_t len )
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200504{
Robert Cragie7cdad772015-10-02 13:31:41 +0100505 return( ecjpake_kkpp_read( ctx->md_info, &ctx->grp, ctx->point_format,
506 &ctx->grp.G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200507 &ctx->Xp1, &ctx->Xp2, ID_PEER,
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200508 buf, len ) );
509}
510
511/*
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200512 * Generate and write the first round message
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200513 */
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200514int mbedtls_ecjpake_write_round_one( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200515 unsigned char *buf, size_t len, size_t *olen,
516 int (*f_rng)(void *, unsigned char *, size_t),
517 void *p_rng )
518{
Robert Cragie7cdad772015-10-02 13:31:41 +0100519 return( ecjpake_kkpp_write( ctx->md_info, &ctx->grp, ctx->point_format,
520 &ctx->grp.G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200521 &ctx->xm1, &ctx->Xm1, &ctx->xm2, &ctx->Xm2,
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200522 ID_MINE, buf, len, olen, f_rng, p_rng ) );
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200523}
524
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200525/*
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200526 * Compute the sum of three points R = A + B + C
527 */
528static int ecjpake_ecp_add3( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
529 const mbedtls_ecp_point *A,
530 const mbedtls_ecp_point *B,
531 const mbedtls_ecp_point *C )
532{
533 int ret;
534 mbedtls_mpi one;
535
536 mbedtls_mpi_init( &one );
537
538 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
539 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, A, &one, B ) );
540 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, R, &one, C ) );
541
542cleanup:
543 mbedtls_mpi_free( &one );
544
545 return( ret );
546}
547
548/*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200549 * 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 +0200550 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200551int mbedtls_ecjpake_read_round_two( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200552 const unsigned char *buf,
553 size_t len )
554{
555 int ret;
556 const unsigned char *p = buf;
557 const unsigned char *end = buf + len;
558 mbedtls_ecp_group grp;
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200559 mbedtls_ecp_point G; /* C: GB, S: GA */
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200560
561 mbedtls_ecp_group_init( &grp );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200562 mbedtls_ecp_point_init( &G );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200563
564 /*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200565 * Server: GA = X3 + X4 + X1 (7.4.2.6.1)
566 * Client: GB = X1 + X2 + X3 (7.4.2.5.1)
567 * Unified: G = Xm1 + Xm2 + Xp1
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200568 * We need that before parsing in order to check Xp as we read it
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200569 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200570 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200571 &ctx->Xm1, &ctx->Xm2, &ctx->Xp1 ) );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200572
573 /*
574 * struct {
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200575 * ECParameters curve_params; // only client reading server msg
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200576 * ECJPAKEKeyKP ecjpake_key_kp;
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200577 * } Client/ServerECJPAKEParams;
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200578 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200579 if( ctx->role == MBEDTLS_ECJPAKE_CLIENT )
Manuel Pégourié-Gonnardd9802af2015-08-17 12:47:38 +0200580 {
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200581 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_group( &grp, &p, len ) );
Manuel Pégourié-Gonnardd9802af2015-08-17 12:47:38 +0200582 if( grp.id != ctx->grp.id )
583 {
584 ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
585 goto cleanup;
586 }
587 }
588
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200589 MBEDTLS_MPI_CHK( ecjpake_kkp_read( ctx->md_info, &ctx->grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100590 ctx->point_format,
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200591 &G, &ctx->Xp, ID_PEER, &p, end ) );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200592
593 if( p != end )
594 {
595 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
596 goto cleanup;
597 }
598
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200599cleanup:
600 mbedtls_ecp_group_free( &grp );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200601 mbedtls_ecp_point_free( &G );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200602
603 return( ret );
604}
605
606/*
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200607 * Compute R = +/- X * S mod N, taking care not to leak S
608 */
609static int ecjpake_mul_secret( mbedtls_mpi *R, int sign,
610 const mbedtls_mpi *X,
611 const mbedtls_mpi *S,
612 const mbedtls_mpi *N,
613 int (*f_rng)(void *, unsigned char *, size_t),
614 void *p_rng )
615{
616 int ret;
617 mbedtls_mpi b; /* Blinding value, then s + N * blinding */
618
619 mbedtls_mpi_init( &b );
620
621 /* b = s + rnd-128-bit * N */
622 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &b, 16, f_rng, p_rng ) );
623 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &b, &b, N ) );
624 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &b, &b, S ) );
625
626 /* R = sign * X * b mod N */
627 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( R, X, &b ) );
628 R->s *= sign;
629 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( R, R, N ) );
630
631cleanup:
632 mbedtls_mpi_free( &b );
633
634 return( ret );
635}
636
637/*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200638 * 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 +0200639 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200640int mbedtls_ecjpake_write_round_two( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200641 unsigned char *buf, size_t len, size_t *olen,
642 int (*f_rng)(void *, unsigned char *, size_t),
643 void *p_rng )
644{
645 int ret;
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200646 mbedtls_ecp_point G; /* C: GA, S: GB */
647 mbedtls_ecp_point Xm; /* C: Xc, S: Xs */
648 mbedtls_mpi xm; /* C: xc, S: xs */
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200649 unsigned char *p = buf;
650 const unsigned char *end = buf + len;
651 size_t ec_len;
652
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200653 mbedtls_ecp_point_init( &G );
654 mbedtls_ecp_point_init( &Xm );
655 mbedtls_mpi_init( &xm );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200656
657 /*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200658 * 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 +0200659 *
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200660 * Client: GA = X1 + X3 + X4 | xs = x2 * s | Xc = xc * GA
661 * Server: GB = X3 + X1 + X2 | xs = x4 * s | Xs = xs * GB
662 * Unified: G = Xm1 + Xp1 + Xp2 | xm = xm2 * s | Xm = xm * G
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200663 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200664 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200665 &ctx->Xp1, &ctx->Xp2, &ctx->Xm1 ) );
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200666 MBEDTLS_MPI_CHK( ecjpake_mul_secret( &xm, 1, &ctx->xm2, &ctx->s,
667 &ctx->grp.N, f_rng, p_rng ) );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200668 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &Xm, &xm, &G, f_rng, p_rng ) );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200669
670 /*
671 * Now write things out
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200672 *
673 * struct {
674 * ECParameters curve_params; // only server writing its message
675 * ECJPAKEKeyKP ecjpake_key_kp;
676 * } Client/ServerECJPAKEParams;
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200677 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200678 if( ctx->role == MBEDTLS_ECJPAKE_SERVER )
679 {
680 if( end < p )
681 {
682 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
683 goto cleanup;
684 }
685 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_group( &ctx->grp, &ec_len,
686 p, end - p ) );
687 p += ec_len;
688 }
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200689
690 if( end < p )
691 {
692 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
693 goto cleanup;
694 }
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200695 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( &ctx->grp, &Xm,
Robert Cragie7cdad772015-10-02 13:31:41 +0100696 ctx->point_format, &ec_len, p, end - p ) );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200697 p += ec_len;
698
699 MBEDTLS_MPI_CHK( ecjpake_zkp_write( ctx->md_info, &ctx->grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100700 ctx->point_format,
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200701 &G, &xm, &Xm, ID_MINE,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200702 &p, end, f_rng, p_rng ) );
703
704 *olen = p - buf;
705
706cleanup:
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200707 mbedtls_ecp_point_free( &G );
708 mbedtls_ecp_point_free( &Xm );
709 mbedtls_mpi_free( &xm );
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +0200710
711 return( ret );
712}
713
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200714/*
715 * Derive PMS (7.4.2.7 / 7.4.2.8)
716 */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +0200717int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200718 unsigned char *buf, size_t len, size_t *olen,
719 int (*f_rng)(void *, unsigned char *, size_t),
720 void *p_rng )
721{
722 int ret;
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200723 mbedtls_ecp_point K;
724 mbedtls_mpi m_xm2_s, one;
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200725 unsigned char kx[MBEDTLS_ECP_MAX_BYTES];
726 size_t x_bytes;
727
728 *olen = mbedtls_md_get_size( ctx->md_info );
729 if( len < *olen )
730 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
731
732 mbedtls_ecp_point_init( &K );
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200733 mbedtls_mpi_init( &m_xm2_s );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200734 mbedtls_mpi_init( &one );
735
736 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200737
738 /*
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200739 * Client: K = ( Xs - X4 * x2 * s ) * x2
740 * Server: K = ( Xc - X2 * x4 * s ) * x4
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200741 * Unified: K = ( Xp - Xp2 * xm2 * s ) * xm2
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200742 */
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200743 MBEDTLS_MPI_CHK( ecjpake_mul_secret( &m_xm2_s, -1, &ctx->xm2, &ctx->s,
744 &ctx->grp.N, f_rng, p_rng ) );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200745 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( &ctx->grp, &K,
746 &one, &ctx->Xp,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200747 &m_xm2_s, &ctx->Xp2 ) );
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200748 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &K, &ctx->xm2, &K,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200749 f_rng, p_rng ) );
750
751 /* PMS = SHA-256( K.X ) */
752 x_bytes = ( ctx->grp.pbits + 7 ) / 8;
753 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &K.X, kx, x_bytes ) );
754 MBEDTLS_MPI_CHK( mbedtls_md( ctx->md_info, kx, x_bytes, buf ) );
755
756cleanup:
757 mbedtls_ecp_point_free( &K );
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200758 mbedtls_mpi_free( &m_xm2_s );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200759 mbedtls_mpi_free( &one );
760
761 return( ret );
762}
763
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200764#undef ID_MINE
765#undef ID_PEER
766
767
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200768#if defined(MBEDTLS_SELF_TEST)
769
770#if defined(MBEDTLS_PLATFORM_C)
771#include "mbedtls/platform.h"
772#else
773#include <stdio.h>
774#define mbedtls_printf printf
775#endif
776
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200777#if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
778 !defined(MBEDTLS_SHA256_C)
779int mbedtls_ecjpake_self_test( int verbose )
780{
781 (void) verbose;
782 return( 0 );
783}
784#else
785
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200786static const unsigned char ecjpake_test_password[] = {
787 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x6a, 0x70, 0x61, 0x6b, 0x65, 0x74,
788 0x65, 0x73, 0x74
789};
790
791static const unsigned char ecjpake_test_x1[] = {
792 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
793 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
794 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21
795};
796
797static const unsigned char ecjpake_test_x2[] = {
798 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
799 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
800 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
801};
802
803static const unsigned char ecjpake_test_x3[] = {
804 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
805 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
806 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
807};
808
809static const unsigned char ecjpake_test_x4[] = {
810 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc,
811 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
812 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1
813};
814
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200815static const unsigned char ecjpake_test_cli_one[] = {
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200816 0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19,
817 0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44,
818 0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad,
819 0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62,
820 0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9,
821 0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d,
822 0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e,
823 0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e,
824 0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73,
825 0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22,
826 0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce,
827 0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00,
828 0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200829 0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e,
830 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62,
831 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5,
832 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb,
833 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35,
834 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0,
835 0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb,
836 0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47,
837 0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39,
838 0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97,
839 0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40,
840 0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d,
841 0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa,
842 0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d,
843 0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200844};
845
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200846static const unsigned char ecjpake_test_srv_one[] = {
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200847 0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb,
848 0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18,
849 0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47,
850 0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f,
851 0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7,
852 0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d,
853 0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64,
854 0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36,
855 0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2,
856 0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec,
857 0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16,
858 0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96,
859 0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3,
860 0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19,
861 0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f,
862 0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8,
863 0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7,
864 0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea,
865 0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5,
866 0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6,
867 0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31,
868 0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d,
869 0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8,
870 0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee,
871 0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84,
872 0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f,
873 0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80,
874 0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12
875};
876
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200877static const unsigned char ecjpake_test_srv_two[] = {
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200878 0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23,
879 0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c,
880 0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f,
881 0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca,
882 0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26,
883 0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55,
884 0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38,
885 0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6,
886 0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9,
887 0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4,
888 0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2,
889 0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8,
890 0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd,
891 0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c
892};
893
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200894static const unsigned char ecjpake_test_cli_two[] = {
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +0200895 0x41, 0x04, 0x69, 0xd5, 0x4e, 0xe8, 0x5e, 0x90, 0xce, 0x3f, 0x12, 0x46,
896 0x74, 0x2d, 0xe5, 0x07, 0xe9, 0x39, 0xe8, 0x1d, 0x1d, 0xc1, 0xc5, 0xcb,
897 0x98, 0x8b, 0x58, 0xc3, 0x10, 0xc9, 0xfd, 0xd9, 0x52, 0x4d, 0x93, 0x72,
898 0x0b, 0x45, 0x54, 0x1c, 0x83, 0xee, 0x88, 0x41, 0x19, 0x1d, 0xa7, 0xce,
899 0xd8, 0x6e, 0x33, 0x12, 0xd4, 0x36, 0x23, 0xc1, 0xd6, 0x3e, 0x74, 0x98,
900 0x9a, 0xba, 0x4a, 0xff, 0xd1, 0xee, 0x41, 0x04, 0x07, 0x7e, 0x8c, 0x31,
901 0xe2, 0x0e, 0x6b, 0xed, 0xb7, 0x60, 0xc1, 0x35, 0x93, 0xe6, 0x9f, 0x15,
902 0xbe, 0x85, 0xc2, 0x7d, 0x68, 0xcd, 0x09, 0xcc, 0xb8, 0xc4, 0x18, 0x36,
903 0x08, 0x91, 0x7c, 0x5c, 0x3d, 0x40, 0x9f, 0xac, 0x39, 0xfe, 0xfe, 0xe8,
904 0x2f, 0x72, 0x92, 0xd3, 0x6f, 0x0d, 0x23, 0xe0, 0x55, 0x91, 0x3f, 0x45,
905 0xa5, 0x2b, 0x85, 0xdd, 0x8a, 0x20, 0x52, 0xe9, 0xe1, 0x29, 0xbb, 0x4d,
906 0x20, 0x0f, 0x01, 0x1f, 0x19, 0x48, 0x35, 0x35, 0xa6, 0xe8, 0x9a, 0x58,
907 0x0c, 0x9b, 0x00, 0x03, 0xba, 0xf2, 0x14, 0x62, 0xec, 0xe9, 0x1a, 0x82,
908 0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c
909};
910
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200911static const unsigned char ecjpake_test_pms[] = {
912 0xf3, 0xd4, 0x7f, 0x59, 0x98, 0x44, 0xdb, 0x92, 0xa5, 0x69, 0xbb, 0xe7,
913 0x98, 0x1e, 0x39, 0xd9, 0x31, 0xfd, 0x74, 0x3b, 0xf2, 0x2e, 0x98, 0xf9,
914 0xb4, 0x38, 0xf7, 0x19, 0xd3, 0xc4, 0xf3, 0x51
915};
916
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +0200917/* Load my private keys and generate the correponding public keys */
918static int ecjpake_test_load( mbedtls_ecjpake_context *ctx,
919 const unsigned char *xm1, size_t len1,
920 const unsigned char *xm2, size_t len2 )
921{
922 int ret;
923
924 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm1, xm1, len1 ) );
925 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm2, xm2, len2 ) );
926 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm1, &ctx->xm1,
927 &ctx->grp.G, NULL, NULL ) );
928 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm2, &ctx->xm2,
929 &ctx->grp.G, NULL, NULL ) );
930
931cleanup:
932 return( ret );
933}
934
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200935/* For tests we don't need a secure RNG;
936 * use the LGC from Numerical Recipes for simplicity */
937static int ecjpake_lgc( void *p, unsigned char *out, size_t len )
938{
939 static uint32_t x = 42;
940 (void) p;
941
942 while( len > 0 )
943 {
944 size_t use_len = len > 4 ? 4 : len;
945 x = 1664525 * x + 1013904223;
946 memcpy( out, &x, use_len );
947 out += use_len;
948 len -= use_len;
949 }
950
951 return( 0 );
952}
953
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200954#define TEST_ASSERT( x ) \
955 do { \
956 if( x ) \
957 ret = 0; \
958 else \
959 { \
960 ret = 1; \
961 goto cleanup; \
962 } \
963 } while( 0 )
964
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200965/*
966 * Checkup routine
967 */
968int mbedtls_ecjpake_self_test( int verbose )
969{
970 int ret;
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200971 mbedtls_ecjpake_context cli;
972 mbedtls_ecjpake_context srv;
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200973 unsigned char buf[512], pms[32];
974 size_t len, pmslen;
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200975
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200976 mbedtls_ecjpake_init( &cli );
977 mbedtls_ecjpake_init( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200978
979 if( verbose != 0 )
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200980 mbedtls_printf( " ECJPAKE test #0 (setup): " );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200981
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +0200982 TEST_ASSERT( mbedtls_ecjpake_setup( &cli, MBEDTLS_ECJPAKE_CLIENT,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200983 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
984 ecjpake_test_password,
985 sizeof( ecjpake_test_password ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200986
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +0200987 TEST_ASSERT( mbedtls_ecjpake_setup( &srv, MBEDTLS_ECJPAKE_SERVER,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200988 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
989 ecjpake_test_password,
990 sizeof( ecjpake_test_password ) ) == 0 );
991
992 if( verbose != 0 )
993 mbedtls_printf( "passed\n" );
994
995 if( verbose != 0 )
996 mbedtls_printf( " ECJPAKE test #1 (random handshake): " );
997
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200998 TEST_ASSERT( mbedtls_ecjpake_write_round_one( &cli,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200999 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1000
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001001 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv, buf, len ) == 0 );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001002
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001003 TEST_ASSERT( mbedtls_ecjpake_write_round_one( &srv,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001004 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1005
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001006 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli, buf, len ) == 0 );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001007
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001008 TEST_ASSERT( mbedtls_ecjpake_write_round_two( &srv,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +02001009 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1010
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001011 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli, buf, len ) == 0 );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +02001012
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001013 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001014 pms, sizeof( pms ), &pmslen, ecjpake_lgc, NULL ) == 0 );
1015
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001016 TEST_ASSERT( mbedtls_ecjpake_write_round_two( &cli,
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +02001017 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1018
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001019 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv, buf, len ) == 0 );
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +02001020
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001021 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001022 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1023
1024 TEST_ASSERT( len == pmslen );
1025 TEST_ASSERT( memcmp( buf, pms, len ) == 0 );
1026
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001027 if( verbose != 0 )
1028 mbedtls_printf( "passed\n" );
1029
1030 if( verbose != 0 )
1031 mbedtls_printf( " ECJPAKE test #2 (reference handshake): " );
1032
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001033 /* Simulate generation of round one */
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001034 MBEDTLS_MPI_CHK( ecjpake_test_load( &cli,
1035 ecjpake_test_x1, sizeof( ecjpake_test_x1 ),
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001036 ecjpake_test_x2, sizeof( ecjpake_test_x2 ) ) );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001037
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001038 MBEDTLS_MPI_CHK( ecjpake_test_load( &srv,
1039 ecjpake_test_x3, sizeof( ecjpake_test_x3 ),
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001040 ecjpake_test_x4, sizeof( ecjpake_test_x4 ) ) );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001041
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001042 /* Read round one */
1043 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv,
1044 ecjpake_test_cli_one,
1045 sizeof( ecjpake_test_cli_one ) ) == 0 );
1046
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001047 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001048 ecjpake_test_srv_one,
1049 sizeof( ecjpake_test_srv_one ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001050
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001051 /* Skip generation of round two, read round two */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001052 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001053 ecjpake_test_srv_two,
1054 sizeof( ecjpake_test_srv_two ) ) == 0 );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +02001055
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001056 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001057 ecjpake_test_cli_two,
1058 sizeof( ecjpake_test_cli_two ) ) == 0 );
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +02001059
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001060 /* Server derives PMS */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001061 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001062 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1063
1064 TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
1065 TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
1066
1067 memset( buf, 0, len ); /* Avoid interferences with next step */
1068
1069 /* Client derives PMS */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001070 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001071 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1072
1073 TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
1074 TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
1075
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001076 if( verbose != 0 )
1077 mbedtls_printf( "passed\n" );
1078
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001079cleanup:
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001080 mbedtls_ecjpake_free( &cli );
1081 mbedtls_ecjpake_free( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001082
1083 if( ret != 0 )
1084 {
1085 if( verbose != 0 )
1086 mbedtls_printf( "failed\n" );
1087
1088 ret = 1;
1089 }
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001090
1091 if( verbose != 0 )
1092 mbedtls_printf( "\n" );
1093
1094 return( ret );
1095}
1096
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +02001097#undef TEST_ASSERT
1098
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001099#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_SHA256_C */
1100
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001101#endif /* MBEDTLS_SELF_TEST */
1102
1103#endif /* MBEDTLS_ECJPAKE_C */