blob: 36c1327bd52b6e2d0b6e30932df952f98773d128 [file] [log] [blame]
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001/*
2 * Elliptic curve J-PAKE
3 *
Bence Szépkúti1e148272020-08-07 13:07:28 +02004 * Copyright The Mbed TLS Contributors
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
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
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
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.
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +020018 */
19
20/*
Manuel Pégourié-Gonnard6b798b92015-08-14 11:18:30 +020021 * References in the code are to the Thread v1.0 Specification,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +020022 * available to members of the Thread Group http://threadgroup.org/
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +020023 */
24
Gilles Peskinedb09ef62020-06-03 01:43:33 +020025#include "common.h"
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +020026
27#if defined(MBEDTLS_ECJPAKE_C)
28
29#include "mbedtls/ecjpake.h"
Hanno Becker71c8e1b2018-12-14 17:09:39 +000030#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000031#include "mbedtls/error.h"
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +020032
Neil Armstrongecaba1c2022-08-11 10:47:08 +020033/* We use MD first if it's available (for compatibility reasons)
34 * and "fall back" to PSA otherwise (which needs psa_crypto_init()). */
35#if !defined(MBEDTLS_MD_C)
36#include "psa/crypto.h"
37#include "mbedtls/psa_util.h"
Andrzej Kurek8a045ce2022-12-23 11:00:06 -050038#if !defined(MBEDTLS_ECJPAKE_ALT)
39#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status, \
40 psa_to_md_errors, \
41 psa_generic_status_to_mbedtls)
42#endif /* !MBEDTLS_ECJPAKE_ALT */
Neil Armstrongecaba1c2022-08-11 10:47:08 +020043#endif /* !MBEDTLS_MD_C */
44
Neil Armstrong0d763412022-08-11 10:32:22 +020045#include "hash_info.h"
46
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +020047#include <string.h>
48
Hanno Becker616d1ca2018-01-24 10:25:05 +000049#if !defined(MBEDTLS_ECJPAKE_ALT)
50
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +020051/*
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +020052 * Convert a mbedtls_ecjpake_role to identifier string
53 */
54static const char * const ecjpake_id[] = {
55 "client",
56 "server"
57};
58
Gilles Peskine449bd832023-01-11 14:50:10 +010059#define ID_MINE (ecjpake_id[ctx->role])
60#define ID_PEER (ecjpake_id[1 - ctx->role])
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +020061
Neil Armstrongecaba1c2022-08-11 10:47:08 +020062/**
Gilles Peskine449bd832023-01-11 14:50:10 +010063 * Helper to Compute a hash from md_type
64 */
65static int mbedtls_ecjpake_compute_hash(mbedtls_md_type_t md_type,
66 const unsigned char *input, size_t ilen,
67 unsigned char *output)
Neil Armstrongecaba1c2022-08-11 10:47:08 +020068{
69#if defined(MBEDTLS_MD_C)
Gilles Peskine449bd832023-01-11 14:50:10 +010070 return mbedtls_md(mbedtls_md_info_from_type(md_type),
71 input, ilen, output);
Neil Armstrongecaba1c2022-08-11 10:47:08 +020072#else
Gilles Peskine449bd832023-01-11 14:50:10 +010073 psa_algorithm_t alg = mbedtls_psa_translate_md(md_type);
Neil Armstrongecaba1c2022-08-11 10:47:08 +020074 psa_status_t status;
Gilles Peskine449bd832023-01-11 14:50:10 +010075 size_t out_size = PSA_HASH_LENGTH(alg);
Neil Armstrongecaba1c2022-08-11 10:47:08 +020076 size_t out_len;
77
Gilles Peskine449bd832023-01-11 14:50:10 +010078 status = psa_hash_compute(alg, input, ilen, output, out_size, &out_len);
Neil Armstrongecaba1c2022-08-11 10:47:08 +020079
Andrzej Kurek8a045ce2022-12-23 11:00:06 -050080 return PSA_TO_MBEDTLS_ERR(status);
Neil Armstrongecaba1c2022-08-11 10:47:08 +020081#endif /* !MBEDTLS_MD_C */
82}
83
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +020084/*
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020085 * Initialize context
86 */
Gilles Peskine449bd832023-01-11 14:50:10 +010087void mbedtls_ecjpake_init(mbedtls_ecjpake_context *ctx)
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020088{
Neil Armstrong0d763412022-08-11 10:32:22 +020089 ctx->md_type = MBEDTLS_MD_NONE;
Gilles Peskine449bd832023-01-11 14:50:10 +010090 mbedtls_ecp_group_init(&ctx->grp);
Manuel Pégourié-Gonnardb7da1942015-10-19 13:35:22 +020091 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020092
Gilles Peskine449bd832023-01-11 14:50:10 +010093 mbedtls_ecp_point_init(&ctx->Xm1);
94 mbedtls_ecp_point_init(&ctx->Xm2);
95 mbedtls_ecp_point_init(&ctx->Xp1);
96 mbedtls_ecp_point_init(&ctx->Xp2);
97 mbedtls_ecp_point_init(&ctx->Xp);
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020098
Gilles Peskine449bd832023-01-11 14:50:10 +010099 mbedtls_mpi_init(&ctx->xm1);
100 mbedtls_mpi_init(&ctx->xm2);
101 mbedtls_mpi_init(&ctx->s);
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200102}
103
104/*
105 * Free context
106 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100107void mbedtls_ecjpake_free(mbedtls_ecjpake_context *ctx)
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200108{
Gilles Peskine449bd832023-01-11 14:50:10 +0100109 if (ctx == NULL) {
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200110 return;
Gilles Peskine449bd832023-01-11 14:50:10 +0100111 }
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200112
Neil Armstrong0d763412022-08-11 10:32:22 +0200113 ctx->md_type = MBEDTLS_MD_NONE;
Gilles Peskine449bd832023-01-11 14:50:10 +0100114 mbedtls_ecp_group_free(&ctx->grp);
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200115
Gilles Peskine449bd832023-01-11 14:50:10 +0100116 mbedtls_ecp_point_free(&ctx->Xm1);
117 mbedtls_ecp_point_free(&ctx->Xm2);
118 mbedtls_ecp_point_free(&ctx->Xp1);
119 mbedtls_ecp_point_free(&ctx->Xp2);
120 mbedtls_ecp_point_free(&ctx->Xp);
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200121
Gilles Peskine449bd832023-01-11 14:50:10 +0100122 mbedtls_mpi_free(&ctx->xm1);
123 mbedtls_mpi_free(&ctx->xm2);
124 mbedtls_mpi_free(&ctx->s);
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200125}
126
127/*
128 * Setup context
129 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100130int mbedtls_ecjpake_setup(mbedtls_ecjpake_context *ctx,
131 mbedtls_ecjpake_role role,
132 mbedtls_md_type_t hash,
133 mbedtls_ecp_group_id curve,
134 const unsigned char *secret,
135 size_t len)
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200136{
Janos Follath24eed8d2019-11-22 13:21:35 +0000137 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker185e5162018-12-19 09:48:50 +0000138
Gilles Peskine449bd832023-01-11 14:50:10 +0100139 if (role != MBEDTLS_ECJPAKE_CLIENT && role != MBEDTLS_ECJPAKE_SERVER) {
140 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
141 }
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200142
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +0200143 ctx->role = role;
144
Neil Armstrongecaba1c2022-08-11 10:47:08 +0200145#if defined(MBEDTLS_MD_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100146 if ((mbedtls_md_info_from_type(hash)) == NULL) {
147 return MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE;
148 }
Neil Armstrongecaba1c2022-08-11 10:47:08 +0200149#else
Gilles Peskine449bd832023-01-11 14:50:10 +0100150 if (mbedtls_psa_translate_md(hash) == MBEDTLS_MD_NONE) {
151 return MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE;
152 }
Neil Armstrongecaba1c2022-08-11 10:47:08 +0200153#endif
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200154
Neil Armstrong0d763412022-08-11 10:32:22 +0200155 ctx->md_type = hash;
156
Gilles Peskine449bd832023-01-11 14:50:10 +0100157 MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&ctx->grp, curve));
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200158
Gilles Peskine449bd832023-01-11 14:50:10 +0100159 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->s, secret, len));
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200160
161cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100162 if (ret != 0) {
163 mbedtls_ecjpake_free(ctx);
164 }
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200165
Gilles Peskine449bd832023-01-11 14:50:10 +0100166 return ret;
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200167}
168
Gilles Peskine449bd832023-01-11 14:50:10 +0100169int mbedtls_ecjpake_set_point_format(mbedtls_ecjpake_context *ctx,
170 int point_format)
Gilles Peskinecd07e222021-05-27 23:17:34 +0200171{
Gilles Peskine449bd832023-01-11 14:50:10 +0100172 switch (point_format) {
Gilles Peskinecd07e222021-05-27 23:17:34 +0200173 case MBEDTLS_ECP_PF_UNCOMPRESSED:
174 case MBEDTLS_ECP_PF_COMPRESSED:
175 ctx->point_format = point_format;
Gilles Peskine449bd832023-01-11 14:50:10 +0100176 return 0;
Gilles Peskinecd07e222021-05-27 23:17:34 +0200177 default:
Gilles Peskine449bd832023-01-11 14:50:10 +0100178 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Gilles Peskinecd07e222021-05-27 23:17:34 +0200179 }
180}
181
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200182/*
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200183 * Check if context is ready for use
184 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100185int mbedtls_ecjpake_check(const mbedtls_ecjpake_context *ctx)
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200186{
Gilles Peskine449bd832023-01-11 14:50:10 +0100187 if (ctx->md_type == MBEDTLS_MD_NONE ||
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200188 ctx->grp.id == MBEDTLS_ECP_DP_NONE ||
Gilles Peskine449bd832023-01-11 14:50:10 +0100189 ctx->s.p == NULL) {
190 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200191 }
192
Gilles Peskine449bd832023-01-11 14:50:10 +0100193 return 0;
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200194}
195
196/*
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200197 * Write a point plus its length to a buffer
198 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100199static int ecjpake_write_len_point(unsigned char **p,
200 const unsigned char *end,
201 const mbedtls_ecp_group *grp,
202 const int pf,
203 const mbedtls_ecp_point *P)
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200204{
Janos Follath24eed8d2019-11-22 13:21:35 +0000205 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200206 size_t len;
207
208 /* Need at least 4 for length plus 1 for point */
Gilles Peskine449bd832023-01-11 14:50:10 +0100209 if (end < *p || end - *p < 5) {
210 return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
211 }
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200212
Gilles Peskine449bd832023-01-11 14:50:10 +0100213 ret = mbedtls_ecp_point_write_binary(grp, P, pf,
214 &len, *p + 4, end - (*p + 4));
215 if (ret != 0) {
216 return ret;
217 }
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200218
Gilles Peskine449bd832023-01-11 14:50:10 +0100219 MBEDTLS_PUT_UINT32_BE(len, *p, 0);
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200220
221 *p += 4 + len;
222
Gilles Peskine449bd832023-01-11 14:50:10 +0100223 return 0;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200224}
225
226/*
227 * Size of the temporary buffer for ecjpake_hash:
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200228 * 3 EC points plus their length, plus ID and its length (4 + 6 bytes)
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200229 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100230#define ECJPAKE_HASH_BUF_LEN (3 * (4 + MBEDTLS_ECP_MAX_PT_LEN) + 4 + 6)
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200231
232/*
233 * Compute hash for ZKP (7.4.2.2.2.1)
234 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100235static int ecjpake_hash(const mbedtls_md_type_t md_type,
236 const mbedtls_ecp_group *grp,
237 const int pf,
238 const mbedtls_ecp_point *G,
239 const mbedtls_ecp_point *V,
240 const mbedtls_ecp_point *X,
241 const char *id,
242 mbedtls_mpi *h)
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200243{
Janos Follath24eed8d2019-11-22 13:21:35 +0000244 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200245 unsigned char buf[ECJPAKE_HASH_BUF_LEN];
246 unsigned char *p = buf;
Gilles Peskine449bd832023-01-11 14:50:10 +0100247 const unsigned char *end = buf + sizeof(buf);
248 const size_t id_len = strlen(id);
Przemek Stekiel51669542022-09-13 12:57:05 +0200249 unsigned char hash[MBEDTLS_HASH_MAX_SIZE];
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200250
251 /* Write things to temporary buffer */
Gilles Peskine449bd832023-01-11 14:50:10 +0100252 MBEDTLS_MPI_CHK(ecjpake_write_len_point(&p, end, grp, pf, G));
253 MBEDTLS_MPI_CHK(ecjpake_write_len_point(&p, end, grp, pf, V));
254 MBEDTLS_MPI_CHK(ecjpake_write_len_point(&p, end, grp, pf, X));
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200255
Gilles Peskine449bd832023-01-11 14:50:10 +0100256 if (end - p < 4) {
257 return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
258 }
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200259
Gilles Peskine449bd832023-01-11 14:50:10 +0100260 MBEDTLS_PUT_UINT32_BE(id_len, p, 0);
Joe Subbiania5cb0d22021-08-23 11:35:25 +0100261 p += 4;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200262
Gilles Peskine449bd832023-01-11 14:50:10 +0100263 if (end < p || (size_t) (end - p) < id_len) {
264 return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
265 }
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200266
Gilles Peskine449bd832023-01-11 14:50:10 +0100267 memcpy(p, id, id_len);
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200268 p += id_len;
269
270 /* Compute hash */
Gilles Peskine449bd832023-01-11 14:50:10 +0100271 MBEDTLS_MPI_CHK(mbedtls_ecjpake_compute_hash(md_type,
272 buf, p - buf, hash));
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200273
274 /* Turn it into an integer mod n */
Gilles Peskine449bd832023-01-11 14:50:10 +0100275 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(h, hash,
276 mbedtls_hash_info_get_size(md_type)));
277 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(h, h, &grp->N));
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200278
279cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100280 return ret;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200281}
282
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200283/*
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200284 * Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3)
285 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100286static int ecjpake_zkp_read(const mbedtls_md_type_t md_type,
287 const mbedtls_ecp_group *grp,
288 const int pf,
289 const mbedtls_ecp_point *G,
290 const mbedtls_ecp_point *X,
291 const char *id,
292 const unsigned char **p,
293 const unsigned char *end)
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200294{
Janos Follath24eed8d2019-11-22 13:21:35 +0000295 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200296 mbedtls_ecp_point V, VV;
297 mbedtls_mpi r, h;
298 size_t r_len;
299
Gilles Peskine449bd832023-01-11 14:50:10 +0100300 mbedtls_ecp_point_init(&V);
301 mbedtls_ecp_point_init(&VV);
302 mbedtls_mpi_init(&r);
303 mbedtls_mpi_init(&h);
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200304
305 /*
306 * struct {
307 * ECPoint V;
308 * opaque r<1..2^8-1>;
309 * } ECSchnorrZKP;
310 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100311 if (end < *p) {
312 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
313 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200314
Gilles Peskine449bd832023-01-11 14:50:10 +0100315 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_point(grp, &V, p, end - *p));
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200316
Gilles Peskine449bd832023-01-11 14:50:10 +0100317 if (end < *p || (size_t) (end - *p) < 1) {
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200318 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
319 goto cleanup;
320 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200321
322 r_len = *(*p)++;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200323
Gilles Peskine449bd832023-01-11 14:50:10 +0100324 if (end < *p || (size_t) (end - *p) < r_len || r_len == 0) {
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200325 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
326 goto cleanup;
327 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200328
Gilles Peskine449bd832023-01-11 14:50:10 +0100329 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&r, *p, r_len));
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200330 *p += r_len;
331
332 /*
333 * Verification
334 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100335 MBEDTLS_MPI_CHK(ecjpake_hash(md_type, grp, pf, G, &V, X, id, &h));
336 MBEDTLS_MPI_CHK(mbedtls_ecp_muladd((mbedtls_ecp_group *) grp,
337 &VV, &h, X, &r, G));
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200338
Gilles Peskine449bd832023-01-11 14:50:10 +0100339 if (mbedtls_ecp_point_cmp(&VV, &V) != 0) {
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200340 ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
341 goto cleanup;
342 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200343
344cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100345 mbedtls_ecp_point_free(&V);
346 mbedtls_ecp_point_free(&VV);
347 mbedtls_mpi_free(&r);
348 mbedtls_mpi_free(&h);
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200349
Gilles Peskine449bd832023-01-11 14:50:10 +0100350 return ret;
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200351}
352
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200353/*
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200354 * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2)
355 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100356static int ecjpake_zkp_write(const mbedtls_md_type_t md_type,
357 const mbedtls_ecp_group *grp,
358 const int pf,
359 const mbedtls_ecp_point *G,
360 const mbedtls_mpi *x,
361 const mbedtls_ecp_point *X,
362 const char *id,
363 unsigned char **p,
364 const unsigned char *end,
365 int (*f_rng)(void *, unsigned char *, size_t),
366 void *p_rng)
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200367{
Janos Follath24eed8d2019-11-22 13:21:35 +0000368 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200369 mbedtls_ecp_point V;
370 mbedtls_mpi v;
371 mbedtls_mpi h; /* later recycled to hold r */
372 size_t len;
373
Gilles Peskine449bd832023-01-11 14:50:10 +0100374 if (end < *p) {
375 return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
376 }
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200377
Gilles Peskine449bd832023-01-11 14:50:10 +0100378 mbedtls_ecp_point_init(&V);
379 mbedtls_mpi_init(&v);
380 mbedtls_mpi_init(&h);
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200381
382 /* Compute signature */
Gilles Peskine449bd832023-01-11 14:50:10 +0100383 MBEDTLS_MPI_CHK(mbedtls_ecp_gen_keypair_base((mbedtls_ecp_group *) grp,
384 G, &v, &V, f_rng, p_rng));
385 MBEDTLS_MPI_CHK(ecjpake_hash(md_type, grp, pf, G, &V, X, id, &h));
386 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&h, &h, x)); /* x*h */
387 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&h, &v, &h)); /* v - x*h */
388 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&h, &h, &grp->N)); /* r */
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200389
390 /* Write it out */
Gilles Peskine449bd832023-01-11 14:50:10 +0100391 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(grp, &V,
392 pf, &len, *p, end - *p));
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200393 *p += len;
394
Gilles Peskine449bd832023-01-11 14:50:10 +0100395 len = mbedtls_mpi_size(&h); /* actually r */
396 if (end < *p || (size_t) (end - *p) < 1 + len || len > 255) {
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200397 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
398 goto cleanup;
399 }
400
Gilles Peskine449bd832023-01-11 14:50:10 +0100401 *(*p)++ = MBEDTLS_BYTE_0(len);
402 MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&h, *p, len)); /* r */
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200403 *p += len;
404
405cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100406 mbedtls_ecp_point_free(&V);
407 mbedtls_mpi_free(&v);
408 mbedtls_mpi_free(&h);
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200409
Gilles Peskine449bd832023-01-11 14:50:10 +0100410 return ret;
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200411}
412
413/*
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200414 * Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof
415 * Output: verified public key X
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200416 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100417static int ecjpake_kkp_read(const mbedtls_md_type_t md_type,
418 const mbedtls_ecp_group *grp,
419 const int pf,
420 const mbedtls_ecp_point *G,
421 mbedtls_ecp_point *X,
422 const char *id,
423 const unsigned char **p,
424 const unsigned char *end)
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200425{
Janos Follath24eed8d2019-11-22 13:21:35 +0000426 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200427
Gilles Peskine449bd832023-01-11 14:50:10 +0100428 if (end < *p) {
429 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
430 }
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200431
432 /*
433 * struct {
434 * ECPoint X;
435 * ECSchnorrZKP zkp;
436 * } ECJPAKEKeyKP;
437 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100438 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_point(grp, X, p, end - *p));
439 if (mbedtls_ecp_is_zero(X)) {
Manuel Pégourié-Gonnard30590952015-08-17 10:37:40 +0200440 ret = MBEDTLS_ERR_ECP_INVALID_KEY;
441 goto cleanup;
442 }
443
Gilles Peskine449bd832023-01-11 14:50:10 +0100444 MBEDTLS_MPI_CHK(ecjpake_zkp_read(md_type, grp, pf, G, X, id, p, end));
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200445
446cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100447 return ret;
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200448}
449
450/*
451 * Generate an ECJPAKEKeyKP
452 * Output: the serialized structure, plus private/public key pair
453 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100454static int ecjpake_kkp_write(const mbedtls_md_type_t md_type,
455 const mbedtls_ecp_group *grp,
456 const int pf,
457 const mbedtls_ecp_point *G,
458 mbedtls_mpi *x,
459 mbedtls_ecp_point *X,
460 const char *id,
461 unsigned char **p,
462 const unsigned char *end,
463 int (*f_rng)(void *, unsigned char *, size_t),
464 void *p_rng)
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200465{
Janos Follath24eed8d2019-11-22 13:21:35 +0000466 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200467 size_t len;
468
Gilles Peskine449bd832023-01-11 14:50:10 +0100469 if (end < *p) {
470 return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
471 }
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200472
473 /* Generate key (7.4.2.3.1) and write it out */
Gilles Peskine449bd832023-01-11 14:50:10 +0100474 MBEDTLS_MPI_CHK(mbedtls_ecp_gen_keypair_base((mbedtls_ecp_group *) grp, G, x, X,
475 f_rng, p_rng));
476 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(grp, X,
477 pf, &len, *p, end - *p));
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200478 *p += len;
479
480 /* Generate and write proof */
Gilles Peskine449bd832023-01-11 14:50:10 +0100481 MBEDTLS_MPI_CHK(ecjpake_zkp_write(md_type, grp, pf, G, x, X, id,
482 p, end, f_rng, p_rng));
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200483
484cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100485 return ret;
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200486}
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200487
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200488/*
489 * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs
Shaun Case8b0ecbc2021-12-20 21:14:10 -0800490 * Outputs: verified peer public keys Xa, Xb
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200491 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100492static int ecjpake_kkpp_read(const mbedtls_md_type_t md_type,
493 const mbedtls_ecp_group *grp,
494 const int pf,
495 const mbedtls_ecp_point *G,
496 mbedtls_ecp_point *Xa,
497 mbedtls_ecp_point *Xb,
498 const char *id,
499 const unsigned char *buf,
500 size_t len)
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200501{
Janos Follath24eed8d2019-11-22 13:21:35 +0000502 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200503 const unsigned char *p = buf;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200504 const unsigned char *end = buf + len;
505
506 /*
507 * struct {
508 * ECJPAKEKeyKP ecjpake_key_kp_pair_list[2];
509 * } ECJPAKEKeyKPPairList;
510 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100511 MBEDTLS_MPI_CHK(ecjpake_kkp_read(md_type, grp, pf, G, Xa, id, &p, end));
512 MBEDTLS_MPI_CHK(ecjpake_kkp_read(md_type, grp, pf, G, Xb, id, &p, end));
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200513
Gilles Peskine449bd832023-01-11 14:50:10 +0100514 if (p != end) {
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200515 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Gilles Peskine449bd832023-01-11 14:50:10 +0100516 }
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200517
518cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100519 return ret;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200520}
521
522/*
523 * Generate a ECJPAKEKeyKPPairList
524 * Outputs: the serialized structure, plus two private/public key pairs
525 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100526static int ecjpake_kkpp_write(const mbedtls_md_type_t md_type,
527 const mbedtls_ecp_group *grp,
528 const int pf,
529 const mbedtls_ecp_point *G,
530 mbedtls_mpi *xm1,
531 mbedtls_ecp_point *Xa,
532 mbedtls_mpi *xm2,
533 mbedtls_ecp_point *Xb,
534 const char *id,
535 unsigned char *buf,
536 size_t len,
537 size_t *olen,
538 int (*f_rng)(void *, unsigned char *, size_t),
539 void *p_rng)
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200540{
Janos Follath24eed8d2019-11-22 13:21:35 +0000541 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200542 unsigned char *p = buf;
543 const unsigned char *end = buf + len;
544
Gilles Peskine449bd832023-01-11 14:50:10 +0100545 MBEDTLS_MPI_CHK(ecjpake_kkp_write(md_type, grp, pf, G, xm1, Xa, id,
546 &p, end, f_rng, p_rng));
547 MBEDTLS_MPI_CHK(ecjpake_kkp_write(md_type, grp, pf, G, xm2, Xb, id,
548 &p, end, f_rng, p_rng));
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200549
550 *olen = p - buf;
551
552cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100553 return ret;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200554}
555
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200556/*
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200557 * Read and process the first round message
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200558 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100559int mbedtls_ecjpake_read_round_one(mbedtls_ecjpake_context *ctx,
560 const unsigned char *buf,
561 size_t len)
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200562{
Gilles Peskine449bd832023-01-11 14:50:10 +0100563 return ecjpake_kkpp_read(ctx->md_type, &ctx->grp, ctx->point_format,
564 &ctx->grp.G,
565 &ctx->Xp1, &ctx->Xp2, ID_PEER,
566 buf, len);
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200567}
568
569/*
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200570 * Generate and write the first round message
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200571 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100572int mbedtls_ecjpake_write_round_one(mbedtls_ecjpake_context *ctx,
573 unsigned char *buf, size_t len, size_t *olen,
574 int (*f_rng)(void *, unsigned char *, size_t),
575 void *p_rng)
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200576{
Gilles Peskine449bd832023-01-11 14:50:10 +0100577 return ecjpake_kkpp_write(ctx->md_type, &ctx->grp, ctx->point_format,
578 &ctx->grp.G,
579 &ctx->xm1, &ctx->Xm1, &ctx->xm2, &ctx->Xm2,
580 ID_MINE, buf, len, olen, f_rng, p_rng);
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200581}
582
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200583/*
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200584 * Compute the sum of three points R = A + B + C
585 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100586static int ecjpake_ecp_add3(mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
587 const mbedtls_ecp_point *A,
588 const mbedtls_ecp_point *B,
589 const mbedtls_ecp_point *C)
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200590{
Janos Follath24eed8d2019-11-22 13:21:35 +0000591 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200592 mbedtls_mpi one;
593
Gilles Peskine449bd832023-01-11 14:50:10 +0100594 mbedtls_mpi_init(&one);
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200595
Gilles Peskine449bd832023-01-11 14:50:10 +0100596 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&one, 1));
597 MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(grp, R, &one, A, &one, B));
598 MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(grp, R, &one, R, &one, C));
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200599
600cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100601 mbedtls_mpi_free(&one);
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200602
Gilles Peskine449bd832023-01-11 14:50:10 +0100603 return ret;
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200604}
605
606/*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200607 * Read and process second round message (C: 7.4.2.5, S: 7.4.2.6)
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200608 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100609int mbedtls_ecjpake_read_round_two(mbedtls_ecjpake_context *ctx,
610 const unsigned char *buf,
611 size_t len)
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200612{
Janos Follath24eed8d2019-11-22 13:21:35 +0000613 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200614 const unsigned char *p = buf;
615 const unsigned char *end = buf + len;
616 mbedtls_ecp_group grp;
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200617 mbedtls_ecp_point G; /* C: GB, S: GA */
Hanno Becker185e5162018-12-19 09:48:50 +0000618
Gilles Peskine449bd832023-01-11 14:50:10 +0100619 mbedtls_ecp_group_init(&grp);
620 mbedtls_ecp_point_init(&G);
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200621
622 /*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200623 * Server: GA = X3 + X4 + X1 (7.4.2.6.1)
624 * Client: GB = X1 + X2 + X3 (7.4.2.5.1)
625 * Unified: G = Xm1 + Xm2 + Xp1
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200626 * We need that before parsing in order to check Xp as we read it
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200627 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100628 MBEDTLS_MPI_CHK(ecjpake_ecp_add3(&ctx->grp, &G,
629 &ctx->Xm1, &ctx->Xm2, &ctx->Xp1));
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200630
631 /*
632 * struct {
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200633 * ECParameters curve_params; // only client reading server msg
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200634 * ECJPAKEKeyKP ecjpake_key_kp;
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200635 * } Client/ServerECJPAKEParams;
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200636 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100637 if (ctx->role == MBEDTLS_ECJPAKE_CLIENT) {
638 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_group(&grp, &p, len));
639 if (grp.id != ctx->grp.id) {
Manuel Pégourié-Gonnardd9802af2015-08-17 12:47:38 +0200640 ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
641 goto cleanup;
642 }
643 }
644
Gilles Peskine449bd832023-01-11 14:50:10 +0100645 MBEDTLS_MPI_CHK(ecjpake_kkp_read(ctx->md_type, &ctx->grp,
646 ctx->point_format,
647 &G, &ctx->Xp, ID_PEER, &p, end));
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200648
Gilles Peskine449bd832023-01-11 14:50:10 +0100649 if (p != end) {
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200650 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
651 goto cleanup;
652 }
653
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200654cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100655 mbedtls_ecp_group_free(&grp);
656 mbedtls_ecp_point_free(&G);
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200657
Gilles Peskine449bd832023-01-11 14:50:10 +0100658 return ret;
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200659}
660
661/*
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200662 * Compute R = +/- X * S mod N, taking care not to leak S
663 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100664static int ecjpake_mul_secret(mbedtls_mpi *R, int sign,
665 const mbedtls_mpi *X,
666 const mbedtls_mpi *S,
667 const mbedtls_mpi *N,
668 int (*f_rng)(void *, unsigned char *, size_t),
669 void *p_rng)
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200670{
Janos Follath24eed8d2019-11-22 13:21:35 +0000671 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200672 mbedtls_mpi b; /* Blinding value, then s + N * blinding */
673
Gilles Peskine449bd832023-01-11 14:50:10 +0100674 mbedtls_mpi_init(&b);
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200675
676 /* b = s + rnd-128-bit * N */
Gilles Peskine449bd832023-01-11 14:50:10 +0100677 MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&b, 16, f_rng, p_rng));
678 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&b, &b, N));
679 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&b, &b, S));
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200680
681 /* R = sign * X * b mod N */
Gilles Peskine449bd832023-01-11 14:50:10 +0100682 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(R, X, &b));
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200683 R->s *= sign;
Gilles Peskine449bd832023-01-11 14:50:10 +0100684 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(R, R, N));
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200685
686cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100687 mbedtls_mpi_free(&b);
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200688
Gilles Peskine449bd832023-01-11 14:50:10 +0100689 return ret;
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200690}
691
692/*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200693 * Generate and write the second round message (S: 7.4.2.5, C: 7.4.2.6)
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200694 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100695int mbedtls_ecjpake_write_round_two(mbedtls_ecjpake_context *ctx,
696 unsigned char *buf, size_t len, size_t *olen,
697 int (*f_rng)(void *, unsigned char *, size_t),
698 void *p_rng)
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200699{
Janos Follath24eed8d2019-11-22 13:21:35 +0000700 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200701 mbedtls_ecp_point G; /* C: GA, S: GB */
702 mbedtls_ecp_point Xm; /* C: Xc, S: Xs */
703 mbedtls_mpi xm; /* C: xc, S: xs */
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200704 unsigned char *p = buf;
705 const unsigned char *end = buf + len;
706 size_t ec_len;
Hanno Becker185e5162018-12-19 09:48:50 +0000707
Gilles Peskine449bd832023-01-11 14:50:10 +0100708 mbedtls_ecp_point_init(&G);
709 mbedtls_ecp_point_init(&Xm);
710 mbedtls_mpi_init(&xm);
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200711
712 /*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200713 * First generate private/public key pair (S: 7.4.2.5.1, C: 7.4.2.6.1)
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200714 *
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200715 * Client: GA = X1 + X3 + X4 | xs = x2 * s | Xc = xc * GA
716 * Server: GB = X3 + X1 + X2 | xs = x4 * s | Xs = xs * GB
717 * Unified: G = Xm1 + Xp1 + Xp2 | xm = xm2 * s | Xm = xm * G
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200718 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100719 MBEDTLS_MPI_CHK(ecjpake_ecp_add3(&ctx->grp, &G,
720 &ctx->Xp1, &ctx->Xp2, &ctx->Xm1));
721 MBEDTLS_MPI_CHK(ecjpake_mul_secret(&xm, 1, &ctx->xm2, &ctx->s,
722 &ctx->grp.N, f_rng, p_rng));
723 MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, &Xm, &xm, &G, f_rng, p_rng));
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200724
725 /*
726 * Now write things out
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200727 *
728 * struct {
729 * ECParameters curve_params; // only server writing its message
730 * ECJPAKEKeyKP ecjpake_key_kp;
731 * } Client/ServerECJPAKEParams;
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200732 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100733 if (ctx->role == MBEDTLS_ECJPAKE_SERVER) {
734 if (end < p) {
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200735 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
736 goto cleanup;
737 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100738 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_group(&ctx->grp, &ec_len,
739 p, end - p));
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200740 p += ec_len;
741 }
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200742
Gilles Peskine449bd832023-01-11 14:50:10 +0100743 if (end < p) {
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200744 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
745 goto cleanup;
746 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100747 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(&ctx->grp, &Xm,
748 ctx->point_format, &ec_len, p, end - p));
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200749 p += ec_len;
750
Gilles Peskine449bd832023-01-11 14:50:10 +0100751 MBEDTLS_MPI_CHK(ecjpake_zkp_write(ctx->md_type, &ctx->grp,
752 ctx->point_format,
753 &G, &xm, &Xm, ID_MINE,
754 &p, end, f_rng, p_rng));
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200755
756 *olen = p - buf;
757
758cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100759 mbedtls_ecp_point_free(&G);
760 mbedtls_ecp_point_free(&Xm);
761 mbedtls_mpi_free(&xm);
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +0200762
Gilles Peskine449bd832023-01-11 14:50:10 +0100763 return ret;
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +0200764}
765
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200766/*
767 * Derive PMS (7.4.2.7 / 7.4.2.8)
768 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100769static int mbedtls_ecjpake_derive_k(mbedtls_ecjpake_context *ctx,
770 mbedtls_ecp_point *K,
771 int (*f_rng)(void *, unsigned char *, size_t),
772 void *p_rng)
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200773{
Janos Follath24eed8d2019-11-22 13:21:35 +0000774 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200775 mbedtls_mpi m_xm2_s, one;
Hanno Becker185e5162018-12-19 09:48:50 +0000776
Gilles Peskine449bd832023-01-11 14:50:10 +0100777 mbedtls_mpi_init(&m_xm2_s);
778 mbedtls_mpi_init(&one);
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200779
Gilles Peskine449bd832023-01-11 14:50:10 +0100780 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&one, 1));
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200781
782 /*
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200783 * Client: K = ( Xs - X4 * x2 * s ) * x2
784 * Server: K = ( Xc - X2 * x4 * s ) * x4
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200785 * Unified: K = ( Xp - Xp2 * xm2 * s ) * xm2
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200786 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100787 MBEDTLS_MPI_CHK(ecjpake_mul_secret(&m_xm2_s, -1, &ctx->xm2, &ctx->s,
788 &ctx->grp.N, f_rng, p_rng));
789 MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(&ctx->grp, K,
790 &one, &ctx->Xp,
791 &m_xm2_s, &ctx->Xp2));
792 MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, K, &ctx->xm2, K,
793 f_rng, p_rng));
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200794
Neil Armstrong12663092022-06-15 16:00:00 +0200795cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100796 mbedtls_mpi_free(&m_xm2_s);
797 mbedtls_mpi_free(&one);
Neil Armstrong12663092022-06-15 16:00:00 +0200798
Gilles Peskine449bd832023-01-11 14:50:10 +0100799 return ret;
Neil Armstrong12663092022-06-15 16:00:00 +0200800}
801
Gilles Peskine449bd832023-01-11 14:50:10 +0100802int mbedtls_ecjpake_derive_secret(mbedtls_ecjpake_context *ctx,
803 unsigned char *buf, size_t len, size_t *olen,
804 int (*f_rng)(void *, unsigned char *, size_t),
805 void *p_rng)
Neil Armstrong12663092022-06-15 16:00:00 +0200806{
807 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
808 mbedtls_ecp_point K;
809 unsigned char kx[MBEDTLS_ECP_MAX_BYTES];
810 size_t x_bytes;
811
Gilles Peskine449bd832023-01-11 14:50:10 +0100812 *olen = mbedtls_hash_info_get_size(ctx->md_type);
813 if (len < *olen) {
814 return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
815 }
Neil Armstrong12663092022-06-15 16:00:00 +0200816
Gilles Peskine449bd832023-01-11 14:50:10 +0100817 mbedtls_ecp_point_init(&K);
Neil Armstrong12663092022-06-15 16:00:00 +0200818
819 ret = mbedtls_ecjpake_derive_k(ctx, &K, f_rng, p_rng);
Gilles Peskine449bd832023-01-11 14:50:10 +0100820 if (ret) {
Neil Armstrong12663092022-06-15 16:00:00 +0200821 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100822 }
Neil Armstrong12663092022-06-15 16:00:00 +0200823
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200824 /* PMS = SHA-256( K.X ) */
Gilles Peskine449bd832023-01-11 14:50:10 +0100825 x_bytes = (ctx->grp.pbits + 7) / 8;
826 MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&K.X, kx, x_bytes));
827 MBEDTLS_MPI_CHK(mbedtls_ecjpake_compute_hash(ctx->md_type,
828 kx, x_bytes, buf));
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200829
830cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100831 mbedtls_ecp_point_free(&K);
Neil Armstrong12663092022-06-15 16:00:00 +0200832
Gilles Peskine449bd832023-01-11 14:50:10 +0100833 return ret;
Neil Armstrong12663092022-06-15 16:00:00 +0200834}
835
Gilles Peskine449bd832023-01-11 14:50:10 +0100836int mbedtls_ecjpake_write_shared_key(mbedtls_ecjpake_context *ctx,
837 unsigned char *buf, size_t len, size_t *olen,
838 int (*f_rng)(void *, unsigned char *, size_t),
839 void *p_rng)
Neil Armstrong12663092022-06-15 16:00:00 +0200840{
841 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
842 mbedtls_ecp_point K;
843
Gilles Peskine449bd832023-01-11 14:50:10 +0100844 mbedtls_ecp_point_init(&K);
Neil Armstrong12663092022-06-15 16:00:00 +0200845
846 ret = mbedtls_ecjpake_derive_k(ctx, &K, f_rng, p_rng);
Gilles Peskine449bd832023-01-11 14:50:10 +0100847 if (ret) {
Neil Armstrong12663092022-06-15 16:00:00 +0200848 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100849 }
Neil Armstrong12663092022-06-15 16:00:00 +0200850
Gilles Peskine449bd832023-01-11 14:50:10 +0100851 ret = mbedtls_ecp_point_write_binary(&ctx->grp, &K, ctx->point_format,
852 olen, buf, len);
853 if (ret != 0) {
Neil Armstrong12663092022-06-15 16:00:00 +0200854 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100855 }
Neil Armstrong12663092022-06-15 16:00:00 +0200856
857cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100858 mbedtls_ecp_point_free(&K);
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200859
Gilles Peskine449bd832023-01-11 14:50:10 +0100860 return ret;
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200861}
862
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200863#undef ID_MINE
864#undef ID_PEER
865
Hanno Becker616d1ca2018-01-24 10:25:05 +0000866#endif /* ! MBEDTLS_ECJPAKE_ALT */
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200867
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200868#if defined(MBEDTLS_SELF_TEST)
869
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200870#include "mbedtls/platform.h"
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200871
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200872#if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
873 !defined(MBEDTLS_SHA256_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100874int mbedtls_ecjpake_self_test(int verbose)
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200875{
876 (void) verbose;
Gilles Peskine449bd832023-01-11 14:50:10 +0100877 return 0;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200878}
879#else
880
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200881static const unsigned char ecjpake_test_password[] = {
882 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x6a, 0x70, 0x61, 0x6b, 0x65, 0x74,
883 0x65, 0x73, 0x74
884};
885
Steven Cooreman64f27732021-01-11 17:20:10 +0100886#if !defined(MBEDTLS_ECJPAKE_ALT)
887
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200888static const unsigned char ecjpake_test_x1[] = {
889 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
890 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
891 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21
892};
893
894static const unsigned char ecjpake_test_x2[] = {
895 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
896 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
897 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
898};
899
900static const unsigned char ecjpake_test_x3[] = {
901 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
902 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
903 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
904};
905
906static const unsigned char ecjpake_test_x4[] = {
907 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc,
908 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
909 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1
910};
911
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200912static const unsigned char ecjpake_test_cli_one[] = {
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200913 0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19,
914 0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44,
915 0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad,
916 0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62,
917 0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9,
918 0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d,
919 0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e,
920 0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e,
921 0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73,
922 0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22,
923 0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce,
924 0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00,
925 0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200926 0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e,
927 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62,
928 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5,
929 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb,
930 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35,
931 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0,
932 0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb,
933 0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47,
934 0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39,
935 0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97,
936 0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40,
937 0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d,
938 0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa,
939 0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d,
940 0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200941};
942
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200943static const unsigned char ecjpake_test_srv_one[] = {
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200944 0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb,
945 0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18,
946 0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47,
947 0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f,
948 0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7,
949 0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d,
950 0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64,
951 0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36,
952 0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2,
953 0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec,
954 0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16,
955 0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96,
956 0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3,
957 0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19,
958 0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f,
959 0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8,
960 0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7,
961 0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea,
962 0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5,
963 0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6,
964 0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31,
965 0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d,
966 0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8,
967 0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee,
968 0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84,
969 0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f,
970 0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80,
971 0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12
972};
973
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200974static const unsigned char ecjpake_test_srv_two[] = {
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200975 0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23,
976 0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c,
977 0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f,
978 0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca,
979 0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26,
980 0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55,
981 0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38,
982 0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6,
983 0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9,
984 0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4,
985 0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2,
986 0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8,
987 0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd,
988 0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c
989};
990
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200991static const unsigned char ecjpake_test_cli_two[] = {
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +0200992 0x41, 0x04, 0x69, 0xd5, 0x4e, 0xe8, 0x5e, 0x90, 0xce, 0x3f, 0x12, 0x46,
993 0x74, 0x2d, 0xe5, 0x07, 0xe9, 0x39, 0xe8, 0x1d, 0x1d, 0xc1, 0xc5, 0xcb,
994 0x98, 0x8b, 0x58, 0xc3, 0x10, 0xc9, 0xfd, 0xd9, 0x52, 0x4d, 0x93, 0x72,
995 0x0b, 0x45, 0x54, 0x1c, 0x83, 0xee, 0x88, 0x41, 0x19, 0x1d, 0xa7, 0xce,
996 0xd8, 0x6e, 0x33, 0x12, 0xd4, 0x36, 0x23, 0xc1, 0xd6, 0x3e, 0x74, 0x98,
997 0x9a, 0xba, 0x4a, 0xff, 0xd1, 0xee, 0x41, 0x04, 0x07, 0x7e, 0x8c, 0x31,
998 0xe2, 0x0e, 0x6b, 0xed, 0xb7, 0x60, 0xc1, 0x35, 0x93, 0xe6, 0x9f, 0x15,
999 0xbe, 0x85, 0xc2, 0x7d, 0x68, 0xcd, 0x09, 0xcc, 0xb8, 0xc4, 0x18, 0x36,
1000 0x08, 0x91, 0x7c, 0x5c, 0x3d, 0x40, 0x9f, 0xac, 0x39, 0xfe, 0xfe, 0xe8,
1001 0x2f, 0x72, 0x92, 0xd3, 0x6f, 0x0d, 0x23, 0xe0, 0x55, 0x91, 0x3f, 0x45,
1002 0xa5, 0x2b, 0x85, 0xdd, 0x8a, 0x20, 0x52, 0xe9, 0xe1, 0x29, 0xbb, 0x4d,
1003 0x20, 0x0f, 0x01, 0x1f, 0x19, 0x48, 0x35, 0x35, 0xa6, 0xe8, 0x9a, 0x58,
1004 0x0c, 0x9b, 0x00, 0x03, 0xba, 0xf2, 0x14, 0x62, 0xec, 0xe9, 0x1a, 0x82,
1005 0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c
1006};
1007
Neil Armstrong12663092022-06-15 16:00:00 +02001008static const unsigned char ecjpake_test_shared_key[] = {
1009 0x04, 0x01, 0xab, 0xe9, 0xf2, 0xc7, 0x3a, 0x99, 0x14, 0xcb, 0x1f, 0x80,
1010 0xfb, 0x9d, 0xdb, 0x7e, 0x00, 0x12, 0xa8, 0x9c, 0x2f, 0x39, 0x27, 0x79,
1011 0xf9, 0x64, 0x40, 0x14, 0x75, 0xea, 0xc1, 0x31, 0x28, 0x43, 0x8f, 0xe1,
1012 0x12, 0x41, 0xd6, 0xc1, 0xe5, 0x5f, 0x7b, 0x80, 0x88, 0x94, 0xc9, 0xc0,
1013 0x27, 0xa3, 0x34, 0x41, 0xf5, 0xcb, 0xa1, 0xfe, 0x6c, 0xc7, 0xe6, 0x12,
1014 0x17, 0xc3, 0xde, 0x27, 0xb4,
1015};
1016
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001017static const unsigned char ecjpake_test_pms[] = {
1018 0xf3, 0xd4, 0x7f, 0x59, 0x98, 0x44, 0xdb, 0x92, 0xa5, 0x69, 0xbb, 0xe7,
1019 0x98, 0x1e, 0x39, 0xd9, 0x31, 0xfd, 0x74, 0x3b, 0xf2, 0x2e, 0x98, 0xf9,
1020 0xb4, 0x38, 0xf7, 0x19, 0xd3, 0xc4, 0xf3, 0x51
1021};
1022
Manuel Pégourié-Gonnardaa3ed6f2021-06-15 11:29:26 +02001023/*
1024 * PRNG for test - !!!INSECURE NEVER USE IN PRODUCTION!!!
1025 *
1026 * This is the linear congruential generator from numerical recipes,
1027 * except we only use the low byte as the output. See
1028 * https://en.wikipedia.org/wiki/Linear_congruential_generator#Parameters_in_common_use
1029 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001030static int self_test_rng(void *ctx, unsigned char *out, size_t len)
Manuel Pégourié-Gonnardaa3ed6f2021-06-15 11:29:26 +02001031{
1032 static uint32_t state = 42;
1033
1034 (void) ctx;
1035
Gilles Peskine449bd832023-01-11 14:50:10 +01001036 for (size_t i = 0; i < len; i++) {
Manuel Pégourié-Gonnardaa3ed6f2021-06-15 11:29:26 +02001037 state = state * 1664525u + 1013904223u;
1038 out[i] = (unsigned char) state;
1039 }
1040
Gilles Peskine449bd832023-01-11 14:50:10 +01001041 return 0;
Manuel Pégourié-Gonnardaa3ed6f2021-06-15 11:29:26 +02001042}
1043
Antonin Décimo36e89b52019-01-23 15:24:37 +01001044/* Load my private keys and generate the corresponding public keys */
Gilles Peskine449bd832023-01-11 14:50:10 +01001045static int ecjpake_test_load(mbedtls_ecjpake_context *ctx,
1046 const unsigned char *xm1, size_t len1,
1047 const unsigned char *xm2, size_t len2)
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001048{
Janos Follath24eed8d2019-11-22 13:21:35 +00001049 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001050
Gilles Peskine449bd832023-01-11 14:50:10 +01001051 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->xm1, xm1, len1));
1052 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->xm2, xm2, len2));
1053 MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, &ctx->Xm1, &ctx->xm1,
1054 &ctx->grp.G, self_test_rng, NULL));
1055 MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, &ctx->Xm2, &ctx->xm2,
1056 &ctx->grp.G, self_test_rng, NULL));
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001057
1058cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01001059 return ret;
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001060}
1061
Steven Cooreman64f27732021-01-11 17:20:10 +01001062#endif /* ! MBEDTLS_ECJPAKE_ALT */
1063
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001064/* For tests we don't need a secure RNG;
1065 * use the LGC from Numerical Recipes for simplicity */
Gilles Peskine449bd832023-01-11 14:50:10 +01001066static int ecjpake_lgc(void *p, unsigned char *out, size_t len)
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001067{
1068 static uint32_t x = 42;
1069 (void) p;
1070
Gilles Peskine449bd832023-01-11 14:50:10 +01001071 while (len > 0) {
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001072 size_t use_len = len > 4 ? 4 : len;
1073 x = 1664525 * x + 1013904223;
Gilles Peskine449bd832023-01-11 14:50:10 +01001074 memcpy(out, &x, use_len);
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001075 out += use_len;
1076 len -= use_len;
1077 }
1078
Gilles Peskine449bd832023-01-11 14:50:10 +01001079 return 0;
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001080}
1081
Gilles Peskine449bd832023-01-11 14:50:10 +01001082#define TEST_ASSERT(x) \
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +02001083 do { \
Gilles Peskine449bd832023-01-11 14:50:10 +01001084 if (x) \
1085 ret = 0; \
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +02001086 else \
1087 { \
1088 ret = 1; \
1089 goto cleanup; \
1090 } \
Gilles Peskine449bd832023-01-11 14:50:10 +01001091 } while (0)
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +02001092
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001093/*
1094 * Checkup routine
1095 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001096int mbedtls_ecjpake_self_test(int verbose)
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001097{
Janos Follath24eed8d2019-11-22 13:21:35 +00001098 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001099 mbedtls_ecjpake_context cli;
1100 mbedtls_ecjpake_context srv;
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001101 unsigned char buf[512], pms[32];
1102 size_t len, pmslen;
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001103
Gilles Peskine449bd832023-01-11 14:50:10 +01001104 mbedtls_ecjpake_init(&cli);
1105 mbedtls_ecjpake_init(&srv);
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001106
Gilles Peskine449bd832023-01-11 14:50:10 +01001107 if (verbose != 0) {
1108 mbedtls_printf(" ECJPAKE test #0 (setup): ");
1109 }
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +02001110
Gilles Peskine449bd832023-01-11 14:50:10 +01001111 TEST_ASSERT(mbedtls_ecjpake_setup(&cli, MBEDTLS_ECJPAKE_CLIENT,
1112 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1113 ecjpake_test_password,
1114 sizeof(ecjpake_test_password)) == 0);
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001115
Gilles Peskine449bd832023-01-11 14:50:10 +01001116 TEST_ASSERT(mbedtls_ecjpake_setup(&srv, MBEDTLS_ECJPAKE_SERVER,
1117 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1118 ecjpake_test_password,
1119 sizeof(ecjpake_test_password)) == 0);
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001120
Gilles Peskine449bd832023-01-11 14:50:10 +01001121 if (verbose != 0) {
1122 mbedtls_printf("passed\n");
1123 }
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001124
Gilles Peskine449bd832023-01-11 14:50:10 +01001125 if (verbose != 0) {
1126 mbedtls_printf(" ECJPAKE test #1 (random handshake): ");
1127 }
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001128
Gilles Peskine449bd832023-01-11 14:50:10 +01001129 TEST_ASSERT(mbedtls_ecjpake_write_round_one(&cli,
1130 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001131
Gilles Peskine449bd832023-01-11 14:50:10 +01001132 TEST_ASSERT(mbedtls_ecjpake_read_round_one(&srv, buf, len) == 0);
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001133
Gilles Peskine449bd832023-01-11 14:50:10 +01001134 TEST_ASSERT(mbedtls_ecjpake_write_round_one(&srv,
1135 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001136
Gilles Peskine449bd832023-01-11 14:50:10 +01001137 TEST_ASSERT(mbedtls_ecjpake_read_round_one(&cli, buf, len) == 0);
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001138
Gilles Peskine449bd832023-01-11 14:50:10 +01001139 TEST_ASSERT(mbedtls_ecjpake_write_round_two(&srv,
1140 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +02001141
Gilles Peskine449bd832023-01-11 14:50:10 +01001142 TEST_ASSERT(mbedtls_ecjpake_read_round_two(&cli, buf, len) == 0);
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +02001143
Gilles Peskine449bd832023-01-11 14:50:10 +01001144 TEST_ASSERT(mbedtls_ecjpake_derive_secret(&cli,
1145 pms, sizeof(pms), &pmslen, ecjpake_lgc, NULL) == 0);
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001146
Gilles Peskine449bd832023-01-11 14:50:10 +01001147 TEST_ASSERT(mbedtls_ecjpake_write_round_two(&cli,
1148 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +02001149
Gilles Peskine449bd832023-01-11 14:50:10 +01001150 TEST_ASSERT(mbedtls_ecjpake_read_round_two(&srv, buf, len) == 0);
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +02001151
Gilles Peskine449bd832023-01-11 14:50:10 +01001152 TEST_ASSERT(mbedtls_ecjpake_derive_secret(&srv,
1153 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001154
Gilles Peskine449bd832023-01-11 14:50:10 +01001155 TEST_ASSERT(len == pmslen);
1156 TEST_ASSERT(memcmp(buf, pms, len) == 0);
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001157
Gilles Peskine449bd832023-01-11 14:50:10 +01001158 if (verbose != 0) {
1159 mbedtls_printf("passed\n");
1160 }
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001161
Steven Cooreman64f27732021-01-11 17:20:10 +01001162#if !defined(MBEDTLS_ECJPAKE_ALT)
1163 /* 'reference handshake' tests can only be run against implementations
1164 * for which we have 100% control over how the random ephemeral keys
1165 * are generated. This is only the case for the internal mbed TLS
1166 * implementation, so these tests are skipped in case the internal
1167 * implementation is swapped out for an alternative one. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001168 if (verbose != 0) {
1169 mbedtls_printf(" ECJPAKE test #2 (reference handshake): ");
1170 }
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001171
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001172 /* Simulate generation of round one */
Gilles Peskine449bd832023-01-11 14:50:10 +01001173 MBEDTLS_MPI_CHK(ecjpake_test_load(&cli,
1174 ecjpake_test_x1, sizeof(ecjpake_test_x1),
1175 ecjpake_test_x2, sizeof(ecjpake_test_x2)));
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001176
Gilles Peskine449bd832023-01-11 14:50:10 +01001177 MBEDTLS_MPI_CHK(ecjpake_test_load(&srv,
1178 ecjpake_test_x3, sizeof(ecjpake_test_x3),
1179 ecjpake_test_x4, sizeof(ecjpake_test_x4)));
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001180
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001181 /* Read round one */
Gilles Peskine449bd832023-01-11 14:50:10 +01001182 TEST_ASSERT(mbedtls_ecjpake_read_round_one(&srv,
1183 ecjpake_test_cli_one,
1184 sizeof(ecjpake_test_cli_one)) == 0);
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001185
Gilles Peskine449bd832023-01-11 14:50:10 +01001186 TEST_ASSERT(mbedtls_ecjpake_read_round_one(&cli,
1187 ecjpake_test_srv_one,
1188 sizeof(ecjpake_test_srv_one)) == 0);
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001189
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001190 /* Skip generation of round two, read round two */
Gilles Peskine449bd832023-01-11 14:50:10 +01001191 TEST_ASSERT(mbedtls_ecjpake_read_round_two(&cli,
1192 ecjpake_test_srv_two,
1193 sizeof(ecjpake_test_srv_two)) == 0);
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +02001194
Gilles Peskine449bd832023-01-11 14:50:10 +01001195 TEST_ASSERT(mbedtls_ecjpake_read_round_two(&srv,
1196 ecjpake_test_cli_two,
1197 sizeof(ecjpake_test_cli_two)) == 0);
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +02001198
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001199 /* Server derives PMS */
Gilles Peskine449bd832023-01-11 14:50:10 +01001200 TEST_ASSERT(mbedtls_ecjpake_derive_secret(&srv,
1201 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001202
Gilles Peskine449bd832023-01-11 14:50:10 +01001203 TEST_ASSERT(len == sizeof(ecjpake_test_pms));
1204 TEST_ASSERT(memcmp(buf, ecjpake_test_pms, len) == 0);
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001205
Neil Armstrong12663092022-06-15 16:00:00 +02001206 /* Server derives K as unsigned binary data */
Gilles Peskine449bd832023-01-11 14:50:10 +01001207 TEST_ASSERT(mbedtls_ecjpake_write_shared_key(&srv,
1208 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Neil Armstrong12663092022-06-15 16:00:00 +02001209
Gilles Peskine449bd832023-01-11 14:50:10 +01001210 TEST_ASSERT(len == sizeof(ecjpake_test_shared_key));
1211 TEST_ASSERT(memcmp(buf, ecjpake_test_shared_key, len) == 0);
Neil Armstrong12663092022-06-15 16:00:00 +02001212
Gilles Peskine449bd832023-01-11 14:50:10 +01001213 memset(buf, 0, len); /* Avoid interferences with next step */
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001214
1215 /* Client derives PMS */
Gilles Peskine449bd832023-01-11 14:50:10 +01001216 TEST_ASSERT(mbedtls_ecjpake_derive_secret(&cli,
1217 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001218
Gilles Peskine449bd832023-01-11 14:50:10 +01001219 TEST_ASSERT(len == sizeof(ecjpake_test_pms));
1220 TEST_ASSERT(memcmp(buf, ecjpake_test_pms, len) == 0);
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001221
Neil Armstrong12663092022-06-15 16:00:00 +02001222 /* Client derives K as unsigned binary data */
Gilles Peskine449bd832023-01-11 14:50:10 +01001223 TEST_ASSERT(mbedtls_ecjpake_write_shared_key(&cli,
1224 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Neil Armstrong12663092022-06-15 16:00:00 +02001225
Gilles Peskine449bd832023-01-11 14:50:10 +01001226 TEST_ASSERT(len == sizeof(ecjpake_test_shared_key));
1227 TEST_ASSERT(memcmp(buf, ecjpake_test_shared_key, len) == 0);
Neil Armstrong12663092022-06-15 16:00:00 +02001228
Gilles Peskine449bd832023-01-11 14:50:10 +01001229 if (verbose != 0) {
1230 mbedtls_printf("passed\n");
1231 }
Steven Cooreman64f27732021-01-11 17:20:10 +01001232#endif /* ! MBEDTLS_ECJPAKE_ALT */
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001233
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001234cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01001235 mbedtls_ecjpake_free(&cli);
1236 mbedtls_ecjpake_free(&srv);
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001237
Gilles Peskine449bd832023-01-11 14:50:10 +01001238 if (ret != 0) {
1239 if (verbose != 0) {
1240 mbedtls_printf("failed\n");
1241 }
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001242
1243 ret = 1;
1244 }
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001245
Gilles Peskine449bd832023-01-11 14:50:10 +01001246 if (verbose != 0) {
1247 mbedtls_printf("\n");
1248 }
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001249
Gilles Peskine449bd832023-01-11 14:50:10 +01001250 return ret;
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001251}
1252
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +02001253#undef TEST_ASSERT
1254
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001255#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_SHA256_C */
1256
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001257#endif /* MBEDTLS_SELF_TEST */
1258
1259#endif /* MBEDTLS_ECJPAKE_C */