Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

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