2 * Elliptic curve J-PAKE
4 * Copyright The Mbed TLS Contributors
5 * SPDX-License-Identifier: Apache-2.0
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
21 * References in the code are to the Thread v1.0 Specification,
22 * available to members of the Thread Group http://threadgroup.org/
27 #if defined(MBEDTLS_ECJPAKE_C)
29 #include "mbedtls/ecjpake.h"
30 #include "mbedtls/platform_util.h"
31 #include "mbedtls/error.h"
35 #if !defined(MBEDTLS_ECJPAKE_ALT)
37 /* Parameter validation macros based on platform_util.h */
38 #define ECJPAKE_VALIDATE_RET( cond ) \
39 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA )
40 #define ECJPAKE_VALIDATE( cond ) \
41 MBEDTLS_INTERNAL_VALIDATE( cond )
44 * Convert a mbedtls_ecjpake_role to identifier string
46 static const char *const ecjpake_id
[] = {
51 #define ID_MINE ( ecjpake_id[ ctx->role ] )
52 #define ID_PEER ( ecjpake_id[ 1 - ctx->role ] )
57 void mbedtls_ecjpake_init(mbedtls_ecjpake_context
*ctx
) {
58 ECJPAKE_VALIDATE(ctx
!= NULL
);
61 mbedtls_ecp_group_init(&ctx
->grp
);
62 ctx
->point_format
= MBEDTLS_ECP_PF_UNCOMPRESSED
;
64 mbedtls_ecp_point_init(&ctx
->Xm1
);
65 mbedtls_ecp_point_init(&ctx
->Xm2
);
66 mbedtls_ecp_point_init(&ctx
->Xp1
);
67 mbedtls_ecp_point_init(&ctx
->Xp2
);
68 mbedtls_ecp_point_init(&ctx
->Xp
);
70 mbedtls_mpi_init(&ctx
->xm1
);
71 mbedtls_mpi_init(&ctx
->xm2
);
72 mbedtls_mpi_init(&ctx
->s
);
78 void mbedtls_ecjpake_free(mbedtls_ecjpake_context
*ctx
) {
83 mbedtls_ecp_group_free(&ctx
->grp
);
85 mbedtls_ecp_point_free(&ctx
->Xm1
);
86 mbedtls_ecp_point_free(&ctx
->Xm2
);
87 mbedtls_ecp_point_free(&ctx
->Xp1
);
88 mbedtls_ecp_point_free(&ctx
->Xp2
);
89 mbedtls_ecp_point_free(&ctx
->Xp
);
91 mbedtls_mpi_free(&ctx
->xm1
);
92 mbedtls_mpi_free(&ctx
->xm2
);
93 mbedtls_mpi_free(&ctx
->s
);
99 int mbedtls_ecjpake_setup(mbedtls_ecjpake_context
*ctx
,
100 mbedtls_ecjpake_role role
,
101 mbedtls_md_type_t hash
,
102 mbedtls_ecp_group_id curve
,
103 const unsigned char *secret
,
105 int ret
= MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED
;
107 ECJPAKE_VALIDATE_RET(ctx
!= NULL
);
108 ECJPAKE_VALIDATE_RET(role
== MBEDTLS_ECJPAKE_CLIENT
||
109 role
== MBEDTLS_ECJPAKE_SERVER
);
110 ECJPAKE_VALIDATE_RET(secret
!= NULL
|| len
== 0);
114 if ((ctx
->md_info
= mbedtls_md_info_from_type(hash
)) == NULL
)
115 return (MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE
);
117 MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&ctx
->grp
, curve
));
119 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx
->s
, secret
, len
));
123 mbedtls_ecjpake_free(ctx
);
129 * Check if context is ready for use
131 int mbedtls_ecjpake_check(const mbedtls_ecjpake_context
*ctx
) {
132 ECJPAKE_VALIDATE_RET(ctx
!= NULL
);
134 if (ctx
->md_info
== NULL
||
135 ctx
->grp
.id
== MBEDTLS_ECP_DP_NONE
||
137 return (MBEDTLS_ERR_ECP_BAD_INPUT_DATA
);
144 * Write a point plus its length to a buffer
146 static int ecjpake_write_len_point(unsigned char **p
,
147 const unsigned char *end
,
148 const mbedtls_ecp_group
*grp
,
150 const mbedtls_ecp_point
*P
) {
151 int ret
= MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED
;
154 /* Need at least 4 for length plus 1 for point */
155 if (end
< *p
|| end
- *p
< 5)
156 return (MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL
);
158 ret
= mbedtls_ecp_point_write_binary(grp
, P
, pf
,
159 &len
, *p
+ 4, end
- (*p
+ 4));
163 (*p
)[0] = (unsigned char)((len
>> 24) & 0xFF);
164 (*p
)[1] = (unsigned char)((len
>> 16) & 0xFF);
165 (*p
)[2] = (unsigned char)((len
>> 8) & 0xFF);
166 (*p
)[3] = (unsigned char)((len
) & 0xFF);
174 * Size of the temporary buffer for ecjpake_hash:
175 * 3 EC points plus their length, plus ID and its length (4 + 6 bytes)
177 #define ECJPAKE_HASH_BUF_LEN ( 3 * ( 4 + MBEDTLS_ECP_MAX_PT_LEN ) + 4 + 6 )
180 * Compute hash for ZKP (7.4.2.2.2.1)
182 static int ecjpake_hash(const mbedtls_md_info_t
*md_info
,
183 const mbedtls_ecp_group
*grp
,
185 const mbedtls_ecp_point
*G
,
186 const mbedtls_ecp_point
*V
,
187 const mbedtls_ecp_point
*X
,
190 int ret
= MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED
;
191 unsigned char buf
[ECJPAKE_HASH_BUF_LEN
];
192 unsigned char *p
= buf
;
193 const unsigned char *end
= buf
+ sizeof(buf
);
194 const size_t id_len
= strlen(id
);
195 unsigned char hash
[MBEDTLS_MD_MAX_SIZE
];
197 /* Write things to temporary buffer */
198 MBEDTLS_MPI_CHK(ecjpake_write_len_point(&p
, end
, grp
, pf
, G
));
199 MBEDTLS_MPI_CHK(ecjpake_write_len_point(&p
, end
, grp
, pf
, V
));
200 MBEDTLS_MPI_CHK(ecjpake_write_len_point(&p
, end
, grp
, pf
, X
));
203 return (MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL
);
205 *p
++ = (unsigned char)((id_len
>> 24) & 0xFF);
206 *p
++ = (unsigned char)((id_len
>> 16) & 0xFF);
207 *p
++ = (unsigned char)((id_len
>> 8) & 0xFF);
208 *p
++ = (unsigned char)((id_len
) & 0xFF);
210 if (end
< p
|| (size_t)(end
- p
) < id_len
)
211 return (MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL
);
213 memcpy(p
, id
, id_len
);
217 MBEDTLS_MPI_CHK(mbedtls_md(md_info
, buf
, p
- buf
, hash
));
219 /* Turn it into an integer mod n */
220 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(h
, hash
,
221 mbedtls_md_get_size(md_info
)));
222 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(h
, h
, &grp
->N
));
229 * Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3)
231 static int ecjpake_zkp_read(const mbedtls_md_info_t
*md_info
,
232 const mbedtls_ecp_group
*grp
,
234 const mbedtls_ecp_point
*G
,
235 const mbedtls_ecp_point
*X
,
237 const unsigned char **p
,
238 const unsigned char *end
) {
239 int ret
= MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED
;
240 mbedtls_ecp_point V
, VV
;
244 mbedtls_ecp_point_init(&V
);
245 mbedtls_ecp_point_init(&VV
);
246 mbedtls_mpi_init(&r
);
247 mbedtls_mpi_init(&h
);
252 * opaque r<1..2^8-1>;
256 return (MBEDTLS_ERR_ECP_BAD_INPUT_DATA
);
258 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_point(grp
, &V
, p
, end
- *p
));
260 if (end
< *p
|| (size_t)(end
- *p
) < 1) {
261 ret
= MBEDTLS_ERR_ECP_BAD_INPUT_DATA
;
267 if (end
< *p
|| (size_t)(end
- *p
) < r_len
) {
268 ret
= MBEDTLS_ERR_ECP_BAD_INPUT_DATA
;
272 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&r
, *p
, r_len
));
278 MBEDTLS_MPI_CHK(ecjpake_hash(md_info
, grp
, pf
, G
, &V
, X
, id
, &h
));
279 MBEDTLS_MPI_CHK(mbedtls_ecp_muladd((mbedtls_ecp_group
*) grp
,
282 if (mbedtls_ecp_point_cmp(&VV
, &V
) != 0) {
283 ret
= MBEDTLS_ERR_ECP_VERIFY_FAILED
;
288 mbedtls_ecp_point_free(&V
);
289 mbedtls_ecp_point_free(&VV
);
290 mbedtls_mpi_free(&r
);
291 mbedtls_mpi_free(&h
);
297 * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2)
299 static int ecjpake_zkp_write(const mbedtls_md_info_t
*md_info
,
300 const mbedtls_ecp_group
*grp
,
302 const mbedtls_ecp_point
*G
,
303 const mbedtls_mpi
*x
,
304 const mbedtls_ecp_point
*X
,
307 const unsigned char *end
,
308 int (*f_rng
)(void *, unsigned char *, size_t),
310 int ret
= MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED
;
313 mbedtls_mpi h
; /* later recycled to hold r */
317 return (MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL
);
319 mbedtls_ecp_point_init(&V
);
320 mbedtls_mpi_init(&v
);
321 mbedtls_mpi_init(&h
);
323 /* Compute signature */
324 MBEDTLS_MPI_CHK(mbedtls_ecp_gen_keypair_base((mbedtls_ecp_group
*) grp
,
325 G
, &v
, &V
, f_rng
, p_rng
));
326 MBEDTLS_MPI_CHK(ecjpake_hash(md_info
, grp
, pf
, G
, &V
, X
, id
, &h
));
327 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&h
, &h
, x
)); /* x*h */
328 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&h
, &v
, &h
)); /* v - x*h */
329 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&h
, &h
, &grp
->N
)); /* r */
332 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(grp
, &V
,
333 pf
, &len
, *p
, end
- *p
));
336 len
= mbedtls_mpi_size(&h
); /* actually r */
337 if (end
< *p
|| (size_t)(end
- *p
) < 1 + len
|| len
> 255) {
338 ret
= MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL
;
342 *(*p
)++ = (unsigned char)(len
& 0xFF);
343 MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&h
, *p
, len
)); /* r */
347 mbedtls_ecp_point_free(&V
);
348 mbedtls_mpi_free(&v
);
349 mbedtls_mpi_free(&h
);
355 * Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof
356 * Output: verified public key X
358 static int ecjpake_kkp_read(const mbedtls_md_info_t
*md_info
,
359 const mbedtls_ecp_group
*grp
,
361 const mbedtls_ecp_point
*G
,
362 mbedtls_ecp_point
*X
,
364 const unsigned char **p
,
365 const unsigned char *end
) {
366 int ret
= MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED
;
369 return (MBEDTLS_ERR_ECP_BAD_INPUT_DATA
);
377 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_point(grp
, X
, p
, end
- *p
));
378 if (mbedtls_ecp_is_zero(X
)) {
379 ret
= MBEDTLS_ERR_ECP_INVALID_KEY
;
383 MBEDTLS_MPI_CHK(ecjpake_zkp_read(md_info
, grp
, pf
, G
, X
, id
, p
, end
));
390 * Generate an ECJPAKEKeyKP
391 * Output: the serialized structure, plus private/public key pair
393 static int ecjpake_kkp_write(const mbedtls_md_info_t
*md_info
,
394 const mbedtls_ecp_group
*grp
,
396 const mbedtls_ecp_point
*G
,
398 mbedtls_ecp_point
*X
,
401 const unsigned char *end
,
402 int (*f_rng
)(void *, unsigned char *, size_t),
404 int ret
= MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED
;
408 return (MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL
);
410 /* Generate key (7.4.2.3.1) and write it out */
411 MBEDTLS_MPI_CHK(mbedtls_ecp_gen_keypair_base((mbedtls_ecp_group
*) grp
, G
, x
, X
,
413 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(grp
, X
,
414 pf
, &len
, *p
, end
- *p
));
417 /* Generate and write proof */
418 MBEDTLS_MPI_CHK(ecjpake_zkp_write(md_info
, grp
, pf
, G
, x
, X
, id
,
419 p
, end
, f_rng
, p_rng
));
426 * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs
427 * Ouputs: verified peer public keys Xa, Xb
429 static int ecjpake_kkpp_read(const mbedtls_md_info_t
*md_info
,
430 const mbedtls_ecp_group
*grp
,
432 const mbedtls_ecp_point
*G
,
433 mbedtls_ecp_point
*Xa
,
434 mbedtls_ecp_point
*Xb
,
436 const unsigned char *buf
,
438 int ret
= MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED
;
439 const unsigned char *p
= buf
;
440 const unsigned char *end
= buf
+ len
;
444 * ECJPAKEKeyKP ecjpake_key_kp_pair_list[2];
445 * } ECJPAKEKeyKPPairList;
447 MBEDTLS_MPI_CHK(ecjpake_kkp_read(md_info
, grp
, pf
, G
, Xa
, id
, &p
, end
));
448 MBEDTLS_MPI_CHK(ecjpake_kkp_read(md_info
, grp
, pf
, G
, Xb
, id
, &p
, end
));
451 ret
= MBEDTLS_ERR_ECP_BAD_INPUT_DATA
;
458 * Generate a ECJPAKEKeyKPPairList
459 * Outputs: the serialized structure, plus two private/public key pairs
461 static int ecjpake_kkpp_write(const mbedtls_md_info_t
*md_info
,
462 const mbedtls_ecp_group
*grp
,
464 const mbedtls_ecp_point
*G
,
466 mbedtls_ecp_point
*Xa
,
468 mbedtls_ecp_point
*Xb
,
473 int (*f_rng
)(void *, unsigned char *, size_t),
475 int ret
= MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED
;
476 unsigned char *p
= buf
;
477 const unsigned char *end
= buf
+ len
;
479 MBEDTLS_MPI_CHK(ecjpake_kkp_write(md_info
, grp
, pf
, G
, xm1
, Xa
, id
,
480 &p
, end
, f_rng
, p_rng
));
481 MBEDTLS_MPI_CHK(ecjpake_kkp_write(md_info
, grp
, pf
, G
, xm2
, Xb
, id
,
482 &p
, end
, f_rng
, p_rng
));
491 * Read and process the first round message
493 int mbedtls_ecjpake_read_round_one(mbedtls_ecjpake_context
*ctx
,
494 const unsigned char *buf
,
496 ECJPAKE_VALIDATE_RET(ctx
!= NULL
);
497 ECJPAKE_VALIDATE_RET(buf
!= NULL
);
499 return (ecjpake_kkpp_read(ctx
->md_info
, &ctx
->grp
, ctx
->point_format
,
501 &ctx
->Xp1
, &ctx
->Xp2
, ID_PEER
,
506 * Generate and write the first round message
508 int mbedtls_ecjpake_write_round_one(mbedtls_ecjpake_context
*ctx
,
509 unsigned char *buf
, size_t len
, size_t *olen
,
510 int (*f_rng
)(void *, unsigned char *, size_t),
512 ECJPAKE_VALIDATE_RET(ctx
!= NULL
);
513 ECJPAKE_VALIDATE_RET(buf
!= NULL
);
514 ECJPAKE_VALIDATE_RET(olen
!= NULL
);
515 ECJPAKE_VALIDATE_RET(f_rng
!= NULL
);
517 return (ecjpake_kkpp_write(ctx
->md_info
, &ctx
->grp
, ctx
->point_format
,
519 &ctx
->xm1
, &ctx
->Xm1
, &ctx
->xm2
, &ctx
->Xm2
,
520 ID_MINE
, buf
, len
, olen
, f_rng
, p_rng
));
524 * Compute the sum of three points R = A + B + C
526 static int ecjpake_ecp_add3(mbedtls_ecp_group
*grp
, mbedtls_ecp_point
*R
,
527 const mbedtls_ecp_point
*A
,
528 const mbedtls_ecp_point
*B
,
529 const mbedtls_ecp_point
*C
) {
530 int ret
= MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED
;
533 mbedtls_mpi_init(&one
);
535 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&one
, 1));
536 MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(grp
, R
, &one
, A
, &one
, B
));
537 MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(grp
, R
, &one
, R
, &one
, C
));
540 mbedtls_mpi_free(&one
);
546 * Read and process second round message (C: 7.4.2.5, S: 7.4.2.6)
548 int mbedtls_ecjpake_read_round_two(mbedtls_ecjpake_context
*ctx
,
549 const unsigned char *buf
,
551 int ret
= MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED
;
552 const unsigned char *p
= buf
;
553 const unsigned char *end
= buf
+ len
;
554 mbedtls_ecp_group grp
;
555 mbedtls_ecp_point G
; /* C: GB, S: GA */
557 ECJPAKE_VALIDATE_RET(ctx
!= NULL
);
558 ECJPAKE_VALIDATE_RET(buf
!= NULL
);
560 mbedtls_ecp_group_init(&grp
);
561 mbedtls_ecp_point_init(&G
);
564 * Server: GA = X3 + X4 + X1 (7.4.2.6.1)
565 * Client: GB = X1 + X2 + X3 (7.4.2.5.1)
566 * Unified: G = Xm1 + Xm2 + Xp1
567 * We need that before parsing in order to check Xp as we read it
569 MBEDTLS_MPI_CHK(ecjpake_ecp_add3(&ctx
->grp
, &G
,
570 &ctx
->Xm1
, &ctx
->Xm2
, &ctx
->Xp1
));
574 * ECParameters curve_params; // only client reading server msg
575 * ECJPAKEKeyKP ecjpake_key_kp;
576 * } Client/ServerECJPAKEParams;
578 if (ctx
->role
== MBEDTLS_ECJPAKE_CLIENT
) {
579 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_group(&grp
, &p
, len
));
580 if (grp
.id
!= ctx
->grp
.id
) {
581 ret
= MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE
;
586 MBEDTLS_MPI_CHK(ecjpake_kkp_read(ctx
->md_info
, &ctx
->grp
,
588 &G
, &ctx
->Xp
, ID_PEER
, &p
, end
));
591 ret
= MBEDTLS_ERR_ECP_BAD_INPUT_DATA
;
596 mbedtls_ecp_group_free(&grp
);
597 mbedtls_ecp_point_free(&G
);
603 * Compute R = +/- X * S mod N, taking care not to leak S
605 static int ecjpake_mul_secret(mbedtls_mpi
*R
, int sign
,
606 const mbedtls_mpi
*X
,
607 const mbedtls_mpi
*S
,
608 const mbedtls_mpi
*N
,
609 int (*f_rng
)(void *, unsigned char *, size_t),
611 int ret
= MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED
;
612 mbedtls_mpi b
; /* Blinding value, then s + N * blinding */
614 mbedtls_mpi_init(&b
);
616 /* b = s + rnd-128-bit * N */
617 MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&b
, 16, f_rng
, p_rng
));
618 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&b
, &b
, N
));
619 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&b
, &b
, S
));
621 /* R = sign * X * b mod N */
622 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(R
, X
, &b
));
624 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(R
, R
, N
));
627 mbedtls_mpi_free(&b
);
633 * Generate and write the second round message (S: 7.4.2.5, C: 7.4.2.6)
635 int mbedtls_ecjpake_write_round_two(mbedtls_ecjpake_context
*ctx
,
636 unsigned char *buf
, size_t len
, size_t *olen
,
637 int (*f_rng
)(void *, unsigned char *, size_t),
639 int ret
= MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED
;
640 mbedtls_ecp_point G
; /* C: GA, S: GB */
641 mbedtls_ecp_point Xm
; /* C: Xc, S: Xs */
642 mbedtls_mpi xm
; /* C: xc, S: xs */
643 unsigned char *p
= buf
;
644 const unsigned char *end
= buf
+ len
;
647 ECJPAKE_VALIDATE_RET(ctx
!= NULL
);
648 ECJPAKE_VALIDATE_RET(buf
!= NULL
);
649 ECJPAKE_VALIDATE_RET(olen
!= NULL
);
650 ECJPAKE_VALIDATE_RET(f_rng
!= NULL
);
652 mbedtls_ecp_point_init(&G
);
653 mbedtls_ecp_point_init(&Xm
);
654 mbedtls_mpi_init(&xm
);
657 * First generate private/public key pair (S: 7.4.2.5.1, C: 7.4.2.6.1)
659 * Client: GA = X1 + X3 + X4 | xs = x2 * s | Xc = xc * GA
660 * Server: GB = X3 + X1 + X2 | xs = x4 * s | Xs = xs * GB
661 * Unified: G = Xm1 + Xp1 + Xp2 | xm = xm2 * s | Xm = xm * G
663 MBEDTLS_MPI_CHK(ecjpake_ecp_add3(&ctx
->grp
, &G
,
664 &ctx
->Xp1
, &ctx
->Xp2
, &ctx
->Xm1
));
665 MBEDTLS_MPI_CHK(ecjpake_mul_secret(&xm
, 1, &ctx
->xm2
, &ctx
->s
,
666 &ctx
->grp
.N
, f_rng
, p_rng
));
667 MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx
->grp
, &Xm
, &xm
, &G
, f_rng
, p_rng
));
670 * Now write things out
673 * ECParameters curve_params; // only server writing its message
674 * ECJPAKEKeyKP ecjpake_key_kp;
675 * } Client/ServerECJPAKEParams;
677 if (ctx
->role
== MBEDTLS_ECJPAKE_SERVER
) {
679 ret
= MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL
;
682 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_group(&ctx
->grp
, &ec_len
,
688 ret
= MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL
;
691 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(&ctx
->grp
, &Xm
,
692 ctx
->point_format
, &ec_len
, p
, end
- p
));
695 MBEDTLS_MPI_CHK(ecjpake_zkp_write(ctx
->md_info
, &ctx
->grp
,
697 &G
, &xm
, &Xm
, ID_MINE
,
698 &p
, end
, f_rng
, p_rng
));
703 mbedtls_ecp_point_free(&G
);
704 mbedtls_ecp_point_free(&Xm
);
705 mbedtls_mpi_free(&xm
);
711 * Derive PMS (7.4.2.7 / 7.4.2.8)
713 int mbedtls_ecjpake_derive_secret(mbedtls_ecjpake_context
*ctx
,
714 unsigned char *buf
, size_t len
, size_t *olen
,
715 int (*f_rng
)(void *, unsigned char *, size_t),
717 int ret
= MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED
;
719 mbedtls_mpi m_xm2_s
, one
;
720 unsigned char kx
[MBEDTLS_ECP_MAX_BYTES
];
723 ECJPAKE_VALIDATE_RET(ctx
!= NULL
);
724 ECJPAKE_VALIDATE_RET(buf
!= NULL
);
725 ECJPAKE_VALIDATE_RET(olen
!= NULL
);
726 ECJPAKE_VALIDATE_RET(f_rng
!= NULL
);
728 *olen
= mbedtls_md_get_size(ctx
->md_info
);
730 return (MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL
);
732 mbedtls_ecp_point_init(&K
);
733 mbedtls_mpi_init(&m_xm2_s
);
734 mbedtls_mpi_init(&one
);
736 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&one
, 1));
739 * Client: K = ( Xs - X4 * x2 * s ) * x2
740 * Server: K = ( Xc - X2 * x4 * s ) * x4
741 * Unified: K = ( Xp - Xp2 * xm2 * s ) * xm2
743 MBEDTLS_MPI_CHK(ecjpake_mul_secret(&m_xm2_s
, -1, &ctx
->xm2
, &ctx
->s
,
744 &ctx
->grp
.N
, f_rng
, p_rng
));
745 MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(&ctx
->grp
, &K
,
747 &m_xm2_s
, &ctx
->Xp2
));
748 MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx
->grp
, &K
, &ctx
->xm2
, &K
,
751 /* PMS = SHA-256( K.X ) */
752 x_bytes
= (ctx
->grp
.pbits
+ 7) / 8;
753 MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&K
.X
, kx
, x_bytes
));
754 MBEDTLS_MPI_CHK(mbedtls_md(ctx
->md_info
, kx
, x_bytes
, buf
));
757 mbedtls_ecp_point_free(&K
);
758 mbedtls_mpi_free(&m_xm2_s
);
759 mbedtls_mpi_free(&one
);
767 #endif /* ! MBEDTLS_ECJPAKE_ALT */
769 #if defined(MBEDTLS_SELF_TEST)
771 #if defined(MBEDTLS_PLATFORM_C)
772 #include "mbedtls/platform.h"
775 #define mbedtls_printf printf
778 #if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
779 !defined(MBEDTLS_SHA256_C)
780 int mbedtls_ecjpake_self_test(int verbose
) {
786 static const unsigned char ecjpake_test_password
[] = {
787 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x6a, 0x70, 0x61, 0x6b, 0x65, 0x74,
791 #if !defined(MBEDTLS_ECJPAKE_ALT)
793 static const unsigned char ecjpake_test_x1
[] = {
794 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
795 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
796 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21
799 static const unsigned char ecjpake_test_x2
[] = {
800 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
801 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
802 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
805 static const unsigned char ecjpake_test_x3
[] = {
806 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
807 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
808 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
811 static const unsigned char ecjpake_test_x4
[] = {
812 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc,
813 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
814 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1
817 static const unsigned char ecjpake_test_cli_one
[] = {
818 0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19,
819 0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44,
820 0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad,
821 0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62,
822 0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9,
823 0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d,
824 0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e,
825 0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e,
826 0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73,
827 0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22,
828 0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce,
829 0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00,
830 0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b,
831 0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e,
832 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62,
833 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5,
834 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb,
835 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35,
836 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0,
837 0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb,
838 0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47,
839 0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39,
840 0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97,
841 0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40,
842 0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d,
843 0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa,
844 0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d,
845 0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0
848 static const unsigned char ecjpake_test_srv_one
[] = {
849 0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb,
850 0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18,
851 0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47,
852 0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f,
853 0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7,
854 0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d,
855 0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64,
856 0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36,
857 0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2,
858 0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec,
859 0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16,
860 0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96,
861 0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3,
862 0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19,
863 0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f,
864 0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8,
865 0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7,
866 0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea,
867 0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5,
868 0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6,
869 0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31,
870 0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d,
871 0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8,
872 0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee,
873 0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84,
874 0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f,
875 0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80,
876 0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12
879 static const unsigned char ecjpake_test_srv_two
[] = {
880 0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23,
881 0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c,
882 0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f,
883 0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca,
884 0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26,
885 0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55,
886 0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38,
887 0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6,
888 0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9,
889 0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4,
890 0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2,
891 0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8,
892 0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd,
893 0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c
896 static const unsigned char ecjpake_test_cli_two
[] = {
897 0x41, 0x04, 0x69, 0xd5, 0x4e, 0xe8, 0x5e, 0x90, 0xce, 0x3f, 0x12, 0x46,
898 0x74, 0x2d, 0xe5, 0x07, 0xe9, 0x39, 0xe8, 0x1d, 0x1d, 0xc1, 0xc5, 0xcb,
899 0x98, 0x8b, 0x58, 0xc3, 0x10, 0xc9, 0xfd, 0xd9, 0x52, 0x4d, 0x93, 0x72,
900 0x0b, 0x45, 0x54, 0x1c, 0x83, 0xee, 0x88, 0x41, 0x19, 0x1d, 0xa7, 0xce,
901 0xd8, 0x6e, 0x33, 0x12, 0xd4, 0x36, 0x23, 0xc1, 0xd6, 0x3e, 0x74, 0x98,
902 0x9a, 0xba, 0x4a, 0xff, 0xd1, 0xee, 0x41, 0x04, 0x07, 0x7e, 0x8c, 0x31,
903 0xe2, 0x0e, 0x6b, 0xed, 0xb7, 0x60, 0xc1, 0x35, 0x93, 0xe6, 0x9f, 0x15,
904 0xbe, 0x85, 0xc2, 0x7d, 0x68, 0xcd, 0x09, 0xcc, 0xb8, 0xc4, 0x18, 0x36,
905 0x08, 0x91, 0x7c, 0x5c, 0x3d, 0x40, 0x9f, 0xac, 0x39, 0xfe, 0xfe, 0xe8,
906 0x2f, 0x72, 0x92, 0xd3, 0x6f, 0x0d, 0x23, 0xe0, 0x55, 0x91, 0x3f, 0x45,
907 0xa5, 0x2b, 0x85, 0xdd, 0x8a, 0x20, 0x52, 0xe9, 0xe1, 0x29, 0xbb, 0x4d,
908 0x20, 0x0f, 0x01, 0x1f, 0x19, 0x48, 0x35, 0x35, 0xa6, 0xe8, 0x9a, 0x58,
909 0x0c, 0x9b, 0x00, 0x03, 0xba, 0xf2, 0x14, 0x62, 0xec, 0xe9, 0x1a, 0x82,
910 0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c
913 static const unsigned char ecjpake_test_pms
[] = {
914 0xf3, 0xd4, 0x7f, 0x59, 0x98, 0x44, 0xdb, 0x92, 0xa5, 0x69, 0xbb, 0xe7,
915 0x98, 0x1e, 0x39, 0xd9, 0x31, 0xfd, 0x74, 0x3b, 0xf2, 0x2e, 0x98, 0xf9,
916 0xb4, 0x38, 0xf7, 0x19, 0xd3, 0xc4, 0xf3, 0x51
919 /* Load my private keys and generate the corresponding public keys */
920 static int ecjpake_test_load(mbedtls_ecjpake_context
*ctx
,
921 const unsigned char *xm1
, size_t len1
,
922 const unsigned char *xm2
, size_t len2
) {
923 int ret
= MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED
;
925 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx
->xm1
, xm1
, len1
));
926 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx
->xm2
, xm2
, len2
));
927 MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx
->grp
, &ctx
->Xm1
, &ctx
->xm1
,
928 &ctx
->grp
.G
, NULL
, NULL
));
929 MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx
->grp
, &ctx
->Xm2
, &ctx
->xm2
,
930 &ctx
->grp
.G
, NULL
, NULL
));
936 #endif /* ! MBEDTLS_ECJPAKE_ALT */
938 /* For tests we don't need a secure RNG;
939 * use the LGC from Numerical Recipes for simplicity */
940 static int ecjpake_lgc(void *p
, unsigned char *out
, size_t len
) {
941 static uint32_t x
= 42;
945 size_t use_len
= len
> 4 ? 4 : len
;
946 x
= 1664525 * x
+ 1013904223;
947 memcpy(out
, &x
, use_len
);
955 #define TEST_ASSERT( x ) \
969 int mbedtls_ecjpake_self_test(int verbose
) {
970 int ret
= MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED
;
971 mbedtls_ecjpake_context cli
;
972 mbedtls_ecjpake_context srv
;
973 unsigned char buf
[512], pms
[32];
976 mbedtls_ecjpake_init(&cli
);
977 mbedtls_ecjpake_init(&srv
);
980 mbedtls_printf(" ECJPAKE test #0 (setup): ");
982 TEST_ASSERT(mbedtls_ecjpake_setup(&cli
, MBEDTLS_ECJPAKE_CLIENT
,
983 MBEDTLS_MD_SHA256
, MBEDTLS_ECP_DP_SECP256R1
,
984 ecjpake_test_password
,
985 sizeof(ecjpake_test_password
)) == 0);
987 TEST_ASSERT(mbedtls_ecjpake_setup(&srv
, MBEDTLS_ECJPAKE_SERVER
,
988 MBEDTLS_MD_SHA256
, MBEDTLS_ECP_DP_SECP256R1
,
989 ecjpake_test_password
,
990 sizeof(ecjpake_test_password
)) == 0);
993 mbedtls_printf("passed\n");
996 mbedtls_printf(" ECJPAKE test #1 (random handshake): ");
998 TEST_ASSERT(mbedtls_ecjpake_write_round_one(&cli
,
999 buf
, sizeof(buf
), &len
, ecjpake_lgc
, NULL
) == 0);
1001 TEST_ASSERT(mbedtls_ecjpake_read_round_one(&srv
, buf
, len
) == 0);
1003 TEST_ASSERT(mbedtls_ecjpake_write_round_one(&srv
,
1004 buf
, sizeof(buf
), &len
, ecjpake_lgc
, NULL
) == 0);
1006 TEST_ASSERT(mbedtls_ecjpake_read_round_one(&cli
, buf
, len
) == 0);
1008 TEST_ASSERT(mbedtls_ecjpake_write_round_two(&srv
,
1009 buf
, sizeof(buf
), &len
, ecjpake_lgc
, NULL
) == 0);
1011 TEST_ASSERT(mbedtls_ecjpake_read_round_two(&cli
, buf
, len
) == 0);
1013 TEST_ASSERT(mbedtls_ecjpake_derive_secret(&cli
,
1014 pms
, sizeof(pms
), &pmslen
, ecjpake_lgc
, NULL
) == 0);
1016 TEST_ASSERT(mbedtls_ecjpake_write_round_two(&cli
,
1017 buf
, sizeof(buf
), &len
, ecjpake_lgc
, NULL
) == 0);
1019 TEST_ASSERT(mbedtls_ecjpake_read_round_two(&srv
, buf
, len
) == 0);
1021 TEST_ASSERT(mbedtls_ecjpake_derive_secret(&srv
,
1022 buf
, sizeof(buf
), &len
, ecjpake_lgc
, NULL
) == 0);
1024 TEST_ASSERT(len
== pmslen
);
1025 TEST_ASSERT(memcmp(buf
, pms
, len
) == 0);
1028 mbedtls_printf("passed\n");
1030 #if !defined(MBEDTLS_ECJPAKE_ALT)
1031 /* 'reference handshake' tests can only be run against implementations
1032 * for which we have 100% control over how the random ephemeral keys
1033 * are generated. This is only the case for the internal mbed TLS
1034 * implementation, so these tests are skipped in case the internal
1035 * implementation is swapped out for an alternative one. */
1037 mbedtls_printf(" ECJPAKE test #2 (reference handshake): ");
1039 /* Simulate generation of round one */
1040 MBEDTLS_MPI_CHK(ecjpake_test_load(&cli
,
1041 ecjpake_test_x1
, sizeof(ecjpake_test_x1
),
1042 ecjpake_test_x2
, sizeof(ecjpake_test_x2
)));
1044 MBEDTLS_MPI_CHK(ecjpake_test_load(&srv
,
1045 ecjpake_test_x3
, sizeof(ecjpake_test_x3
),
1046 ecjpake_test_x4
, sizeof(ecjpake_test_x4
)));
1048 /* Read round one */
1049 TEST_ASSERT(mbedtls_ecjpake_read_round_one(&srv
,
1050 ecjpake_test_cli_one
,
1051 sizeof(ecjpake_test_cli_one
)) == 0);
1053 TEST_ASSERT(mbedtls_ecjpake_read_round_one(&cli
,
1054 ecjpake_test_srv_one
,
1055 sizeof(ecjpake_test_srv_one
)) == 0);
1057 /* Skip generation of round two, read round two */
1058 TEST_ASSERT(mbedtls_ecjpake_read_round_two(&cli
,
1059 ecjpake_test_srv_two
,
1060 sizeof(ecjpake_test_srv_two
)) == 0);
1062 TEST_ASSERT(mbedtls_ecjpake_read_round_two(&srv
,
1063 ecjpake_test_cli_two
,
1064 sizeof(ecjpake_test_cli_two
)) == 0);
1066 /* Server derives PMS */
1067 TEST_ASSERT(mbedtls_ecjpake_derive_secret(&srv
,
1068 buf
, sizeof(buf
), &len
, ecjpake_lgc
, NULL
) == 0);
1070 TEST_ASSERT(len
== sizeof(ecjpake_test_pms
));
1071 TEST_ASSERT(memcmp(buf
, ecjpake_test_pms
, len
) == 0);
1073 memset(buf
, 0, len
); /* Avoid interferences with next step */
1075 /* Client derives PMS */
1076 TEST_ASSERT(mbedtls_ecjpake_derive_secret(&cli
,
1077 buf
, sizeof(buf
), &len
, ecjpake_lgc
, NULL
) == 0);
1079 TEST_ASSERT(len
== sizeof(ecjpake_test_pms
));
1080 TEST_ASSERT(memcmp(buf
, ecjpake_test_pms
, len
) == 0);
1083 mbedtls_printf("passed\n");
1084 #endif /* ! MBEDTLS_ECJPAKE_ALT */
1087 mbedtls_ecjpake_free(&cli
);
1088 mbedtls_ecjpake_free(&srv
);
1092 mbedtls_printf("failed\n");
1098 mbedtls_printf("\n");
1105 #endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_SHA256_C */
1107 #endif /* MBEDTLS_SELF_TEST */
1109 #endif /* MBEDTLS_ECJPAKE_C */