blob: fd54a7d2d5ab5b022218943e5ca3e0f2e3282f45 [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:
171 * 3 EC points plus their length, plus ID (6 bytes)
172 */
173#define ECJPAKE_HASH_BUF_LEN ( 3 * ( 4 + MBEDTLS_ECP_MAX_PT_LEN ) + 6 )
174
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
199 if( end < p || (size_t)( end - p ) < id_len )
200 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
207 memcpy( p, id, id_len );
208 p += id_len;
209
210 /* Compute hash */
211 mbedtls_md( md_info, buf, p - buf, hash );
212
213 /* Turn it into an integer mod n */
214 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( h, hash,
215 mbedtls_md_get_size( md_info ) ) );
216 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( h, h, &grp->N ) );
217
218cleanup:
219 return( ret );
220}
221
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200222/*
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200223 * Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3)
224 */
225static int ecjpake_zkp_read( const mbedtls_md_info_t *md_info,
226 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100227 const int pf,
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200228 const mbedtls_ecp_point *G,
229 const mbedtls_ecp_point *X,
230 const char *id,
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200231 const unsigned char **p,
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200232 const unsigned char *end )
233{
234 int ret;
235 mbedtls_ecp_point V, VV;
236 mbedtls_mpi r, h;
237 size_t r_len;
238
239 mbedtls_ecp_point_init( &V );
240 mbedtls_ecp_point_init( &VV );
241 mbedtls_mpi_init( &r );
242 mbedtls_mpi_init( &h );
243
244 /*
245 * struct {
246 * ECPoint V;
247 * opaque r<1..2^8-1>;
248 * } ECSchnorrZKP;
249 */
250 if( end < *p )
251 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
252
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200253 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, &V, p, end - *p ) );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200254
255 if( end < *p || (size_t)( end - *p ) < 1 )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200256 {
257 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
258 goto cleanup;
259 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200260
261 r_len = *(*p)++;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200262
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200263 if( end < *p || (size_t)( end - *p ) < r_len )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200264 {
265 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
266 goto cleanup;
267 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200268
269 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &r, *p, r_len ) );
270 *p += r_len;
271
272 /*
273 * Verification
274 */
Robert Cragie7cdad772015-10-02 13:31:41 +0100275 MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200276 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( (mbedtls_ecp_group *) grp,
277 &VV, &h, X, &r, G ) );
278
279 if( mbedtls_ecp_point_cmp( &VV, &V ) != 0 )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200280 {
281 ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
282 goto cleanup;
283 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200284
285cleanup:
286 mbedtls_ecp_point_free( &V );
287 mbedtls_ecp_point_free( &VV );
288 mbedtls_mpi_free( &r );
289 mbedtls_mpi_free( &h );
290
291 return( ret );
292}
293
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200294/*
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200295 * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2)
296 */
297static int ecjpake_zkp_write( const mbedtls_md_info_t *md_info,
298 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100299 const int pf,
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200300 const mbedtls_ecp_point *G,
301 const mbedtls_mpi *x,
302 const mbedtls_ecp_point *X,
303 const char *id,
304 unsigned char **p,
305 const unsigned char *end,
306 int (*f_rng)(void *, unsigned char *, size_t),
307 void *p_rng )
308{
309 int ret;
310 mbedtls_ecp_point V;
311 mbedtls_mpi v;
312 mbedtls_mpi h; /* later recycled to hold r */
313 size_t len;
314
315 if( end < *p )
316 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
317
318 mbedtls_ecp_point_init( &V );
319 mbedtls_mpi_init( &v );
320 mbedtls_mpi_init( &h );
321
322 /* Compute signature */
323 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp,
324 G, &v, &V, f_rng, p_rng ) );
Robert Cragie7cdad772015-10-02 13:31:41 +0100325 MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) );
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200326 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &h, &h, x ) ); /* x*h */
327 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &h, &v, &h ) ); /* v - x*h */
328 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &h, &h, &grp->N ) ); /* r */
329
330 /* Write it out */
331 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, &V,
Robert Cragie7cdad772015-10-02 13:31:41 +0100332 pf, &len, *p, end - *p ) );
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200333 *p += len;
334
335 len = mbedtls_mpi_size( &h ); /* actually r */
336 if( end < *p || (size_t)( end - *p ) < 1 + len || len > 255 )
337 {
338 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
339 goto cleanup;
340 }
341
342 *(*p)++ = (unsigned char)( len & 0xFF );
343 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, *p, len ) ); /* r */
344 *p += len;
345
346cleanup:
347 mbedtls_ecp_point_free( &V );
348 mbedtls_mpi_free( &v );
349 mbedtls_mpi_free( &h );
350
351 return( ret );
352}
353
354/*
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200355 * Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof
356 * Output: verified public key X
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200357 */
358static int ecjpake_kkp_read( const mbedtls_md_info_t *md_info,
359 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100360 const int pf,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200361 const mbedtls_ecp_point *G,
362 mbedtls_ecp_point *X,
363 const char *id,
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200364 const unsigned char **p,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200365 const unsigned char *end )
366{
367 int ret;
368
369 if( end < *p )
370 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
371
372 /*
373 * struct {
374 * ECPoint X;
375 * ECSchnorrZKP zkp;
376 * } ECJPAKEKeyKP;
377 */
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200378 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, X, p, end - *p ) );
Manuel Pégourié-Gonnard30590952015-08-17 10:37:40 +0200379 if( mbedtls_ecp_is_zero( X ) )
380 {
381 ret = MBEDTLS_ERR_ECP_INVALID_KEY;
382 goto cleanup;
383 }
384
Robert Cragie7cdad772015-10-02 13:31:41 +0100385 MBEDTLS_MPI_CHK( ecjpake_zkp_read( md_info, grp, pf, G, X, id, p, end ) );
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200386
387cleanup:
388 return( ret );
389}
390
391/*
392 * Generate an ECJPAKEKeyKP
393 * Output: the serialized structure, plus private/public key pair
394 */
395static int ecjpake_kkp_write( const mbedtls_md_info_t *md_info,
396 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100397 const int pf,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200398 const mbedtls_ecp_point *G,
399 mbedtls_mpi *x,
400 mbedtls_ecp_point *X,
401 const char *id,
402 unsigned char **p,
403 const unsigned char *end,
404 int (*f_rng)(void *, unsigned char *, size_t),
405 void *p_rng )
406{
407 int ret;
408 size_t len;
409
410 if( end < *p )
411 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
412
413 /* Generate key (7.4.2.3.1) and write it out */
414 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp, G, x, X,
415 f_rng, p_rng ) );
416 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, X,
Robert Cragie7cdad772015-10-02 13:31:41 +0100417 pf, &len, *p, end - *p ) );
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200418 *p += len;
419
420 /* Generate and write proof */
Robert Cragie7cdad772015-10-02 13:31:41 +0100421 MBEDTLS_MPI_CHK( ecjpake_zkp_write( md_info, grp, pf, G, x, X, id,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200422 p, end, f_rng, p_rng ) );
423
424cleanup:
425 return( ret );
426}
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200427
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200428/*
429 * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs
430 * Ouputs: verified peer public keys Xa, Xb
431 */
432static int ecjpake_kkpp_read( const mbedtls_md_info_t *md_info,
433 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100434 const int pf,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200435 const mbedtls_ecp_point *G,
436 mbedtls_ecp_point *Xa,
437 mbedtls_ecp_point *Xb,
438 const char *id,
439 const unsigned char *buf,
440 size_t len )
441{
442 int ret;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200443 const unsigned char *p = buf;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200444 const unsigned char *end = buf + len;
445
446 /*
447 * struct {
448 * ECJPAKEKeyKP ecjpake_key_kp_pair_list[2];
449 * } ECJPAKEKeyKPPairList;
450 */
Robert Cragie7cdad772015-10-02 13:31:41 +0100451 MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xa, id, &p, end ) );
452 MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xb, id, &p, end ) );
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200453
454 if( p != end )
455 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
456
457cleanup:
458 return( ret );
459}
460
461/*
462 * Generate a ECJPAKEKeyKPPairList
463 * Outputs: the serialized structure, plus two private/public key pairs
464 */
465static int ecjpake_kkpp_write( const mbedtls_md_info_t *md_info,
466 const mbedtls_ecp_group *grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100467 const int pf,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200468 const mbedtls_ecp_point *G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200469 mbedtls_mpi *xm1,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200470 mbedtls_ecp_point *Xa,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200471 mbedtls_mpi *xm2,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200472 mbedtls_ecp_point *Xb,
473 const char *id,
474 unsigned char *buf,
475 size_t len,
476 size_t *olen,
477 int (*f_rng)(void *, unsigned char *, size_t),
478 void *p_rng )
479{
480 int ret;
481 unsigned char *p = buf;
482 const unsigned char *end = buf + len;
483
Robert Cragie7cdad772015-10-02 13:31:41 +0100484 MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm1, Xa, id,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200485 &p, end, f_rng, p_rng ) );
Robert Cragie7cdad772015-10-02 13:31:41 +0100486 MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm2, Xb, id,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200487 &p, end, f_rng, p_rng ) );
488
489 *olen = p - buf;
490
491cleanup:
492 return( ret );
493}
494
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200495/*
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200496 * Read and process the first round message
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200497 */
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200498int mbedtls_ecjpake_read_round_one( mbedtls_ecjpake_context *ctx,
499 const unsigned char *buf,
500 size_t len )
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200501{
Robert Cragie7cdad772015-10-02 13:31:41 +0100502 return( ecjpake_kkpp_read( ctx->md_info, &ctx->grp, ctx->point_format,
503 &ctx->grp.G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200504 &ctx->Xp1, &ctx->Xp2, ID_PEER,
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200505 buf, len ) );
506}
507
508/*
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200509 * Generate and write the first round message
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200510 */
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200511int mbedtls_ecjpake_write_round_one( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200512 unsigned char *buf, size_t len, size_t *olen,
513 int (*f_rng)(void *, unsigned char *, size_t),
514 void *p_rng )
515{
Robert Cragie7cdad772015-10-02 13:31:41 +0100516 return( ecjpake_kkpp_write( ctx->md_info, &ctx->grp, ctx->point_format,
517 &ctx->grp.G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200518 &ctx->xm1, &ctx->Xm1, &ctx->xm2, &ctx->Xm2,
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200519 ID_MINE, buf, len, olen, f_rng, p_rng ) );
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200520}
521
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200522/*
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200523 * Compute the sum of three points R = A + B + C
524 */
525static int ecjpake_ecp_add3( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
526 const mbedtls_ecp_point *A,
527 const mbedtls_ecp_point *B,
528 const mbedtls_ecp_point *C )
529{
530 int ret;
531 mbedtls_mpi one;
532
533 mbedtls_mpi_init( &one );
534
535 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
536 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, A, &one, B ) );
537 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, R, &one, C ) );
538
539cleanup:
540 mbedtls_mpi_free( &one );
541
542 return( ret );
543}
544
545/*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200546 * 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 +0200547 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200548int mbedtls_ecjpake_read_round_two( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200549 const unsigned char *buf,
550 size_t len )
551{
552 int ret;
553 const unsigned char *p = buf;
554 const unsigned char *end = buf + len;
555 mbedtls_ecp_group grp;
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200556 mbedtls_ecp_point G; /* C: GB, S: GA */
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200557
558 mbedtls_ecp_group_init( &grp );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200559 mbedtls_ecp_point_init( &G );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200560
561 /*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200562 * Server: GA = X3 + X4 + X1 (7.4.2.6.1)
563 * Client: GB = X1 + X2 + X3 (7.4.2.5.1)
564 * Unified: G = Xm1 + Xm2 + Xp1
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200565 * We need that before parsing in order to check Xp as we read it
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200566 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200567 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200568 &ctx->Xm1, &ctx->Xm2, &ctx->Xp1 ) );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200569
570 /*
571 * struct {
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200572 * ECParameters curve_params; // only client reading server msg
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200573 * ECJPAKEKeyKP ecjpake_key_kp;
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200574 * } Client/ServerECJPAKEParams;
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200575 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200576 if( ctx->role == MBEDTLS_ECJPAKE_CLIENT )
Manuel Pégourié-Gonnardd9802af2015-08-17 12:47:38 +0200577 {
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200578 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_group( &grp, &p, len ) );
Manuel Pégourié-Gonnardd9802af2015-08-17 12:47:38 +0200579 if( grp.id != ctx->grp.id )
580 {
581 ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
582 goto cleanup;
583 }
584 }
585
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200586 MBEDTLS_MPI_CHK( ecjpake_kkp_read( ctx->md_info, &ctx->grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100587 ctx->point_format,
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200588 &G, &ctx->Xp, ID_PEER, &p, end ) );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200589
590 if( p != end )
591 {
592 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
593 goto cleanup;
594 }
595
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200596cleanup:
597 mbedtls_ecp_group_free( &grp );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200598 mbedtls_ecp_point_free( &G );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200599
600 return( ret );
601}
602
603/*
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200604 * Compute R = +/- X * S mod N, taking care not to leak S
605 */
606static int ecjpake_mul_secret( mbedtls_mpi *R, int sign,
607 const mbedtls_mpi *X,
608 const mbedtls_mpi *S,
609 const mbedtls_mpi *N,
610 int (*f_rng)(void *, unsigned char *, size_t),
611 void *p_rng )
612{
613 int ret;
614 mbedtls_mpi b; /* Blinding value, then s + N * blinding */
615
616 mbedtls_mpi_init( &b );
617
618 /* b = s + rnd-128-bit * N */
619 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &b, 16, f_rng, p_rng ) );
620 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &b, &b, N ) );
621 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &b, &b, S ) );
622
623 /* R = sign * X * b mod N */
624 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( R, X, &b ) );
625 R->s *= sign;
626 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( R, R, N ) );
627
628cleanup:
629 mbedtls_mpi_free( &b );
630
631 return( ret );
632}
633
634/*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200635 * 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 +0200636 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200637int mbedtls_ecjpake_write_round_two( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200638 unsigned char *buf, size_t len, size_t *olen,
639 int (*f_rng)(void *, unsigned char *, size_t),
640 void *p_rng )
641{
642 int ret;
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200643 mbedtls_ecp_point G; /* C: GA, S: GB */
644 mbedtls_ecp_point Xm; /* C: Xc, S: Xs */
645 mbedtls_mpi xm; /* C: xc, S: xs */
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200646 unsigned char *p = buf;
647 const unsigned char *end = buf + len;
648 size_t ec_len;
649
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200650 mbedtls_ecp_point_init( &G );
651 mbedtls_ecp_point_init( &Xm );
652 mbedtls_mpi_init( &xm );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200653
654 /*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200655 * 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 +0200656 *
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200657 * Client: GA = X1 + X3 + X4 | xs = x2 * s | Xc = xc * GA
658 * Server: GB = X3 + X1 + X2 | xs = x4 * s | Xs = xs * GB
659 * Unified: G = Xm1 + Xp1 + Xp2 | xm = xm2 * s | Xm = xm * G
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200660 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200661 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200662 &ctx->Xp1, &ctx->Xp2, &ctx->Xm1 ) );
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200663 MBEDTLS_MPI_CHK( ecjpake_mul_secret( &xm, 1, &ctx->xm2, &ctx->s,
664 &ctx->grp.N, f_rng, p_rng ) );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200665 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &Xm, &xm, &G, f_rng, p_rng ) );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200666
667 /*
668 * Now write things out
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200669 *
670 * struct {
671 * ECParameters curve_params; // only server writing its message
672 * ECJPAKEKeyKP ecjpake_key_kp;
673 * } Client/ServerECJPAKEParams;
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200674 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200675 if( ctx->role == MBEDTLS_ECJPAKE_SERVER )
676 {
677 if( end < p )
678 {
679 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
680 goto cleanup;
681 }
682 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_group( &ctx->grp, &ec_len,
683 p, end - p ) );
684 p += ec_len;
685 }
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200686
687 if( end < p )
688 {
689 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
690 goto cleanup;
691 }
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200692 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( &ctx->grp, &Xm,
Robert Cragie7cdad772015-10-02 13:31:41 +0100693 ctx->point_format, &ec_len, p, end - p ) );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200694 p += ec_len;
695
696 MBEDTLS_MPI_CHK( ecjpake_zkp_write( ctx->md_info, &ctx->grp,
Robert Cragie7cdad772015-10-02 13:31:41 +0100697 ctx->point_format,
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200698 &G, &xm, &Xm, ID_MINE,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200699 &p, end, f_rng, p_rng ) );
700
701 *olen = p - buf;
702
703cleanup:
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200704 mbedtls_ecp_point_free( &G );
705 mbedtls_ecp_point_free( &Xm );
706 mbedtls_mpi_free( &xm );
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +0200707
708 return( ret );
709}
710
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200711/*
712 * Derive PMS (7.4.2.7 / 7.4.2.8)
713 */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +0200714int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200715 unsigned char *buf, size_t len, size_t *olen,
716 int (*f_rng)(void *, unsigned char *, size_t),
717 void *p_rng )
718{
719 int ret;
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200720 mbedtls_ecp_point K;
721 mbedtls_mpi m_xm2_s, one;
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200722 unsigned char kx[MBEDTLS_ECP_MAX_BYTES];
723 size_t x_bytes;
724
725 *olen = mbedtls_md_get_size( ctx->md_info );
726 if( len < *olen )
727 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
728
729 mbedtls_ecp_point_init( &K );
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200730 mbedtls_mpi_init( &m_xm2_s );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200731 mbedtls_mpi_init( &one );
732
733 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200734
735 /*
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200736 * Client: K = ( Xs - X4 * x2 * s ) * x2
737 * Server: K = ( Xc - X2 * x4 * s ) * x4
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200738 * Unified: K = ( Xp - Xp2 * xm2 * s ) * xm2
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200739 */
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200740 MBEDTLS_MPI_CHK( ecjpake_mul_secret( &m_xm2_s, -1, &ctx->xm2, &ctx->s,
741 &ctx->grp.N, f_rng, p_rng ) );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200742 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( &ctx->grp, &K,
743 &one, &ctx->Xp,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200744 &m_xm2_s, &ctx->Xp2 ) );
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200745 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &K, &ctx->xm2, &K,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200746 f_rng, p_rng ) );
747
748 /* PMS = SHA-256( K.X ) */
749 x_bytes = ( ctx->grp.pbits + 7 ) / 8;
750 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &K.X, kx, x_bytes ) );
751 MBEDTLS_MPI_CHK( mbedtls_md( ctx->md_info, kx, x_bytes, buf ) );
752
753cleanup:
754 mbedtls_ecp_point_free( &K );
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200755 mbedtls_mpi_free( &m_xm2_s );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200756 mbedtls_mpi_free( &one );
757
758 return( ret );
759}
760
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200761#undef ID_MINE
762#undef ID_PEER
763
764
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200765#if defined(MBEDTLS_SELF_TEST)
766
767#if defined(MBEDTLS_PLATFORM_C)
768#include "mbedtls/platform.h"
769#else
770#include <stdio.h>
771#define mbedtls_printf printf
772#endif
773
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200774#if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
775 !defined(MBEDTLS_SHA256_C)
776int mbedtls_ecjpake_self_test( int verbose )
777{
778 (void) verbose;
779 return( 0 );
780}
781#else
782
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200783static const unsigned char ecjpake_test_password[] = {
784 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x6a, 0x70, 0x61, 0x6b, 0x65, 0x74,
785 0x65, 0x73, 0x74
786};
787
788static const unsigned char ecjpake_test_x1[] = {
789 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
790 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
791 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21
792};
793
794static const unsigned char ecjpake_test_x2[] = {
795 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
796 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
797 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
798};
799
800static const unsigned char ecjpake_test_x3[] = {
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_x4[] = {
807 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc,
808 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
809 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1
810};
811
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200812static const unsigned char ecjpake_test_cli_one[] = {
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200813 0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19,
814 0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44,
815 0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad,
816 0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62,
817 0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9,
818 0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d,
819 0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e,
820 0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e,
821 0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73,
822 0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22,
823 0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce,
824 0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00,
825 0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200826 0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e,
827 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62,
828 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5,
829 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb,
830 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35,
831 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0,
832 0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb,
833 0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47,
834 0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39,
835 0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97,
836 0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40,
837 0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d,
838 0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa,
839 0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d,
840 0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200841};
842
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200843static const unsigned char ecjpake_test_srv_one[] = {
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200844 0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb,
845 0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18,
846 0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47,
847 0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f,
848 0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7,
849 0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d,
850 0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64,
851 0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36,
852 0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2,
853 0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec,
854 0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16,
855 0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96,
856 0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3,
857 0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19,
858 0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f,
859 0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8,
860 0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7,
861 0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea,
862 0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5,
863 0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6,
864 0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31,
865 0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d,
866 0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8,
867 0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee,
868 0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84,
869 0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f,
870 0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80,
871 0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12
872};
873
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200874static const unsigned char ecjpake_test_srv_two[] = {
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200875 0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23,
876 0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c,
877 0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f,
878 0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca,
879 0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26,
880 0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55,
881 0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38,
882 0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6,
883 0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9,
884 0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4,
885 0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2,
886 0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8,
887 0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd,
888 0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c
889};
890
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200891static const unsigned char ecjpake_test_cli_two[] = {
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +0200892 0x41, 0x04, 0x69, 0xd5, 0x4e, 0xe8, 0x5e, 0x90, 0xce, 0x3f, 0x12, 0x46,
893 0x74, 0x2d, 0xe5, 0x07, 0xe9, 0x39, 0xe8, 0x1d, 0x1d, 0xc1, 0xc5, 0xcb,
894 0x98, 0x8b, 0x58, 0xc3, 0x10, 0xc9, 0xfd, 0xd9, 0x52, 0x4d, 0x93, 0x72,
895 0x0b, 0x45, 0x54, 0x1c, 0x83, 0xee, 0x88, 0x41, 0x19, 0x1d, 0xa7, 0xce,
896 0xd8, 0x6e, 0x33, 0x12, 0xd4, 0x36, 0x23, 0xc1, 0xd6, 0x3e, 0x74, 0x98,
897 0x9a, 0xba, 0x4a, 0xff, 0xd1, 0xee, 0x41, 0x04, 0x07, 0x7e, 0x8c, 0x31,
898 0xe2, 0x0e, 0x6b, 0xed, 0xb7, 0x60, 0xc1, 0x35, 0x93, 0xe6, 0x9f, 0x15,
899 0xbe, 0x85, 0xc2, 0x7d, 0x68, 0xcd, 0x09, 0xcc, 0xb8, 0xc4, 0x18, 0x36,
900 0x08, 0x91, 0x7c, 0x5c, 0x3d, 0x40, 0x9f, 0xac, 0x39, 0xfe, 0xfe, 0xe8,
901 0x2f, 0x72, 0x92, 0xd3, 0x6f, 0x0d, 0x23, 0xe0, 0x55, 0x91, 0x3f, 0x45,
902 0xa5, 0x2b, 0x85, 0xdd, 0x8a, 0x20, 0x52, 0xe9, 0xe1, 0x29, 0xbb, 0x4d,
903 0x20, 0x0f, 0x01, 0x1f, 0x19, 0x48, 0x35, 0x35, 0xa6, 0xe8, 0x9a, 0x58,
904 0x0c, 0x9b, 0x00, 0x03, 0xba, 0xf2, 0x14, 0x62, 0xec, 0xe9, 0x1a, 0x82,
905 0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c
906};
907
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200908static const unsigned char ecjpake_test_pms[] = {
909 0xf3, 0xd4, 0x7f, 0x59, 0x98, 0x44, 0xdb, 0x92, 0xa5, 0x69, 0xbb, 0xe7,
910 0x98, 0x1e, 0x39, 0xd9, 0x31, 0xfd, 0x74, 0x3b, 0xf2, 0x2e, 0x98, 0xf9,
911 0xb4, 0x38, 0xf7, 0x19, 0xd3, 0xc4, 0xf3, 0x51
912};
913
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +0200914/* Load my private keys and generate the correponding public keys */
915static int ecjpake_test_load( mbedtls_ecjpake_context *ctx,
916 const unsigned char *xm1, size_t len1,
917 const unsigned char *xm2, size_t len2 )
918{
919 int ret;
920
921 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm1, xm1, len1 ) );
922 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm2, xm2, len2 ) );
923 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm1, &ctx->xm1,
924 &ctx->grp.G, NULL, NULL ) );
925 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm2, &ctx->xm2,
926 &ctx->grp.G, NULL, NULL ) );
927
928cleanup:
929 return( ret );
930}
931
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200932/* For tests we don't need a secure RNG;
933 * use the LGC from Numerical Recipes for simplicity */
934static int ecjpake_lgc( void *p, unsigned char *out, size_t len )
935{
936 static uint32_t x = 42;
937 (void) p;
938
939 while( len > 0 )
940 {
941 size_t use_len = len > 4 ? 4 : len;
942 x = 1664525 * x + 1013904223;
943 memcpy( out, &x, use_len );
944 out += use_len;
945 len -= use_len;
946 }
947
948 return( 0 );
949}
950
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200951#define TEST_ASSERT( x ) \
952 do { \
953 if( x ) \
954 ret = 0; \
955 else \
956 { \
957 ret = 1; \
958 goto cleanup; \
959 } \
960 } while( 0 )
961
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200962/*
963 * Checkup routine
964 */
965int mbedtls_ecjpake_self_test( int verbose )
966{
967 int ret;
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200968 mbedtls_ecjpake_context cli;
969 mbedtls_ecjpake_context srv;
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200970 unsigned char buf[512], pms[32];
971 size_t len, pmslen;
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200972
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200973 mbedtls_ecjpake_init( &cli );
974 mbedtls_ecjpake_init( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200975
976 if( verbose != 0 )
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200977 mbedtls_printf( " ECJPAKE test #0 (setup): " );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200978
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +0200979 TEST_ASSERT( mbedtls_ecjpake_setup( &cli, MBEDTLS_ECJPAKE_CLIENT,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200980 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
981 ecjpake_test_password,
982 sizeof( ecjpake_test_password ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200983
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +0200984 TEST_ASSERT( mbedtls_ecjpake_setup( &srv, MBEDTLS_ECJPAKE_SERVER,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200985 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
986 ecjpake_test_password,
987 sizeof( ecjpake_test_password ) ) == 0 );
988
989 if( verbose != 0 )
990 mbedtls_printf( "passed\n" );
991
992 if( verbose != 0 )
993 mbedtls_printf( " ECJPAKE test #1 (random handshake): " );
994
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200995 TEST_ASSERT( mbedtls_ecjpake_write_round_one( &cli,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200996 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
997
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200998 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv, buf, len ) == 0 );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200999
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001000 TEST_ASSERT( mbedtls_ecjpake_write_round_one( &srv,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001001 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1002
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001003 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli, buf, len ) == 0 );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001004
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001005 TEST_ASSERT( mbedtls_ecjpake_write_round_two( &srv,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +02001006 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1007
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001008 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli, buf, len ) == 0 );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +02001009
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001010 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001011 pms, sizeof( pms ), &pmslen, ecjpake_lgc, NULL ) == 0 );
1012
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001013 TEST_ASSERT( mbedtls_ecjpake_write_round_two( &cli,
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +02001014 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1015
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001016 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv, buf, len ) == 0 );
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +02001017
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001018 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001019 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1020
1021 TEST_ASSERT( len == pmslen );
1022 TEST_ASSERT( memcmp( buf, pms, len ) == 0 );
1023
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001024 if( verbose != 0 )
1025 mbedtls_printf( "passed\n" );
1026
1027 if( verbose != 0 )
1028 mbedtls_printf( " ECJPAKE test #2 (reference handshake): " );
1029
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001030 /* Simulate generation of round one */
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001031 MBEDTLS_MPI_CHK( ecjpake_test_load( &cli,
1032 ecjpake_test_x1, sizeof( ecjpake_test_x1 ),
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001033 ecjpake_test_x2, sizeof( ecjpake_test_x2 ) ) );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001034
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001035 MBEDTLS_MPI_CHK( ecjpake_test_load( &srv,
1036 ecjpake_test_x3, sizeof( ecjpake_test_x3 ),
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001037 ecjpake_test_x4, sizeof( ecjpake_test_x4 ) ) );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001038
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001039 /* Read round one */
1040 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv,
1041 ecjpake_test_cli_one,
1042 sizeof( ecjpake_test_cli_one ) ) == 0 );
1043
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001044 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001045 ecjpake_test_srv_one,
1046 sizeof( ecjpake_test_srv_one ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001047
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001048 /* Skip generation of round two, read round two */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001049 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001050 ecjpake_test_srv_two,
1051 sizeof( ecjpake_test_srv_two ) ) == 0 );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +02001052
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +02001053 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001054 ecjpake_test_cli_two,
1055 sizeof( ecjpake_test_cli_two ) ) == 0 );
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +02001056
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001057 /* Server derives PMS */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001058 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001059 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1060
1061 TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
1062 TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
1063
1064 memset( buf, 0, len ); /* Avoid interferences with next step */
1065
1066 /* Client derives PMS */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001067 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001068 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1069
1070 TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
1071 TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
1072
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001073 if( verbose != 0 )
1074 mbedtls_printf( "passed\n" );
1075
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001076cleanup:
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001077 mbedtls_ecjpake_free( &cli );
1078 mbedtls_ecjpake_free( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001079
1080 if( ret != 0 )
1081 {
1082 if( verbose != 0 )
1083 mbedtls_printf( "failed\n" );
1084
1085 ret = 1;
1086 }
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001087
1088 if( verbose != 0 )
1089 mbedtls_printf( "\n" );
1090
1091 return( ret );
1092}
1093
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +02001094#undef TEST_ASSERT
1095
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001096#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_SHA256_C */
1097
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001098#endif /* MBEDTLS_SELF_TEST */
1099
1100#endif /* MBEDTLS_ECJPAKE_C */