blob: ec5a4007db43aed1c8399704a6189ff657799057 [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
Hanno Becker616d1ca2018-01-24 10:25:05 +000039#if !defined(MBEDTLS_ECJPAKE_ALT)
40
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +020041/*
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +020042 * Convert a mbedtls_ecjpake_role to identifier string
43 */
44static const char * const ecjpake_id[] = {
45 "client",
46 "server"
47};
48
49#define ID_MINE ( ecjpake_id[ ctx->role ] )
50#define ID_PEER ( ecjpake_id[ 1 - ctx->role ] )
51
52/*
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020053 * Initialize context
54 */
55void mbedtls_ecjpake_init( mbedtls_ecjpake_context *ctx )
56{
57 if( ctx == NULL )
58 return;
59
60 ctx->md_info = NULL;
61 mbedtls_ecp_group_init( &ctx->grp );
Manuel Pégourié-Gonnardb7da1942015-10-19 13:35:22 +020062 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020063
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +020064 mbedtls_ecp_point_init( &ctx->Xm1 );
65 mbedtls_ecp_point_init( &ctx->Xm2 );
66 mbedtls_ecp_point_init( &ctx->Xp1 );
67 mbedtls_ecp_point_init( &ctx->Xp2 );
68 mbedtls_ecp_point_init( &ctx->Xp );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020069
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +020070 mbedtls_mpi_init( &ctx->xm1 );
71 mbedtls_mpi_init( &ctx->xm2 );
72 mbedtls_mpi_init( &ctx->s );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020073}
74
75/*
76 * Free context
77 */
78void mbedtls_ecjpake_free( mbedtls_ecjpake_context *ctx )
79{
80 if( ctx == NULL )
81 return;
82
83 ctx->md_info = NULL;
84 mbedtls_ecp_group_free( &ctx->grp );
85
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +020086 mbedtls_ecp_point_free( &ctx->Xm1 );
87 mbedtls_ecp_point_free( &ctx->Xm2 );
88 mbedtls_ecp_point_free( &ctx->Xp1 );
89 mbedtls_ecp_point_free( &ctx->Xp2 );
90 mbedtls_ecp_point_free( &ctx->Xp );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020091
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +020092 mbedtls_mpi_free( &ctx->xm1 );
93 mbedtls_mpi_free( &ctx->xm2 );
94 mbedtls_mpi_free( &ctx->s );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020095}
96
97/*
98 * Setup context
99 */
100int mbedtls_ecjpake_setup( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +0200101 mbedtls_ecjpake_role role,
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200102 mbedtls_md_type_t hash,
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200103 mbedtls_ecp_group_id curve,
104 const unsigned char *secret,
105 size_t len )
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200106{
107 int ret;
108
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +0200109 ctx->role = role;
110
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200111 if( ( ctx->md_info = mbedtls_md_info_from_type( hash ) ) == NULL )
112 return( MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE );
113
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200114 MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ctx->grp, curve ) );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200115
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200116 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->s, secret, len ) );
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200117
118cleanup:
119 if( ret != 0 )
120 mbedtls_ecjpake_free( ctx );
121
122 return( ret );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200123}
124
125/*
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200126 * Check if context is ready for use
127 */
128int mbedtls_ecjpake_check( const mbedtls_ecjpake_context *ctx )
129{
130 if( ctx->md_info == NULL ||
131 ctx->grp.id == MBEDTLS_ECP_DP_NONE ||
132 ctx->s.p == NULL )
133 {
134 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
135 }
136
137 return( 0 );
138}
139
140/*
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200141 * Write a point plus its length to a buffer
142 */
143static int ecjpake_write_len_point( unsigned char **p,
144 const unsigned char *end,
145 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100146 const int pf,
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200147 const mbedtls_ecp_point *P )
148{
149 int ret;
150 size_t len;
151
152 /* Need at least 4 for length plus 1 for point */
153 if( end < *p || end - *p < 5 )
154 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
155
Robert Cragie7cdad772015-10-02 13:31:41 +0100156 ret = mbedtls_ecp_point_write_binary( grp, P, pf,
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200157 &len, *p + 4, end - ( *p + 4 ) );
158 if( ret != 0 )
159 return( ret );
160
161 (*p)[0] = (unsigned char)( ( len >> 24 ) & 0xFF );
162 (*p)[1] = (unsigned char)( ( len >> 16 ) & 0xFF );
163 (*p)[2] = (unsigned char)( ( len >> 8 ) & 0xFF );
164 (*p)[3] = (unsigned char)( ( len ) & 0xFF );
165
166 *p += 4 + len;
167
168 return( 0 );
169}
170
171/*
172 * Size of the temporary buffer for ecjpake_hash:
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200173 * 3 EC points plus their length, plus ID and its length (4 + 6 bytes)
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200174 */
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200175#define ECJPAKE_HASH_BUF_LEN ( 3 * ( 4 + MBEDTLS_ECP_MAX_PT_LEN ) + 4 + 6 )
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200176
177/*
178 * Compute hash for ZKP (7.4.2.2.2.1)
179 */
180static int ecjpake_hash( const mbedtls_md_info_t *md_info,
181 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100182 const int pf,
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200183 const mbedtls_ecp_point *G,
184 const mbedtls_ecp_point *V,
185 const mbedtls_ecp_point *X,
186 const char *id,
187 mbedtls_mpi *h )
188{
189 int ret;
190 unsigned char buf[ECJPAKE_HASH_BUF_LEN];
191 unsigned char *p = buf;
192 const unsigned char *end = buf + sizeof( buf );
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200193 const size_t id_len = strlen( id );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200194 unsigned char hash[MBEDTLS_MD_MAX_SIZE];
195
196 /* Write things to temporary buffer */
Robert Cragie7cdad772015-10-02 13:31:41 +0100197 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, G ) );
198 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, V ) );
199 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, X ) );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200200
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200201 if( end - p < 4 )
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200202 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
203
204 *p++ = (unsigned char)( ( id_len >> 24 ) & 0xFF );
205 *p++ = (unsigned char)( ( id_len >> 16 ) & 0xFF );
206 *p++ = (unsigned char)( ( id_len >> 8 ) & 0xFF );
207 *p++ = (unsigned char)( ( id_len ) & 0xFF );
208
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200209 if( end < p || (size_t)( end - p ) < id_len )
210 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
211
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200212 memcpy( p, id, id_len );
213 p += id_len;
214
215 /* Compute hash */
216 mbedtls_md( md_info, buf, p - buf, hash );
217
218 /* Turn it into an integer mod n */
219 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( h, hash,
220 mbedtls_md_get_size( md_info ) ) );
221 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( h, h, &grp->N ) );
222
223cleanup:
224 return( ret );
225}
226
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200227/*
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200228 * Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3)
229 */
230static int ecjpake_zkp_read( const mbedtls_md_info_t *md_info,
231 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100232 const int pf,
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200233 const mbedtls_ecp_point *G,
234 const mbedtls_ecp_point *X,
235 const char *id,
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200236 const unsigned char **p,
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200237 const unsigned char *end )
238{
239 int ret;
240 mbedtls_ecp_point V, VV;
241 mbedtls_mpi r, h;
242 size_t r_len;
243
244 mbedtls_ecp_point_init( &V );
245 mbedtls_ecp_point_init( &VV );
246 mbedtls_mpi_init( &r );
247 mbedtls_mpi_init( &h );
248
249 /*
250 * struct {
251 * ECPoint V;
252 * opaque r<1..2^8-1>;
253 * } ECSchnorrZKP;
254 */
255 if( end < *p )
256 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
257
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200258 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, &V, p, end - *p ) );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200259
260 if( end < *p || (size_t)( end - *p ) < 1 )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200261 {
262 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
263 goto cleanup;
264 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200265
266 r_len = *(*p)++;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200267
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200268 if( end < *p || (size_t)( end - *p ) < r_len )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200269 {
270 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
271 goto cleanup;
272 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200273
274 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &r, *p, r_len ) );
275 *p += r_len;
276
277 /*
278 * Verification
279 */
Robert Cragie7cdad772015-10-02 13:31:41 +0100280 MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200281 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( (mbedtls_ecp_group *) grp,
282 &VV, &h, X, &r, G ) );
283
284 if( mbedtls_ecp_point_cmp( &VV, &V ) != 0 )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200285 {
286 ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
287 goto cleanup;
288 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200289
290cleanup:
291 mbedtls_ecp_point_free( &V );
292 mbedtls_ecp_point_free( &VV );
293 mbedtls_mpi_free( &r );
294 mbedtls_mpi_free( &h );
295
296 return( ret );
297}
298
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200299/*
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200300 * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2)
301 */
302static int ecjpake_zkp_write( const mbedtls_md_info_t *md_info,
303 const mbedtls_ecp_group *grp,
Darryl Green11999bb2018-03-13 15:22:58 +0000304 const int pf,
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200305 const mbedtls_ecp_point *G,
306 const mbedtls_mpi *x,
307 const mbedtls_ecp_point *X,
308 const char *id,
309 unsigned char **p,
310 const unsigned char *end,
311 int (*f_rng)(void *, unsigned char *, size_t),
312 void *p_rng )
313{
314 int ret;
315 mbedtls_ecp_point V;
316 mbedtls_mpi v;
317 mbedtls_mpi h; /* later recycled to hold r */
318 size_t len;
319
320 if( end < *p )
321 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
322
323 mbedtls_ecp_point_init( &V );
324 mbedtls_mpi_init( &v );
325 mbedtls_mpi_init( &h );
326
327 /* Compute signature */
328 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp,
329 G, &v, &V, f_rng, p_rng ) );
Robert Cragie7cdad772015-10-02 13:31:41 +0100330 MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) );
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200331 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &h, &h, x ) ); /* x*h */
332 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &h, &v, &h ) ); /* v - x*h */
333 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &h, &h, &grp->N ) ); /* r */
334
335 /* Write it out */
336 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, &V,
Robert Cragie7cdad772015-10-02 13:31:41 +0100337 pf, &len, *p, end - *p ) );
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200338 *p += len;
339
340 len = mbedtls_mpi_size( &h ); /* actually r */
341 if( end < *p || (size_t)( end - *p ) < 1 + len || len > 255 )
342 {
343 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
344 goto cleanup;
345 }
346
347 *(*p)++ = (unsigned char)( len & 0xFF );
348 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, *p, len ) ); /* r */
349 *p += len;
350
351cleanup:
352 mbedtls_ecp_point_free( &V );
353 mbedtls_mpi_free( &v );
354 mbedtls_mpi_free( &h );
355
356 return( ret );
357}
358
359/*
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200360 * Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof
361 * Output: verified public key X
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200362 */
363static int ecjpake_kkp_read( const mbedtls_md_info_t *md_info,
364 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100365 const int pf,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200366 const mbedtls_ecp_point *G,
367 mbedtls_ecp_point *X,
368 const char *id,
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200369 const unsigned char **p,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200370 const unsigned char *end )
371{
372 int ret;
373
374 if( end < *p )
375 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
376
377 /*
378 * struct {
379 * ECPoint X;
380 * ECSchnorrZKP zkp;
381 * } ECJPAKEKeyKP;
382 */
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200383 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, X, p, end - *p ) );
Manuel Pégourié-Gonnard30590952015-08-17 10:37:40 +0200384 if( mbedtls_ecp_is_zero( X ) )
385 {
386 ret = MBEDTLS_ERR_ECP_INVALID_KEY;
387 goto cleanup;
388 }
389
Robert Cragie7cdad772015-10-02 13:31:41 +0100390 MBEDTLS_MPI_CHK( ecjpake_zkp_read( md_info, grp, pf, G, X, id, p, end ) );
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200391
392cleanup:
393 return( ret );
394}
395
396/*
397 * Generate an ECJPAKEKeyKP
398 * Output: the serialized structure, plus private/public key pair
399 */
400static int ecjpake_kkp_write( const mbedtls_md_info_t *md_info,
401 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100402 const int pf,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200403 const mbedtls_ecp_point *G,
404 mbedtls_mpi *x,
405 mbedtls_ecp_point *X,
406 const char *id,
407 unsigned char **p,
408 const unsigned char *end,
409 int (*f_rng)(void *, unsigned char *, size_t),
410 void *p_rng )
411{
412 int ret;
413 size_t len;
414
415 if( end < *p )
416 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
417
418 /* Generate key (7.4.2.3.1) and write it out */
419 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp, G, x, X,
420 f_rng, p_rng ) );
421 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, X,
Robert Cragie7cdad772015-10-02 13:31:41 +0100422 pf, &len, *p, end - *p ) );
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200423 *p += len;
424
425 /* Generate and write proof */
Robert Cragie7cdad772015-10-02 13:31:41 +0100426 MBEDTLS_MPI_CHK( ecjpake_zkp_write( md_info, grp, pf, G, x, X, id,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200427 p, end, f_rng, p_rng ) );
428
429cleanup:
430 return( ret );
431}
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200432
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200433/*
434 * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs
435 * Ouputs: verified peer public keys Xa, Xb
436 */
437static int ecjpake_kkpp_read( const mbedtls_md_info_t *md_info,
438 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100439 const int pf,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200440 const mbedtls_ecp_point *G,
441 mbedtls_ecp_point *Xa,
442 mbedtls_ecp_point *Xb,
443 const char *id,
444 const unsigned char *buf,
445 size_t len )
446{
447 int ret;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200448 const unsigned char *p = buf;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200449 const unsigned char *end = buf + len;
450
451 /*
452 * struct {
453 * ECJPAKEKeyKP ecjpake_key_kp_pair_list[2];
454 * } ECJPAKEKeyKPPairList;
455 */
Robert Cragie7cdad772015-10-02 13:31:41 +0100456 MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xa, id, &p, end ) );
457 MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xb, id, &p, end ) );
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200458
459 if( p != end )
460 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
461
462cleanup:
463 return( ret );
464}
465
466/*
467 * Generate a ECJPAKEKeyKPPairList
468 * Outputs: the serialized structure, plus two private/public key pairs
469 */
470static int ecjpake_kkpp_write( const mbedtls_md_info_t *md_info,
471 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100472 const int pf,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200473 const mbedtls_ecp_point *G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200474 mbedtls_mpi *xm1,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200475 mbedtls_ecp_point *Xa,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200476 mbedtls_mpi *xm2,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200477 mbedtls_ecp_point *Xb,
478 const char *id,
479 unsigned char *buf,
480 size_t len,
481 size_t *olen,
482 int (*f_rng)(void *, unsigned char *, size_t),
483 void *p_rng )
484{
485 int ret;
486 unsigned char *p = buf;
487 const unsigned char *end = buf + len;
488
Robert Cragie7cdad772015-10-02 13:31:41 +0100489 MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm1, Xa, id,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200490 &p, end, f_rng, p_rng ) );
Robert Cragie7cdad772015-10-02 13:31:41 +0100491 MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm2, Xb, id,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200492 &p, end, f_rng, p_rng ) );
493
494 *olen = p - buf;
495
496cleanup:
497 return( ret );
498}
499
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200500/*
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200501 * Read and process the first round message
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200502 */
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200503int mbedtls_ecjpake_read_round_one( mbedtls_ecjpake_context *ctx,
504 const unsigned char *buf,
505 size_t len )
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200506{
Robert Cragie7cdad772015-10-02 13:31:41 +0100507 return( ecjpake_kkpp_read( ctx->md_info, &ctx->grp, ctx->point_format,
508 &ctx->grp.G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200509 &ctx->Xp1, &ctx->Xp2, ID_PEER,
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200510 buf, len ) );
511}
512
513/*
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200514 * Generate and write the first round message
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200515 */
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200516int mbedtls_ecjpake_write_round_one( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200517 unsigned char *buf, size_t len, size_t *olen,
518 int (*f_rng)(void *, unsigned char *, size_t),
519 void *p_rng )
520{
Robert Cragie7cdad772015-10-02 13:31:41 +0100521 return( ecjpake_kkpp_write( ctx->md_info, &ctx->grp, ctx->point_format,
522 &ctx->grp.G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200523 &ctx->xm1, &ctx->Xm1, &ctx->xm2, &ctx->Xm2,
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200524 ID_MINE, buf, len, olen, f_rng, p_rng ) );
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200525}
526
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200527/*
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200528 * Compute the sum of three points R = A + B + C
529 */
530static int ecjpake_ecp_add3( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
531 const mbedtls_ecp_point *A,
532 const mbedtls_ecp_point *B,
533 const mbedtls_ecp_point *C )
534{
535 int ret;
536 mbedtls_mpi one;
537
538 mbedtls_mpi_init( &one );
539
540 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
541 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, A, &one, B ) );
542 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, R, &one, C ) );
543
544cleanup:
545 mbedtls_mpi_free( &one );
546
547 return( ret );
548}
549
550/*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200551 * 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 +0200552 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200553int mbedtls_ecjpake_read_round_two( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200554 const unsigned char *buf,
555 size_t len )
556{
557 int ret;
558 const unsigned char *p = buf;
559 const unsigned char *end = buf + len;
560 mbedtls_ecp_group grp;
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200561 mbedtls_ecp_point G; /* C: GB, S: GA */
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200562
563 mbedtls_ecp_group_init( &grp );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200564 mbedtls_ecp_point_init( &G );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200565
566 /*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200567 * Server: GA = X3 + X4 + X1 (7.4.2.6.1)
568 * Client: GB = X1 + X2 + X3 (7.4.2.5.1)
569 * Unified: G = Xm1 + Xm2 + Xp1
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200570 * We need that before parsing in order to check Xp as we read it
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200571 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200572 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200573 &ctx->Xm1, &ctx->Xm2, &ctx->Xp1 ) );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200574
575 /*
576 * struct {
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200577 * ECParameters curve_params; // only client reading server msg
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200578 * ECJPAKEKeyKP ecjpake_key_kp;
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200579 * } Client/ServerECJPAKEParams;
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200580 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200581 if( ctx->role == MBEDTLS_ECJPAKE_CLIENT )
Manuel Pégourié-Gonnardd9802af2015-08-17 12:47:38 +0200582 {
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200583 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_group( &grp, &p, len ) );
Manuel Pégourié-Gonnardd9802af2015-08-17 12:47:38 +0200584 if( grp.id != ctx->grp.id )
585 {
586 ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
587 goto cleanup;
588 }
589 }
590
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200591 MBEDTLS_MPI_CHK( ecjpake_kkp_read( ctx->md_info, &ctx->grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100592 ctx->point_format,
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200593 &G, &ctx->Xp, ID_PEER, &p, end ) );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200594
595 if( p != end )
596 {
597 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
598 goto cleanup;
599 }
600
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200601cleanup:
602 mbedtls_ecp_group_free( &grp );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200603 mbedtls_ecp_point_free( &G );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200604
605 return( ret );
606}
607
608/*
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200609 * Compute R = +/- X * S mod N, taking care not to leak S
610 */
611static int ecjpake_mul_secret( mbedtls_mpi *R, int sign,
612 const mbedtls_mpi *X,
613 const mbedtls_mpi *S,
614 const mbedtls_mpi *N,
615 int (*f_rng)(void *, unsigned char *, size_t),
616 void *p_rng )
617{
618 int ret;
619 mbedtls_mpi b; /* Blinding value, then s + N * blinding */
620
621 mbedtls_mpi_init( &b );
622
623 /* b = s + rnd-128-bit * N */
624 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &b, 16, f_rng, p_rng ) );
625 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &b, &b, N ) );
626 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &b, &b, S ) );
627
628 /* R = sign * X * b mod N */
629 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( R, X, &b ) );
630 R->s *= sign;
631 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( R, R, N ) );
632
633cleanup:
634 mbedtls_mpi_free( &b );
635
636 return( ret );
637}
638
639/*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200640 * 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 +0200641 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200642int mbedtls_ecjpake_write_round_two( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200643 unsigned char *buf, size_t len, size_t *olen,
644 int (*f_rng)(void *, unsigned char *, size_t),
645 void *p_rng )
646{
647 int ret;
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200648 mbedtls_ecp_point G; /* C: GA, S: GB */
649 mbedtls_ecp_point Xm; /* C: Xc, S: Xs */
650 mbedtls_mpi xm; /* C: xc, S: xs */
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200651 unsigned char *p = buf;
652 const unsigned char *end = buf + len;
653 size_t ec_len;
654
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200655 mbedtls_ecp_point_init( &G );
656 mbedtls_ecp_point_init( &Xm );
657 mbedtls_mpi_init( &xm );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200658
659 /*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200660 * 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 +0200661 *
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200662 * Client: GA = X1 + X3 + X4 | xs = x2 * s | Xc = xc * GA
663 * Server: GB = X3 + X1 + X2 | xs = x4 * s | Xs = xs * GB
664 * Unified: G = Xm1 + Xp1 + Xp2 | xm = xm2 * s | Xm = xm * G
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200665 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200666 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200667 &ctx->Xp1, &ctx->Xp2, &ctx->Xm1 ) );
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200668 MBEDTLS_MPI_CHK( ecjpake_mul_secret( &xm, 1, &ctx->xm2, &ctx->s,
669 &ctx->grp.N, f_rng, p_rng ) );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200670 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &Xm, &xm, &G, f_rng, p_rng ) );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200671
672 /*
673 * Now write things out
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200674 *
675 * struct {
676 * ECParameters curve_params; // only server writing its message
677 * ECJPAKEKeyKP ecjpake_key_kp;
678 * } Client/ServerECJPAKEParams;
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200679 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200680 if( ctx->role == MBEDTLS_ECJPAKE_SERVER )
681 {
682 if( end < p )
683 {
684 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
685 goto cleanup;
686 }
687 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_group( &ctx->grp, &ec_len,
688 p, end - p ) );
689 p += ec_len;
690 }
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200691
692 if( end < p )
693 {
694 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
695 goto cleanup;
696 }
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200697 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( &ctx->grp, &Xm,
Robert Cragie7cdad772015-10-02 13:31:41 +0100698 ctx->point_format, &ec_len, p, end - p ) );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200699 p += ec_len;
700
701 MBEDTLS_MPI_CHK( ecjpake_zkp_write( ctx->md_info, &ctx->grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100702 ctx->point_format,
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200703 &G, &xm, &Xm, ID_MINE,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200704 &p, end, f_rng, p_rng ) );
705
706 *olen = p - buf;
707
708cleanup:
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200709 mbedtls_ecp_point_free( &G );
710 mbedtls_ecp_point_free( &Xm );
711 mbedtls_mpi_free( &xm );
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +0200712
713 return( ret );
714}
715
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200716/*
717 * Derive PMS (7.4.2.7 / 7.4.2.8)
718 */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +0200719int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200720 unsigned char *buf, size_t len, size_t *olen,
721 int (*f_rng)(void *, unsigned char *, size_t),
722 void *p_rng )
723{
724 int ret;
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200725 mbedtls_ecp_point K;
726 mbedtls_mpi m_xm2_s, one;
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200727 unsigned char kx[MBEDTLS_ECP_MAX_BYTES];
728 size_t x_bytes;
729
730 *olen = mbedtls_md_get_size( ctx->md_info );
731 if( len < *olen )
732 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
733
734 mbedtls_ecp_point_init( &K );
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200735 mbedtls_mpi_init( &m_xm2_s );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200736 mbedtls_mpi_init( &one );
737
738 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200739
740 /*
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200741 * Client: K = ( Xs - X4 * x2 * s ) * x2
742 * Server: K = ( Xc - X2 * x4 * s ) * x4
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200743 * Unified: K = ( Xp - Xp2 * xm2 * s ) * xm2
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200744 */
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200745 MBEDTLS_MPI_CHK( ecjpake_mul_secret( &m_xm2_s, -1, &ctx->xm2, &ctx->s,
746 &ctx->grp.N, f_rng, p_rng ) );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200747 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( &ctx->grp, &K,
748 &one, &ctx->Xp,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200749 &m_xm2_s, &ctx->Xp2 ) );
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200750 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &K, &ctx->xm2, &K,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200751 f_rng, p_rng ) );
752
753 /* PMS = SHA-256( K.X ) */
754 x_bytes = ( ctx->grp.pbits + 7 ) / 8;
755 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &K.X, kx, x_bytes ) );
756 MBEDTLS_MPI_CHK( mbedtls_md( ctx->md_info, kx, x_bytes, buf ) );
757
758cleanup:
759 mbedtls_ecp_point_free( &K );
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200760 mbedtls_mpi_free( &m_xm2_s );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200761 mbedtls_mpi_free( &one );
762
763 return( ret );
764}
765
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200766#undef ID_MINE
767#undef ID_PEER
768
Hanno Becker616d1ca2018-01-24 10:25:05 +0000769#endif /* ! MBEDTLS_ECJPAKE_ALT */
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200770
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200771#if defined(MBEDTLS_SELF_TEST)
772
773#if defined(MBEDTLS_PLATFORM_C)
774#include "mbedtls/platform.h"
775#else
776#include <stdio.h>
777#define mbedtls_printf printf
778#endif
779
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200780#if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
781 !defined(MBEDTLS_SHA256_C)
782int mbedtls_ecjpake_self_test( int verbose )
783{
784 (void) verbose;
785 return( 0 );
786}
787#else
788
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200789static const unsigned char ecjpake_test_password[] = {
790 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x6a, 0x70, 0x61, 0x6b, 0x65, 0x74,
791 0x65, 0x73, 0x74
792};
793
794static const unsigned char ecjpake_test_x1[] = {
795 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
796 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
797 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21
798};
799
800static const unsigned char ecjpake_test_x2[] = {
801 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
802 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
803 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
804};
805
806static const unsigned char ecjpake_test_x3[] = {
807 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
808 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
809 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
810};
811
812static const unsigned char ecjpake_test_x4[] = {
813 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc,
814 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
815 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1
816};
817
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200818static const unsigned char ecjpake_test_cli_one[] = {
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200819 0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19,
820 0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44,
821 0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad,
822 0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62,
823 0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9,
824 0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d,
825 0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e,
826 0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e,
827 0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73,
828 0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22,
829 0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce,
830 0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00,
831 0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200832 0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e,
833 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62,
834 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5,
835 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb,
836 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35,
837 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0,
838 0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb,
839 0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47,
840 0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39,
841 0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97,
842 0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40,
843 0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d,
844 0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa,
845 0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d,
846 0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200847};
848
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200849static const unsigned char ecjpake_test_srv_one[] = {
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200850 0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb,
851 0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18,
852 0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47,
853 0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f,
854 0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7,
855 0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d,
856 0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64,
857 0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36,
858 0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2,
859 0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec,
860 0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16,
861 0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96,
862 0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3,
863 0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19,
864 0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f,
865 0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8,
866 0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7,
867 0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea,
868 0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5,
869 0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6,
870 0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31,
871 0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d,
872 0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8,
873 0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee,
874 0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84,
875 0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f,
876 0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80,
877 0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12
878};
879
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200880static const unsigned char ecjpake_test_srv_two[] = {
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200881 0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23,
882 0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c,
883 0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f,
884 0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca,
885 0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26,
886 0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55,
887 0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38,
888 0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6,
889 0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9,
890 0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4,
891 0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2,
892 0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8,
893 0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd,
894 0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c
895};
896
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200897static const unsigned char ecjpake_test_cli_two[] = {
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +0200898 0x41, 0x04, 0x69, 0xd5, 0x4e, 0xe8, 0x5e, 0x90, 0xce, 0x3f, 0x12, 0x46,
899 0x74, 0x2d, 0xe5, 0x07, 0xe9, 0x39, 0xe8, 0x1d, 0x1d, 0xc1, 0xc5, 0xcb,
900 0x98, 0x8b, 0x58, 0xc3, 0x10, 0xc9, 0xfd, 0xd9, 0x52, 0x4d, 0x93, 0x72,
901 0x0b, 0x45, 0x54, 0x1c, 0x83, 0xee, 0x88, 0x41, 0x19, 0x1d, 0xa7, 0xce,
902 0xd8, 0x6e, 0x33, 0x12, 0xd4, 0x36, 0x23, 0xc1, 0xd6, 0x3e, 0x74, 0x98,
903 0x9a, 0xba, 0x4a, 0xff, 0xd1, 0xee, 0x41, 0x04, 0x07, 0x7e, 0x8c, 0x31,
904 0xe2, 0x0e, 0x6b, 0xed, 0xb7, 0x60, 0xc1, 0x35, 0x93, 0xe6, 0x9f, 0x15,
905 0xbe, 0x85, 0xc2, 0x7d, 0x68, 0xcd, 0x09, 0xcc, 0xb8, 0xc4, 0x18, 0x36,
906 0x08, 0x91, 0x7c, 0x5c, 0x3d, 0x40, 0x9f, 0xac, 0x39, 0xfe, 0xfe, 0xe8,
907 0x2f, 0x72, 0x92, 0xd3, 0x6f, 0x0d, 0x23, 0xe0, 0x55, 0x91, 0x3f, 0x45,
908 0xa5, 0x2b, 0x85, 0xdd, 0x8a, 0x20, 0x52, 0xe9, 0xe1, 0x29, 0xbb, 0x4d,
909 0x20, 0x0f, 0x01, 0x1f, 0x19, 0x48, 0x35, 0x35, 0xa6, 0xe8, 0x9a, 0x58,
910 0x0c, 0x9b, 0x00, 0x03, 0xba, 0xf2, 0x14, 0x62, 0xec, 0xe9, 0x1a, 0x82,
911 0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c
912};
913
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200914static const unsigned char ecjpake_test_pms[] = {
915 0xf3, 0xd4, 0x7f, 0x59, 0x98, 0x44, 0xdb, 0x92, 0xa5, 0x69, 0xbb, 0xe7,
916 0x98, 0x1e, 0x39, 0xd9, 0x31, 0xfd, 0x74, 0x3b, 0xf2, 0x2e, 0x98, 0xf9,
917 0xb4, 0x38, 0xf7, 0x19, 0xd3, 0xc4, 0xf3, 0x51
918};
919
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +0200920/* Load my private keys and generate the correponding public keys */
921static int ecjpake_test_load( mbedtls_ecjpake_context *ctx,
922 const unsigned char *xm1, size_t len1,
923 const unsigned char *xm2, size_t len2 )
924{
925 int ret;
926
927 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm1, xm1, len1 ) );
928 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm2, xm2, len2 ) );
929 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm1, &ctx->xm1,
930 &ctx->grp.G, NULL, NULL ) );
931 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm2, &ctx->xm2,
932 &ctx->grp.G, NULL, NULL ) );
933
934cleanup:
935 return( ret );
936}
937
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200938/* For tests we don't need a secure RNG;
939 * use the LGC from Numerical Recipes for simplicity */
940static int ecjpake_lgc( void *p, unsigned char *out, size_t len )
941{
942 static uint32_t x = 42;
943 (void) p;
944
945 while( len > 0 )
946 {
947 size_t use_len = len > 4 ? 4 : len;
948 x = 1664525 * x + 1013904223;
949 memcpy( out, &x, use_len );
950 out += use_len;
951 len -= use_len;
952 }
953
954 return( 0 );
955}
956
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200957#define TEST_ASSERT( x ) \
958 do { \
959 if( x ) \
960 ret = 0; \
961 else \
962 { \
963 ret = 1; \
964 goto cleanup; \
965 } \
966 } while( 0 )
967
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200968/*
969 * Checkup routine
970 */
971int mbedtls_ecjpake_self_test( int verbose )
972{
973 int ret;
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200974 mbedtls_ecjpake_context cli;
975 mbedtls_ecjpake_context srv;
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200976 unsigned char buf[512], pms[32];
977 size_t len, pmslen;
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200978
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200979 mbedtls_ecjpake_init( &cli );
980 mbedtls_ecjpake_init( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200981
982 if( verbose != 0 )
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200983 mbedtls_printf( " ECJPAKE test #0 (setup): " );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200984
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +0200985 TEST_ASSERT( mbedtls_ecjpake_setup( &cli, MBEDTLS_ECJPAKE_CLIENT,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200986 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
987 ecjpake_test_password,
988 sizeof( ecjpake_test_password ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200989
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +0200990 TEST_ASSERT( mbedtls_ecjpake_setup( &srv, MBEDTLS_ECJPAKE_SERVER,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200991 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
992 ecjpake_test_password,
993 sizeof( ecjpake_test_password ) ) == 0 );
994
995 if( verbose != 0 )
996 mbedtls_printf( "passed\n" );
997
998 if( verbose != 0 )
999 mbedtls_printf( " ECJPAKE test #1 (random handshake): " );
1000
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001001 TEST_ASSERT( mbedtls_ecjpake_write_round_one( &cli,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001002 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1003
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001004 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv, buf, len ) == 0 );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001005
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001006 TEST_ASSERT( mbedtls_ecjpake_write_round_one( &srv,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001007 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1008
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001009 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli, buf, len ) == 0 );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001010
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001011 TEST_ASSERT( mbedtls_ecjpake_write_round_two( &srv,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +02001012 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1013
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001014 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli, buf, len ) == 0 );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +02001015
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001016 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001017 pms, sizeof( pms ), &pmslen, ecjpake_lgc, NULL ) == 0 );
1018
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001019 TEST_ASSERT( mbedtls_ecjpake_write_round_two( &cli,
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +02001020 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1021
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001022 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv, buf, len ) == 0 );
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +02001023
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001024 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001025 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1026
1027 TEST_ASSERT( len == pmslen );
1028 TEST_ASSERT( memcmp( buf, pms, len ) == 0 );
1029
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001030 if( verbose != 0 )
1031 mbedtls_printf( "passed\n" );
1032
1033 if( verbose != 0 )
1034 mbedtls_printf( " ECJPAKE test #2 (reference handshake): " );
1035
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001036 /* Simulate generation of round one */
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001037 MBEDTLS_MPI_CHK( ecjpake_test_load( &cli,
1038 ecjpake_test_x1, sizeof( ecjpake_test_x1 ),
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001039 ecjpake_test_x2, sizeof( ecjpake_test_x2 ) ) );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001040
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001041 MBEDTLS_MPI_CHK( ecjpake_test_load( &srv,
1042 ecjpake_test_x3, sizeof( ecjpake_test_x3 ),
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001043 ecjpake_test_x4, sizeof( ecjpake_test_x4 ) ) );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001044
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001045 /* Read round one */
1046 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv,
1047 ecjpake_test_cli_one,
1048 sizeof( ecjpake_test_cli_one ) ) == 0 );
1049
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001050 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001051 ecjpake_test_srv_one,
1052 sizeof( ecjpake_test_srv_one ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001053
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001054 /* Skip generation of round two, read round two */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001055 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001056 ecjpake_test_srv_two,
1057 sizeof( ecjpake_test_srv_two ) ) == 0 );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +02001058
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001059 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001060 ecjpake_test_cli_two,
1061 sizeof( ecjpake_test_cli_two ) ) == 0 );
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +02001062
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001063 /* Server derives PMS */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001064 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001065 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1066
1067 TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
1068 TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
1069
1070 memset( buf, 0, len ); /* Avoid interferences with next step */
1071
1072 /* Client derives PMS */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001073 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001074 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1075
1076 TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
1077 TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
1078
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001079 if( verbose != 0 )
1080 mbedtls_printf( "passed\n" );
1081
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001082cleanup:
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001083 mbedtls_ecjpake_free( &cli );
1084 mbedtls_ecjpake_free( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001085
1086 if( ret != 0 )
1087 {
1088 if( verbose != 0 )
1089 mbedtls_printf( "failed\n" );
1090
1091 ret = 1;
1092 }
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001093
1094 if( verbose != 0 )
1095 mbedtls_printf( "\n" );
1096
1097 return( ret );
1098}
1099
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +02001100#undef TEST_ASSERT
1101
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001102#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_SHA256_C */
1103
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001104#endif /* MBEDTLS_SELF_TEST */
1105
1106#endif /* MBEDTLS_ECJPAKE_C */