blob: b0fda20130db88288f254cfee6d54fdacb030bb7 [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
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +020061 mbedtls_ecp_point_init( &ctx->Xm1 );
62 mbedtls_ecp_point_init( &ctx->Xm2 );
63 mbedtls_ecp_point_init( &ctx->Xp1 );
64 mbedtls_ecp_point_init( &ctx->Xp2 );
65 mbedtls_ecp_point_init( &ctx->Xp );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020066
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +020067 mbedtls_mpi_init( &ctx->xm1 );
68 mbedtls_mpi_init( &ctx->xm2 );
69 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
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +020083 mbedtls_ecp_point_free( &ctx->Xm1 );
84 mbedtls_ecp_point_free( &ctx->Xm2 );
85 mbedtls_ecp_point_free( &ctx->Xp1 );
86 mbedtls_ecp_point_free( &ctx->Xp2 );
87 mbedtls_ecp_point_free( &ctx->Xp );
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020088
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +020089 mbedtls_mpi_free( &ctx->xm1 );
90 mbedtls_mpi_free( &ctx->xm2 );
91 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,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200440 mbedtls_mpi *xm1,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200441 mbedtls_ecp_point *Xa,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200442 mbedtls_mpi *xm2,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200443 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
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200455 MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, G, xm1, Xa, id,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200456 &p, end, f_rng, p_rng ) );
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200457 MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, G, xm2, Xb, id,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200458 &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/*
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200467 * Read and process the first round message
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200468 */
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200469int mbedtls_ecjpake_read_round_one( mbedtls_ecjpake_context *ctx,
470 const unsigned char *buf,
471 size_t len )
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200472{
473 return( ecjpake_kkpp_read( ctx->md_info, &ctx->grp, &ctx->grp.G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200474 &ctx->Xp1, &ctx->Xp2, ID_PEER,
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200475 buf, len ) );
476}
477
478/*
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200479 * Generate and write the first round message
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200480 */
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200481int mbedtls_ecjpake_write_round_one( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200482 unsigned char *buf, size_t len, size_t *olen,
483 int (*f_rng)(void *, unsigned char *, size_t),
484 void *p_rng )
485{
486 return( ecjpake_kkpp_write( ctx->md_info, &ctx->grp, &ctx->grp.G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200487 &ctx->xm1, &ctx->Xm1, &ctx->xm2, &ctx->Xm2,
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200488 ID_MINE, buf, len, olen, f_rng, p_rng ) );
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200489}
490
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200491/*
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200492 * Compute the sum of three points R = A + B + C
493 */
494static int ecjpake_ecp_add3( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
495 const mbedtls_ecp_point *A,
496 const mbedtls_ecp_point *B,
497 const mbedtls_ecp_point *C )
498{
499 int ret;
500 mbedtls_mpi one;
501
502 mbedtls_mpi_init( &one );
503
504 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
505 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, A, &one, B ) );
506 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, R, &one, C ) );
507
508cleanup:
509 mbedtls_mpi_free( &one );
510
511 return( ret );
512}
513
514/*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200515 * Read and process second round message (C: 7.4.2.5, S: 7.4.2.6)
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200516 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200517int mbedtls_ecjpake_read_round_two( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200518 const unsigned char *buf,
519 size_t len )
520{
521 int ret;
522 const unsigned char *p = buf;
523 const unsigned char *end = buf + len;
524 mbedtls_ecp_group grp;
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200525 mbedtls_ecp_point G;
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200526
527 mbedtls_ecp_group_init( &grp );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200528 mbedtls_ecp_point_init( &G );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200529
530 /*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200531 * Server: GA = X3 + X4 + X1 (7.4.2.6.1)
532 * Client: GB = X1 + X2 + X3 (7.4.2.5.1)
533 * Unified: G = Xm1 + Xm2 + Xp1
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200534 * We need that before parsing in order to check Xp as we read it
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200535 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200536 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200537 &ctx->Xm1, &ctx->Xm2, &ctx->Xp1 ) );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200538
539 /*
540 * struct {
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200541 * ECParameters curve_params; // only client reading server msg
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200542 * ECJPAKEKeyKP ecjpake_key_kp;
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200543 * } Client/ServerECJPAKEParams;
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200544 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200545 if( ctx->role == MBEDTLS_ECJPAKE_CLIENT )
546 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_group( &grp, &p, len ) );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200547 MBEDTLS_MPI_CHK( ecjpake_kkp_read( ctx->md_info, &ctx->grp,
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200548 &G, &ctx->Xp, ID_PEER, &p, end ) );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200549
550 if( p != end )
551 {
552 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
553 goto cleanup;
554 }
555
556 /*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200557 * Xs already checked, only thing left to check is the group,
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200558 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200559 if( ctx->role == MBEDTLS_ECJPAKE_CLIENT && grp.id != ctx->grp.id )
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200560 {
561 ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
562 goto cleanup;
563 }
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200564cleanup:
565 mbedtls_ecp_group_free( &grp );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200566 mbedtls_ecp_point_free( &G );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200567
568 return( ret );
569}
570
571/*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200572 * Generate and write the second round message (S: 7.4.2.5, C: 7.4.2.6)
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200573 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200574int mbedtls_ecjpake_write_round_two( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200575 unsigned char *buf, size_t len, size_t *olen,
576 int (*f_rng)(void *, unsigned char *, size_t),
577 void *p_rng )
578{
579 int ret;
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200580 mbedtls_ecp_point G; /* C: GA, S: GB */
581 mbedtls_ecp_point Xm; /* C: Xc, S: Xs */
582 mbedtls_mpi xm; /* C: xc, S: xs */
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200583 unsigned char *p = buf;
584 const unsigned char *end = buf + len;
585 size_t ec_len;
586
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200587 mbedtls_ecp_point_init( &G );
588 mbedtls_ecp_point_init( &Xm );
589 mbedtls_mpi_init( &xm );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200590
591 /*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200592 * First generate private/public key pair (S: 7.4.2.5.1, C: 7.4.2.6.1)
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200593 *
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200594 * Client: GA = X1 + X3 + X4 | xs = x2 * s | Xc = xc * GA
595 * Server: GB = X3 + X1 + X2 | xs = x4 * s | Xs = xs * GB
596 * Unified: G = Xm1 + Xp1 + Xp2 | xm = xm2 * s | Xm = xm * G
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200597 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200598 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200599 &ctx->Xp1, &ctx->Xp2, &ctx->Xm1 ) );
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200600 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &xm, &ctx->xm2, &ctx->s ) );
601 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &xm, &xm, &ctx->grp.N ) );
602 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &Xm, &xm, &G, f_rng, p_rng ) );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200603
604 /*
605 * Now write things out
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200606 *
607 * struct {
608 * ECParameters curve_params; // only server writing its message
609 * ECJPAKEKeyKP ecjpake_key_kp;
610 * } Client/ServerECJPAKEParams;
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200611 */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200612 if( ctx->role == MBEDTLS_ECJPAKE_SERVER )
613 {
614 if( end < p )
615 {
616 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
617 goto cleanup;
618 }
619 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_group( &ctx->grp, &ec_len,
620 p, end - p ) );
621 p += ec_len;
622 }
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200623
624 if( end < p )
625 {
626 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
627 goto cleanup;
628 }
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200629 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( &ctx->grp, &Xm,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200630 MBEDTLS_ECP_PF_UNCOMPRESSED, &ec_len, p, end - p ) );
631 p += ec_len;
632
633 MBEDTLS_MPI_CHK( ecjpake_zkp_write( ctx->md_info, &ctx->grp,
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200634 &G, &xm, &Xm, ID_MINE,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200635 &p, end, f_rng, p_rng ) );
636
637 *olen = p - buf;
638
639cleanup:
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200640 mbedtls_ecp_point_free( &G );
641 mbedtls_ecp_point_free( &Xm );
642 mbedtls_mpi_free( &xm );
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +0200643
644 return( ret );
645}
646
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200647/*
648 * Derive PMS (7.4.2.7 / 7.4.2.8)
649 */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +0200650int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200651 unsigned char *buf, size_t len, size_t *olen,
652 int (*f_rng)(void *, unsigned char *, size_t),
653 void *p_rng )
654{
655 int ret;
656 mbedtls_ecp_point K, *X42;
657 mbedtls_mpi xbs, one;
658 unsigned char kx[MBEDTLS_ECP_MAX_BYTES];
659 size_t x_bytes;
660
661 *olen = mbedtls_md_get_size( ctx->md_info );
662 if( len < *olen )
663 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
664
665 mbedtls_ecp_point_init( &K );
666 mbedtls_mpi_init( &xbs );
667 mbedtls_mpi_init( &one );
668
669 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200670 X42 = ctx->role == MBEDTLS_ECJPAKE_CLIENT ? &ctx->Xp2 : &ctx->Xp2;
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200671
672 /*
673 * Client: K = ( Xs - X4 * x2 * s ) * x2
674 * Server: K = ( Xc - X2 * x4 * s ) * x4
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200675 * Unified: K = ( Xp - X42 * xm2 * x ) * xm2
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200676 */
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200677 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &xbs, &ctx->xm2, &ctx->s ) );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200678 xbs.s *= -1;
679 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &xbs, &xbs, &ctx->grp.N ) );
680
681 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( &ctx->grp, &K,
682 &one, &ctx->Xp,
683 &xbs, X42 ) );
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200684 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &K, &ctx->xm2, &K,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200685 f_rng, p_rng ) );
686
687 /* PMS = SHA-256( K.X ) */
688 x_bytes = ( ctx->grp.pbits + 7 ) / 8;
689 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &K.X, kx, x_bytes ) );
690 MBEDTLS_MPI_CHK( mbedtls_md( ctx->md_info, kx, x_bytes, buf ) );
691
692cleanup:
693 mbedtls_ecp_point_free( &K );
694 mbedtls_mpi_free( &xbs );
695 mbedtls_mpi_free( &one );
696
697 return( ret );
698}
699
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200700#undef ID_MINE
701#undef ID_PEER
702
703
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200704#if defined(MBEDTLS_SELF_TEST)
705
706#if defined(MBEDTLS_PLATFORM_C)
707#include "mbedtls/platform.h"
708#else
709#include <stdio.h>
710#define mbedtls_printf printf
711#endif
712
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200713#if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
714 !defined(MBEDTLS_SHA256_C)
715int mbedtls_ecjpake_self_test( int verbose )
716{
717 (void) verbose;
718 return( 0 );
719}
720#else
721
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200722static const unsigned char ecjpake_test_password[] = {
723 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x6a, 0x70, 0x61, 0x6b, 0x65, 0x74,
724 0x65, 0x73, 0x74
725};
726
727static const unsigned char ecjpake_test_x1[] = {
728 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
729 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
730 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21
731};
732
733static const unsigned char ecjpake_test_x2[] = {
734 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
735 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
736 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
737};
738
739static const unsigned char ecjpake_test_x3[] = {
740 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
741 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
742 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
743};
744
745static const unsigned char ecjpake_test_x4[] = {
746 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc,
747 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
748 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1
749};
750
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200751static const unsigned char ecjpake_test_cli_ext[] = {
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200752 0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19,
753 0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44,
754 0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad,
755 0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62,
756 0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9,
757 0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d,
758 0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e,
759 0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e,
760 0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73,
761 0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22,
762 0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce,
763 0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00,
764 0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200765 0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e,
766 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62,
767 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5,
768 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb,
769 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35,
770 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0,
771 0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb,
772 0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47,
773 0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39,
774 0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97,
775 0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40,
776 0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d,
777 0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa,
778 0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d,
779 0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200780};
781
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200782static const unsigned char ecjpake_test_srv_ext[] = {
783 0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb,
784 0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18,
785 0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47,
786 0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f,
787 0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7,
788 0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d,
789 0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64,
790 0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36,
791 0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2,
792 0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec,
793 0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16,
794 0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96,
795 0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3,
796 0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19,
797 0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f,
798 0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8,
799 0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7,
800 0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea,
801 0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5,
802 0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6,
803 0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31,
804 0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d,
805 0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8,
806 0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee,
807 0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84,
808 0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f,
809 0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80,
810 0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12
811};
812
813static const unsigned char ecjpake_test_srv_kx[] = {
814 0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23,
815 0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c,
816 0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f,
817 0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca,
818 0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26,
819 0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55,
820 0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38,
821 0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6,
822 0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9,
823 0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4,
824 0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2,
825 0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8,
826 0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd,
827 0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c
828};
829
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +0200830static const unsigned char ecjpake_test_cli_kx[] = {
831 0x41, 0x04, 0x69, 0xd5, 0x4e, 0xe8, 0x5e, 0x90, 0xce, 0x3f, 0x12, 0x46,
832 0x74, 0x2d, 0xe5, 0x07, 0xe9, 0x39, 0xe8, 0x1d, 0x1d, 0xc1, 0xc5, 0xcb,
833 0x98, 0x8b, 0x58, 0xc3, 0x10, 0xc9, 0xfd, 0xd9, 0x52, 0x4d, 0x93, 0x72,
834 0x0b, 0x45, 0x54, 0x1c, 0x83, 0xee, 0x88, 0x41, 0x19, 0x1d, 0xa7, 0xce,
835 0xd8, 0x6e, 0x33, 0x12, 0xd4, 0x36, 0x23, 0xc1, 0xd6, 0x3e, 0x74, 0x98,
836 0x9a, 0xba, 0x4a, 0xff, 0xd1, 0xee, 0x41, 0x04, 0x07, 0x7e, 0x8c, 0x31,
837 0xe2, 0x0e, 0x6b, 0xed, 0xb7, 0x60, 0xc1, 0x35, 0x93, 0xe6, 0x9f, 0x15,
838 0xbe, 0x85, 0xc2, 0x7d, 0x68, 0xcd, 0x09, 0xcc, 0xb8, 0xc4, 0x18, 0x36,
839 0x08, 0x91, 0x7c, 0x5c, 0x3d, 0x40, 0x9f, 0xac, 0x39, 0xfe, 0xfe, 0xe8,
840 0x2f, 0x72, 0x92, 0xd3, 0x6f, 0x0d, 0x23, 0xe0, 0x55, 0x91, 0x3f, 0x45,
841 0xa5, 0x2b, 0x85, 0xdd, 0x8a, 0x20, 0x52, 0xe9, 0xe1, 0x29, 0xbb, 0x4d,
842 0x20, 0x0f, 0x01, 0x1f, 0x19, 0x48, 0x35, 0x35, 0xa6, 0xe8, 0x9a, 0x58,
843 0x0c, 0x9b, 0x00, 0x03, 0xba, 0xf2, 0x14, 0x62, 0xec, 0xe9, 0x1a, 0x82,
844 0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c
845};
846
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200847static const unsigned char ecjpake_test_pms[] = {
848 0xf3, 0xd4, 0x7f, 0x59, 0x98, 0x44, 0xdb, 0x92, 0xa5, 0x69, 0xbb, 0xe7,
849 0x98, 0x1e, 0x39, 0xd9, 0x31, 0xfd, 0x74, 0x3b, 0xf2, 0x2e, 0x98, 0xf9,
850 0xb4, 0x38, 0xf7, 0x19, 0xd3, 0xc4, 0xf3, 0x51
851};
852
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +0200853/* Load my private keys and generate the correponding public keys */
854static int ecjpake_test_load( mbedtls_ecjpake_context *ctx,
855 const unsigned char *xm1, size_t len1,
856 const unsigned char *xm2, size_t len2 )
857{
858 int ret;
859
860 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm1, xm1, len1 ) );
861 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm2, xm2, len2 ) );
862 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm1, &ctx->xm1,
863 &ctx->grp.G, NULL, NULL ) );
864 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm2, &ctx->xm2,
865 &ctx->grp.G, NULL, NULL ) );
866
867cleanup:
868 return( ret );
869}
870
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200871/* For tests we don't need a secure RNG;
872 * use the LGC from Numerical Recipes for simplicity */
873static int ecjpake_lgc( void *p, unsigned char *out, size_t len )
874{
875 static uint32_t x = 42;
876 (void) p;
877
878 while( len > 0 )
879 {
880 size_t use_len = len > 4 ? 4 : len;
881 x = 1664525 * x + 1013904223;
882 memcpy( out, &x, use_len );
883 out += use_len;
884 len -= use_len;
885 }
886
887 return( 0 );
888}
889
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200890#define TEST_ASSERT( x ) \
891 do { \
892 if( x ) \
893 ret = 0; \
894 else \
895 { \
896 ret = 1; \
897 goto cleanup; \
898 } \
899 } while( 0 )
900
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200901/*
902 * Checkup routine
903 */
904int mbedtls_ecjpake_self_test( int verbose )
905{
906 int ret;
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200907 mbedtls_ecjpake_context cli;
908 mbedtls_ecjpake_context srv;
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200909 unsigned char buf[512], pms[32];
910 size_t len, pmslen;
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200911
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200912 mbedtls_ecjpake_init( &cli );
913 mbedtls_ecjpake_init( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200914
915 if( verbose != 0 )
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200916 mbedtls_printf( " ECJPAKE test #0 (setup): " );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200917
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +0200918 TEST_ASSERT( mbedtls_ecjpake_setup( &cli, MBEDTLS_ECJPAKE_CLIENT,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200919 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
920 ecjpake_test_password,
921 sizeof( ecjpake_test_password ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200922
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +0200923 TEST_ASSERT( mbedtls_ecjpake_setup( &srv, MBEDTLS_ECJPAKE_SERVER,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200924 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
925 ecjpake_test_password,
926 sizeof( ecjpake_test_password ) ) == 0 );
927
928 if( verbose != 0 )
929 mbedtls_printf( "passed\n" );
930
931 if( verbose != 0 )
932 mbedtls_printf( " ECJPAKE test #1 (random handshake): " );
933
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200934 TEST_ASSERT( mbedtls_ecjpake_write_round_one( &cli,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200935 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
936
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200937 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv, buf, len ) == 0 );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200938
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200939 TEST_ASSERT( mbedtls_ecjpake_write_round_one( &srv,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200940 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
941
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200942 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli, buf, len ) == 0 );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200943
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200944 TEST_ASSERT( mbedtls_ecjpake_write_round_two( &srv,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200945 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
946
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200947 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli, buf, len ) == 0 );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200948
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +0200949 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200950 pms, sizeof( pms ), &pmslen, ecjpake_lgc, NULL ) == 0 );
951
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200952 TEST_ASSERT( mbedtls_ecjpake_write_round_two( &cli,
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +0200953 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
954
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200955 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv, buf, len ) == 0 );
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +0200956
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +0200957 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200958 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
959
960 TEST_ASSERT( len == pmslen );
961 TEST_ASSERT( memcmp( buf, pms, len ) == 0 );
962
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200963 if( verbose != 0 )
964 mbedtls_printf( "passed\n" );
965
966 if( verbose != 0 )
967 mbedtls_printf( " ECJPAKE test #2 (reference handshake): " );
968
969 /* Simulate key generation on client, skip writing client_ext */
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +0200970 MBEDTLS_MPI_CHK( ecjpake_test_load( &cli,
971 ecjpake_test_x1, sizeof( ecjpake_test_x1 ),
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200972 ecjpake_test_x2, sizeof( ecjpake_test_x2 ) ) );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200973
974 /* Server reads client ext */
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200975 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv,
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200976 ecjpake_test_cli_ext,
977 sizeof( ecjpake_test_cli_ext ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200978
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200979 /* Simulate key generation on server, skip writing server_ext */
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +0200980 MBEDTLS_MPI_CHK( ecjpake_test_load( &srv,
981 ecjpake_test_x3, sizeof( ecjpake_test_x3 ),
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200982 ecjpake_test_x4, sizeof( ecjpake_test_x4 ) ) );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200983
984 /* Client reads server ext and key exchange */
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200985 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli,
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200986 ecjpake_test_srv_ext,
987 sizeof( ecjpake_test_srv_ext ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200988
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200989 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli,
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200990 ecjpake_test_srv_kx,
991 sizeof( ecjpake_test_srv_kx ) ) == 0 );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200992
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +0200993 /* Server reads client key exchange */
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200994 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv,
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +0200995 ecjpake_test_cli_kx,
996 sizeof( ecjpake_test_cli_kx ) ) == 0 );
997
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200998 /* Server derives PMS */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +0200999 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001000 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1001
1002 TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
1003 TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
1004
1005 memset( buf, 0, len ); /* Avoid interferences with next step */
1006
1007 /* Client derives PMS */
Manuel Pégourié-Gonnardf7368c92015-08-14 14:33:05 +02001008 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001009 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1010
1011 TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
1012 TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
1013
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001014 if( verbose != 0 )
1015 mbedtls_printf( "passed\n" );
1016
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001017cleanup:
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001018 mbedtls_ecjpake_free( &cli );
1019 mbedtls_ecjpake_free( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001020
1021 if( ret != 0 )
1022 {
1023 if( verbose != 0 )
1024 mbedtls_printf( "failed\n" );
1025
1026 ret = 1;
1027 }
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001028
1029 if( verbose != 0 )
1030 mbedtls_printf( "\n" );
1031
1032 return( ret );
1033}
1034
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +02001035#undef TEST_ASSERT
1036
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001037#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_SHA256_C */
1038
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001039#endif /* MBEDTLS_SELF_TEST */
1040
1041#endif /* MBEDTLS_ECJPAKE_C */