source: azure_iot_hub_mbedtls/trunk/mbedtls-2.16.1/library/ecjpake.c@ 398

Last change on this file since 398 was 398, checked in by coas-nagasima, 5 years ago

mbedTLS版Azure IoT Hub接続サンプルのソースコードを追加

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 38.1 KB
Line 
1/*
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/*
23 * References in the code are to the Thread v1.0 Specification,
24 * available to members of the Thread Group http://threadgroup.org/
25 */
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#include "mbedtls/platform_util.h"
37
38#include <string.h>
39
40#if !defined(MBEDTLS_ECJPAKE_ALT)
41
42/* Parameter validation macros based on platform_util.h */
43#define ECJPAKE_VALIDATE_RET( cond ) \
44 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA )
45#define ECJPAKE_VALIDATE( cond ) \
46 MBEDTLS_INTERNAL_VALIDATE( cond )
47
48/*
49 * Convert a mbedtls_ecjpake_role to identifier string
50 */
51static const char * const ecjpake_id[] = {
52 "client",
53 "server"
54};
55
56#define ID_MINE ( ecjpake_id[ ctx->role ] )
57#define ID_PEER ( ecjpake_id[ 1 - ctx->role ] )
58
59/*
60 * Initialize context
61 */
62void mbedtls_ecjpake_init( mbedtls_ecjpake_context *ctx )
63{
64 ECJPAKE_VALIDATE( ctx != NULL );
65
66 ctx->md_info = NULL;
67 mbedtls_ecp_group_init( &ctx->grp );
68 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
69
70 mbedtls_ecp_point_init( &ctx->Xm1 );
71 mbedtls_ecp_point_init( &ctx->Xm2 );
72 mbedtls_ecp_point_init( &ctx->Xp1 );
73 mbedtls_ecp_point_init( &ctx->Xp2 );
74 mbedtls_ecp_point_init( &ctx->Xp );
75
76 mbedtls_mpi_init( &ctx->xm1 );
77 mbedtls_mpi_init( &ctx->xm2 );
78 mbedtls_mpi_init( &ctx->s );
79}
80
81/*
82 * Free context
83 */
84void mbedtls_ecjpake_free( mbedtls_ecjpake_context *ctx )
85{
86 if( ctx == NULL )
87 return;
88
89 ctx->md_info = NULL;
90 mbedtls_ecp_group_free( &ctx->grp );
91
92 mbedtls_ecp_point_free( &ctx->Xm1 );
93 mbedtls_ecp_point_free( &ctx->Xm2 );
94 mbedtls_ecp_point_free( &ctx->Xp1 );
95 mbedtls_ecp_point_free( &ctx->Xp2 );
96 mbedtls_ecp_point_free( &ctx->Xp );
97
98 mbedtls_mpi_free( &ctx->xm1 );
99 mbedtls_mpi_free( &ctx->xm2 );
100 mbedtls_mpi_free( &ctx->s );
101}
102
103/*
104 * Setup context
105 */
106int mbedtls_ecjpake_setup( mbedtls_ecjpake_context *ctx,
107 mbedtls_ecjpake_role role,
108 mbedtls_md_type_t hash,
109 mbedtls_ecp_group_id curve,
110 const unsigned char *secret,
111 size_t len )
112{
113 int ret;
114
115 ECJPAKE_VALIDATE_RET( ctx != NULL );
116 ECJPAKE_VALIDATE_RET( role == MBEDTLS_ECJPAKE_CLIENT ||
117 role == MBEDTLS_ECJPAKE_SERVER );
118 ECJPAKE_VALIDATE_RET( secret != NULL || len == 0 );
119
120 ctx->role = role;
121
122 if( ( ctx->md_info = mbedtls_md_info_from_type( hash ) ) == NULL )
123 return( MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE );
124
125 MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ctx->grp, curve ) );
126
127 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->s, secret, len ) );
128
129cleanup:
130 if( ret != 0 )
131 mbedtls_ecjpake_free( ctx );
132
133 return( ret );
134}
135
136/*
137 * Check if context is ready for use
138 */
139int mbedtls_ecjpake_check( const mbedtls_ecjpake_context *ctx )
140{
141 ECJPAKE_VALIDATE_RET( ctx != NULL );
142
143 if( ctx->md_info == NULL ||
144 ctx->grp.id == MBEDTLS_ECP_DP_NONE ||
145 ctx->s.p == NULL )
146 {
147 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
148 }
149
150 return( 0 );
151}
152
153/*
154 * Write a point plus its length to a buffer
155 */
156static int ecjpake_write_len_point( unsigned char **p,
157 const unsigned char *end,
158 const mbedtls_ecp_group *grp,
159 const int pf,
160 const mbedtls_ecp_point *P )
161{
162 int ret;
163 size_t len;
164
165 /* Need at least 4 for length plus 1 for point */
166 if( end < *p || end - *p < 5 )
167 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
168
169 ret = mbedtls_ecp_point_write_binary( grp, P, pf,
170 &len, *p + 4, end - ( *p + 4 ) );
171 if( ret != 0 )
172 return( ret );
173
174 (*p)[0] = (unsigned char)( ( len >> 24 ) & 0xFF );
175 (*p)[1] = (unsigned char)( ( len >> 16 ) & 0xFF );
176 (*p)[2] = (unsigned char)( ( len >> 8 ) & 0xFF );
177 (*p)[3] = (unsigned char)( ( len ) & 0xFF );
178
179 *p += 4 + len;
180
181 return( 0 );
182}
183
184/*
185 * Size of the temporary buffer for ecjpake_hash:
186 * 3 EC points plus their length, plus ID and its length (4 + 6 bytes)
187 */
188#define ECJPAKE_HASH_BUF_LEN ( 3 * ( 4 + MBEDTLS_ECP_MAX_PT_LEN ) + 4 + 6 )
189
190/*
191 * Compute hash for ZKP (7.4.2.2.2.1)
192 */
193static int ecjpake_hash( const mbedtls_md_info_t *md_info,
194 const mbedtls_ecp_group *grp,
195 const int pf,
196 const mbedtls_ecp_point *G,
197 const mbedtls_ecp_point *V,
198 const mbedtls_ecp_point *X,
199 const char *id,
200 mbedtls_mpi *h )
201{
202 int ret;
203 unsigned char buf[ECJPAKE_HASH_BUF_LEN];
204 unsigned char *p = buf;
205 const unsigned char *end = buf + sizeof( buf );
206 const size_t id_len = strlen( id );
207 unsigned char hash[MBEDTLS_MD_MAX_SIZE];
208
209 /* Write things to temporary buffer */
210 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, G ) );
211 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, V ) );
212 MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, X ) );
213
214 if( end - p < 4 )
215 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
216
217 *p++ = (unsigned char)( ( id_len >> 24 ) & 0xFF );
218 *p++ = (unsigned char)( ( id_len >> 16 ) & 0xFF );
219 *p++ = (unsigned char)( ( id_len >> 8 ) & 0xFF );
220 *p++ = (unsigned char)( ( id_len ) & 0xFF );
221
222 if( end < p || (size_t)( end - p ) < id_len )
223 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
224
225 memcpy( p, id, id_len );
226 p += id_len;
227
228 /* Compute hash */
229 mbedtls_md( md_info, buf, p - buf, hash );
230
231 /* Turn it into an integer mod n */
232 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( h, hash,
233 mbedtls_md_get_size( md_info ) ) );
234 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( h, h, &grp->N ) );
235
236cleanup:
237 return( ret );
238}
239
240/*
241 * Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3)
242 */
243static int ecjpake_zkp_read( const mbedtls_md_info_t *md_info,
244 const mbedtls_ecp_group *grp,
245 const int pf,
246 const mbedtls_ecp_point *G,
247 const mbedtls_ecp_point *X,
248 const char *id,
249 const unsigned char **p,
250 const unsigned char *end )
251{
252 int ret;
253 mbedtls_ecp_point V, VV;
254 mbedtls_mpi r, h;
255 size_t r_len;
256
257 mbedtls_ecp_point_init( &V );
258 mbedtls_ecp_point_init( &VV );
259 mbedtls_mpi_init( &r );
260 mbedtls_mpi_init( &h );
261
262 /*
263 * struct {
264 * ECPoint V;
265 * opaque r<1..2^8-1>;
266 * } ECSchnorrZKP;
267 */
268 if( end < *p )
269 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
270
271 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, &V, p, end - *p ) );
272
273 if( end < *p || (size_t)( end - *p ) < 1 )
274 {
275 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
276 goto cleanup;
277 }
278
279 r_len = *(*p)++;
280
281 if( end < *p || (size_t)( end - *p ) < r_len )
282 {
283 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
284 goto cleanup;
285 }
286
287 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &r, *p, r_len ) );
288 *p += r_len;
289
290 /*
291 * Verification
292 */
293 MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) );
294 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( (mbedtls_ecp_group *) grp,
295 &VV, &h, X, &r, G ) );
296
297 if( mbedtls_ecp_point_cmp( &VV, &V ) != 0 )
298 {
299 ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
300 goto cleanup;
301 }
302
303cleanup:
304 mbedtls_ecp_point_free( &V );
305 mbedtls_ecp_point_free( &VV );
306 mbedtls_mpi_free( &r );
307 mbedtls_mpi_free( &h );
308
309 return( ret );
310}
311
312/*
313 * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2)
314 */
315static int ecjpake_zkp_write( const mbedtls_md_info_t *md_info,
316 const mbedtls_ecp_group *grp,
317 const int pf,
318 const mbedtls_ecp_point *G,
319 const mbedtls_mpi *x,
320 const mbedtls_ecp_point *X,
321 const char *id,
322 unsigned char **p,
323 const unsigned char *end,
324 int (*f_rng)(void *, unsigned char *, size_t),
325 void *p_rng )
326{
327 int ret;
328 mbedtls_ecp_point V;
329 mbedtls_mpi v;
330 mbedtls_mpi h; /* later recycled to hold r */
331 size_t len;
332
333 if( end < *p )
334 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
335
336 mbedtls_ecp_point_init( &V );
337 mbedtls_mpi_init( &v );
338 mbedtls_mpi_init( &h );
339
340 /* Compute signature */
341 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp,
342 G, &v, &V, f_rng, p_rng ) );
343 MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) );
344 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &h, &h, x ) ); /* x*h */
345 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &h, &v, &h ) ); /* v - x*h */
346 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &h, &h, &grp->N ) ); /* r */
347
348 /* Write it out */
349 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, &V,
350 pf, &len, *p, end - *p ) );
351 *p += len;
352
353 len = mbedtls_mpi_size( &h ); /* actually r */
354 if( end < *p || (size_t)( end - *p ) < 1 + len || len > 255 )
355 {
356 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
357 goto cleanup;
358 }
359
360 *(*p)++ = (unsigned char)( len & 0xFF );
361 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, *p, len ) ); /* r */
362 *p += len;
363
364cleanup:
365 mbedtls_ecp_point_free( &V );
366 mbedtls_mpi_free( &v );
367 mbedtls_mpi_free( &h );
368
369 return( ret );
370}
371
372/*
373 * Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof
374 * Output: verified public key X
375 */
376static int ecjpake_kkp_read( const mbedtls_md_info_t *md_info,
377 const mbedtls_ecp_group *grp,
378 const int pf,
379 const mbedtls_ecp_point *G,
380 mbedtls_ecp_point *X,
381 const char *id,
382 const unsigned char **p,
383 const unsigned char *end )
384{
385 int ret;
386
387 if( end < *p )
388 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
389
390 /*
391 * struct {
392 * ECPoint X;
393 * ECSchnorrZKP zkp;
394 * } ECJPAKEKeyKP;
395 */
396 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, X, p, end - *p ) );
397 if( mbedtls_ecp_is_zero( X ) )
398 {
399 ret = MBEDTLS_ERR_ECP_INVALID_KEY;
400 goto cleanup;
401 }
402
403 MBEDTLS_MPI_CHK( ecjpake_zkp_read( md_info, grp, pf, G, X, id, p, end ) );
404
405cleanup:
406 return( ret );
407}
408
409/*
410 * Generate an ECJPAKEKeyKP
411 * Output: the serialized structure, plus private/public key pair
412 */
413static int ecjpake_kkp_write( const mbedtls_md_info_t *md_info,
414 const mbedtls_ecp_group *grp,
415 const int pf,
416 const mbedtls_ecp_point *G,
417 mbedtls_mpi *x,
418 mbedtls_ecp_point *X,
419 const char *id,
420 unsigned char **p,
421 const unsigned char *end,
422 int (*f_rng)(void *, unsigned char *, size_t),
423 void *p_rng )
424{
425 int ret;
426 size_t len;
427
428 if( end < *p )
429 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
430
431 /* Generate key (7.4.2.3.1) and write it out */
432 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp, G, x, X,
433 f_rng, p_rng ) );
434 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, X,
435 pf, &len, *p, end - *p ) );
436 *p += len;
437
438 /* Generate and write proof */
439 MBEDTLS_MPI_CHK( ecjpake_zkp_write( md_info, grp, pf, G, x, X, id,
440 p, end, f_rng, p_rng ) );
441
442cleanup:
443 return( ret );
444}
445
446/*
447 * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs
448 * Ouputs: verified peer public keys Xa, Xb
449 */
450static int ecjpake_kkpp_read( const mbedtls_md_info_t *md_info,
451 const mbedtls_ecp_group *grp,
452 const int pf,
453 const mbedtls_ecp_point *G,
454 mbedtls_ecp_point *Xa,
455 mbedtls_ecp_point *Xb,
456 const char *id,
457 const unsigned char *buf,
458 size_t len )
459{
460 int ret;
461 const unsigned char *p = buf;
462 const unsigned char *end = buf + len;
463
464 /*
465 * struct {
466 * ECJPAKEKeyKP ecjpake_key_kp_pair_list[2];
467 * } ECJPAKEKeyKPPairList;
468 */
469 MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xa, id, &p, end ) );
470 MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xb, id, &p, end ) );
471
472 if( p != end )
473 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
474
475cleanup:
476 return( ret );
477}
478
479/*
480 * Generate a ECJPAKEKeyKPPairList
481 * Outputs: the serialized structure, plus two private/public key pairs
482 */
483static int ecjpake_kkpp_write( const mbedtls_md_info_t *md_info,
484 const mbedtls_ecp_group *grp,
485 const int pf,
486 const mbedtls_ecp_point *G,
487 mbedtls_mpi *xm1,
488 mbedtls_ecp_point *Xa,
489 mbedtls_mpi *xm2,
490 mbedtls_ecp_point *Xb,
491 const char *id,
492 unsigned char *buf,
493 size_t len,
494 size_t *olen,
495 int (*f_rng)(void *, unsigned char *, size_t),
496 void *p_rng )
497{
498 int ret;
499 unsigned char *p = buf;
500 const unsigned char *end = buf + len;
501
502 MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm1, Xa, id,
503 &p, end, f_rng, p_rng ) );
504 MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm2, Xb, id,
505 &p, end, f_rng, p_rng ) );
506
507 *olen = p - buf;
508
509cleanup:
510 return( ret );
511}
512
513/*
514 * Read and process the first round message
515 */
516int mbedtls_ecjpake_read_round_one( mbedtls_ecjpake_context *ctx,
517 const unsigned char *buf,
518 size_t len )
519{
520 ECJPAKE_VALIDATE_RET( ctx != NULL );
521 ECJPAKE_VALIDATE_RET( buf != NULL );
522
523 return( ecjpake_kkpp_read( ctx->md_info, &ctx->grp, ctx->point_format,
524 &ctx->grp.G,
525 &ctx->Xp1, &ctx->Xp2, ID_PEER,
526 buf, len ) );
527}
528
529/*
530 * Generate and write the first round message
531 */
532int mbedtls_ecjpake_write_round_one( mbedtls_ecjpake_context *ctx,
533 unsigned char *buf, size_t len, size_t *olen,
534 int (*f_rng)(void *, unsigned char *, size_t),
535 void *p_rng )
536{
537 ECJPAKE_VALIDATE_RET( ctx != NULL );
538 ECJPAKE_VALIDATE_RET( buf != NULL );
539 ECJPAKE_VALIDATE_RET( olen != NULL );
540 ECJPAKE_VALIDATE_RET( f_rng != NULL );
541
542 return( ecjpake_kkpp_write( ctx->md_info, &ctx->grp, ctx->point_format,
543 &ctx->grp.G,
544 &ctx->xm1, &ctx->Xm1, &ctx->xm2, &ctx->Xm2,
545 ID_MINE, buf, len, olen, f_rng, p_rng ) );
546}
547
548/*
549 * Compute the sum of three points R = A + B + C
550 */
551static int ecjpake_ecp_add3( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
552 const mbedtls_ecp_point *A,
553 const mbedtls_ecp_point *B,
554 const mbedtls_ecp_point *C )
555{
556 int ret;
557 mbedtls_mpi one;
558
559 mbedtls_mpi_init( &one );
560
561 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
562 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, A, &one, B ) );
563 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, R, &one, C ) );
564
565cleanup:
566 mbedtls_mpi_free( &one );
567
568 return( ret );
569}
570
571/*
572 * Read and process second round message (C: 7.4.2.5, S: 7.4.2.6)
573 */
574int mbedtls_ecjpake_read_round_two( mbedtls_ecjpake_context *ctx,
575 const unsigned char *buf,
576 size_t len )
577{
578 int ret;
579 const unsigned char *p = buf;
580 const unsigned char *end = buf + len;
581 mbedtls_ecp_group grp;
582 mbedtls_ecp_point G; /* C: GB, S: GA */
583
584 ECJPAKE_VALIDATE_RET( ctx != NULL );
585 ECJPAKE_VALIDATE_RET( buf != NULL );
586
587 mbedtls_ecp_group_init( &grp );
588 mbedtls_ecp_point_init( &G );
589
590 /*
591 * Server: GA = X3 + X4 + X1 (7.4.2.6.1)
592 * Client: GB = X1 + X2 + X3 (7.4.2.5.1)
593 * Unified: G = Xm1 + Xm2 + Xp1
594 * We need that before parsing in order to check Xp as we read it
595 */
596 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G,
597 &ctx->Xm1, &ctx->Xm2, &ctx->Xp1 ) );
598
599 /*
600 * struct {
601 * ECParameters curve_params; // only client reading server msg
602 * ECJPAKEKeyKP ecjpake_key_kp;
603 * } Client/ServerECJPAKEParams;
604 */
605 if( ctx->role == MBEDTLS_ECJPAKE_CLIENT )
606 {
607 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_group( &grp, &p, len ) );
608 if( grp.id != ctx->grp.id )
609 {
610 ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
611 goto cleanup;
612 }
613 }
614
615 MBEDTLS_MPI_CHK( ecjpake_kkp_read( ctx->md_info, &ctx->grp,
616 ctx->point_format,
617 &G, &ctx->Xp, ID_PEER, &p, end ) );
618
619 if( p != end )
620 {
621 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
622 goto cleanup;
623 }
624
625cleanup:
626 mbedtls_ecp_group_free( &grp );
627 mbedtls_ecp_point_free( &G );
628
629 return( ret );
630}
631
632/*
633 * Compute R = +/- X * S mod N, taking care not to leak S
634 */
635static int ecjpake_mul_secret( mbedtls_mpi *R, int sign,
636 const mbedtls_mpi *X,
637 const mbedtls_mpi *S,
638 const mbedtls_mpi *N,
639 int (*f_rng)(void *, unsigned char *, size_t),
640 void *p_rng )
641{
642 int ret;
643 mbedtls_mpi b; /* Blinding value, then s + N * blinding */
644
645 mbedtls_mpi_init( &b );
646
647 /* b = s + rnd-128-bit * N */
648 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &b, 16, f_rng, p_rng ) );
649 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &b, &b, N ) );
650 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &b, &b, S ) );
651
652 /* R = sign * X * b mod N */
653 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( R, X, &b ) );
654 R->s *= sign;
655 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( R, R, N ) );
656
657cleanup:
658 mbedtls_mpi_free( &b );
659
660 return( ret );
661}
662
663/*
664 * Generate and write the second round message (S: 7.4.2.5, C: 7.4.2.6)
665 */
666int mbedtls_ecjpake_write_round_two( mbedtls_ecjpake_context *ctx,
667 unsigned char *buf, size_t len, size_t *olen,
668 int (*f_rng)(void *, unsigned char *, size_t),
669 void *p_rng )
670{
671 int ret;
672 mbedtls_ecp_point G; /* C: GA, S: GB */
673 mbedtls_ecp_point Xm; /* C: Xc, S: Xs */
674 mbedtls_mpi xm; /* C: xc, S: xs */
675 unsigned char *p = buf;
676 const unsigned char *end = buf + len;
677 size_t ec_len;
678
679 ECJPAKE_VALIDATE_RET( ctx != NULL );
680 ECJPAKE_VALIDATE_RET( buf != NULL );
681 ECJPAKE_VALIDATE_RET( olen != NULL );
682 ECJPAKE_VALIDATE_RET( f_rng != NULL );
683
684 mbedtls_ecp_point_init( &G );
685 mbedtls_ecp_point_init( &Xm );
686 mbedtls_mpi_init( &xm );
687
688 /*
689 * First generate private/public key pair (S: 7.4.2.5.1, C: 7.4.2.6.1)
690 *
691 * Client: GA = X1 + X3 + X4 | xs = x2 * s | Xc = xc * GA
692 * Server: GB = X3 + X1 + X2 | xs = x4 * s | Xs = xs * GB
693 * Unified: G = Xm1 + Xp1 + Xp2 | xm = xm2 * s | Xm = xm * G
694 */
695 MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G,
696 &ctx->Xp1, &ctx->Xp2, &ctx->Xm1 ) );
697 MBEDTLS_MPI_CHK( ecjpake_mul_secret( &xm, 1, &ctx->xm2, &ctx->s,
698 &ctx->grp.N, f_rng, p_rng ) );
699 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &Xm, &xm, &G, f_rng, p_rng ) );
700
701 /*
702 * Now write things out
703 *
704 * struct {
705 * ECParameters curve_params; // only server writing its message
706 * ECJPAKEKeyKP ecjpake_key_kp;
707 * } Client/ServerECJPAKEParams;
708 */
709 if( ctx->role == MBEDTLS_ECJPAKE_SERVER )
710 {
711 if( end < p )
712 {
713 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
714 goto cleanup;
715 }
716 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_group( &ctx->grp, &ec_len,
717 p, end - p ) );
718 p += ec_len;
719 }
720
721 if( end < p )
722 {
723 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
724 goto cleanup;
725 }
726 MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( &ctx->grp, &Xm,
727 ctx->point_format, &ec_len, p, end - p ) );
728 p += ec_len;
729
730 MBEDTLS_MPI_CHK( ecjpake_zkp_write( ctx->md_info, &ctx->grp,
731 ctx->point_format,
732 &G, &xm, &Xm, ID_MINE,
733 &p, end, f_rng, p_rng ) );
734
735 *olen = p - buf;
736
737cleanup:
738 mbedtls_ecp_point_free( &G );
739 mbedtls_ecp_point_free( &Xm );
740 mbedtls_mpi_free( &xm );
741
742 return( ret );
743}
744
745/*
746 * Derive PMS (7.4.2.7 / 7.4.2.8)
747 */
748int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx,
749 unsigned char *buf, size_t len, size_t *olen,
750 int (*f_rng)(void *, unsigned char *, size_t),
751 void *p_rng )
752{
753 int ret;
754 mbedtls_ecp_point K;
755 mbedtls_mpi m_xm2_s, one;
756 unsigned char kx[MBEDTLS_ECP_MAX_BYTES];
757 size_t x_bytes;
758
759 ECJPAKE_VALIDATE_RET( ctx != NULL );
760 ECJPAKE_VALIDATE_RET( buf != NULL );
761 ECJPAKE_VALIDATE_RET( olen != NULL );
762 ECJPAKE_VALIDATE_RET( f_rng != NULL );
763
764 *olen = mbedtls_md_get_size( ctx->md_info );
765 if( len < *olen )
766 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
767
768 mbedtls_ecp_point_init( &K );
769 mbedtls_mpi_init( &m_xm2_s );
770 mbedtls_mpi_init( &one );
771
772 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
773
774 /*
775 * Client: K = ( Xs - X4 * x2 * s ) * x2
776 * Server: K = ( Xc - X2 * x4 * s ) * x4
777 * Unified: K = ( Xp - Xp2 * xm2 * s ) * xm2
778 */
779 MBEDTLS_MPI_CHK( ecjpake_mul_secret( &m_xm2_s, -1, &ctx->xm2, &ctx->s,
780 &ctx->grp.N, f_rng, p_rng ) );
781 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( &ctx->grp, &K,
782 &one, &ctx->Xp,
783 &m_xm2_s, &ctx->Xp2 ) );
784 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &K, &ctx->xm2, &K,
785 f_rng, p_rng ) );
786
787 /* PMS = SHA-256( K.X ) */
788 x_bytes = ( ctx->grp.pbits + 7 ) / 8;
789 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &K.X, kx, x_bytes ) );
790 MBEDTLS_MPI_CHK( mbedtls_md( ctx->md_info, kx, x_bytes, buf ) );
791
792cleanup:
793 mbedtls_ecp_point_free( &K );
794 mbedtls_mpi_free( &m_xm2_s );
795 mbedtls_mpi_free( &one );
796
797 return( ret );
798}
799
800#undef ID_MINE
801#undef ID_PEER
802
803#endif /* ! MBEDTLS_ECJPAKE_ALT */
804
805#if defined(MBEDTLS_SELF_TEST)
806
807#if defined(MBEDTLS_PLATFORM_C)
808#include "mbedtls/platform.h"
809#else
810#include <stdio.h>
811#define mbedtls_printf printf
812#endif
813
814#if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
815 !defined(MBEDTLS_SHA256_C)
816int mbedtls_ecjpake_self_test( int verbose )
817{
818 (void) verbose;
819 return( 0 );
820}
821#else
822
823static const unsigned char ecjpake_test_password[] = {
824 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x6a, 0x70, 0x61, 0x6b, 0x65, 0x74,
825 0x65, 0x73, 0x74
826};
827
828static const unsigned char ecjpake_test_x1[] = {
829 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
830 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
831 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21
832};
833
834static const unsigned char ecjpake_test_x2[] = {
835 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
836 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
837 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
838};
839
840static const unsigned char ecjpake_test_x3[] = {
841 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
842 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
843 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
844};
845
846static const unsigned char ecjpake_test_x4[] = {
847 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc,
848 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
849 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1
850};
851
852static const unsigned char ecjpake_test_cli_one[] = {
853 0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19,
854 0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44,
855 0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad,
856 0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62,
857 0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9,
858 0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d,
859 0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e,
860 0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e,
861 0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73,
862 0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22,
863 0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce,
864 0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00,
865 0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b,
866 0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e,
867 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62,
868 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5,
869 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb,
870 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35,
871 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0,
872 0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb,
873 0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47,
874 0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39,
875 0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97,
876 0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40,
877 0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d,
878 0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa,
879 0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d,
880 0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0
881};
882
883static const unsigned char ecjpake_test_srv_one[] = {
884 0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb,
885 0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18,
886 0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47,
887 0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f,
888 0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7,
889 0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d,
890 0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64,
891 0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36,
892 0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2,
893 0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec,
894 0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16,
895 0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96,
896 0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3,
897 0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19,
898 0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f,
899 0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8,
900 0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7,
901 0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea,
902 0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5,
903 0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6,
904 0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31,
905 0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d,
906 0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8,
907 0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee,
908 0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84,
909 0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f,
910 0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80,
911 0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12
912};
913
914static const unsigned char ecjpake_test_srv_two[] = {
915 0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23,
916 0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c,
917 0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f,
918 0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca,
919 0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26,
920 0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55,
921 0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38,
922 0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6,
923 0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9,
924 0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4,
925 0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2,
926 0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8,
927 0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd,
928 0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c
929};
930
931static const unsigned char ecjpake_test_cli_two[] = {
932 0x41, 0x04, 0x69, 0xd5, 0x4e, 0xe8, 0x5e, 0x90, 0xce, 0x3f, 0x12, 0x46,
933 0x74, 0x2d, 0xe5, 0x07, 0xe9, 0x39, 0xe8, 0x1d, 0x1d, 0xc1, 0xc5, 0xcb,
934 0x98, 0x8b, 0x58, 0xc3, 0x10, 0xc9, 0xfd, 0xd9, 0x52, 0x4d, 0x93, 0x72,
935 0x0b, 0x45, 0x54, 0x1c, 0x83, 0xee, 0x88, 0x41, 0x19, 0x1d, 0xa7, 0xce,
936 0xd8, 0x6e, 0x33, 0x12, 0xd4, 0x36, 0x23, 0xc1, 0xd6, 0x3e, 0x74, 0x98,
937 0x9a, 0xba, 0x4a, 0xff, 0xd1, 0xee, 0x41, 0x04, 0x07, 0x7e, 0x8c, 0x31,
938 0xe2, 0x0e, 0x6b, 0xed, 0xb7, 0x60, 0xc1, 0x35, 0x93, 0xe6, 0x9f, 0x15,
939 0xbe, 0x85, 0xc2, 0x7d, 0x68, 0xcd, 0x09, 0xcc, 0xb8, 0xc4, 0x18, 0x36,
940 0x08, 0x91, 0x7c, 0x5c, 0x3d, 0x40, 0x9f, 0xac, 0x39, 0xfe, 0xfe, 0xe8,
941 0x2f, 0x72, 0x92, 0xd3, 0x6f, 0x0d, 0x23, 0xe0, 0x55, 0x91, 0x3f, 0x45,
942 0xa5, 0x2b, 0x85, 0xdd, 0x8a, 0x20, 0x52, 0xe9, 0xe1, 0x29, 0xbb, 0x4d,
943 0x20, 0x0f, 0x01, 0x1f, 0x19, 0x48, 0x35, 0x35, 0xa6, 0xe8, 0x9a, 0x58,
944 0x0c, 0x9b, 0x00, 0x03, 0xba, 0xf2, 0x14, 0x62, 0xec, 0xe9, 0x1a, 0x82,
945 0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c
946};
947
948static const unsigned char ecjpake_test_pms[] = {
949 0xf3, 0xd4, 0x7f, 0x59, 0x98, 0x44, 0xdb, 0x92, 0xa5, 0x69, 0xbb, 0xe7,
950 0x98, 0x1e, 0x39, 0xd9, 0x31, 0xfd, 0x74, 0x3b, 0xf2, 0x2e, 0x98, 0xf9,
951 0xb4, 0x38, 0xf7, 0x19, 0xd3, 0xc4, 0xf3, 0x51
952};
953
954/* Load my private keys and generate the correponding public keys */
955static int ecjpake_test_load( mbedtls_ecjpake_context *ctx,
956 const unsigned char *xm1, size_t len1,
957 const unsigned char *xm2, size_t len2 )
958{
959 int ret;
960
961 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm1, xm1, len1 ) );
962 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm2, xm2, len2 ) );
963 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm1, &ctx->xm1,
964 &ctx->grp.G, NULL, NULL ) );
965 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm2, &ctx->xm2,
966 &ctx->grp.G, NULL, NULL ) );
967
968cleanup:
969 return( ret );
970}
971
972/* For tests we don't need a secure RNG;
973 * use the LGC from Numerical Recipes for simplicity */
974static int ecjpake_lgc( void *p, unsigned char *out, size_t len )
975{
976 static uint32_t x = 42;
977 (void) p;
978
979 while( len > 0 )
980 {
981 size_t use_len = len > 4 ? 4 : len;
982 x = 1664525 * x + 1013904223;
983 memcpy( out, &x, use_len );
984 out += use_len;
985 len -= use_len;
986 }
987
988 return( 0 );
989}
990
991#define TEST_ASSERT( x ) \
992 do { \
993 if( x ) \
994 ret = 0; \
995 else \
996 { \
997 ret = 1; \
998 goto cleanup; \
999 } \
1000 } while( 0 )
1001
1002/*
1003 * Checkup routine
1004 */
1005int mbedtls_ecjpake_self_test( int verbose )
1006{
1007 int ret;
1008 mbedtls_ecjpake_context cli;
1009 mbedtls_ecjpake_context srv;
1010 unsigned char buf[512], pms[32];
1011 size_t len, pmslen;
1012
1013 mbedtls_ecjpake_init( &cli );
1014 mbedtls_ecjpake_init( &srv );
1015
1016 if( verbose != 0 )
1017 mbedtls_printf( " ECJPAKE test #0 (setup): " );
1018
1019 TEST_ASSERT( mbedtls_ecjpake_setup( &cli, MBEDTLS_ECJPAKE_CLIENT,
1020 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1021 ecjpake_test_password,
1022 sizeof( ecjpake_test_password ) ) == 0 );
1023
1024 TEST_ASSERT( mbedtls_ecjpake_setup( &srv, MBEDTLS_ECJPAKE_SERVER,
1025 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1026 ecjpake_test_password,
1027 sizeof( ecjpake_test_password ) ) == 0 );
1028
1029 if( verbose != 0 )
1030 mbedtls_printf( "passed\n" );
1031
1032 if( verbose != 0 )
1033 mbedtls_printf( " ECJPAKE test #1 (random handshake): " );
1034
1035 TEST_ASSERT( mbedtls_ecjpake_write_round_one( &cli,
1036 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1037
1038 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv, buf, len ) == 0 );
1039
1040 TEST_ASSERT( mbedtls_ecjpake_write_round_one( &srv,
1041 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1042
1043 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli, buf, len ) == 0 );
1044
1045 TEST_ASSERT( mbedtls_ecjpake_write_round_two( &srv,
1046 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1047
1048 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli, buf, len ) == 0 );
1049
1050 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli,
1051 pms, sizeof( pms ), &pmslen, ecjpake_lgc, NULL ) == 0 );
1052
1053 TEST_ASSERT( mbedtls_ecjpake_write_round_two( &cli,
1054 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1055
1056 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv, buf, len ) == 0 );
1057
1058 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv,
1059 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1060
1061 TEST_ASSERT( len == pmslen );
1062 TEST_ASSERT( memcmp( buf, pms, len ) == 0 );
1063
1064 if( verbose != 0 )
1065 mbedtls_printf( "passed\n" );
1066
1067 if( verbose != 0 )
1068 mbedtls_printf( " ECJPAKE test #2 (reference handshake): " );
1069
1070 /* Simulate generation of round one */
1071 MBEDTLS_MPI_CHK( ecjpake_test_load( &cli,
1072 ecjpake_test_x1, sizeof( ecjpake_test_x1 ),
1073 ecjpake_test_x2, sizeof( ecjpake_test_x2 ) ) );
1074
1075 MBEDTLS_MPI_CHK( ecjpake_test_load( &srv,
1076 ecjpake_test_x3, sizeof( ecjpake_test_x3 ),
1077 ecjpake_test_x4, sizeof( ecjpake_test_x4 ) ) );
1078
1079 /* Read round one */
1080 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv,
1081 ecjpake_test_cli_one,
1082 sizeof( ecjpake_test_cli_one ) ) == 0 );
1083
1084 TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli,
1085 ecjpake_test_srv_one,
1086 sizeof( ecjpake_test_srv_one ) ) == 0 );
1087
1088 /* Skip generation of round two, read round two */
1089 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli,
1090 ecjpake_test_srv_two,
1091 sizeof( ecjpake_test_srv_two ) ) == 0 );
1092
1093 TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv,
1094 ecjpake_test_cli_two,
1095 sizeof( ecjpake_test_cli_two ) ) == 0 );
1096
1097 /* Server derives PMS */
1098 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv,
1099 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1100
1101 TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
1102 TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
1103
1104 memset( buf, 0, len ); /* Avoid interferences with next step */
1105
1106 /* Client derives PMS */
1107 TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli,
1108 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
1109
1110 TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
1111 TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
1112
1113 if( verbose != 0 )
1114 mbedtls_printf( "passed\n" );
1115
1116cleanup:
1117 mbedtls_ecjpake_free( &cli );
1118 mbedtls_ecjpake_free( &srv );
1119
1120 if( ret != 0 )
1121 {
1122 if( verbose != 0 )
1123 mbedtls_printf( "failed\n" );
1124
1125 ret = 1;
1126 }
1127
1128 if( verbose != 0 )
1129 mbedtls_printf( "\n" );
1130
1131 return( ret );
1132}
1133
1134#undef TEST_ASSERT
1135
1136#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_SHA256_C */
1137
1138#endif /* MBEDTLS_SELF_TEST */
1139
1140#endif /* MBEDTLS_ECJPAKE_C */
Note: See TracBrowser for help on using the repository browser.