mbed os with nrf51 internal bandgap enabled to read battery level

Dependents:   BLE_file_test BLE_Blink ExternalEncoder

Committer:
elessair
Date:
Sun Oct 23 15:10:02 2016 +0000
Revision:
0:f269e3021894
Initial commit

Who changed what in which revision?

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