blob: b80ca1a06c97e59832ba0893ab6d1596f3158f57 [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é-Gonnardcb7cd032015-08-13 10:09:10 +0200581static const unsigned char ecjpake_test_cli_ext[] = {
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200582 0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19,
583 0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44,
584 0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad,
585 0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62,
586 0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9,
587 0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d,
588 0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e,
589 0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e,
590 0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73,
591 0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22,
592 0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce,
593 0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00,
594 0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200595 0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e,
596 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62,
597 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5,
598 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb,
599 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35,
600 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0,
601 0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb,
602 0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47,
603 0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39,
604 0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97,
605 0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40,
606 0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d,
607 0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa,
608 0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d,
609 0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200610};
611
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200612static const unsigned char ecjpake_test_srv_ext[] = {
613 0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb,
614 0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18,
615 0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47,
616 0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f,
617 0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7,
618 0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d,
619 0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64,
620 0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36,
621 0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2,
622 0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec,
623 0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16,
624 0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96,
625 0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3,
626 0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19,
627 0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f,
628 0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8,
629 0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7,
630 0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea,
631 0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5,
632 0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6,
633 0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31,
634 0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d,
635 0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8,
636 0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee,
637 0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84,
638 0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f,
639 0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80,
640 0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12
641};
642
643static const unsigned char ecjpake_test_srv_kx[] = {
644 0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23,
645 0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c,
646 0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f,
647 0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca,
648 0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26,
649 0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55,
650 0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38,
651 0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6,
652 0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9,
653 0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4,
654 0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2,
655 0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8,
656 0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd,
657 0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c
658};
659
660#if 0
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200661/* For tests we don't need a secure RNG;
662 * use the LGC from Numerical Recipes for simplicity */
663static int ecjpake_lgc( void *p, unsigned char *out, size_t len )
664{
665 static uint32_t x = 42;
666 (void) p;
667
668 while( len > 0 )
669 {
670 size_t use_len = len > 4 ? 4 : len;
671 x = 1664525 * x + 1013904223;
672 memcpy( out, &x, use_len );
673 out += use_len;
674 len -= use_len;
675 }
676
677 return( 0 );
678}
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200679#endif
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200680
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200681#define TEST_ASSERT( x ) \
682 do { \
683 if( x ) \
684 ret = 0; \
685 else \
686 { \
687 ret = 1; \
688 goto cleanup; \
689 } \
690 } while( 0 )
691
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200692/*
693 * Checkup routine
694 */
695int mbedtls_ecjpake_self_test( int verbose )
696{
697 int ret;
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200698 mbedtls_ecjpake_context ctx;
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200699 char secret[] = "test passphrase";
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200700
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200701 mbedtls_ecjpake_init( &ctx );
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200702
703 /* Common to all tests */
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200704 TEST_ASSERT( mbedtls_ecjpake_setup( &ctx,
705 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
706 (const unsigned char *) secret,
707 sizeof( secret ) - 1 ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200708
709 if( verbose != 0 )
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200710 mbedtls_printf( " ECJPAKE test #1 (read in sequence): " );
711
712 /* This is not realistic because it uses the same context for client and
713 * server, but it ensures the context has all of X1 to X4 when reading the
714 * key exchange message, so this is convenient for a quick test */
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200715
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200716 TEST_ASSERT( mbedtls_ecjpake_tls_read_client_ext( &ctx,
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200717 ecjpake_test_cli_ext,
718 sizeof( ecjpake_test_cli_ext ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200719
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200720 TEST_ASSERT( mbedtls_ecjpake_tls_read_server_ext( &ctx,
721 ecjpake_test_srv_ext,
722 sizeof( ecjpake_test_srv_ext ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200723
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200724 TEST_ASSERT( mbedtls_ecjpake_tls_read_server_params( &ctx,
725 ecjpake_test_srv_kx,
726 sizeof( ecjpake_test_srv_kx ) ) == 0 );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200727
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200728 if( verbose != 0 )
729 mbedtls_printf( "passed\n" );
730
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200731cleanup:
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200732 mbedtls_ecjpake_free( &ctx );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200733
734 if( ret != 0 )
735 {
736 if( verbose != 0 )
737 mbedtls_printf( "failed\n" );
738
739 ret = 1;
740 }
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200741
742 if( verbose != 0 )
743 mbedtls_printf( "\n" );
744
745 return( ret );
746}
747
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200748#undef TEST_ASSERT
749
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200750#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_SHA256_C */
751
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200752#endif /* MBEDTLS_SELF_TEST */
753
754#endif /* MBEDTLS_ECJPAKE_C */