blob: 08d54d79af5b09730ebd29f4220183e0e3969d60 [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é-Gonnardcb7cd032015-08-13 10:09:10 +0200515 * Read and process ServerECJPAKEParams (7.4.2.5)
516 */
517int mbedtls_ecjpake_tls_read_server_params( mbedtls_ecjpake_context *ctx,
518 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;
525 mbedtls_ecp_point GB;
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200526
527 mbedtls_ecp_group_init( &grp );
528 mbedtls_ecp_point_init( &GB );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200529
530 /*
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200531 * Client: GB = X1 + X2 + X3 (7.4.2.5.1)
532 * Unified: GB = Xm1 + Xm2 + Xp1
533 * We need that before parsing in order to check Xp as we read it
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200534 */
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200535 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &GB,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200536 &ctx->Xm1, &ctx->Xm2, &ctx->Xp1 ) );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200537
538 /*
539 * struct {
540 * ECParameters curve_params;
541 * ECJPAKEKeyKP ecjpake_key_kp;
542 * } ServerECJPAKEParams;
543 */
544 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_group( &grp, &p, len ) );
545 MBEDTLS_MPI_CHK( ecjpake_kkp_read( ctx->md_info, &ctx->grp,
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200546 &GB, &ctx->Xp, ID_PEER, &p, end ) );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200547
548 if( p != end )
549 {
550 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
551 goto cleanup;
552 }
553
554 /*
555 * Xs already checked, only thing left to check is the group
556 */
557 if( grp.id != ctx->grp.id )
558 {
559 ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
560 goto cleanup;
561 }
562
563cleanup:
564 mbedtls_ecp_group_free( &grp );
565 mbedtls_ecp_point_free( &GB );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200566
567 return( ret );
568}
569
570/*
571 * Generate and write ServerECJPAKEParams (7.4.2.5)
572 */
573int mbedtls_ecjpake_tls_write_server_params( mbedtls_ecjpake_context *ctx,
574 unsigned char *buf, size_t len, size_t *olen,
575 int (*f_rng)(void *, unsigned char *, size_t),
576 void *p_rng )
577{
578 int ret;
579 mbedtls_ecp_point GB, Xs;
580 mbedtls_mpi xs;
581 unsigned char *p = buf;
582 const unsigned char *end = buf + len;
583 size_t ec_len;
584
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +0200585 if( end < p )
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200586 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
587
588 mbedtls_ecp_point_init( &GB );
589 mbedtls_ecp_point_init( &Xs );
590 mbedtls_mpi_init( &xs );
591
592 /*
593 * First generate private/public key pair (7.4.2.5.1)
594 *
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200595 * Server: GB = X1 + X2 + X3
596 * Unified:
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200597 * xs = x4 * s mod n
598 * Xs = xs * GB
599 */
600 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &GB,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200601 &ctx->Xp1, &ctx->Xp2, &ctx->Xm1 ) );
602 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &xs, &ctx->xm2, &ctx->s ) );
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200603 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &xs, &xs, &ctx->grp.N ) );
604 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &Xs, &xs, &GB, f_rng, p_rng ) );
605
606 /*
607 * Now write things out
608 */
609 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_group( &ctx->grp, &ec_len,
610 p, end - p ) );
611 p += ec_len;
612
613 if( end < p )
614 {
615 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
616 goto cleanup;
617 }
618 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( &ctx->grp, &Xs,
619 MBEDTLS_ECP_PF_UNCOMPRESSED, &ec_len, p, end - p ) );
620 p += ec_len;
621
622 MBEDTLS_MPI_CHK( ecjpake_zkp_write( ctx->md_info, &ctx->grp,
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200623 &GB, &xs, &Xs, ID_MINE,
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200624 &p, end, f_rng, p_rng ) );
625
626 *olen = p - buf;
627
628cleanup:
629 mbedtls_ecp_point_free( &GB );
630 mbedtls_ecp_point_free( &Xs );
631 mbedtls_mpi_free( &xs );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200632
633 return( ret );
634}
635
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +0200636/*
637 * Read and process ClientECJPAKEParams (7.4.2.6)
638 */
639int mbedtls_ecjpake_tls_read_client_params( mbedtls_ecjpake_context *ctx,
640 const unsigned char *buf,
641 size_t len )
642{
643 int ret;
644 const unsigned char *p = buf;
645 const unsigned char *end = buf + len;
646 mbedtls_ecp_group grp;
647 mbedtls_ecp_point GA;
648
649 mbedtls_ecp_group_init( &grp );
650 mbedtls_ecp_point_init( &GA );
651
652 /*
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200653 * Server: GA = X1 + X3 + X4 (7.4.2.6.1)
654 * Unified: G = Xp1 + Xm1 + Xm2
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +0200655 * We need that before parsing in order to check Xc as we read it
656 */
657 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &GA,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200658 &ctx->Xp1, &ctx->Xm1, &ctx->Xm2 ) );
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +0200659
660 /*
661 * struct {
662 * ECJPAKEKeyKP ecjpake_key_kp;
663 * } CLientECJPAKEParams;
664 */
665 MBEDTLS_MPI_CHK( ecjpake_kkp_read( ctx->md_info, &ctx->grp,
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200666 &GA, &ctx->Xp, ID_PEER, &p, end ) );
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +0200667
668 if( p != end )
669 {
670 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
671 goto cleanup;
672 }
673
674cleanup:
675 mbedtls_ecp_group_free( &grp );
676 mbedtls_ecp_point_free( &GA );
677
678 return( ret );
679}
680
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +0200681/*
682 * Generate and write ClientECJPAKEParams (7.4.2.6)
683 */
684int mbedtls_ecjpake_tls_write_client_params( mbedtls_ecjpake_context *ctx,
685 unsigned char *buf, size_t len, size_t *olen,
686 int (*f_rng)(void *, unsigned char *, size_t),
687 void *p_rng )
688{
689 int ret;
690 mbedtls_ecp_point GA, Xc;
691 mbedtls_mpi xc;
692 unsigned char *p = buf;
693 const unsigned char *end = buf + len;
694 size_t ec_len;
695
696 if( end < p )
697 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
698
699 mbedtls_ecp_point_init( &GA );
700 mbedtls_ecp_point_init( &Xc );
701 mbedtls_mpi_init( &xc );
702
703 /*
704 * First generate private/public key pair (7.4.2.6.1)
705 *
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200706 * Client: GA = X1 + X3 + X4
707 * Unified: G = Xm1 + Xp1 + Xp2
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +0200708 * xc = x2 * s mod n
709 * Xc = xc * GA
710 */
711 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &GA,
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200712 &ctx->Xm1, &ctx->Xp1, &ctx->Xp2 ) );
713 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &xc, &ctx->xm2, &ctx->s ) );
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +0200714 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &xc, &xc, &ctx->grp.N ) );
715 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &Xc, &xc, &GA, f_rng, p_rng ) );
716
717 /*
718 * Now write things out
719 */
720 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( &ctx->grp, &Xc,
721 MBEDTLS_ECP_PF_UNCOMPRESSED, &ec_len, p, end - p ) );
722 p += ec_len;
723
724 MBEDTLS_MPI_CHK( ecjpake_zkp_write( ctx->md_info, &ctx->grp,
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200725 &GA, &xc, &Xc, ID_MINE,
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +0200726 &p, end, f_rng, p_rng ) );
727
728 *olen = p - buf;
729
730cleanup:
731 mbedtls_ecp_point_free( &GA );
732 mbedtls_ecp_point_free( &Xc );
733 mbedtls_mpi_free( &xc );
734
735 return( ret );
736}
737
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200738/*
739 * Derive PMS (7.4.2.7 / 7.4.2.8)
740 */
741int mbedtls_ecjpake_tls_derive_pms( mbedtls_ecjpake_context *ctx,
742 unsigned char *buf, size_t len, size_t *olen,
743 int (*f_rng)(void *, unsigned char *, size_t),
744 void *p_rng )
745{
746 int ret;
747 mbedtls_ecp_point K, *X42;
748 mbedtls_mpi xbs, one;
749 unsigned char kx[MBEDTLS_ECP_MAX_BYTES];
750 size_t x_bytes;
751
752 *olen = mbedtls_md_get_size( ctx->md_info );
753 if( len < *olen )
754 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
755
756 mbedtls_ecp_point_init( &K );
757 mbedtls_mpi_init( &xbs );
758 mbedtls_mpi_init( &one );
759
760 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200761 X42 = ctx->role == MBEDTLS_ECJPAKE_CLIENT ? &ctx->Xp2 : &ctx->Xp2;
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200762
763 /*
764 * Client: K = ( Xs - X4 * x2 * s ) * x2
765 * Server: K = ( Xc - X2 * x4 * s ) * x4
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200766 * Unified: K = ( Xp - X42 * xm2 * x ) * xm2
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200767 */
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200768 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &xbs, &ctx->xm2, &ctx->s ) );
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200769 xbs.s *= -1;
770 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &xbs, &xbs, &ctx->grp.N ) );
771
772 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( &ctx->grp, &K,
773 &one, &ctx->Xp,
774 &xbs, X42 ) );
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200775 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &K, &ctx->xm2, &K,
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200776 f_rng, p_rng ) );
777
778 /* PMS = SHA-256( K.X ) */
779 x_bytes = ( ctx->grp.pbits + 7 ) / 8;
780 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &K.X, kx, x_bytes ) );
781 MBEDTLS_MPI_CHK( mbedtls_md( ctx->md_info, kx, x_bytes, buf ) );
782
783cleanup:
784 mbedtls_ecp_point_free( &K );
785 mbedtls_mpi_free( &xbs );
786 mbedtls_mpi_free( &one );
787
788 return( ret );
789}
790
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200791#undef ID_MINE
792#undef ID_PEER
793
794
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200795#if defined(MBEDTLS_SELF_TEST)
796
797#if defined(MBEDTLS_PLATFORM_C)
798#include "mbedtls/platform.h"
799#else
800#include <stdio.h>
801#define mbedtls_printf printf
802#endif
803
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200804#if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
805 !defined(MBEDTLS_SHA256_C)
806int mbedtls_ecjpake_self_test( int verbose )
807{
808 (void) verbose;
809 return( 0 );
810}
811#else
812
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200813static const unsigned char ecjpake_test_password[] = {
814 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x6a, 0x70, 0x61, 0x6b, 0x65, 0x74,
815 0x65, 0x73, 0x74
816};
817
818static const unsigned char ecjpake_test_x1[] = {
819 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
820 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
821 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21
822};
823
824static const unsigned char ecjpake_test_x2[] = {
825 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
826 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
827 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
828};
829
830static const unsigned char ecjpake_test_x3[] = {
831 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
832 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
833 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
834};
835
836static const unsigned char ecjpake_test_x4[] = {
837 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc,
838 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
839 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1
840};
841
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200842static const unsigned char ecjpake_test_cli_ext[] = {
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200843 0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19,
844 0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44,
845 0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad,
846 0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62,
847 0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9,
848 0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d,
849 0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e,
850 0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e,
851 0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73,
852 0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22,
853 0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce,
854 0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00,
855 0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200856 0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e,
857 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62,
858 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5,
859 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb,
860 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35,
861 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0,
862 0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb,
863 0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47,
864 0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39,
865 0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97,
866 0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40,
867 0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d,
868 0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa,
869 0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d,
870 0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200871};
872
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200873static const unsigned char ecjpake_test_srv_ext[] = {
874 0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb,
875 0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18,
876 0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47,
877 0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f,
878 0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7,
879 0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d,
880 0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64,
881 0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36,
882 0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2,
883 0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec,
884 0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16,
885 0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96,
886 0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3,
887 0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19,
888 0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f,
889 0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8,
890 0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7,
891 0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea,
892 0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5,
893 0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6,
894 0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31,
895 0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d,
896 0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8,
897 0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee,
898 0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84,
899 0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f,
900 0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80,
901 0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12
902};
903
904static const unsigned char ecjpake_test_srv_kx[] = {
905 0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23,
906 0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c,
907 0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f,
908 0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca,
909 0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26,
910 0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55,
911 0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38,
912 0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6,
913 0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9,
914 0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4,
915 0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2,
916 0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8,
917 0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd,
918 0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c
919};
920
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +0200921static const unsigned char ecjpake_test_cli_kx[] = {
922 0x41, 0x04, 0x69, 0xd5, 0x4e, 0xe8, 0x5e, 0x90, 0xce, 0x3f, 0x12, 0x46,
923 0x74, 0x2d, 0xe5, 0x07, 0xe9, 0x39, 0xe8, 0x1d, 0x1d, 0xc1, 0xc5, 0xcb,
924 0x98, 0x8b, 0x58, 0xc3, 0x10, 0xc9, 0xfd, 0xd9, 0x52, 0x4d, 0x93, 0x72,
925 0x0b, 0x45, 0x54, 0x1c, 0x83, 0xee, 0x88, 0x41, 0x19, 0x1d, 0xa7, 0xce,
926 0xd8, 0x6e, 0x33, 0x12, 0xd4, 0x36, 0x23, 0xc1, 0xd6, 0x3e, 0x74, 0x98,
927 0x9a, 0xba, 0x4a, 0xff, 0xd1, 0xee, 0x41, 0x04, 0x07, 0x7e, 0x8c, 0x31,
928 0xe2, 0x0e, 0x6b, 0xed, 0xb7, 0x60, 0xc1, 0x35, 0x93, 0xe6, 0x9f, 0x15,
929 0xbe, 0x85, 0xc2, 0x7d, 0x68, 0xcd, 0x09, 0xcc, 0xb8, 0xc4, 0x18, 0x36,
930 0x08, 0x91, 0x7c, 0x5c, 0x3d, 0x40, 0x9f, 0xac, 0x39, 0xfe, 0xfe, 0xe8,
931 0x2f, 0x72, 0x92, 0xd3, 0x6f, 0x0d, 0x23, 0xe0, 0x55, 0x91, 0x3f, 0x45,
932 0xa5, 0x2b, 0x85, 0xdd, 0x8a, 0x20, 0x52, 0xe9, 0xe1, 0x29, 0xbb, 0x4d,
933 0x20, 0x0f, 0x01, 0x1f, 0x19, 0x48, 0x35, 0x35, 0xa6, 0xe8, 0x9a, 0x58,
934 0x0c, 0x9b, 0x00, 0x03, 0xba, 0xf2, 0x14, 0x62, 0xec, 0xe9, 0x1a, 0x82,
935 0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c
936};
937
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200938static const unsigned char ecjpake_test_pms[] = {
939 0xf3, 0xd4, 0x7f, 0x59, 0x98, 0x44, 0xdb, 0x92, 0xa5, 0x69, 0xbb, 0xe7,
940 0x98, 0x1e, 0x39, 0xd9, 0x31, 0xfd, 0x74, 0x3b, 0xf2, 0x2e, 0x98, 0xf9,
941 0xb4, 0x38, 0xf7, 0x19, 0xd3, 0xc4, 0xf3, 0x51
942};
943
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +0200944/* Load my private keys and generate the correponding public keys */
945static int ecjpake_test_load( mbedtls_ecjpake_context *ctx,
946 const unsigned char *xm1, size_t len1,
947 const unsigned char *xm2, size_t len2 )
948{
949 int ret;
950
951 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm1, xm1, len1 ) );
952 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm2, xm2, len2 ) );
953 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm1, &ctx->xm1,
954 &ctx->grp.G, NULL, NULL ) );
955 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm2, &ctx->xm2,
956 &ctx->grp.G, NULL, NULL ) );
957
958cleanup:
959 return( ret );
960}
961
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200962/* For tests we don't need a secure RNG;
963 * use the LGC from Numerical Recipes for simplicity */
964static int ecjpake_lgc( void *p, unsigned char *out, size_t len )
965{
966 static uint32_t x = 42;
967 (void) p;
968
969 while( len > 0 )
970 {
971 size_t use_len = len > 4 ? 4 : len;
972 x = 1664525 * x + 1013904223;
973 memcpy( out, &x, use_len );
974 out += use_len;
975 len -= use_len;
976 }
977
978 return( 0 );
979}
980
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200981#define TEST_ASSERT( x ) \
982 do { \
983 if( x ) \
984 ret = 0; \
985 else \
986 { \
987 ret = 1; \
988 goto cleanup; \
989 } \
990 } while( 0 )
991
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200992/*
993 * Checkup routine
994 */
995int mbedtls_ecjpake_self_test( int verbose )
996{
997 int ret;
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200998 mbedtls_ecjpake_context cli;
999 mbedtls_ecjpake_context srv;
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001000 unsigned char buf[512], pms[32];
1001 size_t len, pmslen;
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001002
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001003 mbedtls_ecjpake_init( &cli );
1004 mbedtls_ecjpake_init( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001005
1006 if( verbose != 0 )
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001007 mbedtls_printf( " ECJPAKE test #0 (setup): " );
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +02001008
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +02001009 TEST_ASSERT( mbedtls_ecjpake_setup( &cli, MBEDTLS_ECJPAKE_CLIENT,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001010 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1011 ecjpake_test_password,
1012 sizeof( ecjpake_test_password ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001013
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +02001014 TEST_ASSERT( mbedtls_ecjpake_setup( &srv, MBEDTLS_ECJPAKE_SERVER,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001015 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1016 ecjpake_test_password,
1017 sizeof( ecjpake_test_password ) ) == 0 );
1018
1019 if( verbose != 0 )
1020 mbedtls_printf( "passed\n" );
1021
1022 if( verbose != 0 )
1023 mbedtls_printf( " ECJPAKE test #1 (random handshake): " );
1024
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001025 TEST_ASSERT( mbedtls_ecjpake_write_round_one( &cli,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001026 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1027
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001028 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv, buf, len ) == 0 );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001029
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001030 TEST_ASSERT( mbedtls_ecjpake_write_round_one( &srv,
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001031 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1032
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001033 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli, buf, len ) == 0 );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001034
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +02001035 TEST_ASSERT( mbedtls_ecjpake_tls_write_server_params( &srv,
1036 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1037
1038 TEST_ASSERT( mbedtls_ecjpake_tls_read_server_params( &cli, buf, len ) == 0 );
1039
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001040 TEST_ASSERT( mbedtls_ecjpake_tls_derive_pms( &cli,
1041 pms, sizeof( pms ), &pmslen, ecjpake_lgc, NULL ) == 0 );
1042
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +02001043 TEST_ASSERT( mbedtls_ecjpake_tls_write_client_params( &cli,
1044 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1045
1046 TEST_ASSERT( mbedtls_ecjpake_tls_read_client_params( &srv, buf, len ) == 0 );
1047
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001048 TEST_ASSERT( mbedtls_ecjpake_tls_derive_pms( &srv,
1049 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1050
1051 TEST_ASSERT( len == pmslen );
1052 TEST_ASSERT( memcmp( buf, pms, len ) == 0 );
1053
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001054 if( verbose != 0 )
1055 mbedtls_printf( "passed\n" );
1056
1057 if( verbose != 0 )
1058 mbedtls_printf( " ECJPAKE test #2 (reference handshake): " );
1059
1060 /* Simulate key generation on client, skip writing client_ext */
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001061 MBEDTLS_MPI_CHK( ecjpake_test_load( &cli,
1062 ecjpake_test_x1, sizeof( ecjpake_test_x1 ),
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001063 ecjpake_test_x2, sizeof( ecjpake_test_x2 ) ) );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001064
1065 /* Server reads client ext */
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001066 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv,
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +02001067 ecjpake_test_cli_ext,
1068 sizeof( ecjpake_test_cli_ext ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001069
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001070 /* Simulate key generation on server, skip writing server_ext */
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001071 MBEDTLS_MPI_CHK( ecjpake_test_load( &srv,
1072 ecjpake_test_x3, sizeof( ecjpake_test_x3 ),
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001073 ecjpake_test_x4, sizeof( ecjpake_test_x4 ) ) );
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001074
1075 /* Client reads server ext and key exchange */
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +02001076 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli,
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +02001077 ecjpake_test_srv_ext,
1078 sizeof( ecjpake_test_srv_ext ) ) == 0 );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001079
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001080 TEST_ASSERT( mbedtls_ecjpake_tls_read_server_params( &cli,
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +02001081 ecjpake_test_srv_kx,
1082 sizeof( ecjpake_test_srv_kx ) ) == 0 );
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +02001083
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +02001084 /* Server reads client key exchange */
1085 TEST_ASSERT( mbedtls_ecjpake_tls_read_client_params( &srv,
1086 ecjpake_test_cli_kx,
1087 sizeof( ecjpake_test_cli_kx ) ) == 0 );
1088
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001089 /* Server derives PMS */
1090 TEST_ASSERT( mbedtls_ecjpake_tls_derive_pms( &srv,
1091 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1092
1093 TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
1094 TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
1095
1096 memset( buf, 0, len ); /* Avoid interferences with next step */
1097
1098 /* Client derives PMS */
1099 TEST_ASSERT( mbedtls_ecjpake_tls_derive_pms( &cli,
1100 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1101
1102 TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
1103 TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
1104
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001105 if( verbose != 0 )
1106 mbedtls_printf( "passed\n" );
1107
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001108cleanup:
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001109 mbedtls_ecjpake_free( &cli );
1110 mbedtls_ecjpake_free( &srv );
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001111
1112 if( ret != 0 )
1113 {
1114 if( verbose != 0 )
1115 mbedtls_printf( "failed\n" );
1116
1117 ret = 1;
1118 }
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001119
1120 if( verbose != 0 )
1121 mbedtls_printf( "\n" );
1122
1123 return( ret );
1124}
1125
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +02001126#undef TEST_ASSERT
1127
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001128#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_SHA256_C */
1129
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001130#endif /* MBEDTLS_SELF_TEST */
1131
1132#endif /* MBEDTLS_ECJPAKE_C */