Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
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 */
Generated on Tue Jul 12 2022 13:54:17 by
