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