blob: 95be8a3cbf7a3069cdda537d31a8eced7ef22461 [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/*
503 * Read and process ServerECJPAKEParams (7.4.2.5)
504 */
505int mbedtls_ecjpake_tls_read_server_params( mbedtls_ecjpake_context *ctx,
506 const unsigned char *buf,
507 size_t len )
508{
509 int ret;
510 const unsigned char *p = buf;
511 const unsigned char *end = buf + len;
512 mbedtls_ecp_group grp;
513 mbedtls_ecp_point GB;
514 mbedtls_mpi one;
515
516 mbedtls_ecp_group_init( &grp );
517 mbedtls_ecp_point_init( &GB );
518 mbedtls_mpi_init( &one );
519
520 /*
521 * We need that before parsing in order to check Xs as we read it
522 * GB = X1 + X2 + X3 (7.4.2.5.1)
523 */
524 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
525 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( &ctx->grp, &GB, &one, &ctx->X1,
526 &one, &ctx->X2 ) );
527 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( &ctx->grp, &GB, &one, &GB,
528 &one, &ctx->X3 ) );
529
530 /*
531 * struct {
532 * ECParameters curve_params;
533 * ECJPAKEKeyKP ecjpake_key_kp;
534 * } ServerECJPAKEParams;
535 */
536 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_group( &grp, &p, len ) );
537 MBEDTLS_MPI_CHK( ecjpake_kkp_read( ctx->md_info, &ctx->grp,
538 &GB, &ctx->Xp, "server", &p, end ) );
539
540 if( p != end )
541 {
542 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
543 goto cleanup;
544 }
545
546 /*
547 * Xs already checked, only thing left to check is the group
548 */
549 if( grp.id != ctx->grp.id )
550 {
551 ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
552 goto cleanup;
553 }
554
555cleanup:
556 mbedtls_ecp_group_free( &grp );
557 mbedtls_ecp_point_free( &GB );
558 mbedtls_mpi_free( &one );
559
560 return( ret );
561}
562
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200563#if defined(MBEDTLS_SELF_TEST)
564
565#if defined(MBEDTLS_PLATFORM_C)
566#include "mbedtls/platform.h"
567#else
568#include <stdio.h>
569#define mbedtls_printf printf
570#endif
571
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200572#if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
573 !defined(MBEDTLS_SHA256_C)
574int mbedtls_ecjpake_self_test( int verbose )
575{
576 (void) verbose;
577 return( 0 );
578}
579#else
580
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200581static const unsigned char ecjpake_test_password[] = {
582 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x6a, 0x70, 0x61, 0x6b, 0x65, 0x74,
583 0x65, 0x73, 0x74
584};
585
586static const unsigned char ecjpake_test_x1[] = {
587 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
588 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
589 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21
590};
591
592static const unsigned char ecjpake_test_x2[] = {
593 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
594 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
595 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
596};
597
598static const unsigned char ecjpake_test_x3[] = {
599 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
600 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
601 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
602};
603
604static const unsigned char ecjpake_test_x4[] = {
605 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc,
606 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
607 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1
608};
609
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200610static const unsigned char ecjpake_test_cli_ext[] = {
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200611 0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19,
612 0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44,
613 0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad,
614 0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62,
615 0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9,
616 0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d,
617 0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e,
618 0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e,
619 0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73,
620 0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22,
621 0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce,
622 0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00,
623 0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200624 0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e,
625 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62,
626 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5,
627 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb,
628 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35,
629 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0,
630 0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb,
631 0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47,
632 0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39,
633 0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97,
634 0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40,
635 0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d,
636 0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa,
637 0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d,
638 0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200639};
640
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200641static const unsigned char ecjpake_test_srv_ext[] = {
642 0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb,
643 0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18,
644 0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47,
645 0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f,
646 0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7,
647 0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d,
648 0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64,
649 0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36,
650 0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2,
651 0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec,
652 0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16,
653 0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96,
654 0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3,
655 0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19,
656 0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f,
657 0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8,
658 0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7,
659 0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea,
660 0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5,
661 0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6,
662 0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31,
663 0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d,
664 0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8,
665 0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee,
666 0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84,
667 0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f,
668 0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80,
669 0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12
670};
671
672static const unsigned char ecjpake_test_srv_kx[] = {
673 0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23,
674 0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c,
675 0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f,
676 0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca,
677 0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26,
678 0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55,
679 0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38,
680 0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6,
681 0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9,
682 0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4,
683 0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2,
684 0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8,
685 0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd,
686 0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c
687};
688
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200689/* For tests we don't need a secure RNG;
690 * use the LGC from Numerical Recipes for simplicity */
691static int ecjpake_lgc( void *p, unsigned char *out, size_t len )
692{
693 static uint32_t x = 42;
694 (void) p;
695
696 while( len > 0 )
697 {
698 size_t use_len = len > 4 ? 4 : len;
699 x = 1664525 * x + 1013904223;
700 memcpy( out, &x, use_len );
701 out += use_len;
702 len -= use_len;
703 }
704
705 return( 0 );
706}
707
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200708#define TEST_ASSERT( x ) \
709 do { \
710 if( x ) \
711 ret = 0; \
712 else \
713 { \
714 ret = 1; \
715 goto cleanup; \
716 } \
717 } while( 0 )
718
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200719/*
720 * Checkup routine
721 */
722int mbedtls_ecjpake_self_test( int verbose )
723{
724 int ret;
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200725 mbedtls_ecjpake_context cli;
726 mbedtls_ecjpake_context srv;
727 unsigned char buf[512];
728 size_t len;
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200729
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200730 mbedtls_ecjpake_init( &cli );
731 mbedtls_ecjpake_init( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200732
733 if( verbose != 0 )
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200734 mbedtls_printf( " ECJPAKE test #0 (setup): " );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200735
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200736 TEST_ASSERT( mbedtls_ecjpake_setup( &cli,
737 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
738 ecjpake_test_password,
739 sizeof( ecjpake_test_password ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200740
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200741 TEST_ASSERT( mbedtls_ecjpake_setup( &srv,
742 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
743 ecjpake_test_password,
744 sizeof( ecjpake_test_password ) ) == 0 );
745
746 if( verbose != 0 )
747 mbedtls_printf( "passed\n" );
748
749 if( verbose != 0 )
750 mbedtls_printf( " ECJPAKE test #1 (random handshake): " );
751
752 TEST_ASSERT( mbedtls_ecjpake_tls_write_client_ext( &cli,
753 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
754
755 TEST_ASSERT( mbedtls_ecjpake_tls_read_client_ext( &srv, buf, len ) == 0 );
756
757 TEST_ASSERT( mbedtls_ecjpake_tls_write_server_ext( &srv,
758 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
759
760 TEST_ASSERT( mbedtls_ecjpake_tls_read_server_ext( &cli, buf, len ) == 0 );
761
762 if( verbose != 0 )
763 mbedtls_printf( "passed\n" );
764
765 if( verbose != 0 )
766 mbedtls_printf( " ECJPAKE test #2 (reference handshake): " );
767
768 /* Simulate key generation on client, skip writing client_ext */
769 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &cli.xa,
770 ecjpake_test_x1, sizeof( ecjpake_test_x1 ) ) );
771 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &cli.xb,
772 ecjpake_test_x2, sizeof( ecjpake_test_x2 ) ) );
773 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &cli.grp, &cli.X1, &cli.xa,
774 &cli.grp.G, NULL, NULL ) );
775 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &cli.grp, &cli.X2, &cli.xb,
776 &cli.grp.G, NULL, NULL ) );
777
778 /* Server reads client ext */
779 TEST_ASSERT( mbedtls_ecjpake_tls_read_client_ext( &srv,
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200780 ecjpake_test_cli_ext,
781 sizeof( ecjpake_test_cli_ext ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200782
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200783 /* Simulate key generation on server, skip writing server_ext */
784 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &srv.xa,
785 ecjpake_test_x3, sizeof( ecjpake_test_x3 ) ) );
786 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &srv.xb,
787 ecjpake_test_x4, sizeof( ecjpake_test_x4 ) ) );
788 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &srv.grp, &srv.X3, &srv.xa,
789 &srv.grp.G, NULL, NULL ) );
790 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &srv.grp, &srv.X4, &srv.xb,
791 &srv.grp.G, NULL, NULL ) );
792
793 /* Client reads server ext and key exchange */
794 TEST_ASSERT( mbedtls_ecjpake_tls_read_server_ext( &cli,
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200795 ecjpake_test_srv_ext,
796 sizeof( ecjpake_test_srv_ext ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200797
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200798 TEST_ASSERT( mbedtls_ecjpake_tls_read_server_params( &cli,
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200799 ecjpake_test_srv_kx,
800 sizeof( ecjpake_test_srv_kx ) ) == 0 );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200801
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200802 if( verbose != 0 )
803 mbedtls_printf( "passed\n" );
804
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200805cleanup:
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200806 mbedtls_ecjpake_free( &cli );
807 mbedtls_ecjpake_free( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200808
809 if( ret != 0 )
810 {
811 if( verbose != 0 )
812 mbedtls_printf( "failed\n" );
813
814 ret = 1;
815 }
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200816
817 if( verbose != 0 )
818 mbedtls_printf( "\n" );
819
820 return( ret );
821}
822
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200823#undef TEST_ASSERT
824
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200825#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_SHA256_C */
826
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200827#endif /* MBEDTLS_SELF_TEST */
828
829#endif /* MBEDTLS_ECJPAKE_C */