Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ecjpake.c Source File

ecjpake.c

00001 /*
00002  *  Elliptic curve J-PAKE
00003  *
00004  *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
00005  *  SPDX-License-Identifier: Apache-2.0
00006  *
00007  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
00008  *  not use this file except in compliance with the License.
00009  *  You may obtain a copy of the License at
00010  *
00011  *  http://www.apache.org/licenses/LICENSE-2.0
00012  *
00013  *  Unless required by applicable law or agreed to in writing, software
00014  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
00015  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00016  *  See the License for the specific language governing permissions and
00017  *  limitations under the License.
00018  *
00019  *  This file is part of mbed TLS (https://tls.mbed.org)
00020  */
00021 
00022 /*
00023  * References in the code are to the Thread v1.0 Specification,
00024  * available to members of the Thread Group http://threadgroup.org/
00025  */
00026 
00027 #if !defined(MBEDTLS_CONFIG_FILE)
00028 #include "mbedtls/config.h"
00029 #else
00030 #include MBEDTLS_CONFIG_FILE
00031 #endif
00032 
00033 #if defined(MBEDTLS_ECJPAKE_C)
00034 
00035 #include "mbedtls/ecjpake.h"
00036 
00037 #include <string.h>
00038 
00039 #if !defined(MBEDTLS_ECJPAKE_ALT)
00040 
00041 /*
00042  * Convert a mbedtls_ecjpake_role to identifier string
00043  */
00044 static const char * const ecjpake_id[] = {
00045     "client",
00046     "server"
00047 };
00048 
00049 #define ID_MINE     ( ecjpake_id[ ctx->role ] )
00050 #define ID_PEER     ( ecjpake_id[ 1 - ctx->role ] )
00051 
00052 /*
00053  * Initialize context
00054  */
00055 void mbedtls_ecjpake_init( mbedtls_ecjpake_context *ctx )
00056 {
00057     if( ctx == NULL )
00058         return;
00059 
00060     ctx->md_info = NULL;
00061     mbedtls_ecp_group_init( &ctx->grp );
00062     ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
00063 
00064     mbedtls_ecp_point_init( &ctx->Xm1 );
00065     mbedtls_ecp_point_init( &ctx->Xm2 );
00066     mbedtls_ecp_point_init( &ctx->Xp1 );
00067     mbedtls_ecp_point_init( &ctx->Xp2 );
00068     mbedtls_ecp_point_init( &ctx->Xp  );
00069 
00070     mbedtls_mpi_init( &ctx->xm1 );
00071     mbedtls_mpi_init( &ctx->xm2 );
00072     mbedtls_mpi_init( &ctx->s   );
00073 }
00074 
00075 /*
00076  * Free context
00077  */
00078 void mbedtls_ecjpake_free( mbedtls_ecjpake_context *ctx )
00079 {
00080     if( ctx == NULL )
00081         return;
00082 
00083     ctx->md_info = NULL;
00084     mbedtls_ecp_group_free( &ctx->grp );
00085 
00086     mbedtls_ecp_point_free( &ctx->Xm1 );
00087     mbedtls_ecp_point_free( &ctx->Xm2 );
00088     mbedtls_ecp_point_free( &ctx->Xp1 );
00089     mbedtls_ecp_point_free( &ctx->Xp2 );
00090     mbedtls_ecp_point_free( &ctx->Xp  );
00091 
00092     mbedtls_mpi_free( &ctx->xm1 );
00093     mbedtls_mpi_free( &ctx->xm2 );
00094     mbedtls_mpi_free( &ctx->s   );
00095 }
00096 
00097 /*
00098  * Setup context
00099  */
00100 int mbedtls_ecjpake_setup( mbedtls_ecjpake_context *ctx,
00101                            mbedtls_ecjpake_role role,
00102                            mbedtls_md_type_t hash,
00103                            mbedtls_ecp_group_id curve,
00104                            const unsigned char *secret,
00105                            size_t len )
00106 {
00107     int ret;
00108 
00109     ctx->role = role;
00110 
00111     if( ( ctx->md_info = mbedtls_md_info_from_type( hash ) ) == NULL )
00112         return( MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE );
00113 
00114     MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ctx->grp, curve ) );
00115 
00116     MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->s, secret, len ) );
00117 
00118 cleanup:
00119     if( ret != 0 )
00120         mbedtls_ecjpake_free( ctx );
00121 
00122     return( ret );
00123 }
00124 
00125 /*
00126  * Check if context is ready for use
00127  */
00128 int mbedtls_ecjpake_check( const mbedtls_ecjpake_context *ctx )
00129 {
00130     if( ctx->md_info == NULL ||
00131         ctx->grp.id  == MBEDTLS_ECP_DP_NONE ||
00132         ctx->s.p  == NULL )
00133     {
00134         return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
00135     }
00136 
00137     return( 0 );
00138 }
00139 
00140 /*
00141  * Write a point plus its length to a buffer
00142  */
00143 static int ecjpake_write_len_point( unsigned char **p,
00144                                     const unsigned char *end,
00145                                     const mbedtls_ecp_group *grp,
00146                                     const int pf,
00147                                     const mbedtls_ecp_point *P )
00148 {
00149     int ret;
00150     size_t len;
00151 
00152     /* Need at least 4 for length plus 1 for point */
00153     if( end < *p || end - *p < 5 )
00154         return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
00155 
00156     ret = mbedtls_ecp_point_write_binary( grp, P, pf,
00157                                           &len, *p + 4, end - ( *p + 4 ) );
00158     if( ret != 0 )
00159         return( ret );
00160 
00161     (*p)[0] = (unsigned char)( ( len >> 24 ) & 0xFF );
00162     (*p)[1] = (unsigned char)( ( len >> 16 ) & 0xFF );
00163     (*p)[2] = (unsigned char)( ( len >>  8 ) & 0xFF );
00164     (*p)[3] = (unsigned char)( ( len       ) & 0xFF );
00165 
00166     *p += 4 + len;
00167 
00168     return( 0 );
00169 }
00170 
00171 /*
00172  * Size of the temporary buffer for ecjpake_hash:
00173  * 3 EC points plus their length, plus ID and its length (4 + 6 bytes)
00174  */
00175 #define ECJPAKE_HASH_BUF_LEN    ( 3 * ( 4 + MBEDTLS_ECP_MAX_PT_LEN ) + 4 + 6 )
00176 
00177 /*
00178  * Compute hash for ZKP (7.4.2.2.2.1)
00179  */
00180 static int ecjpake_hash( const mbedtls_md_info_t *md_info,
00181                          const mbedtls_ecp_group *grp,
00182                          const int pf,
00183                          const mbedtls_ecp_point *G,
00184                          const mbedtls_ecp_point *V,
00185                          const mbedtls_ecp_point *X,
00186                          const char *id,
00187                          mbedtls_mpi *h )
00188 {
00189     int ret;
00190     unsigned char buf[ECJPAKE_HASH_BUF_LEN];
00191     unsigned char *p = buf;
00192     const unsigned char *end = buf + sizeof( buf );
00193     const size_t id_len = strlen( id );
00194     unsigned char hash[MBEDTLS_MD_MAX_SIZE];
00195 
00196     /* Write things to temporary buffer */
00197     MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, G ) );
00198     MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, V ) );
00199     MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, X ) );
00200 
00201     if( end - p < 4 )
00202         return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
00203 
00204     *p++ = (unsigned char)( ( id_len >> 24 ) & 0xFF );
00205     *p++ = (unsigned char)( ( id_len >> 16 ) & 0xFF );
00206     *p++ = (unsigned char)( ( id_len >>  8 ) & 0xFF );
00207     *p++ = (unsigned char)( ( id_len       ) & 0xFF );
00208 
00209     if( end < p || (size_t)( end - p ) < id_len )
00210         return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
00211 
00212     memcpy( p, id, id_len );
00213     p += id_len;
00214 
00215     /* Compute hash */
00216     mbedtls_md( md_info, buf, p - buf, hash );
00217 
00218     /* Turn it into an integer mod n */
00219     MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( h, hash,
00220                                         mbedtls_md_get_size( md_info ) ) );
00221     MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( h, h, &grp->N  ) );
00222 
00223 cleanup:
00224     return( ret );
00225 }
00226 
00227 /*
00228  * Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3)
00229  */
00230 static int ecjpake_zkp_read( const mbedtls_md_info_t *md_info,
00231                              const mbedtls_ecp_group *grp,
00232                              const int pf,
00233                              const mbedtls_ecp_point *G,
00234                              const mbedtls_ecp_point *X,
00235                              const char *id,
00236                              const unsigned char **p,
00237                              const unsigned char *end )
00238 {
00239     int ret;
00240     mbedtls_ecp_point V, VV;
00241     mbedtls_mpi r, h;
00242     size_t r_len;
00243 
00244     mbedtls_ecp_point_init( &V );
00245     mbedtls_ecp_point_init( &VV );
00246     mbedtls_mpi_init( &r );
00247     mbedtls_mpi_init( &h );
00248 
00249     /*
00250      * struct {
00251      *     ECPoint V;
00252      *     opaque r<1..2^8-1>;
00253      * } ECSchnorrZKP;
00254      */
00255     if( end < *p )
00256         return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
00257 
00258     MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, &V, p, end - *p ) );
00259 
00260     if( end < *p || (size_t)( end - *p ) < 1 )
00261     {
00262         ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
00263         goto cleanup;
00264     }
00265 
00266     r_len = *(*p)++;
00267 
00268     if( end < *p || (size_t)( end - *p ) < r_len )
00269     {
00270         ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
00271         goto cleanup;
00272     }
00273 
00274     MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &r, *p, r_len ) );
00275     *p += r_len;
00276 
00277     /*
00278      * Verification
00279      */
00280     MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) );
00281     MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( (mbedtls_ecp_group *) grp,
00282                      &VV, &h, X, &r, G ) );
00283 
00284     if( mbedtls_ecp_point_cmp( &VV, &V ) != 0 )
00285     {
00286         ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
00287         goto cleanup;
00288     }
00289 
00290 cleanup:
00291     mbedtls_ecp_point_free( &V );
00292     mbedtls_ecp_point_free( &VV );
00293     mbedtls_mpi_free( &r );
00294     mbedtls_mpi_free( &h );
00295 
00296     return( ret );
00297 }
00298 
00299 /*
00300  * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2)
00301  */
00302 static int ecjpake_zkp_write( const mbedtls_md_info_t *md_info,
00303                               const mbedtls_ecp_group *grp,
00304                               const int pf, 
00305                               const mbedtls_ecp_point *G,
00306                               const mbedtls_mpi *x,
00307                               const mbedtls_ecp_point *X,
00308                               const char *id,
00309                               unsigned char **p,
00310                               const unsigned char *end,
00311                               int (*f_rng)(void *, unsigned char *, size_t),
00312                               void *p_rng )
00313 {
00314     int ret;
00315     mbedtls_ecp_point V;
00316     mbedtls_mpi v;
00317     mbedtls_mpi h; /* later recycled to hold r */
00318     size_t len;
00319 
00320     if( end < *p )
00321         return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
00322 
00323     mbedtls_ecp_point_init( &V );
00324     mbedtls_mpi_init( &v );
00325     mbedtls_mpi_init( &h );
00326 
00327     /* Compute signature */
00328     MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp,
00329                                                    G, &v, &V, f_rng, p_rng ) );
00330     MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) );
00331     MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &h, &h, x ) ); /* x*h */
00332     MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &h, &v, &h ) ); /* v - x*h */
00333     MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &h, &h, &grp->N  ) ); /* r */
00334 
00335     /* Write it out */
00336     MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, &V,
00337                 pf, &len, *p, end - *p ) );
00338     *p += len;
00339 
00340     len = mbedtls_mpi_size( &h ); /* actually r */
00341     if( end < *p || (size_t)( end - *p ) < 1 + len || len > 255 )
00342     {
00343         ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
00344         goto cleanup;
00345     }
00346 
00347     *(*p)++ = (unsigned char)( len & 0xFF );
00348     MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, *p, len ) ); /* r */
00349     *p += len;
00350 
00351 cleanup:
00352     mbedtls_ecp_point_free( &V );
00353     mbedtls_mpi_free( &v );
00354     mbedtls_mpi_free( &h );
00355 
00356     return( ret );
00357 }
00358 
00359 /*
00360  * Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof
00361  * Output: verified public key X
00362  */
00363 static int ecjpake_kkp_read( const mbedtls_md_info_t *md_info,
00364                              const mbedtls_ecp_group *grp,
00365                              const int pf,
00366                              const mbedtls_ecp_point *G,
00367                              mbedtls_ecp_point *X,
00368                              const char *id,
00369                              const unsigned char **p,
00370                              const unsigned char *end )
00371 {
00372     int ret;
00373 
00374     if( end < *p )
00375         return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
00376 
00377     /*
00378      * struct {
00379      *     ECPoint X;
00380      *     ECSchnorrZKP zkp;
00381      * } ECJPAKEKeyKP;
00382      */
00383     MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, X, p, end - *p ) );
00384     if( mbedtls_ecp_is_zero( X ) )
00385     {
00386         ret = MBEDTLS_ERR_ECP_INVALID_KEY;
00387         goto cleanup;
00388     }
00389 
00390     MBEDTLS_MPI_CHK( ecjpake_zkp_read( md_info, grp, pf, G, X, id, p, end ) );
00391 
00392 cleanup:
00393     return( ret );
00394 }
00395 
00396 /*
00397  * Generate an ECJPAKEKeyKP
00398  * Output: the serialized structure, plus private/public key pair
00399  */
00400 static int ecjpake_kkp_write( const mbedtls_md_info_t *md_info,
00401                               const mbedtls_ecp_group *grp,
00402                               const int pf,
00403                               const mbedtls_ecp_point *G,
00404                               mbedtls_mpi *x,
00405                               mbedtls_ecp_point *X,
00406                               const char *id,
00407                               unsigned char **p,
00408                               const unsigned char *end,
00409                               int (*f_rng)(void *, unsigned char *, size_t),
00410                               void *p_rng )
00411 {
00412     int ret;
00413     size_t len;
00414 
00415     if( end < *p )
00416         return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
00417 
00418     /* Generate key (7.4.2.3.1) and write it out */
00419     MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp, G, x, X,
00420                                                    f_rng, p_rng ) );
00421     MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, X,
00422                 pf, &len, *p, end - *p ) );
00423     *p += len;
00424 
00425     /* Generate and write proof */
00426     MBEDTLS_MPI_CHK( ecjpake_zkp_write( md_info, grp, pf, G, x, X, id,
00427                                         p, end, f_rng, p_rng ) );
00428 
00429 cleanup:
00430     return( ret );
00431 }
00432 
00433 /*
00434  * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs
00435  * Ouputs: verified peer public keys Xa, Xb
00436  */
00437 static int ecjpake_kkpp_read( const mbedtls_md_info_t *md_info,
00438                               const mbedtls_ecp_group *grp,
00439                               const int pf,
00440                               const mbedtls_ecp_point *G,
00441                               mbedtls_ecp_point *Xa,
00442                               mbedtls_ecp_point *Xb,
00443                               const char *id,
00444                               const unsigned char *buf,
00445                               size_t len )
00446 {
00447     int ret;
00448     const unsigned char *p = buf;
00449     const unsigned char *end = buf + len;
00450 
00451     /*
00452      * struct {
00453      *     ECJPAKEKeyKP ecjpake_key_kp_pair_list[2];
00454      * } ECJPAKEKeyKPPairList;
00455      */
00456     MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xa, id, &p, end ) );
00457     MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xb, id, &p, end ) );
00458 
00459     if( p != end )
00460         ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
00461 
00462 cleanup:
00463     return( ret );
00464 }
00465 
00466 /*
00467  * Generate a ECJPAKEKeyKPPairList
00468  * Outputs: the serialized structure, plus two private/public key pairs
00469  */
00470 static int ecjpake_kkpp_write( const mbedtls_md_info_t *md_info,
00471                                const mbedtls_ecp_group *grp,
00472                                const int pf,
00473                                const mbedtls_ecp_point *G,
00474                                mbedtls_mpi *xm1,
00475                                mbedtls_ecp_point *Xa,
00476                                mbedtls_mpi *xm2,
00477                                mbedtls_ecp_point *Xb,
00478                                const char *id,
00479                                unsigned char *buf,
00480                                size_t len,
00481                                size_t *olen,
00482                                int (*f_rng)(void *, unsigned char *, size_t),
00483                                void *p_rng )
00484 {
00485     int ret;
00486     unsigned char *p = buf;
00487     const unsigned char *end = buf + len;
00488 
00489     MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm1, Xa, id,
00490                 &p, end, f_rng, p_rng ) );
00491     MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm2, Xb, id,
00492                 &p, end, f_rng, p_rng ) );
00493 
00494     *olen = p - buf;
00495 
00496 cleanup:
00497     return( ret );
00498 }
00499 
00500 /*
00501  * Read and process the first round message
00502  */
00503 int mbedtls_ecjpake_read_round_one( mbedtls_ecjpake_context *ctx,
00504                                     const unsigned char *buf,
00505                                     size_t len )
00506 {
00507     return( ecjpake_kkpp_read( ctx->md_info, &ctx->grp, ctx->point_format,
00508                                &ctx->grp.G ,
00509                                &ctx->Xp1, &ctx->Xp2, ID_PEER,
00510                                buf, len ) );
00511 }
00512 
00513 /*
00514  * Generate and write the first round message
00515  */
00516 int mbedtls_ecjpake_write_round_one( mbedtls_ecjpake_context *ctx,
00517                             unsigned char *buf, size_t len, size_t *olen,
00518                             int (*f_rng)(void *, unsigned char *, size_t),
00519                             void *p_rng )
00520 {
00521     return( ecjpake_kkpp_write( ctx->md_info, &ctx->grp, ctx->point_format,
00522                                 &ctx->grp.G ,
00523                                 &ctx->xm1, &ctx->Xm1, &ctx->xm2, &ctx->Xm2,
00524                                 ID_MINE, buf, len, olen, f_rng, p_rng ) );
00525 }
00526 
00527 /*
00528  * Compute the sum of three points R = A + B + C
00529  */
00530 static int ecjpake_ecp_add3( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
00531                              const mbedtls_ecp_point *A,
00532                              const mbedtls_ecp_point *B,
00533                              const mbedtls_ecp_point *C )
00534 {
00535     int ret;
00536     mbedtls_mpi one;
00537 
00538     mbedtls_mpi_init( &one );
00539 
00540     MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
00541     MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, A, &one, B ) );
00542     MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, R, &one, C ) );
00543 
00544 cleanup:
00545     mbedtls_mpi_free( &one );
00546 
00547     return( ret );
00548 }
00549 
00550 /*
00551  * Read and process second round message (C: 7.4.2.5, S: 7.4.2.6)
00552  */
00553 int mbedtls_ecjpake_read_round_two( mbedtls_ecjpake_context *ctx,
00554                                             const unsigned char *buf,
00555                                             size_t len )
00556 {
00557     int ret;
00558     const unsigned char *p = buf;
00559     const unsigned char *end = buf + len;
00560     mbedtls_ecp_group grp;
00561     mbedtls_ecp_point G;    /* C: GB, S: GA */
00562 
00563     mbedtls_ecp_group_init( &grp );
00564     mbedtls_ecp_point_init( &G );
00565 
00566     /*
00567      * Server: GA = X3  + X4  + X1      (7.4.2.6.1)
00568      * Client: GB = X1  + X2  + X3      (7.4.2.5.1)
00569      * Unified: G = Xm1 + Xm2 + Xp1
00570      * We need that before parsing in order to check Xp as we read it
00571      */
00572     MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G,
00573                                        &ctx->Xm1, &ctx->Xm2, &ctx->Xp1 ) );
00574 
00575     /*
00576      * struct {
00577      *     ECParameters curve_params;   // only client reading server msg
00578      *     ECJPAKEKeyKP ecjpake_key_kp;
00579      * } Client/ServerECJPAKEParams;
00580      */
00581     if( ctx->role == MBEDTLS_ECJPAKE_CLIENT )
00582     {
00583         MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_group( &grp, &p, len ) );
00584         if( grp.id  != ctx->grp.id  )
00585         {
00586             ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
00587             goto cleanup;
00588         }
00589     }
00590 
00591     MBEDTLS_MPI_CHK( ecjpake_kkp_read( ctx->md_info, &ctx->grp,
00592                             ctx->point_format,
00593                             &G, &ctx->Xp, ID_PEER, &p, end ) );
00594 
00595     if( p != end )
00596     {
00597         ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
00598         goto cleanup;
00599     }
00600 
00601 cleanup:
00602     mbedtls_ecp_group_free( &grp );
00603     mbedtls_ecp_point_free( &G );
00604 
00605     return( ret );
00606 }
00607 
00608 /*
00609  * Compute R = +/- X * S mod N, taking care not to leak S
00610  */
00611 static int ecjpake_mul_secret( mbedtls_mpi *R, int sign,
00612                                const mbedtls_mpi *X,
00613                                const mbedtls_mpi *S,
00614                                const mbedtls_mpi *N,
00615                                int (*f_rng)(void *, unsigned char *, size_t),
00616                                void *p_rng )
00617 {
00618     int ret;
00619     mbedtls_mpi b; /* Blinding value, then s + N * blinding */
00620 
00621     mbedtls_mpi_init( &b );
00622 
00623     /* b = s + rnd-128-bit * N */
00624     MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &b, 16, f_rng, p_rng ) );
00625     MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &b, &b, N ) );
00626     MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &b, &b, S ) );
00627 
00628     /* R = sign * X * b mod N */
00629     MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( R, X, &b ) );
00630     R->s  *= sign;
00631     MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( R, R, N ) );
00632 
00633 cleanup:
00634     mbedtls_mpi_free( &b );
00635 
00636     return( ret );
00637 }
00638 
00639 /*
00640  * Generate and write the second round message (S: 7.4.2.5, C: 7.4.2.6)
00641  */
00642 int mbedtls_ecjpake_write_round_two( mbedtls_ecjpake_context *ctx,
00643                             unsigned char *buf, size_t len, size_t *olen,
00644                             int (*f_rng)(void *, unsigned char *, size_t),
00645                             void *p_rng )
00646 {
00647     int ret;
00648     mbedtls_ecp_point G;    /* C: GA, S: GB */
00649     mbedtls_ecp_point Xm;   /* C: Xc, S: Xs */
00650     mbedtls_mpi xm;         /* C: xc, S: xs */
00651     unsigned char *p = buf;
00652     const unsigned char *end = buf + len;
00653     size_t ec_len;
00654 
00655     mbedtls_ecp_point_init( &G );
00656     mbedtls_ecp_point_init( &Xm );
00657     mbedtls_mpi_init( &xm );
00658 
00659     /*
00660      * First generate private/public key pair (S: 7.4.2.5.1, C: 7.4.2.6.1)
00661      *
00662      * Client:  GA = X1  + X3  + X4  | xs = x2  * s | Xc = xc * GA
00663      * Server:  GB = X3  + X1  + X2  | xs = x4  * s | Xs = xs * GB
00664      * Unified: G  = Xm1 + Xp1 + Xp2 | xm = xm2 * s | Xm = xm * G
00665      */
00666     MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G,
00667                                        &ctx->Xp1, &ctx->Xp2, &ctx->Xm1 ) );
00668     MBEDTLS_MPI_CHK( ecjpake_mul_secret( &xm, 1, &ctx->xm2, &ctx->s,
00669                                          &ctx->grp.N , f_rng, p_rng ) );
00670     MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &Xm, &xm, &G, f_rng, p_rng ) );
00671 
00672     /*
00673      * Now write things out
00674      *
00675      * struct {
00676      *     ECParameters curve_params;   // only server writing its message
00677      *     ECJPAKEKeyKP ecjpake_key_kp;
00678      * } Client/ServerECJPAKEParams;
00679      */
00680     if( ctx->role == MBEDTLS_ECJPAKE_SERVER )
00681     {
00682         if( end < p )
00683         {
00684             ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
00685             goto cleanup;
00686         }
00687         MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_group( &ctx->grp, &ec_len,
00688                                                       p, end - p ) );
00689         p += ec_len;
00690     }
00691 
00692     if( end < p )
00693     {
00694         ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
00695         goto cleanup;
00696     }
00697     MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( &ctx->grp, &Xm,
00698                      ctx->point_format, &ec_len, p, end - p ) );
00699     p += ec_len;
00700 
00701     MBEDTLS_MPI_CHK( ecjpake_zkp_write( ctx->md_info, &ctx->grp,
00702                                         ctx->point_format,
00703                                         &G, &xm, &Xm, ID_MINE,
00704                                         &p, end, f_rng, p_rng ) );
00705 
00706     *olen = p - buf;
00707 
00708 cleanup:
00709     mbedtls_ecp_point_free( &G );
00710     mbedtls_ecp_point_free( &Xm );
00711     mbedtls_mpi_free( &xm );
00712 
00713     return( ret );
00714 }
00715 
00716 /*
00717  * Derive PMS (7.4.2.7 / 7.4.2.8)
00718  */
00719 int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx,
00720                             unsigned char *buf, size_t len, size_t *olen,
00721                             int (*f_rng)(void *, unsigned char *, size_t),
00722                             void *p_rng )
00723 {
00724     int ret;
00725     mbedtls_ecp_point K;
00726     mbedtls_mpi m_xm2_s, one;
00727     unsigned char kx[MBEDTLS_ECP_MAX_BYTES];
00728     size_t x_bytes;
00729 
00730     *olen = mbedtls_md_get_size( ctx->md_info );
00731     if( len < *olen )
00732         return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
00733 
00734     mbedtls_ecp_point_init( &K );
00735     mbedtls_mpi_init( &m_xm2_s );
00736     mbedtls_mpi_init( &one );
00737 
00738     MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
00739 
00740     /*
00741      * Client:  K = ( Xs - X4  * x2  * s ) * x2
00742      * Server:  K = ( Xc - X2  * x4  * s ) * x4
00743      * Unified: K = ( Xp - Xp2 * xm2 * s ) * xm2
00744      */
00745     MBEDTLS_MPI_CHK( ecjpake_mul_secret( &m_xm2_s, -1, &ctx->xm2, &ctx->s,
00746                                          &ctx->grp.N , f_rng, p_rng ) );
00747     MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( &ctx->grp, &K,
00748                                          &one, &ctx->Xp,
00749                                          &m_xm2_s, &ctx->Xp2 ) );
00750     MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &K, &ctx->xm2, &K,
00751                                       f_rng, p_rng ) );
00752 
00753     /* PMS = SHA-256( K.X ) */
00754     x_bytes = ( ctx->grp.pbits  + 7 ) / 8;
00755     MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &K.X , kx, x_bytes ) );
00756     MBEDTLS_MPI_CHK( mbedtls_md( ctx->md_info, kx, x_bytes, buf ) );
00757 
00758 cleanup:
00759     mbedtls_ecp_point_free( &K );
00760     mbedtls_mpi_free( &m_xm2_s );
00761     mbedtls_mpi_free( &one );
00762 
00763     return( ret );
00764 }
00765 
00766 #undef ID_MINE
00767 #undef ID_PEER
00768 
00769 #endif /* ! MBEDTLS_ECJPAKE_ALT */
00770 
00771 #if defined(MBEDTLS_SELF_TEST)
00772 
00773 #if defined(MBEDTLS_PLATFORM_C)
00774 #include "mbedtls/platform.h"
00775 #else
00776 #include <stdio.h>
00777 #define mbedtls_printf     printf
00778 #endif
00779 
00780 #if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
00781     !defined(MBEDTLS_SHA256_C)
00782 int mbedtls_ecjpake_self_test( int verbose )
00783 {
00784     (void) verbose;
00785     return( 0 );
00786 }
00787 #else
00788 
00789 static const unsigned char ecjpake_test_password[] = {
00790     0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x6a, 0x70, 0x61, 0x6b, 0x65, 0x74,
00791     0x65, 0x73, 0x74
00792 };
00793 
00794 static const unsigned char ecjpake_test_x1[] = {
00795     0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
00796     0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
00797     0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21
00798 };
00799 
00800 static const unsigned char ecjpake_test_x2[] = {
00801     0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
00802     0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
00803     0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
00804 };
00805 
00806 static const unsigned char ecjpake_test_x3[] = {
00807     0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
00808     0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
00809     0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
00810 };
00811 
00812 static const unsigned char ecjpake_test_x4[] = {
00813     0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc,
00814     0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
00815     0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1
00816 };
00817 
00818 static const unsigned char ecjpake_test_cli_one[] = {
00819     0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19,
00820     0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44,
00821     0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad,
00822     0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62,
00823     0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9,
00824     0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d,
00825     0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e,
00826     0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e,
00827     0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73,
00828     0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22,
00829     0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce,
00830     0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00,
00831     0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b,
00832     0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e,
00833     0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62,
00834     0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5,
00835     0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb,
00836     0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35,
00837     0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0,
00838     0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb,
00839     0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47,
00840     0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39,
00841     0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97,
00842     0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40,
00843     0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d,
00844     0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa,
00845     0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d,
00846     0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0
00847 };
00848 
00849 static const unsigned char ecjpake_test_srv_one[] = {
00850     0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb,
00851     0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18,
00852     0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47,
00853     0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f,
00854     0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7,
00855     0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d,
00856     0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64,
00857     0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36,
00858     0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2,
00859     0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec,
00860     0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16,
00861     0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96,
00862     0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3,
00863     0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19,
00864     0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f,
00865     0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8,
00866     0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7,
00867     0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea,
00868     0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5,
00869     0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6,
00870     0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31,
00871     0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d,
00872     0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8,
00873     0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee,
00874     0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84,
00875     0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f,
00876     0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80,
00877     0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12
00878 };
00879 
00880 static const unsigned char ecjpake_test_srv_two[] = {
00881     0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23,
00882     0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c,
00883     0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f,
00884     0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca,
00885     0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26,
00886     0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55,
00887     0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38,
00888     0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6,
00889     0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9,
00890     0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4,
00891     0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2,
00892     0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8,
00893     0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd,
00894     0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c
00895 };
00896 
00897 static const unsigned char ecjpake_test_cli_two[] = {
00898     0x41, 0x04, 0x69, 0xd5, 0x4e, 0xe8, 0x5e, 0x90, 0xce, 0x3f, 0x12, 0x46,
00899     0x74, 0x2d, 0xe5, 0x07, 0xe9, 0x39, 0xe8, 0x1d, 0x1d, 0xc1, 0xc5, 0xcb,
00900     0x98, 0x8b, 0x58, 0xc3, 0x10, 0xc9, 0xfd, 0xd9, 0x52, 0x4d, 0x93, 0x72,
00901     0x0b, 0x45, 0x54, 0x1c, 0x83, 0xee, 0x88, 0x41, 0x19, 0x1d, 0xa7, 0xce,
00902     0xd8, 0x6e, 0x33, 0x12, 0xd4, 0x36, 0x23, 0xc1, 0xd6, 0x3e, 0x74, 0x98,
00903     0x9a, 0xba, 0x4a, 0xff, 0xd1, 0xee, 0x41, 0x04, 0x07, 0x7e, 0x8c, 0x31,
00904     0xe2, 0x0e, 0x6b, 0xed, 0xb7, 0x60, 0xc1, 0x35, 0x93, 0xe6, 0x9f, 0x15,
00905     0xbe, 0x85, 0xc2, 0x7d, 0x68, 0xcd, 0x09, 0xcc, 0xb8, 0xc4, 0x18, 0x36,
00906     0x08, 0x91, 0x7c, 0x5c, 0x3d, 0x40, 0x9f, 0xac, 0x39, 0xfe, 0xfe, 0xe8,
00907     0x2f, 0x72, 0x92, 0xd3, 0x6f, 0x0d, 0x23, 0xe0, 0x55, 0x91, 0x3f, 0x45,
00908     0xa5, 0x2b, 0x85, 0xdd, 0x8a, 0x20, 0x52, 0xe9, 0xe1, 0x29, 0xbb, 0x4d,
00909     0x20, 0x0f, 0x01, 0x1f, 0x19, 0x48, 0x35, 0x35, 0xa6, 0xe8, 0x9a, 0x58,
00910     0x0c, 0x9b, 0x00, 0x03, 0xba, 0xf2, 0x14, 0x62, 0xec, 0xe9, 0x1a, 0x82,
00911     0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c
00912 };
00913 
00914 static const unsigned char ecjpake_test_pms[] = {
00915     0xf3, 0xd4, 0x7f, 0x59, 0x98, 0x44, 0xdb, 0x92, 0xa5, 0x69, 0xbb, 0xe7,
00916     0x98, 0x1e, 0x39, 0xd9, 0x31, 0xfd, 0x74, 0x3b, 0xf2, 0x2e, 0x98, 0xf9,
00917     0xb4, 0x38, 0xf7, 0x19, 0xd3, 0xc4, 0xf3, 0x51
00918 };
00919 
00920 /* Load my private keys and generate the correponding public keys */
00921 static int ecjpake_test_load( mbedtls_ecjpake_context *ctx,
00922                               const unsigned char *xm1, size_t len1,
00923                               const unsigned char *xm2, size_t len2 )
00924 {
00925     int ret;
00926 
00927     MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm1, xm1, len1 ) );
00928     MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm2, xm2, len2 ) );
00929     MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm1, &ctx->xm1,
00930                                       &ctx->grp.G , NULL, NULL ) );
00931     MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm2, &ctx->xm2,
00932                                       &ctx->grp.G , NULL, NULL ) );
00933 
00934 cleanup:
00935     return( ret );
00936 }
00937 
00938 /* For tests we don't need a secure RNG;
00939  * use the LGC from Numerical Recipes for simplicity */
00940 static int ecjpake_lgc( void *p, unsigned char *out, size_t len )
00941 {
00942     static uint32_t x = 42;
00943     (void) p;
00944 
00945     while( len > 0 )
00946     {
00947         size_t use_len = len > 4 ? 4 : len;
00948         x = 1664525 * x + 1013904223;
00949         memcpy( out, &x, use_len );
00950         out += use_len;
00951         len -= use_len;
00952     }
00953 
00954     return( 0 );
00955 }
00956 
00957 #define TEST_ASSERT( x )    \
00958     do {                    \
00959         if( x )             \
00960             ret = 0;        \
00961         else                \
00962         {                   \
00963             ret = 1;        \
00964             goto cleanup;   \
00965         }                   \
00966     } while( 0 )
00967 
00968 /*
00969  * Checkup routine
00970  */
00971 int mbedtls_ecjpake_self_test( int verbose )
00972 {
00973     int ret;
00974     mbedtls_ecjpake_context cli;
00975     mbedtls_ecjpake_context srv;
00976     unsigned char buf[512], pms[32];
00977     size_t len, pmslen;
00978 
00979     mbedtls_ecjpake_init( &cli );
00980     mbedtls_ecjpake_init( &srv );
00981 
00982     if( verbose != 0 )
00983         mbedtls_printf( "  ECJPAKE test #0 (setup): " );
00984 
00985     TEST_ASSERT( mbedtls_ecjpake_setup( &cli, MBEDTLS_ECJPAKE_CLIENT,
00986                     MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
00987                     ecjpake_test_password,
00988             sizeof( ecjpake_test_password ) ) == 0 );
00989 
00990     TEST_ASSERT( mbedtls_ecjpake_setup( &srv, MBEDTLS_ECJPAKE_SERVER,
00991                     MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
00992                     ecjpake_test_password,
00993             sizeof( ecjpake_test_password ) ) == 0 );
00994 
00995     if( verbose != 0 )
00996         mbedtls_printf( "passed\n" );
00997 
00998     if( verbose != 0 )
00999         mbedtls_printf( "  ECJPAKE test #1 (random handshake): " );
01000 
01001     TEST_ASSERT( mbedtls_ecjpake_write_round_one( &cli,
01002                  buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
01003 
01004     TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv, buf, len ) == 0 );
01005 
01006     TEST_ASSERT( mbedtls_ecjpake_write_round_one( &srv,
01007                  buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
01008 
01009     TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli, buf, len ) == 0 );
01010 
01011     TEST_ASSERT( mbedtls_ecjpake_write_round_two( &srv,
01012                  buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
01013 
01014     TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli, buf, len ) == 0 );
01015 
01016     TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli,
01017                  pms, sizeof( pms ), &pmslen, ecjpake_lgc, NULL ) == 0 );
01018 
01019     TEST_ASSERT( mbedtls_ecjpake_write_round_two( &cli,
01020                  buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
01021 
01022     TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv, buf, len ) == 0 );
01023 
01024     TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv,
01025                  buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
01026 
01027     TEST_ASSERT( len == pmslen );
01028     TEST_ASSERT( memcmp( buf, pms, len ) == 0 );
01029 
01030     if( verbose != 0 )
01031         mbedtls_printf( "passed\n" );
01032 
01033     if( verbose != 0 )
01034         mbedtls_printf( "  ECJPAKE test #2 (reference handshake): " );
01035 
01036     /* Simulate generation of round one */
01037     MBEDTLS_MPI_CHK( ecjpake_test_load( &cli,
01038                 ecjpake_test_x1, sizeof( ecjpake_test_x1 ),
01039                 ecjpake_test_x2, sizeof( ecjpake_test_x2 ) ) );
01040 
01041     MBEDTLS_MPI_CHK( ecjpake_test_load( &srv,
01042                 ecjpake_test_x3, sizeof( ecjpake_test_x3 ),
01043                 ecjpake_test_x4, sizeof( ecjpake_test_x4 ) ) );
01044 
01045     /* Read round one */
01046     TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv,
01047                                     ecjpake_test_cli_one,
01048                             sizeof( ecjpake_test_cli_one ) ) == 0 );
01049 
01050     TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli,
01051                                     ecjpake_test_srv_one,
01052                             sizeof( ecjpake_test_srv_one ) ) == 0 );
01053 
01054     /* Skip generation of round two, read round two */
01055     TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli,
01056                                     ecjpake_test_srv_two,
01057                             sizeof( ecjpake_test_srv_two ) ) == 0 );
01058 
01059     TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv,
01060                                     ecjpake_test_cli_two,
01061                             sizeof( ecjpake_test_cli_two ) ) == 0 );
01062 
01063     /* Server derives PMS */
01064     TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv,
01065                  buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
01066 
01067     TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
01068     TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
01069 
01070     memset( buf, 0, len ); /* Avoid interferences with next step */
01071 
01072     /* Client derives PMS */
01073     TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli,
01074                  buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
01075 
01076     TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
01077     TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
01078 
01079     if( verbose != 0 )
01080         mbedtls_printf( "passed\n" );
01081 
01082 cleanup:
01083     mbedtls_ecjpake_free( &cli );
01084     mbedtls_ecjpake_free( &srv );
01085 
01086     if( ret != 0 )
01087     {
01088         if( verbose != 0 )
01089             mbedtls_printf( "failed\n" );
01090 
01091         ret = 1;
01092     }
01093 
01094     if( verbose != 0 )
01095         mbedtls_printf( "\n" );
01096 
01097     return( ret );
01098 }
01099 
01100 #undef TEST_ASSERT
01101 
01102 #endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_SHA256_C */
01103 
01104 #endif /* MBEDTLS_SELF_TEST */
01105 
01106 #endif /* MBEDTLS_ECJPAKE_C */