~bibledit/bibledit/client

« back to all changes in this revision

Viewing changes to mbedtls_2.x/ecjpake.c

  • Committer: Teus Benschop
  • Date: 2024-08-17 17:08:44 UTC
  • Revision ID: teusjannette@gmail.com-20240817170844-0qf789ywtms3hyz7
new upstream version

Show diffs side-by-side

added added

removed removed

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