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