Coverage Report

Created: 2024-11-21 07:03

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