blob: 651d3e73b0c250467375bcb99748adc184ca19b4 [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é-Gonnard8489f172015-08-07 17:47:39 +020023 * We implement EC-JPAKE as defined in Chapter 7.4 of the Thread v1.0
24 * Specification. References below are to this document.
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é-Gonnard7af8bc12015-08-12 16:58:50 +020040 * Initialize context
41 */
42void mbedtls_ecjpake_init( mbedtls_ecjpake_context *ctx )
43{
44 if( ctx == NULL )
45 return;
46
47 ctx->md_info = NULL;
48 mbedtls_ecp_group_init( &ctx->grp );
49
50 mbedtls_ecp_point_init( &ctx->X1 );
51 mbedtls_ecp_point_init( &ctx->X2 );
52 mbedtls_ecp_point_init( &ctx->X3 );
53 mbedtls_ecp_point_init( &ctx->X4 );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +020054 mbedtls_ecp_point_init( &ctx->Xp );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020055
56 mbedtls_mpi_init( &ctx->xa );
57 mbedtls_mpi_init( &ctx->xb );
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +020058 mbedtls_mpi_init( &ctx->s );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020059}
60
61/*
62 * Free context
63 */
64void mbedtls_ecjpake_free( mbedtls_ecjpake_context *ctx )
65{
66 if( ctx == NULL )
67 return;
68
69 ctx->md_info = NULL;
70 mbedtls_ecp_group_free( &ctx->grp );
71
72 mbedtls_ecp_point_free( &ctx->X1 );
73 mbedtls_ecp_point_free( &ctx->X2 );
74 mbedtls_ecp_point_free( &ctx->X3 );
75 mbedtls_ecp_point_free( &ctx->X4 );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +020076 mbedtls_ecp_point_free( &ctx->Xp );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020077
78 mbedtls_mpi_free( &ctx->xa );
79 mbedtls_mpi_free( &ctx->xb );
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +020080 mbedtls_mpi_free( &ctx->s );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020081}
82
83/*
84 * Setup context
85 */
86int mbedtls_ecjpake_setup( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +020087 mbedtls_ecjpake_role role,
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020088 mbedtls_md_type_t hash,
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +020089 mbedtls_ecp_group_id curve,
90 const unsigned char *secret,
91 size_t len )
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020092{
93 int ret;
94
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +020095 ctx->role = role;
96
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020097 if( ( ctx->md_info = mbedtls_md_info_from_type( hash ) ) == NULL )
98 return( MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE );
99
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200100 MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ctx->grp, curve ) );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200101
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200102 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->s, secret, len ) );
103 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->s, &ctx->s, &ctx->grp.N ) );
104
105cleanup:
106 if( ret != 0 )
107 mbedtls_ecjpake_free( ctx );
108
109 return( ret );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200110}
111
112/*
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200113 * Write a point plus its length to a buffer
114 */
115static int ecjpake_write_len_point( unsigned char **p,
116 const unsigned char *end,
117 const mbedtls_ecp_group *grp,
118 const mbedtls_ecp_point *P )
119{
120 int ret;
121 size_t len;
122
123 /* Need at least 4 for length plus 1 for point */
124 if( end < *p || end - *p < 5 )
125 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
126
127 ret = mbedtls_ecp_point_write_binary( grp, P, MBEDTLS_ECP_PF_UNCOMPRESSED,
128 &len, *p + 4, end - ( *p + 4 ) );
129 if( ret != 0 )
130 return( ret );
131
132 (*p)[0] = (unsigned char)( ( len >> 24 ) & 0xFF );
133 (*p)[1] = (unsigned char)( ( len >> 16 ) & 0xFF );
134 (*p)[2] = (unsigned char)( ( len >> 8 ) & 0xFF );
135 (*p)[3] = (unsigned char)( ( len ) & 0xFF );
136
137 *p += 4 + len;
138
139 return( 0 );
140}
141
142/*
143 * Size of the temporary buffer for ecjpake_hash:
144 * 3 EC points plus their length, plus ID (6 bytes)
145 */
146#define ECJPAKE_HASH_BUF_LEN ( 3 * ( 4 + MBEDTLS_ECP_MAX_PT_LEN ) + 6 )
147
148/*
149 * Compute hash for ZKP (7.4.2.2.2.1)
150 */
151static int ecjpake_hash( const mbedtls_md_info_t *md_info,
152 const mbedtls_ecp_group *grp,
153 const mbedtls_ecp_point *G,
154 const mbedtls_ecp_point *V,
155 const mbedtls_ecp_point *X,
156 const char *id,
157 mbedtls_mpi *h )
158{
159 int ret;
160 unsigned char buf[ECJPAKE_HASH_BUF_LEN];
161 unsigned char *p = buf;
162 const unsigned char *end = buf + sizeof( buf );
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200163 const size_t id_len = strlen( id );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200164 unsigned char hash[MBEDTLS_MD_MAX_SIZE];
165
166 /* Write things to temporary buffer */
167 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, G ) );
168 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, V ) );
169 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, X ) );
170
171 if( end < p || (size_t)( end - p ) < id_len )
172 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
173
174 *p++ = (unsigned char)( ( id_len >> 24 ) & 0xFF );
175 *p++ = (unsigned char)( ( id_len >> 16 ) & 0xFF );
176 *p++ = (unsigned char)( ( id_len >> 8 ) & 0xFF );
177 *p++ = (unsigned char)( ( id_len ) & 0xFF );
178
179 memcpy( p, id, id_len );
180 p += id_len;
181
182 /* Compute hash */
183 mbedtls_md( md_info, buf, p - buf, hash );
184
185 /* Turn it into an integer mod n */
186 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( h, hash,
187 mbedtls_md_get_size( md_info ) ) );
188 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( h, h, &grp->N ) );
189
190cleanup:
191 return( ret );
192}
193
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200194/*
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200195 * Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3)
196 */
197static int ecjpake_zkp_read( const mbedtls_md_info_t *md_info,
198 const mbedtls_ecp_group *grp,
199 const mbedtls_ecp_point *G,
200 const mbedtls_ecp_point *X,
201 const char *id,
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200202 const unsigned char **p,
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200203 const unsigned char *end )
204{
205 int ret;
206 mbedtls_ecp_point V, VV;
207 mbedtls_mpi r, h;
208 size_t r_len;
209
210 mbedtls_ecp_point_init( &V );
211 mbedtls_ecp_point_init( &VV );
212 mbedtls_mpi_init( &r );
213 mbedtls_mpi_init( &h );
214
215 /*
216 * struct {
217 * ECPoint V;
218 * opaque r<1..2^8-1>;
219 * } ECSchnorrZKP;
220 */
221 if( end < *p )
222 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
223
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200224 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, &V, p, end - *p ) );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200225
226 if( end < *p || (size_t)( end - *p ) < 1 )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200227 {
228 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
229 goto cleanup;
230 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200231
232 r_len = *(*p)++;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200233
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200234 if( end < *p || (size_t)( end - *p ) < r_len )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200235 {
236 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
237 goto cleanup;
238 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200239
240 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &r, *p, r_len ) );
241 *p += r_len;
242
243 /*
244 * Verification
245 */
246 MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, G, &V, X, id, &h ) );
247 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( (mbedtls_ecp_group *) grp,
248 &VV, &h, X, &r, G ) );
249
250 if( mbedtls_ecp_point_cmp( &VV, &V ) != 0 )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200251 {
252 ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
253 goto cleanup;
254 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200255
256cleanup:
257 mbedtls_ecp_point_free( &V );
258 mbedtls_ecp_point_free( &VV );
259 mbedtls_mpi_free( &r );
260 mbedtls_mpi_free( &h );
261
262 return( ret );
263}
264
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200265/*
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200266 * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2)
267 */
268static int ecjpake_zkp_write( const mbedtls_md_info_t *md_info,
269 const mbedtls_ecp_group *grp,
270 const mbedtls_ecp_point *G,
271 const mbedtls_mpi *x,
272 const mbedtls_ecp_point *X,
273 const char *id,
274 unsigned char **p,
275 const unsigned char *end,
276 int (*f_rng)(void *, unsigned char *, size_t),
277 void *p_rng )
278{
279 int ret;
280 mbedtls_ecp_point V;
281 mbedtls_mpi v;
282 mbedtls_mpi h; /* later recycled to hold r */
283 size_t len;
284
285 if( end < *p )
286 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
287
288 mbedtls_ecp_point_init( &V );
289 mbedtls_mpi_init( &v );
290 mbedtls_mpi_init( &h );
291
292 /* Compute signature */
293 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp,
294 G, &v, &V, f_rng, p_rng ) );
295 MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, G, &V, X, id, &h ) );
296 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &h, &h, x ) ); /* x*h */
297 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &h, &v, &h ) ); /* v - x*h */
298 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &h, &h, &grp->N ) ); /* r */
299
300 /* Write it out */
301 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, &V,
302 MBEDTLS_ECP_PF_UNCOMPRESSED, &len, *p, end - *p ) );
303 *p += len;
304
305 len = mbedtls_mpi_size( &h ); /* actually r */
306 if( end < *p || (size_t)( end - *p ) < 1 + len || len > 255 )
307 {
308 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
309 goto cleanup;
310 }
311
312 *(*p)++ = (unsigned char)( len & 0xFF );
313 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, *p, len ) ); /* r */
314 *p += len;
315
316cleanup:
317 mbedtls_ecp_point_free( &V );
318 mbedtls_mpi_free( &v );
319 mbedtls_mpi_free( &h );
320
321 return( ret );
322}
323
324/*
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200325 * Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof
326 * Output: verified public key X
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200327 */
328static int ecjpake_kkp_read( const mbedtls_md_info_t *md_info,
329 const mbedtls_ecp_group *grp,
330 const mbedtls_ecp_point *G,
331 mbedtls_ecp_point *X,
332 const char *id,
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200333 const unsigned char **p,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200334 const unsigned char *end )
335{
336 int ret;
337
338 if( end < *p )
339 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
340
341 /*
342 * struct {
343 * ECPoint X;
344 * ECSchnorrZKP zkp;
345 * } ECJPAKEKeyKP;
346 */
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200347 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, X, p, end - *p ) );
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200348 MBEDTLS_MPI_CHK( ecjpake_zkp_read( md_info, grp, G, X, id, p, end ) );
349
350cleanup:
351 return( ret );
352}
353
354/*
355 * Generate an ECJPAKEKeyKP
356 * Output: the serialized structure, plus private/public key pair
357 */
358static int ecjpake_kkp_write( const mbedtls_md_info_t *md_info,
359 const mbedtls_ecp_group *grp,
360 const mbedtls_ecp_point *G,
361 mbedtls_mpi *x,
362 mbedtls_ecp_point *X,
363 const char *id,
364 unsigned char **p,
365 const unsigned char *end,
366 int (*f_rng)(void *, unsigned char *, size_t),
367 void *p_rng )
368{
369 int ret;
370 size_t len;
371
372 if( end < *p )
373 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
374
375 /* Generate key (7.4.2.3.1) and write it out */
376 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp, G, x, X,
377 f_rng, p_rng ) );
378 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, X,
379 MBEDTLS_ECP_PF_UNCOMPRESSED, &len, *p, end - *p ) );
380 *p += len;
381
382 /* Generate and write proof */
383 MBEDTLS_MPI_CHK( ecjpake_zkp_write( md_info, grp, G, x, X, id,
384 p, end, f_rng, p_rng ) );
385
386cleanup:
387 return( ret );
388}
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200389
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200390/*
391 * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs
392 * Ouputs: verified peer public keys Xa, Xb
393 */
394static int ecjpake_kkpp_read( const mbedtls_md_info_t *md_info,
395 const mbedtls_ecp_group *grp,
396 const mbedtls_ecp_point *G,
397 mbedtls_ecp_point *Xa,
398 mbedtls_ecp_point *Xb,
399 const char *id,
400 const unsigned char *buf,
401 size_t len )
402{
403 int ret;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200404 const unsigned char *p = buf;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200405 const unsigned char *end = buf + len;
406
407 /*
408 * struct {
409 * ECJPAKEKeyKP ecjpake_key_kp_pair_list[2];
410 * } ECJPAKEKeyKPPairList;
411 */
412 MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, G, Xa, id, &p, end ) );
413 MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, G, Xb, id, &p, end ) );
414
415 if( p != end )
416 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
417
418cleanup:
419 return( ret );
420}
421
422/*
423 * Generate a ECJPAKEKeyKPPairList
424 * Outputs: the serialized structure, plus two private/public key pairs
425 */
426static int ecjpake_kkpp_write( const mbedtls_md_info_t *md_info,
427 const mbedtls_ecp_group *grp,
428 const mbedtls_ecp_point *G,
429 mbedtls_mpi *xa,
430 mbedtls_ecp_point *Xa,
431 mbedtls_mpi *xb,
432 mbedtls_ecp_point *Xb,
433 const char *id,
434 unsigned char *buf,
435 size_t len,
436 size_t *olen,
437 int (*f_rng)(void *, unsigned char *, size_t),
438 void *p_rng )
439{
440 int ret;
441 unsigned char *p = buf;
442 const unsigned char *end = buf + len;
443
444 MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, G, xa, Xa, id,
445 &p, end, f_rng, p_rng ) );
446 MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, G, xb, Xb, id,
447 &p, end, f_rng, p_rng ) );
448
449 *olen = p - buf;
450
451cleanup:
452 return( ret );
453}
454
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200455/*
456 * Read the contents of the ClientHello extension
457 */
458int mbedtls_ecjpake_tls_read_client_ext( mbedtls_ecjpake_context *ctx,
459 const unsigned char *buf,
460 size_t len )
461{
462 return( ecjpake_kkpp_read( ctx->md_info, &ctx->grp, &ctx->grp.G,
463 &ctx->X1, &ctx->X2, "client",
464 buf, len ) );
465}
466
467/*
468 * Read the contents of the ServerHello extension
469 */
470int mbedtls_ecjpake_tls_read_server_ext( mbedtls_ecjpake_context *ctx,
471 const unsigned char *buf,
472 size_t len )
473{
474 return( ecjpake_kkpp_read( ctx->md_info, &ctx->grp, &ctx->grp.G,
475 &ctx->X3, &ctx->X4, "server",
476 buf, len ) );
477}
478
479/*
480 * Generate the contents of the ClientHello extension
481 */
482int mbedtls_ecjpake_tls_write_client_ext( mbedtls_ecjpake_context *ctx,
483 unsigned char *buf, size_t len, size_t *olen,
484 int (*f_rng)(void *, unsigned char *, size_t),
485 void *p_rng )
486{
487 return( ecjpake_kkpp_write( ctx->md_info, &ctx->grp, &ctx->grp.G,
488 &ctx->xa, &ctx->X1, &ctx->xb, &ctx->X2,
489 "client", buf, len, olen, f_rng, p_rng ) );
490}
491
492/*
493 * Generate the contents of the ServerHello extension
494 */
495int mbedtls_ecjpake_tls_write_server_ext( mbedtls_ecjpake_context *ctx,
496 unsigned char *buf, size_t len, size_t *olen,
497 int (*f_rng)(void *, unsigned char *, size_t),
498 void *p_rng )
499{
500 return( ecjpake_kkpp_write( ctx->md_info, &ctx->grp, &ctx->grp.G,
501 &ctx->xa, &ctx->X3, &ctx->xb, &ctx->X4,
502 "server", buf, len, olen, f_rng, p_rng ) );
503}
504
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200505/*
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200506 * Compute the sum of three points R = A + B + C
507 */
508static int ecjpake_ecp_add3( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
509 const mbedtls_ecp_point *A,
510 const mbedtls_ecp_point *B,
511 const mbedtls_ecp_point *C )
512{
513 int ret;
514 mbedtls_mpi one;
515
516 mbedtls_mpi_init( &one );
517
518 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
519 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, A, &one, B ) );
520 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, R, &one, C ) );
521
522cleanup:
523 mbedtls_mpi_free( &one );
524
525 return( ret );
526}
527
528/*
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200529 * Read and process ServerECJPAKEParams (7.4.2.5)
530 */
531int mbedtls_ecjpake_tls_read_server_params( mbedtls_ecjpake_context *ctx,
532 const unsigned char *buf,
533 size_t len )
534{
535 int ret;
536 const unsigned char *p = buf;
537 const unsigned char *end = buf + len;
538 mbedtls_ecp_group grp;
539 mbedtls_ecp_point GB;
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200540
541 mbedtls_ecp_group_init( &grp );
542 mbedtls_ecp_point_init( &GB );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200543
544 /*
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200545 * GB = X1 + X2 + X3 (7.4.2.5.1)
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200546 * We need that before parsing in order to check Xs as we read it
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200547 */
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200548 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &GB,
549 &ctx->X1, &ctx->X2, &ctx->X3 ) );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200550
551 /*
552 * struct {
553 * ECParameters curve_params;
554 * ECJPAKEKeyKP ecjpake_key_kp;
555 * } ServerECJPAKEParams;
556 */
557 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_group( &grp, &p, len ) );
558 MBEDTLS_MPI_CHK( ecjpake_kkp_read( ctx->md_info, &ctx->grp,
559 &GB, &ctx->Xp, "server", &p, end ) );
560
561 if( p != end )
562 {
563 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
564 goto cleanup;
565 }
566
567 /*
568 * Xs already checked, only thing left to check is the group
569 */
570 if( grp.id != ctx->grp.id )
571 {
572 ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
573 goto cleanup;
574 }
575
576cleanup:
577 mbedtls_ecp_group_free( &grp );
578 mbedtls_ecp_point_free( &GB );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200579
580 return( ret );
581}
582
583/*
584 * Generate and write ServerECJPAKEParams (7.4.2.5)
585 */
586int mbedtls_ecjpake_tls_write_server_params( mbedtls_ecjpake_context *ctx,
587 unsigned char *buf, size_t len, size_t *olen,
588 int (*f_rng)(void *, unsigned char *, size_t),
589 void *p_rng )
590{
591 int ret;
592 mbedtls_ecp_point GB, Xs;
593 mbedtls_mpi xs;
594 unsigned char *p = buf;
595 const unsigned char *end = buf + len;
596 size_t ec_len;
597
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +0200598 if( end < p )
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200599 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
600
601 mbedtls_ecp_point_init( &GB );
602 mbedtls_ecp_point_init( &Xs );
603 mbedtls_mpi_init( &xs );
604
605 /*
606 * First generate private/public key pair (7.4.2.5.1)
607 *
608 * GB = X1 + X2 + X3
609 * xs = x4 * s mod n
610 * Xs = xs * GB
611 */
612 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &GB,
613 &ctx->X1, &ctx->X2, &ctx->X3 ) );
614 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &xs, &ctx->xb, &ctx->s ) );
615 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &xs, &xs, &ctx->grp.N ) );
616 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &Xs, &xs, &GB, f_rng, p_rng ) );
617
618 /*
619 * Now write things out
620 */
621 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_group( &ctx->grp, &ec_len,
622 p, end - p ) );
623 p += ec_len;
624
625 if( end < p )
626 {
627 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
628 goto cleanup;
629 }
630 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( &ctx->grp, &Xs,
631 MBEDTLS_ECP_PF_UNCOMPRESSED, &ec_len, p, end - p ) );
632 p += ec_len;
633
634 MBEDTLS_MPI_CHK( ecjpake_zkp_write( ctx->md_info, &ctx->grp,
635 &GB, &xs, &Xs, "server",
636 &p, end, f_rng, p_rng ) );
637
638 *olen = p - buf;
639
640cleanup:
641 mbedtls_ecp_point_free( &GB );
642 mbedtls_ecp_point_free( &Xs );
643 mbedtls_mpi_free( &xs );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200644
645 return( ret );
646}
647
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +0200648/*
649 * Read and process ClientECJPAKEParams (7.4.2.6)
650 */
651int mbedtls_ecjpake_tls_read_client_params( mbedtls_ecjpake_context *ctx,
652 const unsigned char *buf,
653 size_t len )
654{
655 int ret;
656 const unsigned char *p = buf;
657 const unsigned char *end = buf + len;
658 mbedtls_ecp_group grp;
659 mbedtls_ecp_point GA;
660
661 mbedtls_ecp_group_init( &grp );
662 mbedtls_ecp_point_init( &GA );
663
664 /*
665 * GA = X1 + X3 + X4 (7.4.2.6.1)
666 * We need that before parsing in order to check Xc as we read it
667 */
668 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &GA,
669 &ctx->X1, &ctx->X3, &ctx->X4 ) );
670
671 /*
672 * struct {
673 * ECJPAKEKeyKP ecjpake_key_kp;
674 * } CLientECJPAKEParams;
675 */
676 MBEDTLS_MPI_CHK( ecjpake_kkp_read( ctx->md_info, &ctx->grp,
677 &GA, &ctx->Xp, "client", &p, end ) );
678
679 if( p != end )
680 {
681 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
682 goto cleanup;
683 }
684
685cleanup:
686 mbedtls_ecp_group_free( &grp );
687 mbedtls_ecp_point_free( &GA );
688
689 return( ret );
690}
691
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +0200692/*
693 * Generate and write ClientECJPAKEParams (7.4.2.6)
694 */
695int mbedtls_ecjpake_tls_write_client_params( mbedtls_ecjpake_context *ctx,
696 unsigned char *buf, size_t len, size_t *olen,
697 int (*f_rng)(void *, unsigned char *, size_t),
698 void *p_rng )
699{
700 int ret;
701 mbedtls_ecp_point GA, Xc;
702 mbedtls_mpi xc;
703 unsigned char *p = buf;
704 const unsigned char *end = buf + len;
705 size_t ec_len;
706
707 if( end < p )
708 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
709
710 mbedtls_ecp_point_init( &GA );
711 mbedtls_ecp_point_init( &Xc );
712 mbedtls_mpi_init( &xc );
713
714 /*
715 * First generate private/public key pair (7.4.2.6.1)
716 *
717 * GA = X1 + X3 + X4
718 * xc = x2 * s mod n
719 * Xc = xc * GA
720 */
721 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &GA,
722 &ctx->X1, &ctx->X3, &ctx->X4 ) );
723 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &xc, &ctx->xb, &ctx->s ) );
724 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &xc, &xc, &ctx->grp.N ) );
725 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &Xc, &xc, &GA, f_rng, p_rng ) );
726
727 /*
728 * Now write things out
729 */
730 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( &ctx->grp, &Xc,
731 MBEDTLS_ECP_PF_UNCOMPRESSED, &ec_len, p, end - p ) );
732 p += ec_len;
733
734 MBEDTLS_MPI_CHK( ecjpake_zkp_write( ctx->md_info, &ctx->grp,
735 &GA, &xc, &Xc, "client",
736 &p, end, f_rng, p_rng ) );
737
738 *olen = p - buf;
739
740cleanup:
741 mbedtls_ecp_point_free( &GA );
742 mbedtls_ecp_point_free( &Xc );
743 mbedtls_mpi_free( &xc );
744
745 return( ret );
746}
747
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200748#if defined(MBEDTLS_SELF_TEST)
749
750#if defined(MBEDTLS_PLATFORM_C)
751#include "mbedtls/platform.h"
752#else
753#include <stdio.h>
754#define mbedtls_printf printf
755#endif
756
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200757#if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
758 !defined(MBEDTLS_SHA256_C)
759int mbedtls_ecjpake_self_test( int verbose )
760{
761 (void) verbose;
762 return( 0 );
763}
764#else
765
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200766static const unsigned char ecjpake_test_password[] = {
767 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x6a, 0x70, 0x61, 0x6b, 0x65, 0x74,
768 0x65, 0x73, 0x74
769};
770
771static const unsigned char ecjpake_test_x1[] = {
772 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
773 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
774 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21
775};
776
777static const unsigned char ecjpake_test_x2[] = {
778 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
779 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
780 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
781};
782
783static const unsigned char ecjpake_test_x3[] = {
784 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
785 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
786 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
787};
788
789static const unsigned char ecjpake_test_x4[] = {
790 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc,
791 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
792 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1
793};
794
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200795static const unsigned char ecjpake_test_cli_ext[] = {
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200796 0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19,
797 0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44,
798 0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad,
799 0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62,
800 0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9,
801 0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d,
802 0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e,
803 0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e,
804 0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73,
805 0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22,
806 0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce,
807 0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00,
808 0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200809 0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e,
810 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62,
811 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5,
812 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb,
813 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35,
814 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0,
815 0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb,
816 0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47,
817 0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39,
818 0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97,
819 0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40,
820 0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d,
821 0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa,
822 0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d,
823 0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200824};
825
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200826static const unsigned char ecjpake_test_srv_ext[] = {
827 0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb,
828 0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18,
829 0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47,
830 0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f,
831 0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7,
832 0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d,
833 0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64,
834 0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36,
835 0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2,
836 0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec,
837 0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16,
838 0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96,
839 0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3,
840 0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19,
841 0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f,
842 0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8,
843 0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7,
844 0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea,
845 0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5,
846 0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6,
847 0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31,
848 0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d,
849 0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8,
850 0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee,
851 0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84,
852 0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f,
853 0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80,
854 0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12
855};
856
857static const unsigned char ecjpake_test_srv_kx[] = {
858 0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23,
859 0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c,
860 0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f,
861 0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca,
862 0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26,
863 0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55,
864 0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38,
865 0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6,
866 0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9,
867 0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4,
868 0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2,
869 0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8,
870 0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd,
871 0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c
872};
873
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +0200874static const unsigned char ecjpake_test_cli_kx[] = {
875 0x41, 0x04, 0x69, 0xd5, 0x4e, 0xe8, 0x5e, 0x90, 0xce, 0x3f, 0x12, 0x46,
876 0x74, 0x2d, 0xe5, 0x07, 0xe9, 0x39, 0xe8, 0x1d, 0x1d, 0xc1, 0xc5, 0xcb,
877 0x98, 0x8b, 0x58, 0xc3, 0x10, 0xc9, 0xfd, 0xd9, 0x52, 0x4d, 0x93, 0x72,
878 0x0b, 0x45, 0x54, 0x1c, 0x83, 0xee, 0x88, 0x41, 0x19, 0x1d, 0xa7, 0xce,
879 0xd8, 0x6e, 0x33, 0x12, 0xd4, 0x36, 0x23, 0xc1, 0xd6, 0x3e, 0x74, 0x98,
880 0x9a, 0xba, 0x4a, 0xff, 0xd1, 0xee, 0x41, 0x04, 0x07, 0x7e, 0x8c, 0x31,
881 0xe2, 0x0e, 0x6b, 0xed, 0xb7, 0x60, 0xc1, 0x35, 0x93, 0xe6, 0x9f, 0x15,
882 0xbe, 0x85, 0xc2, 0x7d, 0x68, 0xcd, 0x09, 0xcc, 0xb8, 0xc4, 0x18, 0x36,
883 0x08, 0x91, 0x7c, 0x5c, 0x3d, 0x40, 0x9f, 0xac, 0x39, 0xfe, 0xfe, 0xe8,
884 0x2f, 0x72, 0x92, 0xd3, 0x6f, 0x0d, 0x23, 0xe0, 0x55, 0x91, 0x3f, 0x45,
885 0xa5, 0x2b, 0x85, 0xdd, 0x8a, 0x20, 0x52, 0xe9, 0xe1, 0x29, 0xbb, 0x4d,
886 0x20, 0x0f, 0x01, 0x1f, 0x19, 0x48, 0x35, 0x35, 0xa6, 0xe8, 0x9a, 0x58,
887 0x0c, 0x9b, 0x00, 0x03, 0xba, 0xf2, 0x14, 0x62, 0xec, 0xe9, 0x1a, 0x82,
888 0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c
889};
890
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200891/* For tests we don't need a secure RNG;
892 * use the LGC from Numerical Recipes for simplicity */
893static int ecjpake_lgc( void *p, unsigned char *out, size_t len )
894{
895 static uint32_t x = 42;
896 (void) p;
897
898 while( len > 0 )
899 {
900 size_t use_len = len > 4 ? 4 : len;
901 x = 1664525 * x + 1013904223;
902 memcpy( out, &x, use_len );
903 out += use_len;
904 len -= use_len;
905 }
906
907 return( 0 );
908}
909
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200910#define TEST_ASSERT( x ) \
911 do { \
912 if( x ) \
913 ret = 0; \
914 else \
915 { \
916 ret = 1; \
917 goto cleanup; \
918 } \
919 } while( 0 )
920
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200921/*
922 * Checkup routine
923 */
924int mbedtls_ecjpake_self_test( int verbose )
925{
926 int ret;
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200927 mbedtls_ecjpake_context cli;
928 mbedtls_ecjpake_context srv;
929 unsigned char buf[512];
930 size_t len;
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200931
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200932 mbedtls_ecjpake_init( &cli );
933 mbedtls_ecjpake_init( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200934
935 if( verbose != 0 )
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200936 mbedtls_printf( " ECJPAKE test #0 (setup): " );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200937
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +0200938 TEST_ASSERT( mbedtls_ecjpake_setup( &cli, MBEDTLS_ECJPAKE_CLIENT,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200939 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
940 ecjpake_test_password,
941 sizeof( ecjpake_test_password ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200942
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +0200943 TEST_ASSERT( mbedtls_ecjpake_setup( &srv, MBEDTLS_ECJPAKE_SERVER,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200944 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
945 ecjpake_test_password,
946 sizeof( ecjpake_test_password ) ) == 0 );
947
948 if( verbose != 0 )
949 mbedtls_printf( "passed\n" );
950
951 if( verbose != 0 )
952 mbedtls_printf( " ECJPAKE test #1 (random handshake): " );
953
954 TEST_ASSERT( mbedtls_ecjpake_tls_write_client_ext( &cli,
955 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
956
957 TEST_ASSERT( mbedtls_ecjpake_tls_read_client_ext( &srv, buf, len ) == 0 );
958
959 TEST_ASSERT( mbedtls_ecjpake_tls_write_server_ext( &srv,
960 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
961
962 TEST_ASSERT( mbedtls_ecjpake_tls_read_server_ext( &cli, buf, len ) == 0 );
963
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200964 TEST_ASSERT( mbedtls_ecjpake_tls_write_server_params( &srv,
965 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
966
967 TEST_ASSERT( mbedtls_ecjpake_tls_read_server_params( &cli, buf, len ) == 0 );
968
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +0200969 TEST_ASSERT( mbedtls_ecjpake_tls_write_client_params( &cli,
970 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
971
972 TEST_ASSERT( mbedtls_ecjpake_tls_read_client_params( &srv, buf, len ) == 0 );
973
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200974 if( verbose != 0 )
975 mbedtls_printf( "passed\n" );
976
977 if( verbose != 0 )
978 mbedtls_printf( " ECJPAKE test #2 (reference handshake): " );
979
980 /* Simulate key generation on client, skip writing client_ext */
981 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &cli.xa,
982 ecjpake_test_x1, sizeof( ecjpake_test_x1 ) ) );
983 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &cli.xb,
984 ecjpake_test_x2, sizeof( ecjpake_test_x2 ) ) );
985 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &cli.grp, &cli.X1, &cli.xa,
986 &cli.grp.G, NULL, NULL ) );
987 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &cli.grp, &cli.X2, &cli.xb,
988 &cli.grp.G, NULL, NULL ) );
989
990 /* Server reads client ext */
991 TEST_ASSERT( mbedtls_ecjpake_tls_read_client_ext( &srv,
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200992 ecjpake_test_cli_ext,
993 sizeof( ecjpake_test_cli_ext ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200994
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200995 /* Simulate key generation on server, skip writing server_ext */
996 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &srv.xa,
997 ecjpake_test_x3, sizeof( ecjpake_test_x3 ) ) );
998 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &srv.xb,
999 ecjpake_test_x4, sizeof( ecjpake_test_x4 ) ) );
1000 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &srv.grp, &srv.X3, &srv.xa,
1001 &srv.grp.G, NULL, NULL ) );
1002 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &srv.grp, &srv.X4, &srv.xb,
1003 &srv.grp.G, NULL, NULL ) );
1004
1005 /* Client reads server ext and key exchange */
1006 TEST_ASSERT( mbedtls_ecjpake_tls_read_server_ext( &cli,
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +02001007 ecjpake_test_srv_ext,
1008 sizeof( ecjpake_test_srv_ext ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001009
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001010 TEST_ASSERT( mbedtls_ecjpake_tls_read_server_params( &cli,
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +02001011 ecjpake_test_srv_kx,
1012 sizeof( ecjpake_test_srv_kx ) ) == 0 );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +02001013
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +02001014 /* Server reads client key exchange */
1015 TEST_ASSERT( mbedtls_ecjpake_tls_read_client_params( &srv,
1016 ecjpake_test_cli_kx,
1017 sizeof( ecjpake_test_cli_kx ) ) == 0 );
1018
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001019 if( verbose != 0 )
1020 mbedtls_printf( "passed\n" );
1021
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001022cleanup:
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001023 mbedtls_ecjpake_free( &cli );
1024 mbedtls_ecjpake_free( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001025
1026 if( ret != 0 )
1027 {
1028 if( verbose != 0 )
1029 mbedtls_printf( "failed\n" );
1030
1031 ret = 1;
1032 }
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001033
1034 if( verbose != 0 )
1035 mbedtls_printf( "\n" );
1036
1037 return( ret );
1038}
1039
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +02001040#undef TEST_ASSERT
1041
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001042#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_SHA256_C */
1043
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001044#endif /* MBEDTLS_SELF_TEST */
1045
1046#endif /* MBEDTLS_ECJPAKE_C */