RTC auf true

Committer:
kevman
Date:
Wed Nov 28 15:10:15 2018 +0000
Revision:
0:38ceb79fef03
RTC modified

Who changed what in which revision?

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