blob: 63de6e666359306b3bdde934ebfa715a9c8c2950 [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é-Gonnard5f188292015-08-14 10:52:39 +0200748/*
749 * Derive PMS (7.4.2.7 / 7.4.2.8)
750 */
751int mbedtls_ecjpake_tls_derive_pms( mbedtls_ecjpake_context *ctx,
752 unsigned char *buf, size_t len, size_t *olen,
753 int (*f_rng)(void *, unsigned char *, size_t),
754 void *p_rng )
755{
756 int ret;
757 mbedtls_ecp_point K, *X42;
758 mbedtls_mpi xbs, one;
759 unsigned char kx[MBEDTLS_ECP_MAX_BYTES];
760 size_t x_bytes;
761
762 *olen = mbedtls_md_get_size( ctx->md_info );
763 if( len < *olen )
764 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
765
766 mbedtls_ecp_point_init( &K );
767 mbedtls_mpi_init( &xbs );
768 mbedtls_mpi_init( &one );
769
770 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
771 X42 = ctx->role == MBEDTLS_ECJPAKE_CLIENT ? &ctx->X4 : &ctx->X2;
772
773 /*
774 * Client: K = ( Xs - X4 * x2 * s ) * x2
775 * Server: K = ( Xc - X2 * x4 * s ) * x4
776 * Unified: K = ( Xp - X42 * xb * x ) * xb
777 */
778 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &xbs, &ctx->xb, &ctx->s ) );
779 xbs.s *= -1;
780 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &xbs, &xbs, &ctx->grp.N ) );
781
782 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( &ctx->grp, &K,
783 &one, &ctx->Xp,
784 &xbs, X42 ) );
785 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &K, &ctx->xb, &K,
786 f_rng, p_rng ) );
787
788 /* PMS = SHA-256( K.X ) */
789 x_bytes = ( ctx->grp.pbits + 7 ) / 8;
790 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &K.X, kx, x_bytes ) );
791 MBEDTLS_MPI_CHK( mbedtls_md( ctx->md_info, kx, x_bytes, buf ) );
792
793cleanup:
794 mbedtls_ecp_point_free( &K );
795 mbedtls_mpi_free( &xbs );
796 mbedtls_mpi_free( &one );
797
798 return( ret );
799}
800
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200801#if defined(MBEDTLS_SELF_TEST)
802
803#if defined(MBEDTLS_PLATFORM_C)
804#include "mbedtls/platform.h"
805#else
806#include <stdio.h>
807#define mbedtls_printf printf
808#endif
809
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200810#if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
811 !defined(MBEDTLS_SHA256_C)
812int mbedtls_ecjpake_self_test( int verbose )
813{
814 (void) verbose;
815 return( 0 );
816}
817#else
818
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200819static const unsigned char ecjpake_test_password[] = {
820 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x6a, 0x70, 0x61, 0x6b, 0x65, 0x74,
821 0x65, 0x73, 0x74
822};
823
824static const unsigned char ecjpake_test_x1[] = {
825 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
826 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
827 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21
828};
829
830static const unsigned char ecjpake_test_x2[] = {
831 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
832 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
833 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
834};
835
836static const unsigned char ecjpake_test_x3[] = {
837 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
838 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
839 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
840};
841
842static const unsigned char ecjpake_test_x4[] = {
843 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc,
844 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
845 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1
846};
847
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200848static const unsigned char ecjpake_test_cli_ext[] = {
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200849 0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19,
850 0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44,
851 0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad,
852 0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62,
853 0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9,
854 0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d,
855 0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e,
856 0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e,
857 0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73,
858 0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22,
859 0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce,
860 0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00,
861 0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200862 0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e,
863 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62,
864 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5,
865 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb,
866 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35,
867 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0,
868 0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb,
869 0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47,
870 0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39,
871 0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97,
872 0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40,
873 0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d,
874 0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa,
875 0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d,
876 0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200877};
878
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200879static const unsigned char ecjpake_test_srv_ext[] = {
880 0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb,
881 0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18,
882 0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47,
883 0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f,
884 0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7,
885 0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d,
886 0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64,
887 0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36,
888 0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2,
889 0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec,
890 0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16,
891 0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96,
892 0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3,
893 0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19,
894 0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f,
895 0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8,
896 0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7,
897 0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea,
898 0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5,
899 0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6,
900 0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31,
901 0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d,
902 0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8,
903 0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee,
904 0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84,
905 0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f,
906 0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80,
907 0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12
908};
909
910static const unsigned char ecjpake_test_srv_kx[] = {
911 0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23,
912 0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c,
913 0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f,
914 0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca,
915 0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26,
916 0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55,
917 0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38,
918 0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6,
919 0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9,
920 0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4,
921 0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2,
922 0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8,
923 0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd,
924 0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c
925};
926
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +0200927static const unsigned char ecjpake_test_cli_kx[] = {
928 0x41, 0x04, 0x69, 0xd5, 0x4e, 0xe8, 0x5e, 0x90, 0xce, 0x3f, 0x12, 0x46,
929 0x74, 0x2d, 0xe5, 0x07, 0xe9, 0x39, 0xe8, 0x1d, 0x1d, 0xc1, 0xc5, 0xcb,
930 0x98, 0x8b, 0x58, 0xc3, 0x10, 0xc9, 0xfd, 0xd9, 0x52, 0x4d, 0x93, 0x72,
931 0x0b, 0x45, 0x54, 0x1c, 0x83, 0xee, 0x88, 0x41, 0x19, 0x1d, 0xa7, 0xce,
932 0xd8, 0x6e, 0x33, 0x12, 0xd4, 0x36, 0x23, 0xc1, 0xd6, 0x3e, 0x74, 0x98,
933 0x9a, 0xba, 0x4a, 0xff, 0xd1, 0xee, 0x41, 0x04, 0x07, 0x7e, 0x8c, 0x31,
934 0xe2, 0x0e, 0x6b, 0xed, 0xb7, 0x60, 0xc1, 0x35, 0x93, 0xe6, 0x9f, 0x15,
935 0xbe, 0x85, 0xc2, 0x7d, 0x68, 0xcd, 0x09, 0xcc, 0xb8, 0xc4, 0x18, 0x36,
936 0x08, 0x91, 0x7c, 0x5c, 0x3d, 0x40, 0x9f, 0xac, 0x39, 0xfe, 0xfe, 0xe8,
937 0x2f, 0x72, 0x92, 0xd3, 0x6f, 0x0d, 0x23, 0xe0, 0x55, 0x91, 0x3f, 0x45,
938 0xa5, 0x2b, 0x85, 0xdd, 0x8a, 0x20, 0x52, 0xe9, 0xe1, 0x29, 0xbb, 0x4d,
939 0x20, 0x0f, 0x01, 0x1f, 0x19, 0x48, 0x35, 0x35, 0xa6, 0xe8, 0x9a, 0x58,
940 0x0c, 0x9b, 0x00, 0x03, 0xba, 0xf2, 0x14, 0x62, 0xec, 0xe9, 0x1a, 0x82,
941 0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c
942};
943
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200944static const unsigned char ecjpake_test_pms[] = {
945 0xf3, 0xd4, 0x7f, 0x59, 0x98, 0x44, 0xdb, 0x92, 0xa5, 0x69, 0xbb, 0xe7,
946 0x98, 0x1e, 0x39, 0xd9, 0x31, 0xfd, 0x74, 0x3b, 0xf2, 0x2e, 0x98, 0xf9,
947 0xb4, 0x38, 0xf7, 0x19, 0xd3, 0xc4, 0xf3, 0x51
948};
949
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200950/* For tests we don't need a secure RNG;
951 * use the LGC from Numerical Recipes for simplicity */
952static int ecjpake_lgc( void *p, unsigned char *out, size_t len )
953{
954 static uint32_t x = 42;
955 (void) p;
956
957 while( len > 0 )
958 {
959 size_t use_len = len > 4 ? 4 : len;
960 x = 1664525 * x + 1013904223;
961 memcpy( out, &x, use_len );
962 out += use_len;
963 len -= use_len;
964 }
965
966 return( 0 );
967}
968
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200969#define TEST_ASSERT( x ) \
970 do { \
971 if( x ) \
972 ret = 0; \
973 else \
974 { \
975 ret = 1; \
976 goto cleanup; \
977 } \
978 } while( 0 )
979
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200980/*
981 * Checkup routine
982 */
983int mbedtls_ecjpake_self_test( int verbose )
984{
985 int ret;
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200986 mbedtls_ecjpake_context cli;
987 mbedtls_ecjpake_context srv;
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200988 unsigned char buf[512], pms[32];
989 size_t len, pmslen;
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200990
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200991 mbedtls_ecjpake_init( &cli );
992 mbedtls_ecjpake_init( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200993
994 if( verbose != 0 )
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200995 mbedtls_printf( " ECJPAKE test #0 (setup): " );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200996
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +0200997 TEST_ASSERT( mbedtls_ecjpake_setup( &cli, MBEDTLS_ECJPAKE_CLIENT,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200998 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
999 ecjpake_test_password,
1000 sizeof( ecjpake_test_password ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001001
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +02001002 TEST_ASSERT( mbedtls_ecjpake_setup( &srv, MBEDTLS_ECJPAKE_SERVER,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001003 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1004 ecjpake_test_password,
1005 sizeof( ecjpake_test_password ) ) == 0 );
1006
1007 if( verbose != 0 )
1008 mbedtls_printf( "passed\n" );
1009
1010 if( verbose != 0 )
1011 mbedtls_printf( " ECJPAKE test #1 (random handshake): " );
1012
1013 TEST_ASSERT( mbedtls_ecjpake_tls_write_client_ext( &cli,
1014 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1015
1016 TEST_ASSERT( mbedtls_ecjpake_tls_read_client_ext( &srv, buf, len ) == 0 );
1017
1018 TEST_ASSERT( mbedtls_ecjpake_tls_write_server_ext( &srv,
1019 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1020
1021 TEST_ASSERT( mbedtls_ecjpake_tls_read_server_ext( &cli, buf, len ) == 0 );
1022
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +02001023 TEST_ASSERT( mbedtls_ecjpake_tls_write_server_params( &srv,
1024 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1025
1026 TEST_ASSERT( mbedtls_ecjpake_tls_read_server_params( &cli, buf, len ) == 0 );
1027
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001028 TEST_ASSERT( mbedtls_ecjpake_tls_derive_pms( &cli,
1029 pms, sizeof( pms ), &pmslen, ecjpake_lgc, NULL ) == 0 );
1030
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +02001031 TEST_ASSERT( mbedtls_ecjpake_tls_write_client_params( &cli,
1032 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1033
1034 TEST_ASSERT( mbedtls_ecjpake_tls_read_client_params( &srv, buf, len ) == 0 );
1035
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001036 TEST_ASSERT( mbedtls_ecjpake_tls_derive_pms( &srv,
1037 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1038
1039 TEST_ASSERT( len == pmslen );
1040 TEST_ASSERT( memcmp( buf, pms, len ) == 0 );
1041
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001042 if( verbose != 0 )
1043 mbedtls_printf( "passed\n" );
1044
1045 if( verbose != 0 )
1046 mbedtls_printf( " ECJPAKE test #2 (reference handshake): " );
1047
1048 /* Simulate key generation on client, skip writing client_ext */
1049 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &cli.xa,
1050 ecjpake_test_x1, sizeof( ecjpake_test_x1 ) ) );
1051 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &cli.xb,
1052 ecjpake_test_x2, sizeof( ecjpake_test_x2 ) ) );
1053 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &cli.grp, &cli.X1, &cli.xa,
1054 &cli.grp.G, NULL, NULL ) );
1055 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &cli.grp, &cli.X2, &cli.xb,
1056 &cli.grp.G, NULL, NULL ) );
1057
1058 /* Server reads client ext */
1059 TEST_ASSERT( mbedtls_ecjpake_tls_read_client_ext( &srv,
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +02001060 ecjpake_test_cli_ext,
1061 sizeof( ecjpake_test_cli_ext ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001062
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001063 /* Simulate key generation on server, skip writing server_ext */
1064 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &srv.xa,
1065 ecjpake_test_x3, sizeof( ecjpake_test_x3 ) ) );
1066 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &srv.xb,
1067 ecjpake_test_x4, sizeof( ecjpake_test_x4 ) ) );
1068 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &srv.grp, &srv.X3, &srv.xa,
1069 &srv.grp.G, NULL, NULL ) );
1070 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &srv.grp, &srv.X4, &srv.xb,
1071 &srv.grp.G, NULL, NULL ) );
1072
1073 /* Client reads server ext and key exchange */
1074 TEST_ASSERT( mbedtls_ecjpake_tls_read_server_ext( &cli,
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +02001075 ecjpake_test_srv_ext,
1076 sizeof( ecjpake_test_srv_ext ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001077
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001078 TEST_ASSERT( mbedtls_ecjpake_tls_read_server_params( &cli,
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +02001079 ecjpake_test_srv_kx,
1080 sizeof( ecjpake_test_srv_kx ) ) == 0 );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +02001081
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +02001082 /* Server reads client key exchange */
1083 TEST_ASSERT( mbedtls_ecjpake_tls_read_client_params( &srv,
1084 ecjpake_test_cli_kx,
1085 sizeof( ecjpake_test_cli_kx ) ) == 0 );
1086
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001087 /* Server derives PMS */
1088 TEST_ASSERT( mbedtls_ecjpake_tls_derive_pms( &srv,
1089 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1090
1091 TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
1092 TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
1093
1094 memset( buf, 0, len ); /* Avoid interferences with next step */
1095
1096 /* Client derives PMS */
1097 TEST_ASSERT( mbedtls_ecjpake_tls_derive_pms( &cli,
1098 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1099
1100 TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
1101 TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
1102
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001103 if( verbose != 0 )
1104 mbedtls_printf( "passed\n" );
1105
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001106cleanup:
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001107 mbedtls_ecjpake_free( &cli );
1108 mbedtls_ecjpake_free( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001109
1110 if( ret != 0 )
1111 {
1112 if( verbose != 0 )
1113 mbedtls_printf( "failed\n" );
1114
1115 ret = 1;
1116 }
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001117
1118 if( verbose != 0 )
1119 mbedtls_printf( "\n" );
1120
1121 return( ret );
1122}
1123
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +02001124#undef TEST_ASSERT
1125
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001126#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_SHA256_C */
1127
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001128#endif /* MBEDTLS_SELF_TEST */
1129
1130#endif /* MBEDTLS_ECJPAKE_C */