Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/mbedtls/library/ecjpake.c
9898 views
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
#define ID_MINE (ecjpake_id[ctx->role])
34
#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
{
43
return mbedtls_md(mbedtls_md_info_from_type(md_type),
44
input, ilen, output);
45
}
46
47
/*
48
* Initialize context
49
*/
50
void mbedtls_ecjpake_init(mbedtls_ecjpake_context *ctx)
51
{
52
ctx->md_type = MBEDTLS_MD_NONE;
53
mbedtls_ecp_group_init(&ctx->grp);
54
ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
55
56
mbedtls_ecp_point_init(&ctx->Xm1);
57
mbedtls_ecp_point_init(&ctx->Xm2);
58
mbedtls_ecp_point_init(&ctx->Xp1);
59
mbedtls_ecp_point_init(&ctx->Xp2);
60
mbedtls_ecp_point_init(&ctx->Xp);
61
62
mbedtls_mpi_init(&ctx->xm1);
63
mbedtls_mpi_init(&ctx->xm2);
64
mbedtls_mpi_init(&ctx->s);
65
}
66
67
/*
68
* Free context
69
*/
70
void mbedtls_ecjpake_free(mbedtls_ecjpake_context *ctx)
71
{
72
if (ctx == NULL) {
73
return;
74
}
75
76
ctx->md_type = MBEDTLS_MD_NONE;
77
mbedtls_ecp_group_free(&ctx->grp);
78
79
mbedtls_ecp_point_free(&ctx->Xm1);
80
mbedtls_ecp_point_free(&ctx->Xm2);
81
mbedtls_ecp_point_free(&ctx->Xp1);
82
mbedtls_ecp_point_free(&ctx->Xp2);
83
mbedtls_ecp_point_free(&ctx->Xp);
84
85
mbedtls_mpi_free(&ctx->xm1);
86
mbedtls_mpi_free(&ctx->xm2);
87
mbedtls_mpi_free(&ctx->s);
88
}
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
{
100
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
101
102
if (role != MBEDTLS_ECJPAKE_CLIENT && role != MBEDTLS_ECJPAKE_SERVER) {
103
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
104
}
105
106
ctx->role = role;
107
108
if ((mbedtls_md_info_from_type(hash)) == NULL) {
109
return MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE;
110
}
111
112
ctx->md_type = hash;
113
114
MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&ctx->grp, curve));
115
116
MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->s, secret, len));
117
118
cleanup:
119
if (ret != 0) {
120
mbedtls_ecjpake_free(ctx);
121
}
122
123
return ret;
124
}
125
126
int mbedtls_ecjpake_set_point_format(mbedtls_ecjpake_context *ctx,
127
int point_format)
128
{
129
switch (point_format) {
130
case MBEDTLS_ECP_PF_UNCOMPRESSED:
131
case MBEDTLS_ECP_PF_COMPRESSED:
132
ctx->point_format = point_format;
133
return 0;
134
default:
135
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
136
}
137
}
138
139
/*
140
* Check if context is ready for use
141
*/
142
int mbedtls_ecjpake_check(const mbedtls_ecjpake_context *ctx)
143
{
144
if (ctx->md_type == MBEDTLS_MD_NONE ||
145
ctx->grp.id == MBEDTLS_ECP_DP_NONE ||
146
ctx->s.p == NULL) {
147
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
148
}
149
150
return 0;
151
}
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
{
162
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
163
size_t len;
164
165
/* Need at least 4 for length plus 1 for point */
166
if (end < *p || end - *p < 5) {
167
return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
168
}
169
170
ret = mbedtls_ecp_point_write_binary(grp, P, pf,
171
&len, *p + 4, (size_t) (end - (*p + 4)));
172
if (ret != 0) {
173
return ret;
174
}
175
176
MBEDTLS_PUT_UINT32_BE(len, *p, 0);
177
178
*p += 4 + len;
179
180
return 0;
181
}
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
{
201
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
202
unsigned char buf[ECJPAKE_HASH_BUF_LEN];
203
unsigned char *p = buf;
204
const unsigned char *end = buf + sizeof(buf);
205
const size_t id_len = strlen(id);
206
unsigned char hash[MBEDTLS_MD_MAX_SIZE];
207
208
/* Write things to temporary buffer */
209
MBEDTLS_MPI_CHK(ecjpake_write_len_point(&p, end, grp, pf, G));
210
MBEDTLS_MPI_CHK(ecjpake_write_len_point(&p, end, grp, pf, V));
211
MBEDTLS_MPI_CHK(ecjpake_write_len_point(&p, end, grp, pf, X));
212
213
if (end - p < 4) {
214
return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
215
}
216
217
MBEDTLS_PUT_UINT32_BE(id_len, p, 0);
218
p += 4;
219
220
if (end < p || (size_t) (end - p) < id_len) {
221
return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
222
}
223
224
memcpy(p, id, id_len);
225
p += id_len;
226
227
/* Compute hash */
228
MBEDTLS_MPI_CHK(mbedtls_ecjpake_compute_hash(md_type,
229
buf, (size_t) (p - buf), hash));
230
231
/* Turn it into an integer mod n */
232
MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(h, hash,
233
mbedtls_md_get_size_from_type(md_type)));
234
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(h, h, &grp->N));
235
236
cleanup:
237
return ret;
238
}
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
{
252
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
253
mbedtls_ecp_point V, VV;
254
mbedtls_mpi r, h;
255
size_t r_len;
256
257
mbedtls_ecp_point_init(&V);
258
mbedtls_ecp_point_init(&VV);
259
mbedtls_mpi_init(&r);
260
mbedtls_mpi_init(&h);
261
262
/*
263
* struct {
264
* ECPoint V;
265
* opaque r<1..2^8-1>;
266
* } ECSchnorrZKP;
267
*/
268
if (end < *p) {
269
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
270
}
271
272
MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_point(grp, &V, p, (size_t) (end - *p)));
273
274
if (end < *p || (size_t) (end - *p) < 1) {
275
ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
276
goto cleanup;
277
}
278
279
r_len = *(*p)++;
280
281
if (end < *p || (size_t) (end - *p) < r_len || r_len == 0) {
282
ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
283
goto cleanup;
284
}
285
286
MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&r, *p, r_len));
287
*p += r_len;
288
289
/*
290
* Verification
291
*/
292
MBEDTLS_MPI_CHK(ecjpake_hash(md_type, grp, pf, G, &V, X, id, &h));
293
MBEDTLS_MPI_CHK(mbedtls_ecp_muladd((mbedtls_ecp_group *) grp,
294
&VV, &h, X, &r, G));
295
296
if (mbedtls_ecp_point_cmp(&VV, &V) != 0) {
297
ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
298
goto cleanup;
299
}
300
301
cleanup:
302
mbedtls_ecp_point_free(&V);
303
mbedtls_ecp_point_free(&VV);
304
mbedtls_mpi_free(&r);
305
mbedtls_mpi_free(&h);
306
307
return ret;
308
}
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
{
325
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
326
mbedtls_ecp_point V;
327
mbedtls_mpi v;
328
mbedtls_mpi h; /* later recycled to hold r */
329
size_t len;
330
331
if (end < *p) {
332
return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
333
}
334
335
mbedtls_ecp_point_init(&V);
336
mbedtls_mpi_init(&v);
337
mbedtls_mpi_init(&h);
338
339
/* Compute signature */
340
MBEDTLS_MPI_CHK(mbedtls_ecp_gen_keypair_base((mbedtls_ecp_group *) grp,
341
G, &v, &V, f_rng, p_rng));
342
MBEDTLS_MPI_CHK(ecjpake_hash(md_type, grp, pf, G, &V, X, id, &h));
343
MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&h, &h, x)); /* x*h */
344
MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&h, &v, &h)); /* v - x*h */
345
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&h, &h, &grp->N)); /* r */
346
347
/* Write it out */
348
MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(grp, &V,
349
pf, &len, *p, (size_t) (end - *p)));
350
*p += len;
351
352
len = mbedtls_mpi_size(&h); /* actually r */
353
if (end < *p || (size_t) (end - *p) < 1 + len || len > 255) {
354
ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
355
goto cleanup;
356
}
357
358
*(*p)++ = MBEDTLS_BYTE_0(len);
359
MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&h, *p, len)); /* r */
360
*p += len;
361
362
cleanup:
363
mbedtls_ecp_point_free(&V);
364
mbedtls_mpi_free(&v);
365
mbedtls_mpi_free(&h);
366
367
return ret;
368
}
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
{
383
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
384
385
if (end < *p) {
386
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
387
}
388
389
/*
390
* struct {
391
* ECPoint X;
392
* ECSchnorrZKP zkp;
393
* } ECJPAKEKeyKP;
394
*/
395
MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_point(grp, X, p, (size_t) (end - *p)));
396
if (mbedtls_ecp_is_zero(X)) {
397
ret = MBEDTLS_ERR_ECP_INVALID_KEY;
398
goto cleanup;
399
}
400
401
MBEDTLS_MPI_CHK(ecjpake_zkp_read(md_type, grp, pf, G, X, id, p, end));
402
403
cleanup:
404
return ret;
405
}
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
{
423
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
424
size_t len;
425
426
if (end < *p) {
427
return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
428
}
429
430
/* Generate key (7.4.2.3.1) and write it out */
431
MBEDTLS_MPI_CHK(mbedtls_ecp_gen_keypair_base((mbedtls_ecp_group *) grp, G, x, X,
432
f_rng, p_rng));
433
MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(grp, X,
434
pf, &len, *p, (size_t) (end - *p)));
435
*p += len;
436
437
/* Generate and write proof */
438
MBEDTLS_MPI_CHK(ecjpake_zkp_write(md_type, grp, pf, G, x, X, id,
439
p, end, f_rng, p_rng));
440
441
cleanup:
442
return ret;
443
}
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
{
459
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
460
const unsigned char *p = buf;
461
const unsigned char *end = buf + len;
462
463
/*
464
* struct {
465
* ECJPAKEKeyKP ecjpake_key_kp_pair_list[2];
466
* } ECJPAKEKeyKPPairList;
467
*/
468
MBEDTLS_MPI_CHK(ecjpake_kkp_read(md_type, grp, pf, G, Xa, id, &p, end));
469
MBEDTLS_MPI_CHK(ecjpake_kkp_read(md_type, grp, pf, G, Xb, id, &p, end));
470
471
if (p != end) {
472
ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
473
}
474
475
cleanup:
476
return ret;
477
}
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
{
498
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
499
unsigned char *p = buf;
500
const unsigned char *end = buf + len;
501
502
MBEDTLS_MPI_CHK(ecjpake_kkp_write(md_type, grp, pf, G, xm1, Xa, id,
503
&p, end, f_rng, p_rng));
504
MBEDTLS_MPI_CHK(ecjpake_kkp_write(md_type, grp, pf, G, xm2, Xb, id,
505
&p, end, f_rng, p_rng));
506
507
*olen = (size_t) (p - buf);
508
509
cleanup:
510
return ret;
511
}
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
{
520
return ecjpake_kkpp_read(ctx->md_type, &ctx->grp, ctx->point_format,
521
&ctx->grp.G,
522
&ctx->Xp1, &ctx->Xp2, ID_PEER,
523
buf, len);
524
}
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
{
534
return ecjpake_kkpp_write(ctx->md_type, &ctx->grp, ctx->point_format,
535
&ctx->grp.G,
536
&ctx->xm1, &ctx->Xm1, &ctx->xm2, &ctx->Xm2,
537
ID_MINE, buf, len, olen, f_rng, p_rng);
538
}
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
{
548
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
549
mbedtls_mpi one;
550
551
mbedtls_mpi_init(&one);
552
553
MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&one, 1));
554
MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(grp, R, &one, A, &one, B));
555
MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(grp, R, &one, R, &one, C));
556
557
cleanup:
558
mbedtls_mpi_free(&one);
559
560
return ret;
561
}
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
{
570
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
571
const unsigned char *p = buf;
572
const unsigned char *end = buf + len;
573
mbedtls_ecp_group grp;
574
mbedtls_ecp_point G; /* C: GB, S: GA */
575
576
mbedtls_ecp_group_init(&grp);
577
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
MBEDTLS_MPI_CHK(ecjpake_ecp_add3(&ctx->grp, &G,
586
&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
if (ctx->role == MBEDTLS_ECJPAKE_CLIENT) {
595
MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_group(&grp, &p, len));
596
if (grp.id != ctx->grp.id) {
597
ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
598
goto cleanup;
599
}
600
}
601
602
MBEDTLS_MPI_CHK(ecjpake_kkp_read(ctx->md_type, &ctx->grp,
603
ctx->point_format,
604
&G, &ctx->Xp, ID_PEER, &p, end));
605
606
if (p != end) {
607
ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
608
goto cleanup;
609
}
610
611
cleanup:
612
mbedtls_ecp_group_free(&grp);
613
mbedtls_ecp_point_free(&G);
614
615
return ret;
616
}
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
{
628
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
629
mbedtls_mpi b; /* Blinding value, then s + N * blinding */
630
631
mbedtls_mpi_init(&b);
632
633
/* b = s + rnd-128-bit * N */
634
MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&b, 16, f_rng, p_rng));
635
MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&b, &b, N));
636
MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&b, &b, S));
637
638
/* R = sign * X * b mod N */
639
MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(R, X, &b));
640
R->s *= sign;
641
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(R, R, N));
642
643
cleanup:
644
mbedtls_mpi_free(&b);
645
646
return ret;
647
}
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
{
657
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
658
mbedtls_ecp_point G; /* C: GA, S: GB */
659
mbedtls_ecp_point Xm; /* C: Xc, S: Xs */
660
mbedtls_mpi xm; /* C: xc, S: xs */
661
unsigned char *p = buf;
662
const unsigned char *end = buf + len;
663
size_t ec_len;
664
665
mbedtls_ecp_point_init(&G);
666
mbedtls_ecp_point_init(&Xm);
667
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
MBEDTLS_MPI_CHK(ecjpake_ecp_add3(&ctx->grp, &G,
677
&ctx->Xp1, &ctx->Xp2, &ctx->Xm1));
678
MBEDTLS_MPI_CHK(ecjpake_mul_secret(&xm, 1, &ctx->xm2, &ctx->s,
679
&ctx->grp.N, f_rng, p_rng));
680
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
if (ctx->role == MBEDTLS_ECJPAKE_SERVER) {
691
if (end < p) {
692
ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
693
goto cleanup;
694
}
695
MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_group(&ctx->grp, &ec_len,
696
p, (size_t) (end - p)));
697
p += ec_len;
698
}
699
700
if (end < p) {
701
ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
702
goto cleanup;
703
}
704
MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(&ctx->grp, &Xm,
705
ctx->point_format, &ec_len, p, (size_t) (end - p)));
706
p += ec_len;
707
708
MBEDTLS_MPI_CHK(ecjpake_zkp_write(ctx->md_type, &ctx->grp,
709
ctx->point_format,
710
&G, &xm, &Xm, ID_MINE,
711
&p, end, f_rng, p_rng));
712
713
*olen = (size_t) (p - buf);
714
715
cleanup:
716
mbedtls_ecp_point_free(&G);
717
mbedtls_ecp_point_free(&Xm);
718
mbedtls_mpi_free(&xm);
719
720
return ret;
721
}
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
{
731
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
732
mbedtls_mpi m_xm2_s, one;
733
734
mbedtls_mpi_init(&m_xm2_s);
735
mbedtls_mpi_init(&one);
736
737
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
MBEDTLS_MPI_CHK(ecjpake_mul_secret(&m_xm2_s, -1, &ctx->xm2, &ctx->s,
745
&ctx->grp.N, f_rng, p_rng));
746
MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(&ctx->grp, K,
747
&one, &ctx->Xp,
748
&m_xm2_s, &ctx->Xp2));
749
MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, K, &ctx->xm2, K,
750
f_rng, p_rng));
751
752
cleanup:
753
mbedtls_mpi_free(&m_xm2_s);
754
mbedtls_mpi_free(&one);
755
756
return ret;
757
}
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
{
764
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
765
mbedtls_ecp_point K;
766
unsigned char kx[MBEDTLS_ECP_MAX_BYTES];
767
size_t x_bytes;
768
769
*olen = mbedtls_md_get_size_from_type(ctx->md_type);
770
if (len < *olen) {
771
return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
772
}
773
774
mbedtls_ecp_point_init(&K);
775
776
ret = mbedtls_ecjpake_derive_k(ctx, &K, f_rng, p_rng);
777
if (ret) {
778
goto cleanup;
779
}
780
781
/* PMS = SHA-256( K.X ) */
782
x_bytes = (ctx->grp.pbits + 7) / 8;
783
MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&K.X, kx, x_bytes));
784
MBEDTLS_MPI_CHK(mbedtls_ecjpake_compute_hash(ctx->md_type,
785
kx, x_bytes, buf));
786
787
cleanup:
788
mbedtls_ecp_point_free(&K);
789
790
return ret;
791
}
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
{
798
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
799
mbedtls_ecp_point K;
800
801
mbedtls_ecp_point_init(&K);
802
803
ret = mbedtls_ecjpake_derive_k(ctx, &K, f_rng, p_rng);
804
if (ret) {
805
goto cleanup;
806
}
807
808
ret = mbedtls_ecp_point_write_binary(&ctx->grp, &K, ctx->point_format,
809
olen, buf, len);
810
if (ret != 0) {
811
goto cleanup;
812
}
813
814
cleanup:
815
mbedtls_ecp_point_free(&K);
816
817
return ret;
818
}
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
{
989
static uint32_t state = 42;
990
991
(void) ctx;
992
993
for (size_t i = 0; i < len; i++) {
994
state = state * 1664525u + 1013904223u;
995
out[i] = (unsigned char) state;
996
}
997
998
return 0;
999
}
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
{
1006
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1007
1008
MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->xm1, xm1, len1));
1009
MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->xm2, xm2, len2));
1010
MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, &ctx->Xm1, &ctx->xm1,
1011
&ctx->grp.G, self_test_rng, NULL));
1012
MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, &ctx->Xm2, &ctx->xm2,
1013
&ctx->grp.G, self_test_rng, NULL));
1014
1015
cleanup:
1016
return ret;
1017
}
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
{
1025
static uint32_t x = 42;
1026
(void) p;
1027
1028
while (len > 0) {
1029
size_t use_len = len > 4 ? 4 : len;
1030
x = 1664525 * x + 1013904223;
1031
memcpy(out, &x, use_len);
1032
out += use_len;
1033
len -= use_len;
1034
}
1035
1036
return 0;
1037
}
1038
1039
#define TEST_ASSERT(x) \
1040
do { \
1041
if (x) \
1042
ret = 0; \
1043
else \
1044
{ \
1045
ret = 1; \
1046
goto cleanup; \
1047
} \
1048
} while (0)
1049
1050
/*
1051
* Checkup routine
1052
*/
1053
int mbedtls_ecjpake_self_test(int verbose)
1054
{
1055
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1056
mbedtls_ecjpake_context cli;
1057
mbedtls_ecjpake_context srv;
1058
unsigned char buf[512], pms[32];
1059
size_t len, pmslen;
1060
1061
mbedtls_ecjpake_init(&cli);
1062
mbedtls_ecjpake_init(&srv);
1063
1064
if (verbose != 0) {
1065
mbedtls_printf(" ECJPAKE test #0 (setup): ");
1066
}
1067
1068
TEST_ASSERT(mbedtls_ecjpake_setup(&cli, MBEDTLS_ECJPAKE_CLIENT,
1069
MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1070
ecjpake_test_password,
1071
sizeof(ecjpake_test_password)) == 0);
1072
1073
TEST_ASSERT(mbedtls_ecjpake_setup(&srv, MBEDTLS_ECJPAKE_SERVER,
1074
MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1075
ecjpake_test_password,
1076
sizeof(ecjpake_test_password)) == 0);
1077
1078
if (verbose != 0) {
1079
mbedtls_printf("passed\n");
1080
}
1081
1082
if (verbose != 0) {
1083
mbedtls_printf(" ECJPAKE test #1 (random handshake): ");
1084
}
1085
1086
TEST_ASSERT(mbedtls_ecjpake_write_round_one(&cli,
1087
buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
1088
1089
TEST_ASSERT(mbedtls_ecjpake_read_round_one(&srv, buf, len) == 0);
1090
1091
TEST_ASSERT(mbedtls_ecjpake_write_round_one(&srv,
1092
buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
1093
1094
TEST_ASSERT(mbedtls_ecjpake_read_round_one(&cli, buf, len) == 0);
1095
1096
TEST_ASSERT(mbedtls_ecjpake_write_round_two(&srv,
1097
buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
1098
1099
TEST_ASSERT(mbedtls_ecjpake_read_round_two(&cli, buf, len) == 0);
1100
1101
TEST_ASSERT(mbedtls_ecjpake_derive_secret(&cli,
1102
pms, sizeof(pms), &pmslen, ecjpake_lgc, NULL) == 0);
1103
1104
TEST_ASSERT(mbedtls_ecjpake_write_round_two(&cli,
1105
buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
1106
1107
TEST_ASSERT(mbedtls_ecjpake_read_round_two(&srv, buf, len) == 0);
1108
1109
TEST_ASSERT(mbedtls_ecjpake_derive_secret(&srv,
1110
buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
1111
1112
TEST_ASSERT(len == pmslen);
1113
TEST_ASSERT(memcmp(buf, pms, len) == 0);
1114
1115
if (verbose != 0) {
1116
mbedtls_printf("passed\n");
1117
}
1118
1119
#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
if (verbose != 0) {
1126
mbedtls_printf(" ECJPAKE test #2 (reference handshake): ");
1127
}
1128
1129
/* Simulate generation of round one */
1130
MBEDTLS_MPI_CHK(ecjpake_test_load(&cli,
1131
ecjpake_test_x1, sizeof(ecjpake_test_x1),
1132
ecjpake_test_x2, sizeof(ecjpake_test_x2)));
1133
1134
MBEDTLS_MPI_CHK(ecjpake_test_load(&srv,
1135
ecjpake_test_x3, sizeof(ecjpake_test_x3),
1136
ecjpake_test_x4, sizeof(ecjpake_test_x4)));
1137
1138
/* Read round one */
1139
TEST_ASSERT(mbedtls_ecjpake_read_round_one(&srv,
1140
ecjpake_test_cli_one,
1141
sizeof(ecjpake_test_cli_one)) == 0);
1142
1143
TEST_ASSERT(mbedtls_ecjpake_read_round_one(&cli,
1144
ecjpake_test_srv_one,
1145
sizeof(ecjpake_test_srv_one)) == 0);
1146
1147
/* Skip generation of round two, read round two */
1148
TEST_ASSERT(mbedtls_ecjpake_read_round_two(&cli,
1149
ecjpake_test_srv_two,
1150
sizeof(ecjpake_test_srv_two)) == 0);
1151
1152
TEST_ASSERT(mbedtls_ecjpake_read_round_two(&srv,
1153
ecjpake_test_cli_two,
1154
sizeof(ecjpake_test_cli_two)) == 0);
1155
1156
/* Server derives PMS */
1157
TEST_ASSERT(mbedtls_ecjpake_derive_secret(&srv,
1158
buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
1159
1160
TEST_ASSERT(len == sizeof(ecjpake_test_pms));
1161
TEST_ASSERT(memcmp(buf, ecjpake_test_pms, len) == 0);
1162
1163
/* Server derives K as unsigned binary data */
1164
TEST_ASSERT(mbedtls_ecjpake_write_shared_key(&srv,
1165
buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
1166
1167
TEST_ASSERT(len == sizeof(ecjpake_test_shared_key));
1168
TEST_ASSERT(memcmp(buf, ecjpake_test_shared_key, len) == 0);
1169
1170
memset(buf, 0, len); /* Avoid interferences with next step */
1171
1172
/* Client derives PMS */
1173
TEST_ASSERT(mbedtls_ecjpake_derive_secret(&cli,
1174
buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
1175
1176
TEST_ASSERT(len == sizeof(ecjpake_test_pms));
1177
TEST_ASSERT(memcmp(buf, ecjpake_test_pms, len) == 0);
1178
1179
/* Client derives K as unsigned binary data */
1180
TEST_ASSERT(mbedtls_ecjpake_write_shared_key(&cli,
1181
buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
1182
1183
TEST_ASSERT(len == sizeof(ecjpake_test_shared_key));
1184
TEST_ASSERT(memcmp(buf, ecjpake_test_shared_key, len) == 0);
1185
1186
if (verbose != 0) {
1187
mbedtls_printf("passed\n");
1188
}
1189
#endif /* ! MBEDTLS_ECJPAKE_ALT */
1190
1191
cleanup:
1192
mbedtls_ecjpake_free(&cli);
1193
mbedtls_ecjpake_free(&srv);
1194
1195
if (ret != 0) {
1196
if (verbose != 0) {
1197
mbedtls_printf("failed\n");
1198
}
1199
1200
ret = 1;
1201
}
1202
1203
if (verbose != 0) {
1204
mbedtls_printf("\n");
1205
}
1206
1207
return ret;
1208
}
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 */
1217
1218