blob: dffab222e5028e06e6c9a3a3ae23fc9b4ba66125 [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,
87 mbedtls_md_type_t hash,
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +020088 mbedtls_ecp_group_id curve,
89 const unsigned char *secret,
90 size_t len )
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020091{
92 int ret;
93
94 if( ( ctx->md_info = mbedtls_md_info_from_type( hash ) ) == NULL )
95 return( MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE );
96
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +020097 MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ctx->grp, curve ) );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020098
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +020099 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->s, secret, len ) );
100 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->s, &ctx->s, &ctx->grp.N ) );
101
102cleanup:
103 if( ret != 0 )
104 mbedtls_ecjpake_free( ctx );
105
106 return( ret );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200107}
108
109/*
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200110 * Write a point plus its length to a buffer
111 */
112static int ecjpake_write_len_point( unsigned char **p,
113 const unsigned char *end,
114 const mbedtls_ecp_group *grp,
115 const mbedtls_ecp_point *P )
116{
117 int ret;
118 size_t len;
119
120 /* Need at least 4 for length plus 1 for point */
121 if( end < *p || end - *p < 5 )
122 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
123
124 ret = mbedtls_ecp_point_write_binary( grp, P, MBEDTLS_ECP_PF_UNCOMPRESSED,
125 &len, *p + 4, end - ( *p + 4 ) );
126 if( ret != 0 )
127 return( ret );
128
129 (*p)[0] = (unsigned char)( ( len >> 24 ) & 0xFF );
130 (*p)[1] = (unsigned char)( ( len >> 16 ) & 0xFF );
131 (*p)[2] = (unsigned char)( ( len >> 8 ) & 0xFF );
132 (*p)[3] = (unsigned char)( ( len ) & 0xFF );
133
134 *p += 4 + len;
135
136 return( 0 );
137}
138
139/*
140 * Size of the temporary buffer for ecjpake_hash:
141 * 3 EC points plus their length, plus ID (6 bytes)
142 */
143#define ECJPAKE_HASH_BUF_LEN ( 3 * ( 4 + MBEDTLS_ECP_MAX_PT_LEN ) + 6 )
144
145/*
146 * Compute hash for ZKP (7.4.2.2.2.1)
147 */
148static int ecjpake_hash( const mbedtls_md_info_t *md_info,
149 const mbedtls_ecp_group *grp,
150 const mbedtls_ecp_point *G,
151 const mbedtls_ecp_point *V,
152 const mbedtls_ecp_point *X,
153 const char *id,
154 mbedtls_mpi *h )
155{
156 int ret;
157 unsigned char buf[ECJPAKE_HASH_BUF_LEN];
158 unsigned char *p = buf;
159 const unsigned char *end = buf + sizeof( buf );
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200160 const size_t id_len = strlen( id );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200161 unsigned char hash[MBEDTLS_MD_MAX_SIZE];
162
163 /* Write things to temporary buffer */
164 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, G ) );
165 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, V ) );
166 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, X ) );
167
168 if( end < p || (size_t)( end - p ) < id_len )
169 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
170
171 *p++ = (unsigned char)( ( id_len >> 24 ) & 0xFF );
172 *p++ = (unsigned char)( ( id_len >> 16 ) & 0xFF );
173 *p++ = (unsigned char)( ( id_len >> 8 ) & 0xFF );
174 *p++ = (unsigned char)( ( id_len ) & 0xFF );
175
176 memcpy( p, id, id_len );
177 p += id_len;
178
179 /* Compute hash */
180 mbedtls_md( md_info, buf, p - buf, hash );
181
182 /* Turn it into an integer mod n */
183 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( h, hash,
184 mbedtls_md_get_size( md_info ) ) );
185 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( h, h, &grp->N ) );
186
187cleanup:
188 return( ret );
189}
190
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200191/*
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200192 * Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3)
193 */
194static int ecjpake_zkp_read( const mbedtls_md_info_t *md_info,
195 const mbedtls_ecp_group *grp,
196 const mbedtls_ecp_point *G,
197 const mbedtls_ecp_point *X,
198 const char *id,
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200199 const unsigned char **p,
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200200 const unsigned char *end )
201{
202 int ret;
203 mbedtls_ecp_point V, VV;
204 mbedtls_mpi r, h;
205 size_t r_len;
206
207 mbedtls_ecp_point_init( &V );
208 mbedtls_ecp_point_init( &VV );
209 mbedtls_mpi_init( &r );
210 mbedtls_mpi_init( &h );
211
212 /*
213 * struct {
214 * ECPoint V;
215 * opaque r<1..2^8-1>;
216 * } ECSchnorrZKP;
217 */
218 if( end < *p )
219 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
220
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200221 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, &V, p, end - *p ) );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200222
223 if( end < *p || (size_t)( end - *p ) < 1 )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200224 {
225 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
226 goto cleanup;
227 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200228
229 r_len = *(*p)++;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200230
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200231 if( end < *p || (size_t)( end - *p ) < r_len )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200232 {
233 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
234 goto cleanup;
235 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200236
237 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &r, *p, r_len ) );
238 *p += r_len;
239
240 /*
241 * Verification
242 */
243 MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, G, &V, X, id, &h ) );
244 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( (mbedtls_ecp_group *) grp,
245 &VV, &h, X, &r, G ) );
246
247 if( mbedtls_ecp_point_cmp( &VV, &V ) != 0 )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200248 {
249 ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
250 goto cleanup;
251 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200252
253cleanup:
254 mbedtls_ecp_point_free( &V );
255 mbedtls_ecp_point_free( &VV );
256 mbedtls_mpi_free( &r );
257 mbedtls_mpi_free( &h );
258
259 return( ret );
260}
261
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200262/*
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200263 * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2)
264 */
265static int ecjpake_zkp_write( const mbedtls_md_info_t *md_info,
266 const mbedtls_ecp_group *grp,
267 const mbedtls_ecp_point *G,
268 const mbedtls_mpi *x,
269 const mbedtls_ecp_point *X,
270 const char *id,
271 unsigned char **p,
272 const unsigned char *end,
273 int (*f_rng)(void *, unsigned char *, size_t),
274 void *p_rng )
275{
276 int ret;
277 mbedtls_ecp_point V;
278 mbedtls_mpi v;
279 mbedtls_mpi h; /* later recycled to hold r */
280 size_t len;
281
282 if( end < *p )
283 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
284
285 mbedtls_ecp_point_init( &V );
286 mbedtls_mpi_init( &v );
287 mbedtls_mpi_init( &h );
288
289 /* Compute signature */
290 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp,
291 G, &v, &V, f_rng, p_rng ) );
292 MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, G, &V, X, id, &h ) );
293 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &h, &h, x ) ); /* x*h */
294 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &h, &v, &h ) ); /* v - x*h */
295 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &h, &h, &grp->N ) ); /* r */
296
297 /* Write it out */
298 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, &V,
299 MBEDTLS_ECP_PF_UNCOMPRESSED, &len, *p, end - *p ) );
300 *p += len;
301
302 len = mbedtls_mpi_size( &h ); /* actually r */
303 if( end < *p || (size_t)( end - *p ) < 1 + len || len > 255 )
304 {
305 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
306 goto cleanup;
307 }
308
309 *(*p)++ = (unsigned char)( len & 0xFF );
310 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, *p, len ) ); /* r */
311 *p += len;
312
313cleanup:
314 mbedtls_ecp_point_free( &V );
315 mbedtls_mpi_free( &v );
316 mbedtls_mpi_free( &h );
317
318 return( ret );
319}
320
321/*
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200322 * Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof
323 * Output: verified public key X
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200324 */
325static int ecjpake_kkp_read( const mbedtls_md_info_t *md_info,
326 const mbedtls_ecp_group *grp,
327 const mbedtls_ecp_point *G,
328 mbedtls_ecp_point *X,
329 const char *id,
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200330 const unsigned char **p,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200331 const unsigned char *end )
332{
333 int ret;
334
335 if( end < *p )
336 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
337
338 /*
339 * struct {
340 * ECPoint X;
341 * ECSchnorrZKP zkp;
342 * } ECJPAKEKeyKP;
343 */
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200344 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, X, p, end - *p ) );
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200345 MBEDTLS_MPI_CHK( ecjpake_zkp_read( md_info, grp, G, X, id, p, end ) );
346
347cleanup:
348 return( ret );
349}
350
351/*
352 * Generate an ECJPAKEKeyKP
353 * Output: the serialized structure, plus private/public key pair
354 */
355static int ecjpake_kkp_write( const mbedtls_md_info_t *md_info,
356 const mbedtls_ecp_group *grp,
357 const mbedtls_ecp_point *G,
358 mbedtls_mpi *x,
359 mbedtls_ecp_point *X,
360 const char *id,
361 unsigned char **p,
362 const unsigned char *end,
363 int (*f_rng)(void *, unsigned char *, size_t),
364 void *p_rng )
365{
366 int ret;
367 size_t len;
368
369 if( end < *p )
370 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
371
372 /* Generate key (7.4.2.3.1) and write it out */
373 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp, G, x, X,
374 f_rng, p_rng ) );
375 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, X,
376 MBEDTLS_ECP_PF_UNCOMPRESSED, &len, *p, end - *p ) );
377 *p += len;
378
379 /* Generate and write proof */
380 MBEDTLS_MPI_CHK( ecjpake_zkp_write( md_info, grp, G, x, X, id,
381 p, end, f_rng, p_rng ) );
382
383cleanup:
384 return( ret );
385}
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200386
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200387/*
388 * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs
389 * Ouputs: verified peer public keys Xa, Xb
390 */
391static int ecjpake_kkpp_read( const mbedtls_md_info_t *md_info,
392 const mbedtls_ecp_group *grp,
393 const mbedtls_ecp_point *G,
394 mbedtls_ecp_point *Xa,
395 mbedtls_ecp_point *Xb,
396 const char *id,
397 const unsigned char *buf,
398 size_t len )
399{
400 int ret;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200401 const unsigned char *p = buf;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200402 const unsigned char *end = buf + len;
403
404 /*
405 * struct {
406 * ECJPAKEKeyKP ecjpake_key_kp_pair_list[2];
407 * } ECJPAKEKeyKPPairList;
408 */
409 MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, G, Xa, id, &p, end ) );
410 MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, G, Xb, id, &p, end ) );
411
412 if( p != end )
413 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
414
415cleanup:
416 return( ret );
417}
418
419/*
420 * Generate a ECJPAKEKeyKPPairList
421 * Outputs: the serialized structure, plus two private/public key pairs
422 */
423static int ecjpake_kkpp_write( const mbedtls_md_info_t *md_info,
424 const mbedtls_ecp_group *grp,
425 const mbedtls_ecp_point *G,
426 mbedtls_mpi *xa,
427 mbedtls_ecp_point *Xa,
428 mbedtls_mpi *xb,
429 mbedtls_ecp_point *Xb,
430 const char *id,
431 unsigned char *buf,
432 size_t len,
433 size_t *olen,
434 int (*f_rng)(void *, unsigned char *, size_t),
435 void *p_rng )
436{
437 int ret;
438 unsigned char *p = buf;
439 const unsigned char *end = buf + len;
440
441 MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, G, xa, Xa, id,
442 &p, end, f_rng, p_rng ) );
443 MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, G, xb, Xb, id,
444 &p, end, f_rng, p_rng ) );
445
446 *olen = p - buf;
447
448cleanup:
449 return( ret );
450}
451
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200452/*
453 * Read the contents of the ClientHello extension
454 */
455int mbedtls_ecjpake_tls_read_client_ext( mbedtls_ecjpake_context *ctx,
456 const unsigned char *buf,
457 size_t len )
458{
459 return( ecjpake_kkpp_read( ctx->md_info, &ctx->grp, &ctx->grp.G,
460 &ctx->X1, &ctx->X2, "client",
461 buf, len ) );
462}
463
464/*
465 * Read the contents of the ServerHello extension
466 */
467int mbedtls_ecjpake_tls_read_server_ext( mbedtls_ecjpake_context *ctx,
468 const unsigned char *buf,
469 size_t len )
470{
471 return( ecjpake_kkpp_read( ctx->md_info, &ctx->grp, &ctx->grp.G,
472 &ctx->X3, &ctx->X4, "server",
473 buf, len ) );
474}
475
476/*
477 * Generate the contents of the ClientHello extension
478 */
479int mbedtls_ecjpake_tls_write_client_ext( mbedtls_ecjpake_context *ctx,
480 unsigned char *buf, size_t len, size_t *olen,
481 int (*f_rng)(void *, unsigned char *, size_t),
482 void *p_rng )
483{
484 return( ecjpake_kkpp_write( ctx->md_info, &ctx->grp, &ctx->grp.G,
485 &ctx->xa, &ctx->X1, &ctx->xb, &ctx->X2,
486 "client", buf, len, olen, f_rng, p_rng ) );
487}
488
489/*
490 * Generate the contents of the ServerHello extension
491 */
492int mbedtls_ecjpake_tls_write_server_ext( mbedtls_ecjpake_context *ctx,
493 unsigned char *buf, size_t len, size_t *olen,
494 int (*f_rng)(void *, unsigned char *, size_t),
495 void *p_rng )
496{
497 return( ecjpake_kkpp_write( ctx->md_info, &ctx->grp, &ctx->grp.G,
498 &ctx->xa, &ctx->X3, &ctx->xb, &ctx->X4,
499 "server", buf, len, olen, f_rng, p_rng ) );
500}
501
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200502/*
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200503 * Compute the sum of three points R = A + B + C
504 */
505static int ecjpake_ecp_add3( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
506 const mbedtls_ecp_point *A,
507 const mbedtls_ecp_point *B,
508 const mbedtls_ecp_point *C )
509{
510 int ret;
511 mbedtls_mpi one;
512
513 mbedtls_mpi_init( &one );
514
515 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
516 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, A, &one, B ) );
517 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, R, &one, C ) );
518
519cleanup:
520 mbedtls_mpi_free( &one );
521
522 return( ret );
523}
524
525/*
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200526 * Read and process ServerECJPAKEParams (7.4.2.5)
527 */
528int mbedtls_ecjpake_tls_read_server_params( mbedtls_ecjpake_context *ctx,
529 const unsigned char *buf,
530 size_t len )
531{
532 int ret;
533 const unsigned char *p = buf;
534 const unsigned char *end = buf + len;
535 mbedtls_ecp_group grp;
536 mbedtls_ecp_point GB;
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200537
538 mbedtls_ecp_group_init( &grp );
539 mbedtls_ecp_point_init( &GB );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200540
541 /*
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200542 * GB = X1 + X2 + X3 (7.4.2.5.1)
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200543 * We need that before parsing in order to check Xs as we read it
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200544 */
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200545 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &GB,
546 &ctx->X1, &ctx->X2, &ctx->X3 ) );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200547
548 /*
549 * struct {
550 * ECParameters curve_params;
551 * ECJPAKEKeyKP ecjpake_key_kp;
552 * } ServerECJPAKEParams;
553 */
554 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_group( &grp, &p, len ) );
555 MBEDTLS_MPI_CHK( ecjpake_kkp_read( ctx->md_info, &ctx->grp,
556 &GB, &ctx->Xp, "server", &p, end ) );
557
558 if( p != end )
559 {
560 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
561 goto cleanup;
562 }
563
564 /*
565 * Xs already checked, only thing left to check is the group
566 */
567 if( grp.id != ctx->grp.id )
568 {
569 ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
570 goto cleanup;
571 }
572
573cleanup:
574 mbedtls_ecp_group_free( &grp );
575 mbedtls_ecp_point_free( &GB );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200576
577 return( ret );
578}
579
580/*
581 * Generate and write ServerECJPAKEParams (7.4.2.5)
582 */
583int mbedtls_ecjpake_tls_write_server_params( mbedtls_ecjpake_context *ctx,
584 unsigned char *buf, size_t len, size_t *olen,
585 int (*f_rng)(void *, unsigned char *, size_t),
586 void *p_rng )
587{
588 int ret;
589 mbedtls_ecp_point GB, Xs;
590 mbedtls_mpi xs;
591 unsigned char *p = buf;
592 const unsigned char *end = buf + len;
593 size_t ec_len;
594
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +0200595 if( end < p )
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200596 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
597
598 mbedtls_ecp_point_init( &GB );
599 mbedtls_ecp_point_init( &Xs );
600 mbedtls_mpi_init( &xs );
601
602 /*
603 * First generate private/public key pair (7.4.2.5.1)
604 *
605 * GB = X1 + X2 + X3
606 * xs = x4 * s mod n
607 * Xs = xs * GB
608 */
609 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &GB,
610 &ctx->X1, &ctx->X2, &ctx->X3 ) );
611 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &xs, &ctx->xb, &ctx->s ) );
612 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &xs, &xs, &ctx->grp.N ) );
613 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &Xs, &xs, &GB, f_rng, p_rng ) );
614
615 /*
616 * Now write things out
617 */
618 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_group( &ctx->grp, &ec_len,
619 p, end - p ) );
620 p += ec_len;
621
622 if( end < p )
623 {
624 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
625 goto cleanup;
626 }
627 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( &ctx->grp, &Xs,
628 MBEDTLS_ECP_PF_UNCOMPRESSED, &ec_len, p, end - p ) );
629 p += ec_len;
630
631 MBEDTLS_MPI_CHK( ecjpake_zkp_write( ctx->md_info, &ctx->grp,
632 &GB, &xs, &Xs, "server",
633 &p, end, f_rng, p_rng ) );
634
635 *olen = p - buf;
636
637cleanup:
638 mbedtls_ecp_point_free( &GB );
639 mbedtls_ecp_point_free( &Xs );
640 mbedtls_mpi_free( &xs );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200641
642 return( ret );
643}
644
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +0200645/*
646 * Read and process ClientECJPAKEParams (7.4.2.6)
647 */
648int mbedtls_ecjpake_tls_read_client_params( mbedtls_ecjpake_context *ctx,
649 const unsigned char *buf,
650 size_t len )
651{
652 int ret;
653 const unsigned char *p = buf;
654 const unsigned char *end = buf + len;
655 mbedtls_ecp_group grp;
656 mbedtls_ecp_point GA;
657
658 mbedtls_ecp_group_init( &grp );
659 mbedtls_ecp_point_init( &GA );
660
661 /*
662 * GA = X1 + X3 + X4 (7.4.2.6.1)
663 * We need that before parsing in order to check Xc as we read it
664 */
665 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &GA,
666 &ctx->X1, &ctx->X3, &ctx->X4 ) );
667
668 /*
669 * struct {
670 * ECJPAKEKeyKP ecjpake_key_kp;
671 * } CLientECJPAKEParams;
672 */
673 MBEDTLS_MPI_CHK( ecjpake_kkp_read( ctx->md_info, &ctx->grp,
674 &GA, &ctx->Xp, "client", &p, end ) );
675
676 if( p != end )
677 {
678 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
679 goto cleanup;
680 }
681
682cleanup:
683 mbedtls_ecp_group_free( &grp );
684 mbedtls_ecp_point_free( &GA );
685
686 return( ret );
687}
688
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +0200689/*
690 * Generate and write ClientECJPAKEParams (7.4.2.6)
691 */
692int mbedtls_ecjpake_tls_write_client_params( mbedtls_ecjpake_context *ctx,
693 unsigned char *buf, size_t len, size_t *olen,
694 int (*f_rng)(void *, unsigned char *, size_t),
695 void *p_rng )
696{
697 int ret;
698 mbedtls_ecp_point GA, Xc;
699 mbedtls_mpi xc;
700 unsigned char *p = buf;
701 const unsigned char *end = buf + len;
702 size_t ec_len;
703
704 if( end < p )
705 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
706
707 mbedtls_ecp_point_init( &GA );
708 mbedtls_ecp_point_init( &Xc );
709 mbedtls_mpi_init( &xc );
710
711 /*
712 * First generate private/public key pair (7.4.2.6.1)
713 *
714 * GA = X1 + X3 + X4
715 * xc = x2 * s mod n
716 * Xc = xc * GA
717 */
718 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &GA,
719 &ctx->X1, &ctx->X3, &ctx->X4 ) );
720 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &xc, &ctx->xb, &ctx->s ) );
721 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &xc, &xc, &ctx->grp.N ) );
722 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &Xc, &xc, &GA, f_rng, p_rng ) );
723
724 /*
725 * Now write things out
726 */
727 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( &ctx->grp, &Xc,
728 MBEDTLS_ECP_PF_UNCOMPRESSED, &ec_len, p, end - p ) );
729 p += ec_len;
730
731 MBEDTLS_MPI_CHK( ecjpake_zkp_write( ctx->md_info, &ctx->grp,
732 &GA, &xc, &Xc, "client",
733 &p, end, f_rng, p_rng ) );
734
735 *olen = p - buf;
736
737cleanup:
738 mbedtls_ecp_point_free( &GA );
739 mbedtls_ecp_point_free( &Xc );
740 mbedtls_mpi_free( &xc );
741
742 return( ret );
743}
744
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200745#if defined(MBEDTLS_SELF_TEST)
746
747#if defined(MBEDTLS_PLATFORM_C)
748#include "mbedtls/platform.h"
749#else
750#include <stdio.h>
751#define mbedtls_printf printf
752#endif
753
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200754#if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
755 !defined(MBEDTLS_SHA256_C)
756int mbedtls_ecjpake_self_test( int verbose )
757{
758 (void) verbose;
759 return( 0 );
760}
761#else
762
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200763static const unsigned char ecjpake_test_password[] = {
764 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x6a, 0x70, 0x61, 0x6b, 0x65, 0x74,
765 0x65, 0x73, 0x74
766};
767
768static const unsigned char ecjpake_test_x1[] = {
769 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
770 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
771 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21
772};
773
774static const unsigned char ecjpake_test_x2[] = {
775 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
776 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
777 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
778};
779
780static const unsigned char ecjpake_test_x3[] = {
781 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
782 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
783 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
784};
785
786static const unsigned char ecjpake_test_x4[] = {
787 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc,
788 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
789 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1
790};
791
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200792static const unsigned char ecjpake_test_cli_ext[] = {
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200793 0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19,
794 0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44,
795 0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad,
796 0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62,
797 0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9,
798 0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d,
799 0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e,
800 0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e,
801 0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73,
802 0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22,
803 0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce,
804 0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00,
805 0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200806 0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e,
807 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62,
808 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5,
809 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb,
810 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35,
811 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0,
812 0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb,
813 0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47,
814 0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39,
815 0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97,
816 0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40,
817 0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d,
818 0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa,
819 0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d,
820 0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200821};
822
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200823static const unsigned char ecjpake_test_srv_ext[] = {
824 0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb,
825 0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18,
826 0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47,
827 0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f,
828 0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7,
829 0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d,
830 0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64,
831 0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36,
832 0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2,
833 0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec,
834 0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16,
835 0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96,
836 0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3,
837 0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19,
838 0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f,
839 0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8,
840 0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7,
841 0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea,
842 0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5,
843 0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6,
844 0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31,
845 0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d,
846 0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8,
847 0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee,
848 0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84,
849 0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f,
850 0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80,
851 0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12
852};
853
854static const unsigned char ecjpake_test_srv_kx[] = {
855 0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23,
856 0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c,
857 0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f,
858 0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca,
859 0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26,
860 0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55,
861 0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38,
862 0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6,
863 0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9,
864 0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4,
865 0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2,
866 0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8,
867 0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd,
868 0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c
869};
870
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +0200871static const unsigned char ecjpake_test_cli_kx[] = {
872 0x41, 0x04, 0x69, 0xd5, 0x4e, 0xe8, 0x5e, 0x90, 0xce, 0x3f, 0x12, 0x46,
873 0x74, 0x2d, 0xe5, 0x07, 0xe9, 0x39, 0xe8, 0x1d, 0x1d, 0xc1, 0xc5, 0xcb,
874 0x98, 0x8b, 0x58, 0xc3, 0x10, 0xc9, 0xfd, 0xd9, 0x52, 0x4d, 0x93, 0x72,
875 0x0b, 0x45, 0x54, 0x1c, 0x83, 0xee, 0x88, 0x41, 0x19, 0x1d, 0xa7, 0xce,
876 0xd8, 0x6e, 0x33, 0x12, 0xd4, 0x36, 0x23, 0xc1, 0xd6, 0x3e, 0x74, 0x98,
877 0x9a, 0xba, 0x4a, 0xff, 0xd1, 0xee, 0x41, 0x04, 0x07, 0x7e, 0x8c, 0x31,
878 0xe2, 0x0e, 0x6b, 0xed, 0xb7, 0x60, 0xc1, 0x35, 0x93, 0xe6, 0x9f, 0x15,
879 0xbe, 0x85, 0xc2, 0x7d, 0x68, 0xcd, 0x09, 0xcc, 0xb8, 0xc4, 0x18, 0x36,
880 0x08, 0x91, 0x7c, 0x5c, 0x3d, 0x40, 0x9f, 0xac, 0x39, 0xfe, 0xfe, 0xe8,
881 0x2f, 0x72, 0x92, 0xd3, 0x6f, 0x0d, 0x23, 0xe0, 0x55, 0x91, 0x3f, 0x45,
882 0xa5, 0x2b, 0x85, 0xdd, 0x8a, 0x20, 0x52, 0xe9, 0xe1, 0x29, 0xbb, 0x4d,
883 0x20, 0x0f, 0x01, 0x1f, 0x19, 0x48, 0x35, 0x35, 0xa6, 0xe8, 0x9a, 0x58,
884 0x0c, 0x9b, 0x00, 0x03, 0xba, 0xf2, 0x14, 0x62, 0xec, 0xe9, 0x1a, 0x82,
885 0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c
886};
887
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200888/* For tests we don't need a secure RNG;
889 * use the LGC from Numerical Recipes for simplicity */
890static int ecjpake_lgc( void *p, unsigned char *out, size_t len )
891{
892 static uint32_t x = 42;
893 (void) p;
894
895 while( len > 0 )
896 {
897 size_t use_len = len > 4 ? 4 : len;
898 x = 1664525 * x + 1013904223;
899 memcpy( out, &x, use_len );
900 out += use_len;
901 len -= use_len;
902 }
903
904 return( 0 );
905}
906
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200907#define TEST_ASSERT( x ) \
908 do { \
909 if( x ) \
910 ret = 0; \
911 else \
912 { \
913 ret = 1; \
914 goto cleanup; \
915 } \
916 } while( 0 )
917
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200918/*
919 * Checkup routine
920 */
921int mbedtls_ecjpake_self_test( int verbose )
922{
923 int ret;
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200924 mbedtls_ecjpake_context cli;
925 mbedtls_ecjpake_context srv;
926 unsigned char buf[512];
927 size_t len;
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200928
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200929 mbedtls_ecjpake_init( &cli );
930 mbedtls_ecjpake_init( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200931
932 if( verbose != 0 )
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200933 mbedtls_printf( " ECJPAKE test #0 (setup): " );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200934
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200935 TEST_ASSERT( mbedtls_ecjpake_setup( &cli,
936 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
937 ecjpake_test_password,
938 sizeof( ecjpake_test_password ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200939
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200940 TEST_ASSERT( mbedtls_ecjpake_setup( &srv,
941 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
942 ecjpake_test_password,
943 sizeof( ecjpake_test_password ) ) == 0 );
944
945 if( verbose != 0 )
946 mbedtls_printf( "passed\n" );
947
948 if( verbose != 0 )
949 mbedtls_printf( " ECJPAKE test #1 (random handshake): " );
950
951 TEST_ASSERT( mbedtls_ecjpake_tls_write_client_ext( &cli,
952 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
953
954 TEST_ASSERT( mbedtls_ecjpake_tls_read_client_ext( &srv, buf, len ) == 0 );
955
956 TEST_ASSERT( mbedtls_ecjpake_tls_write_server_ext( &srv,
957 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
958
959 TEST_ASSERT( mbedtls_ecjpake_tls_read_server_ext( &cli, buf, len ) == 0 );
960
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200961 TEST_ASSERT( mbedtls_ecjpake_tls_write_server_params( &srv,
962 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
963
964 TEST_ASSERT( mbedtls_ecjpake_tls_read_server_params( &cli, buf, len ) == 0 );
965
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +0200966 TEST_ASSERT( mbedtls_ecjpake_tls_write_client_params( &cli,
967 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
968
969 TEST_ASSERT( mbedtls_ecjpake_tls_read_client_params( &srv, buf, len ) == 0 );
970
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200971 if( verbose != 0 )
972 mbedtls_printf( "passed\n" );
973
974 if( verbose != 0 )
975 mbedtls_printf( " ECJPAKE test #2 (reference handshake): " );
976
977 /* Simulate key generation on client, skip writing client_ext */
978 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &cli.xa,
979 ecjpake_test_x1, sizeof( ecjpake_test_x1 ) ) );
980 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &cli.xb,
981 ecjpake_test_x2, sizeof( ecjpake_test_x2 ) ) );
982 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &cli.grp, &cli.X1, &cli.xa,
983 &cli.grp.G, NULL, NULL ) );
984 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &cli.grp, &cli.X2, &cli.xb,
985 &cli.grp.G, NULL, NULL ) );
986
987 /* Server reads client ext */
988 TEST_ASSERT( mbedtls_ecjpake_tls_read_client_ext( &srv,
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200989 ecjpake_test_cli_ext,
990 sizeof( ecjpake_test_cli_ext ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200991
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200992 /* Simulate key generation on server, skip writing server_ext */
993 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &srv.xa,
994 ecjpake_test_x3, sizeof( ecjpake_test_x3 ) ) );
995 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &srv.xb,
996 ecjpake_test_x4, sizeof( ecjpake_test_x4 ) ) );
997 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &srv.grp, &srv.X3, &srv.xa,
998 &srv.grp.G, NULL, NULL ) );
999 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &srv.grp, &srv.X4, &srv.xb,
1000 &srv.grp.G, NULL, NULL ) );
1001
1002 /* Client reads server ext and key exchange */
1003 TEST_ASSERT( mbedtls_ecjpake_tls_read_server_ext( &cli,
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +02001004 ecjpake_test_srv_ext,
1005 sizeof( ecjpake_test_srv_ext ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001006
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001007 TEST_ASSERT( mbedtls_ecjpake_tls_read_server_params( &cli,
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +02001008 ecjpake_test_srv_kx,
1009 sizeof( ecjpake_test_srv_kx ) ) == 0 );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +02001010
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +02001011 /* Server reads client key exchange */
1012 TEST_ASSERT( mbedtls_ecjpake_tls_read_client_params( &srv,
1013 ecjpake_test_cli_kx,
1014 sizeof( ecjpake_test_cli_kx ) ) == 0 );
1015
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001016 if( verbose != 0 )
1017 mbedtls_printf( "passed\n" );
1018
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001019cleanup:
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001020 mbedtls_ecjpake_free( &cli );
1021 mbedtls_ecjpake_free( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001022
1023 if( ret != 0 )
1024 {
1025 if( verbose != 0 )
1026 mbedtls_printf( "failed\n" );
1027
1028 ret = 1;
1029 }
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001030
1031 if( verbose != 0 )
1032 mbedtls_printf( "\n" );
1033
1034 return( ret );
1035}
1036
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +02001037#undef TEST_ASSERT
1038
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001039#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_SHA256_C */
1040
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001041#endif /* MBEDTLS_SELF_TEST */
1042
1043#endif /* MBEDTLS_ECJPAKE_C */