blob: 987c7e3961bdd2ea2250440146e317e2e04303d1 [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é-Gonnard6b798b92015-08-14 11:18:30 +020023 * References in the code are to the Thread v1.0 Specification,
24 * available from the Thread Group http://threadgroup.org/
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é-Gonnarde0ad57b2015-08-14 11:10:39 +020040 * Convert a mbedtls_ecjpake_role to identifier string
41 */
42static const char * const ecjpake_id[] = {
43 "client",
44 "server"
45};
46
47#define ID_MINE ( ecjpake_id[ ctx->role ] )
48#define ID_PEER ( ecjpake_id[ 1 - ctx->role ] )
49
50/*
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020051 * Initialize context
52 */
53void mbedtls_ecjpake_init( mbedtls_ecjpake_context *ctx )
54{
55 if( ctx == NULL )
56 return;
57
58 ctx->md_info = NULL;
59 mbedtls_ecp_group_init( &ctx->grp );
60
61 mbedtls_ecp_point_init( &ctx->X1 );
62 mbedtls_ecp_point_init( &ctx->X2 );
63 mbedtls_ecp_point_init( &ctx->X3 );
64 mbedtls_ecp_point_init( &ctx->X4 );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +020065 mbedtls_ecp_point_init( &ctx->Xp );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020066
67 mbedtls_mpi_init( &ctx->xa );
68 mbedtls_mpi_init( &ctx->xb );
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +020069 mbedtls_mpi_init( &ctx->s );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020070}
71
72/*
73 * Free context
74 */
75void mbedtls_ecjpake_free( mbedtls_ecjpake_context *ctx )
76{
77 if( ctx == NULL )
78 return;
79
80 ctx->md_info = NULL;
81 mbedtls_ecp_group_free( &ctx->grp );
82
83 mbedtls_ecp_point_free( &ctx->X1 );
84 mbedtls_ecp_point_free( &ctx->X2 );
85 mbedtls_ecp_point_free( &ctx->X3 );
86 mbedtls_ecp_point_free( &ctx->X4 );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +020087 mbedtls_ecp_point_free( &ctx->Xp );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020088
89 mbedtls_mpi_free( &ctx->xa );
90 mbedtls_mpi_free( &ctx->xb );
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +020091 mbedtls_mpi_free( &ctx->s );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020092}
93
94/*
95 * Setup context
96 */
97int mbedtls_ecjpake_setup( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +020098 mbedtls_ecjpake_role role,
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020099 mbedtls_md_type_t hash,
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200100 mbedtls_ecp_group_id curve,
101 const unsigned char *secret,
102 size_t len )
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200103{
104 int ret;
105
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +0200106 ctx->role = role;
107
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200108 if( ( ctx->md_info = mbedtls_md_info_from_type( hash ) ) == NULL )
109 return( MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE );
110
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200111 MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ctx->grp, curve ) );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200112
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200113 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->s, secret, len ) );
114 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->s, &ctx->s, &ctx->grp.N ) );
115
116cleanup:
117 if( ret != 0 )
118 mbedtls_ecjpake_free( ctx );
119
120 return( ret );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200121}
122
123/*
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200124 * Write a point plus its length to a buffer
125 */
126static int ecjpake_write_len_point( unsigned char **p,
127 const unsigned char *end,
128 const mbedtls_ecp_group *grp,
129 const mbedtls_ecp_point *P )
130{
131 int ret;
132 size_t len;
133
134 /* Need at least 4 for length plus 1 for point */
135 if( end < *p || end - *p < 5 )
136 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
137
138 ret = mbedtls_ecp_point_write_binary( grp, P, MBEDTLS_ECP_PF_UNCOMPRESSED,
139 &len, *p + 4, end - ( *p + 4 ) );
140 if( ret != 0 )
141 return( ret );
142
143 (*p)[0] = (unsigned char)( ( len >> 24 ) & 0xFF );
144 (*p)[1] = (unsigned char)( ( len >> 16 ) & 0xFF );
145 (*p)[2] = (unsigned char)( ( len >> 8 ) & 0xFF );
146 (*p)[3] = (unsigned char)( ( len ) & 0xFF );
147
148 *p += 4 + len;
149
150 return( 0 );
151}
152
153/*
154 * Size of the temporary buffer for ecjpake_hash:
155 * 3 EC points plus their length, plus ID (6 bytes)
156 */
157#define ECJPAKE_HASH_BUF_LEN ( 3 * ( 4 + MBEDTLS_ECP_MAX_PT_LEN ) + 6 )
158
159/*
160 * Compute hash for ZKP (7.4.2.2.2.1)
161 */
162static int ecjpake_hash( const mbedtls_md_info_t *md_info,
163 const mbedtls_ecp_group *grp,
164 const mbedtls_ecp_point *G,
165 const mbedtls_ecp_point *V,
166 const mbedtls_ecp_point *X,
167 const char *id,
168 mbedtls_mpi *h )
169{
170 int ret;
171 unsigned char buf[ECJPAKE_HASH_BUF_LEN];
172 unsigned char *p = buf;
173 const unsigned char *end = buf + sizeof( buf );
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200174 const size_t id_len = strlen( id );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200175 unsigned char hash[MBEDTLS_MD_MAX_SIZE];
176
177 /* Write things to temporary buffer */
178 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, G ) );
179 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, V ) );
180 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, X ) );
181
182 if( end < p || (size_t)( end - p ) < id_len )
183 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
184
185 *p++ = (unsigned char)( ( id_len >> 24 ) & 0xFF );
186 *p++ = (unsigned char)( ( id_len >> 16 ) & 0xFF );
187 *p++ = (unsigned char)( ( id_len >> 8 ) & 0xFF );
188 *p++ = (unsigned char)( ( id_len ) & 0xFF );
189
190 memcpy( p, id, id_len );
191 p += id_len;
192
193 /* Compute hash */
194 mbedtls_md( md_info, buf, p - buf, hash );
195
196 /* Turn it into an integer mod n */
197 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( h, hash,
198 mbedtls_md_get_size( md_info ) ) );
199 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( h, h, &grp->N ) );
200
201cleanup:
202 return( ret );
203}
204
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200205/*
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200206 * Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3)
207 */
208static int ecjpake_zkp_read( const mbedtls_md_info_t *md_info,
209 const mbedtls_ecp_group *grp,
210 const mbedtls_ecp_point *G,
211 const mbedtls_ecp_point *X,
212 const char *id,
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200213 const unsigned char **p,
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200214 const unsigned char *end )
215{
216 int ret;
217 mbedtls_ecp_point V, VV;
218 mbedtls_mpi r, h;
219 size_t r_len;
220
221 mbedtls_ecp_point_init( &V );
222 mbedtls_ecp_point_init( &VV );
223 mbedtls_mpi_init( &r );
224 mbedtls_mpi_init( &h );
225
226 /*
227 * struct {
228 * ECPoint V;
229 * opaque r<1..2^8-1>;
230 * } ECSchnorrZKP;
231 */
232 if( end < *p )
233 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
234
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200235 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, &V, p, end - *p ) );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200236
237 if( end < *p || (size_t)( end - *p ) < 1 )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200238 {
239 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
240 goto cleanup;
241 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200242
243 r_len = *(*p)++;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200244
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200245 if( end < *p || (size_t)( end - *p ) < r_len )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200246 {
247 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
248 goto cleanup;
249 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200250
251 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &r, *p, r_len ) );
252 *p += r_len;
253
254 /*
255 * Verification
256 */
257 MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, G, &V, X, id, &h ) );
258 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( (mbedtls_ecp_group *) grp,
259 &VV, &h, X, &r, G ) );
260
261 if( mbedtls_ecp_point_cmp( &VV, &V ) != 0 )
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200262 {
263 ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
264 goto cleanup;
265 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200266
267cleanup:
268 mbedtls_ecp_point_free( &V );
269 mbedtls_ecp_point_free( &VV );
270 mbedtls_mpi_free( &r );
271 mbedtls_mpi_free( &h );
272
273 return( ret );
274}
275
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200276/*
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200277 * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2)
278 */
279static int ecjpake_zkp_write( const mbedtls_md_info_t *md_info,
280 const mbedtls_ecp_group *grp,
281 const mbedtls_ecp_point *G,
282 const mbedtls_mpi *x,
283 const mbedtls_ecp_point *X,
284 const char *id,
285 unsigned char **p,
286 const unsigned char *end,
287 int (*f_rng)(void *, unsigned char *, size_t),
288 void *p_rng )
289{
290 int ret;
291 mbedtls_ecp_point V;
292 mbedtls_mpi v;
293 mbedtls_mpi h; /* later recycled to hold r */
294 size_t len;
295
296 if( end < *p )
297 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
298
299 mbedtls_ecp_point_init( &V );
300 mbedtls_mpi_init( &v );
301 mbedtls_mpi_init( &h );
302
303 /* Compute signature */
304 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp,
305 G, &v, &V, f_rng, p_rng ) );
306 MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, G, &V, X, id, &h ) );
307 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &h, &h, x ) ); /* x*h */
308 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &h, &v, &h ) ); /* v - x*h */
309 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &h, &h, &grp->N ) ); /* r */
310
311 /* Write it out */
312 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, &V,
313 MBEDTLS_ECP_PF_UNCOMPRESSED, &len, *p, end - *p ) );
314 *p += len;
315
316 len = mbedtls_mpi_size( &h ); /* actually r */
317 if( end < *p || (size_t)( end - *p ) < 1 + len || len > 255 )
318 {
319 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
320 goto cleanup;
321 }
322
323 *(*p)++ = (unsigned char)( len & 0xFF );
324 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, *p, len ) ); /* r */
325 *p += len;
326
327cleanup:
328 mbedtls_ecp_point_free( &V );
329 mbedtls_mpi_free( &v );
330 mbedtls_mpi_free( &h );
331
332 return( ret );
333}
334
335/*
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200336 * Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof
337 * Output: verified public key X
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200338 */
339static int ecjpake_kkp_read( const mbedtls_md_info_t *md_info,
340 const mbedtls_ecp_group *grp,
341 const mbedtls_ecp_point *G,
342 mbedtls_ecp_point *X,
343 const char *id,
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200344 const unsigned char **p,
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200345 const unsigned char *end )
346{
347 int ret;
348
349 if( end < *p )
350 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
351
352 /*
353 * struct {
354 * ECPoint X;
355 * ECSchnorrZKP zkp;
356 * } ECJPAKEKeyKP;
357 */
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200358 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, X, p, end - *p ) );
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200359 MBEDTLS_MPI_CHK( ecjpake_zkp_read( md_info, grp, G, X, id, p, end ) );
360
361cleanup:
362 return( ret );
363}
364
365/*
366 * Generate an ECJPAKEKeyKP
367 * Output: the serialized structure, plus private/public key pair
368 */
369static int ecjpake_kkp_write( const mbedtls_md_info_t *md_info,
370 const mbedtls_ecp_group *grp,
371 const mbedtls_ecp_point *G,
372 mbedtls_mpi *x,
373 mbedtls_ecp_point *X,
374 const char *id,
375 unsigned char **p,
376 const unsigned char *end,
377 int (*f_rng)(void *, unsigned char *, size_t),
378 void *p_rng )
379{
380 int ret;
381 size_t len;
382
383 if( end < *p )
384 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
385
386 /* Generate key (7.4.2.3.1) and write it out */
387 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp, G, x, X,
388 f_rng, p_rng ) );
389 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, X,
390 MBEDTLS_ECP_PF_UNCOMPRESSED, &len, *p, end - *p ) );
391 *p += len;
392
393 /* Generate and write proof */
394 MBEDTLS_MPI_CHK( ecjpake_zkp_write( md_info, grp, G, x, X, id,
395 p, end, f_rng, p_rng ) );
396
397cleanup:
398 return( ret );
399}
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200400
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200401/*
402 * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs
403 * Ouputs: verified peer public keys Xa, Xb
404 */
405static int ecjpake_kkpp_read( const mbedtls_md_info_t *md_info,
406 const mbedtls_ecp_group *grp,
407 const mbedtls_ecp_point *G,
408 mbedtls_ecp_point *Xa,
409 mbedtls_ecp_point *Xb,
410 const char *id,
411 const unsigned char *buf,
412 size_t len )
413{
414 int ret;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200415 const unsigned char *p = buf;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200416 const unsigned char *end = buf + len;
417
418 /*
419 * struct {
420 * ECJPAKEKeyKP ecjpake_key_kp_pair_list[2];
421 * } ECJPAKEKeyKPPairList;
422 */
423 MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, G, Xa, id, &p, end ) );
424 MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, G, Xb, id, &p, end ) );
425
426 if( p != end )
427 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
428
429cleanup:
430 return( ret );
431}
432
433/*
434 * Generate a ECJPAKEKeyKPPairList
435 * Outputs: the serialized structure, plus two private/public key pairs
436 */
437static int ecjpake_kkpp_write( const mbedtls_md_info_t *md_info,
438 const mbedtls_ecp_group *grp,
439 const mbedtls_ecp_point *G,
440 mbedtls_mpi *xa,
441 mbedtls_ecp_point *Xa,
442 mbedtls_mpi *xb,
443 mbedtls_ecp_point *Xb,
444 const char *id,
445 unsigned char *buf,
446 size_t len,
447 size_t *olen,
448 int (*f_rng)(void *, unsigned char *, size_t),
449 void *p_rng )
450{
451 int ret;
452 unsigned char *p = buf;
453 const unsigned char *end = buf + len;
454
455 MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, G, xa, Xa, id,
456 &p, end, f_rng, p_rng ) );
457 MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, G, xb, Xb, id,
458 &p, end, f_rng, p_rng ) );
459
460 *olen = p - buf;
461
462cleanup:
463 return( ret );
464}
465
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200466/*
467 * Read the contents of the ClientHello extension
468 */
469int mbedtls_ecjpake_tls_read_client_ext( mbedtls_ecjpake_context *ctx,
470 const unsigned char *buf,
471 size_t len )
472{
473 return( ecjpake_kkpp_read( ctx->md_info, &ctx->grp, &ctx->grp.G,
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200474 &ctx->X1, &ctx->X2, ID_PEER,
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200475 buf, len ) );
476}
477
478/*
479 * Read the contents of the ServerHello extension
480 */
481int mbedtls_ecjpake_tls_read_server_ext( mbedtls_ecjpake_context *ctx,
482 const unsigned char *buf,
483 size_t len )
484{
485 return( ecjpake_kkpp_read( ctx->md_info, &ctx->grp, &ctx->grp.G,
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200486 &ctx->X3, &ctx->X4, ID_PEER,
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200487 buf, len ) );
488}
489
490/*
491 * Generate the contents of the ClientHello extension
492 */
493int mbedtls_ecjpake_tls_write_client_ext( mbedtls_ecjpake_context *ctx,
494 unsigned char *buf, size_t len, size_t *olen,
495 int (*f_rng)(void *, unsigned char *, size_t),
496 void *p_rng )
497{
498 return( ecjpake_kkpp_write( ctx->md_info, &ctx->grp, &ctx->grp.G,
499 &ctx->xa, &ctx->X1, &ctx->xb, &ctx->X2,
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200500 ID_MINE, buf, len, olen, f_rng, p_rng ) );
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200501}
502
503/*
504 * Generate the contents of the ServerHello extension
505 */
506int mbedtls_ecjpake_tls_write_server_ext( mbedtls_ecjpake_context *ctx,
507 unsigned char *buf, size_t len, size_t *olen,
508 int (*f_rng)(void *, unsigned char *, size_t),
509 void *p_rng )
510{
511 return( ecjpake_kkpp_write( ctx->md_info, &ctx->grp, &ctx->grp.G,
512 &ctx->xa, &ctx->X3, &ctx->xb, &ctx->X4,
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200513 ID_MINE, buf, len, olen, f_rng, p_rng ) );
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200514}
515
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200516/*
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200517 * Compute the sum of three points R = A + B + C
518 */
519static int ecjpake_ecp_add3( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
520 const mbedtls_ecp_point *A,
521 const mbedtls_ecp_point *B,
522 const mbedtls_ecp_point *C )
523{
524 int ret;
525 mbedtls_mpi one;
526
527 mbedtls_mpi_init( &one );
528
529 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
530 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, A, &one, B ) );
531 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, R, &one, C ) );
532
533cleanup:
534 mbedtls_mpi_free( &one );
535
536 return( ret );
537}
538
539/*
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200540 * Read and process ServerECJPAKEParams (7.4.2.5)
541 */
542int mbedtls_ecjpake_tls_read_server_params( mbedtls_ecjpake_context *ctx,
543 const unsigned char *buf,
544 size_t len )
545{
546 int ret;
547 const unsigned char *p = buf;
548 const unsigned char *end = buf + len;
549 mbedtls_ecp_group grp;
550 mbedtls_ecp_point GB;
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200551
552 mbedtls_ecp_group_init( &grp );
553 mbedtls_ecp_point_init( &GB );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200554
555 /*
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200556 * GB = X1 + X2 + X3 (7.4.2.5.1)
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200557 * We need that before parsing in order to check Xs as we read it
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200558 */
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200559 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &GB,
560 &ctx->X1, &ctx->X2, &ctx->X3 ) );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200561
562 /*
563 * struct {
564 * ECParameters curve_params;
565 * ECJPAKEKeyKP ecjpake_key_kp;
566 * } ServerECJPAKEParams;
567 */
568 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_group( &grp, &p, len ) );
569 MBEDTLS_MPI_CHK( ecjpake_kkp_read( ctx->md_info, &ctx->grp,
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200570 &GB, &ctx->Xp, ID_PEER, &p, end ) );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200571
572 if( p != end )
573 {
574 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
575 goto cleanup;
576 }
577
578 /*
579 * Xs already checked, only thing left to check is the group
580 */
581 if( grp.id != ctx->grp.id )
582 {
583 ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
584 goto cleanup;
585 }
586
587cleanup:
588 mbedtls_ecp_group_free( &grp );
589 mbedtls_ecp_point_free( &GB );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200590
591 return( ret );
592}
593
594/*
595 * Generate and write ServerECJPAKEParams (7.4.2.5)
596 */
597int mbedtls_ecjpake_tls_write_server_params( mbedtls_ecjpake_context *ctx,
598 unsigned char *buf, size_t len, size_t *olen,
599 int (*f_rng)(void *, unsigned char *, size_t),
600 void *p_rng )
601{
602 int ret;
603 mbedtls_ecp_point GB, Xs;
604 mbedtls_mpi xs;
605 unsigned char *p = buf;
606 const unsigned char *end = buf + len;
607 size_t ec_len;
608
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +0200609 if( end < p )
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200610 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
611
612 mbedtls_ecp_point_init( &GB );
613 mbedtls_ecp_point_init( &Xs );
614 mbedtls_mpi_init( &xs );
615
616 /*
617 * First generate private/public key pair (7.4.2.5.1)
618 *
619 * GB = X1 + X2 + X3
620 * xs = x4 * s mod n
621 * Xs = xs * GB
622 */
623 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &GB,
624 &ctx->X1, &ctx->X2, &ctx->X3 ) );
625 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &xs, &ctx->xb, &ctx->s ) );
626 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &xs, &xs, &ctx->grp.N ) );
627 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &Xs, &xs, &GB, f_rng, p_rng ) );
628
629 /*
630 * Now write things out
631 */
632 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_group( &ctx->grp, &ec_len,
633 p, end - p ) );
634 p += ec_len;
635
636 if( end < p )
637 {
638 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
639 goto cleanup;
640 }
641 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( &ctx->grp, &Xs,
642 MBEDTLS_ECP_PF_UNCOMPRESSED, &ec_len, p, end - p ) );
643 p += ec_len;
644
645 MBEDTLS_MPI_CHK( ecjpake_zkp_write( ctx->md_info, &ctx->grp,
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200646 &GB, &xs, &Xs, ID_MINE,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200647 &p, end, f_rng, p_rng ) );
648
649 *olen = p - buf;
650
651cleanup:
652 mbedtls_ecp_point_free( &GB );
653 mbedtls_ecp_point_free( &Xs );
654 mbedtls_mpi_free( &xs );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200655
656 return( ret );
657}
658
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +0200659/*
660 * Read and process ClientECJPAKEParams (7.4.2.6)
661 */
662int mbedtls_ecjpake_tls_read_client_params( mbedtls_ecjpake_context *ctx,
663 const unsigned char *buf,
664 size_t len )
665{
666 int ret;
667 const unsigned char *p = buf;
668 const unsigned char *end = buf + len;
669 mbedtls_ecp_group grp;
670 mbedtls_ecp_point GA;
671
672 mbedtls_ecp_group_init( &grp );
673 mbedtls_ecp_point_init( &GA );
674
675 /*
676 * GA = X1 + X3 + X4 (7.4.2.6.1)
677 * We need that before parsing in order to check Xc as we read it
678 */
679 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &GA,
680 &ctx->X1, &ctx->X3, &ctx->X4 ) );
681
682 /*
683 * struct {
684 * ECJPAKEKeyKP ecjpake_key_kp;
685 * } CLientECJPAKEParams;
686 */
687 MBEDTLS_MPI_CHK( ecjpake_kkp_read( ctx->md_info, &ctx->grp,
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200688 &GA, &ctx->Xp, ID_PEER, &p, end ) );
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +0200689
690 if( p != end )
691 {
692 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
693 goto cleanup;
694 }
695
696cleanup:
697 mbedtls_ecp_group_free( &grp );
698 mbedtls_ecp_point_free( &GA );
699
700 return( ret );
701}
702
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +0200703/*
704 * Generate and write ClientECJPAKEParams (7.4.2.6)
705 */
706int mbedtls_ecjpake_tls_write_client_params( mbedtls_ecjpake_context *ctx,
707 unsigned char *buf, size_t len, size_t *olen,
708 int (*f_rng)(void *, unsigned char *, size_t),
709 void *p_rng )
710{
711 int ret;
712 mbedtls_ecp_point GA, Xc;
713 mbedtls_mpi xc;
714 unsigned char *p = buf;
715 const unsigned char *end = buf + len;
716 size_t ec_len;
717
718 if( end < p )
719 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
720
721 mbedtls_ecp_point_init( &GA );
722 mbedtls_ecp_point_init( &Xc );
723 mbedtls_mpi_init( &xc );
724
725 /*
726 * First generate private/public key pair (7.4.2.6.1)
727 *
728 * GA = X1 + X3 + X4
729 * xc = x2 * s mod n
730 * Xc = xc * GA
731 */
732 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &GA,
733 &ctx->X1, &ctx->X3, &ctx->X4 ) );
734 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &xc, &ctx->xb, &ctx->s ) );
735 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &xc, &xc, &ctx->grp.N ) );
736 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &Xc, &xc, &GA, f_rng, p_rng ) );
737
738 /*
739 * Now write things out
740 */
741 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( &ctx->grp, &Xc,
742 MBEDTLS_ECP_PF_UNCOMPRESSED, &ec_len, p, end - p ) );
743 p += ec_len;
744
745 MBEDTLS_MPI_CHK( ecjpake_zkp_write( ctx->md_info, &ctx->grp,
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200746 &GA, &xc, &Xc, ID_MINE,
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +0200747 &p, end, f_rng, p_rng ) );
748
749 *olen = p - buf;
750
751cleanup:
752 mbedtls_ecp_point_free( &GA );
753 mbedtls_ecp_point_free( &Xc );
754 mbedtls_mpi_free( &xc );
755
756 return( ret );
757}
758
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200759/*
760 * Derive PMS (7.4.2.7 / 7.4.2.8)
761 */
762int mbedtls_ecjpake_tls_derive_pms( mbedtls_ecjpake_context *ctx,
763 unsigned char *buf, size_t len, size_t *olen,
764 int (*f_rng)(void *, unsigned char *, size_t),
765 void *p_rng )
766{
767 int ret;
768 mbedtls_ecp_point K, *X42;
769 mbedtls_mpi xbs, one;
770 unsigned char kx[MBEDTLS_ECP_MAX_BYTES];
771 size_t x_bytes;
772
773 *olen = mbedtls_md_get_size( ctx->md_info );
774 if( len < *olen )
775 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
776
777 mbedtls_ecp_point_init( &K );
778 mbedtls_mpi_init( &xbs );
779 mbedtls_mpi_init( &one );
780
781 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
782 X42 = ctx->role == MBEDTLS_ECJPAKE_CLIENT ? &ctx->X4 : &ctx->X2;
783
784 /*
785 * Client: K = ( Xs - X4 * x2 * s ) * x2
786 * Server: K = ( Xc - X2 * x4 * s ) * x4
787 * Unified: K = ( Xp - X42 * xb * x ) * xb
788 */
789 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &xbs, &ctx->xb, &ctx->s ) );
790 xbs.s *= -1;
791 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &xbs, &xbs, &ctx->grp.N ) );
792
793 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( &ctx->grp, &K,
794 &one, &ctx->Xp,
795 &xbs, X42 ) );
796 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &K, &ctx->xb, &K,
797 f_rng, p_rng ) );
798
799 /* PMS = SHA-256( K.X ) */
800 x_bytes = ( ctx->grp.pbits + 7 ) / 8;
801 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &K.X, kx, x_bytes ) );
802 MBEDTLS_MPI_CHK( mbedtls_md( ctx->md_info, kx, x_bytes, buf ) );
803
804cleanup:
805 mbedtls_ecp_point_free( &K );
806 mbedtls_mpi_free( &xbs );
807 mbedtls_mpi_free( &one );
808
809 return( ret );
810}
811
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200812#undef ID_MINE
813#undef ID_PEER
814
815
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200816#if defined(MBEDTLS_SELF_TEST)
817
818#if defined(MBEDTLS_PLATFORM_C)
819#include "mbedtls/platform.h"
820#else
821#include <stdio.h>
822#define mbedtls_printf printf
823#endif
824
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200825#if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
826 !defined(MBEDTLS_SHA256_C)
827int mbedtls_ecjpake_self_test( int verbose )
828{
829 (void) verbose;
830 return( 0 );
831}
832#else
833
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200834static const unsigned char ecjpake_test_password[] = {
835 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x6a, 0x70, 0x61, 0x6b, 0x65, 0x74,
836 0x65, 0x73, 0x74
837};
838
839static const unsigned char ecjpake_test_x1[] = {
840 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
841 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
842 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21
843};
844
845static const unsigned char ecjpake_test_x2[] = {
846 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
847 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
848 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
849};
850
851static const unsigned char ecjpake_test_x3[] = {
852 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
853 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
854 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
855};
856
857static const unsigned char ecjpake_test_x4[] = {
858 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc,
859 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
860 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1
861};
862
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200863static const unsigned char ecjpake_test_cli_ext[] = {
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200864 0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19,
865 0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44,
866 0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad,
867 0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62,
868 0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9,
869 0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d,
870 0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e,
871 0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e,
872 0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73,
873 0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22,
874 0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce,
875 0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00,
876 0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200877 0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e,
878 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62,
879 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5,
880 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb,
881 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35,
882 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0,
883 0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb,
884 0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47,
885 0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39,
886 0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97,
887 0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40,
888 0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d,
889 0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa,
890 0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d,
891 0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200892};
893
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200894static const unsigned char ecjpake_test_srv_ext[] = {
895 0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb,
896 0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18,
897 0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47,
898 0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f,
899 0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7,
900 0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d,
901 0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64,
902 0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36,
903 0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2,
904 0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec,
905 0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16,
906 0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96,
907 0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3,
908 0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19,
909 0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f,
910 0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8,
911 0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7,
912 0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea,
913 0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5,
914 0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6,
915 0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31,
916 0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d,
917 0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8,
918 0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee,
919 0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84,
920 0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f,
921 0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80,
922 0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12
923};
924
925static const unsigned char ecjpake_test_srv_kx[] = {
926 0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23,
927 0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c,
928 0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f,
929 0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca,
930 0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26,
931 0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55,
932 0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38,
933 0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6,
934 0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9,
935 0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4,
936 0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2,
937 0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8,
938 0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd,
939 0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c
940};
941
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +0200942static const unsigned char ecjpake_test_cli_kx[] = {
943 0x41, 0x04, 0x69, 0xd5, 0x4e, 0xe8, 0x5e, 0x90, 0xce, 0x3f, 0x12, 0x46,
944 0x74, 0x2d, 0xe5, 0x07, 0xe9, 0x39, 0xe8, 0x1d, 0x1d, 0xc1, 0xc5, 0xcb,
945 0x98, 0x8b, 0x58, 0xc3, 0x10, 0xc9, 0xfd, 0xd9, 0x52, 0x4d, 0x93, 0x72,
946 0x0b, 0x45, 0x54, 0x1c, 0x83, 0xee, 0x88, 0x41, 0x19, 0x1d, 0xa7, 0xce,
947 0xd8, 0x6e, 0x33, 0x12, 0xd4, 0x36, 0x23, 0xc1, 0xd6, 0x3e, 0x74, 0x98,
948 0x9a, 0xba, 0x4a, 0xff, 0xd1, 0xee, 0x41, 0x04, 0x07, 0x7e, 0x8c, 0x31,
949 0xe2, 0x0e, 0x6b, 0xed, 0xb7, 0x60, 0xc1, 0x35, 0x93, 0xe6, 0x9f, 0x15,
950 0xbe, 0x85, 0xc2, 0x7d, 0x68, 0xcd, 0x09, 0xcc, 0xb8, 0xc4, 0x18, 0x36,
951 0x08, 0x91, 0x7c, 0x5c, 0x3d, 0x40, 0x9f, 0xac, 0x39, 0xfe, 0xfe, 0xe8,
952 0x2f, 0x72, 0x92, 0xd3, 0x6f, 0x0d, 0x23, 0xe0, 0x55, 0x91, 0x3f, 0x45,
953 0xa5, 0x2b, 0x85, 0xdd, 0x8a, 0x20, 0x52, 0xe9, 0xe1, 0x29, 0xbb, 0x4d,
954 0x20, 0x0f, 0x01, 0x1f, 0x19, 0x48, 0x35, 0x35, 0xa6, 0xe8, 0x9a, 0x58,
955 0x0c, 0x9b, 0x00, 0x03, 0xba, 0xf2, 0x14, 0x62, 0xec, 0xe9, 0x1a, 0x82,
956 0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c
957};
958
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200959static const unsigned char ecjpake_test_pms[] = {
960 0xf3, 0xd4, 0x7f, 0x59, 0x98, 0x44, 0xdb, 0x92, 0xa5, 0x69, 0xbb, 0xe7,
961 0x98, 0x1e, 0x39, 0xd9, 0x31, 0xfd, 0x74, 0x3b, 0xf2, 0x2e, 0x98, 0xf9,
962 0xb4, 0x38, 0xf7, 0x19, 0xd3, 0xc4, 0xf3, 0x51
963};
964
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200965/* For tests we don't need a secure RNG;
966 * use the LGC from Numerical Recipes for simplicity */
967static int ecjpake_lgc( void *p, unsigned char *out, size_t len )
968{
969 static uint32_t x = 42;
970 (void) p;
971
972 while( len > 0 )
973 {
974 size_t use_len = len > 4 ? 4 : len;
975 x = 1664525 * x + 1013904223;
976 memcpy( out, &x, use_len );
977 out += use_len;
978 len -= use_len;
979 }
980
981 return( 0 );
982}
983
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200984#define TEST_ASSERT( x ) \
985 do { \
986 if( x ) \
987 ret = 0; \
988 else \
989 { \
990 ret = 1; \
991 goto cleanup; \
992 } \
993 } while( 0 )
994
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200995/*
996 * Checkup routine
997 */
998int mbedtls_ecjpake_self_test( int verbose )
999{
1000 int ret;
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001001 mbedtls_ecjpake_context cli;
1002 mbedtls_ecjpake_context srv;
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001003 unsigned char buf[512], pms[32];
1004 size_t len, pmslen;
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001005
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001006 mbedtls_ecjpake_init( &cli );
1007 mbedtls_ecjpake_init( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001008
1009 if( verbose != 0 )
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001010 mbedtls_printf( " ECJPAKE test #0 (setup): " );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +02001011
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +02001012 TEST_ASSERT( mbedtls_ecjpake_setup( &cli, MBEDTLS_ECJPAKE_CLIENT,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001013 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1014 ecjpake_test_password,
1015 sizeof( ecjpake_test_password ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001016
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +02001017 TEST_ASSERT( mbedtls_ecjpake_setup( &srv, MBEDTLS_ECJPAKE_SERVER,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001018 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1019 ecjpake_test_password,
1020 sizeof( ecjpake_test_password ) ) == 0 );
1021
1022 if( verbose != 0 )
1023 mbedtls_printf( "passed\n" );
1024
1025 if( verbose != 0 )
1026 mbedtls_printf( " ECJPAKE test #1 (random handshake): " );
1027
1028 TEST_ASSERT( mbedtls_ecjpake_tls_write_client_ext( &cli,
1029 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1030
1031 TEST_ASSERT( mbedtls_ecjpake_tls_read_client_ext( &srv, buf, len ) == 0 );
1032
1033 TEST_ASSERT( mbedtls_ecjpake_tls_write_server_ext( &srv,
1034 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1035
1036 TEST_ASSERT( mbedtls_ecjpake_tls_read_server_ext( &cli, buf, len ) == 0 );
1037
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +02001038 TEST_ASSERT( mbedtls_ecjpake_tls_write_server_params( &srv,
1039 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1040
1041 TEST_ASSERT( mbedtls_ecjpake_tls_read_server_params( &cli, buf, len ) == 0 );
1042
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001043 TEST_ASSERT( mbedtls_ecjpake_tls_derive_pms( &cli,
1044 pms, sizeof( pms ), &pmslen, ecjpake_lgc, NULL ) == 0 );
1045
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +02001046 TEST_ASSERT( mbedtls_ecjpake_tls_write_client_params( &cli,
1047 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1048
1049 TEST_ASSERT( mbedtls_ecjpake_tls_read_client_params( &srv, buf, len ) == 0 );
1050
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001051 TEST_ASSERT( mbedtls_ecjpake_tls_derive_pms( &srv,
1052 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1053
1054 TEST_ASSERT( len == pmslen );
1055 TEST_ASSERT( memcmp( buf, pms, len ) == 0 );
1056
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001057 if( verbose != 0 )
1058 mbedtls_printf( "passed\n" );
1059
1060 if( verbose != 0 )
1061 mbedtls_printf( " ECJPAKE test #2 (reference handshake): " );
1062
1063 /* Simulate key generation on client, skip writing client_ext */
1064 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &cli.xa,
1065 ecjpake_test_x1, sizeof( ecjpake_test_x1 ) ) );
1066 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &cli.xb,
1067 ecjpake_test_x2, sizeof( ecjpake_test_x2 ) ) );
1068 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &cli.grp, &cli.X1, &cli.xa,
1069 &cli.grp.G, NULL, NULL ) );
1070 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &cli.grp, &cli.X2, &cli.xb,
1071 &cli.grp.G, NULL, NULL ) );
1072
1073 /* Server reads client ext */
1074 TEST_ASSERT( mbedtls_ecjpake_tls_read_client_ext( &srv,
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +02001075 ecjpake_test_cli_ext,
1076 sizeof( ecjpake_test_cli_ext ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001077
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001078 /* Simulate key generation on server, skip writing server_ext */
1079 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &srv.xa,
1080 ecjpake_test_x3, sizeof( ecjpake_test_x3 ) ) );
1081 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &srv.xb,
1082 ecjpake_test_x4, sizeof( ecjpake_test_x4 ) ) );
1083 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &srv.grp, &srv.X3, &srv.xa,
1084 &srv.grp.G, NULL, NULL ) );
1085 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &srv.grp, &srv.X4, &srv.xb,
1086 &srv.grp.G, NULL, NULL ) );
1087
1088 /* Client reads server ext and key exchange */
1089 TEST_ASSERT( mbedtls_ecjpake_tls_read_server_ext( &cli,
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +02001090 ecjpake_test_srv_ext,
1091 sizeof( ecjpake_test_srv_ext ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001092
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001093 TEST_ASSERT( mbedtls_ecjpake_tls_read_server_params( &cli,
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +02001094 ecjpake_test_srv_kx,
1095 sizeof( ecjpake_test_srv_kx ) ) == 0 );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +02001096
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +02001097 /* Server reads client key exchange */
1098 TEST_ASSERT( mbedtls_ecjpake_tls_read_client_params( &srv,
1099 ecjpake_test_cli_kx,
1100 sizeof( ecjpake_test_cli_kx ) ) == 0 );
1101
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001102 /* Server derives PMS */
1103 TEST_ASSERT( mbedtls_ecjpake_tls_derive_pms( &srv,
1104 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1105
1106 TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
1107 TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
1108
1109 memset( buf, 0, len ); /* Avoid interferences with next step */
1110
1111 /* Client derives PMS */
1112 TEST_ASSERT( mbedtls_ecjpake_tls_derive_pms( &cli,
1113 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1114
1115 TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
1116 TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
1117
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001118 if( verbose != 0 )
1119 mbedtls_printf( "passed\n" );
1120
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001121cleanup:
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001122 mbedtls_ecjpake_free( &cli );
1123 mbedtls_ecjpake_free( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001124
1125 if( ret != 0 )
1126 {
1127 if( verbose != 0 )
1128 mbedtls_printf( "failed\n" );
1129
1130 ret = 1;
1131 }
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001132
1133 if( verbose != 0 )
1134 mbedtls_printf( "\n" );
1135
1136 return( ret );
1137}
1138
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +02001139#undef TEST_ASSERT
1140
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001141#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_SHA256_C */
1142
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001143#endif /* MBEDTLS_SELF_TEST */
1144
1145#endif /* MBEDTLS_ECJPAKE_C */